{"id":6,"date":"2026-03-26T02:54:54","date_gmt":"2026-03-26T02:54:54","guid":{"rendered":"https:\/\/bpo.link-ceo.com.br\/?page_id=6"},"modified":"2026-03-29T16:14:23","modified_gmt":"2026-03-29T16:14:23","slug":"painel","status":"publish","type":"page","link":"https:\/\/bpo.link-ceo.com.br\/","title":{"rendered":"Painel"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"6\" class=\"elementor elementor-6\">\n\t\t\t\t<div class=\"elementor-element elementor-element-0c7eb67 e-con-full e-flex e-con e-parent\" data-id=\"0c7eb67\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f77fb80 elementor-widget__width-inherit elementor-widget elementor-widget-html\" data-id=\"f77fb80\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\n<html lang=\"pt-BR\" data-theme=\"dark\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=0.85, minimum-scale=0.5, maximum-scale=3.0, viewport-fit=cover\">\n<title>Link Task \u2014 Painel Scrum<\/title>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Exo+2:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap\" rel=\"stylesheet\">\n<script src=\"https:\/\/cdn.jsdelivr.net\/npm\/chart.js@4.4.0\/dist\/chart.umd.min.js\"><\/script>\n<script src=\"https:\/\/accounts.google.com\/gsi\/client\" async><\/script>\n<style>\n\/* ============ AUTH OVERLAY ============ *\/\n.auth-overlay {\n  position: fixed; inset: 0; z-index: 3000;\n  background: var(--bg-base);\n  display: flex; align-items: center; justify-content: center;\n  flex-direction: column; gap: 0;\n  transition: opacity .3s;\n}\n.auth-overlay.hidden { opacity: 0; pointer-events: none; }\n\n.auth-box {\n  background: var(--bg-surface);\n  border-radius: var(--radius-xl); padding: 40px 36px;\n  max-width: 420px; width: 92%; text-align: center;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 3px 4px 0 0 var(--card-3d-dark), 0 16px 48px rgba(0,0,0,.35);\n  position: relative; overflow: hidden;\n}\n.auth-box::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%);\n  pointer-events: none;\n}\n.auth-box > * { position: relative; z-index: 1; }\n\n.auth-logo { margin-bottom: 20px; display: flex; justify-content: center; }\n.auth-title {\n  font-size: 22px; font-weight: 800; margin-bottom: 6px;\n  background: linear-gradient(135deg, var(--blue), var(--green));\n  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;\n}\n.auth-sub { font-size: 14px; color: var(--text-secondary); margin-bottom: 28px; line-height: 1.5; }\n\n.auth-client-setup {\n  background: var(--bg-elevated); border-radius: var(--radius-md);\n  padding: 16px; margin-bottom: 20px; text-align: left;\n}\n.auth-client-setup-title {\n  font-size: 12px; font-weight: 700; color: var(--text-muted);\n  text-transform: uppercase; letter-spacing: .6px; margin-bottom: 10px;\n}\n.auth-client-input { display: flex; gap: 8px; align-items: center; }\n.auth-client-input input {\n  flex: 1; background: var(--input-bg); border: 1px solid var(--border-soft);\n  border-radius: var(--radius-sm); color: var(--text-primary);\n  font-family: var(--font-mono); font-size: 12px; padding: 8px 10px;\n  outline: none; transition: var(--transition);\n}\n.auth-client-input input:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(91,155,213,.15); }\n.auth-client-input input::placeholder { color: var(--text-muted); }\n\n.auth-hint {\n  font-size: 11px; color: var(--text-muted); margin-top: 8px; line-height: 1.5;\n}\n.auth-hint a { color: var(--blue-light); text-decoration: none; }\n.auth-hint a:hover { text-decoration: underline; }\n\n.auth-google-btn-wrap { display: flex; justify-content: center; margin-bottom: 16px; min-height: 44px; }\n.auth-error {\n  background: rgba(248,81,73,.1); border: 1px solid rgba(248,81,73,.25);\n  border-radius: var(--radius-sm); padding: 8px 12px;\n  font-size: 12px; color: var(--red); margin-bottom: 12px; display: none;\n}\n.auth-error.show { display: block; }\n\n\/* User pill in header *\/\n.user-pill {\n  display: flex; align-items: center; gap: 8px; padding: 4px 12px 4px 4px;\n  border-radius: 99px; background: var(--bg-elevated); border: 1px solid var(--border);\n  cursor: pointer; transition: var(--transition); font-size: 13px;\n}\n.user-pill:hover { background: var(--bg-hover); border-color: var(--blue); }\n.user-avatar {\n  width: 28px; height: 28px; border-radius: 50%;\n  object-fit: cover; border: 2px solid var(--blue);\n}\n.user-avatar-placeholder {\n  width: 28px; height: 28px; border-radius: 50%;\n  background: linear-gradient(135deg, var(--blue), var(--green));\n  display: flex; align-items: center; justify-content: center;\n  font-size: 12px; font-weight: 800; color: #fff; flex-shrink: 0;\n}\n.user-name { font-weight: 600; color: var(--text-primary); max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n\/* Logout dropdown *\/\n.user-menu {\n  position: absolute; top: calc(100% + 8px); right: 0;\n  background: var(--bg-surface); border: 1px solid var(--border);\n  border-radius: var(--radius-md); padding: 6px; min-width: 180px;\n  box-shadow: var(--shadow-lg); z-index: 200;\n  display: none;\n}\n.user-menu.open { display: block; animation: chipIn .15s ease; }\n.user-menu-item {\n  padding: 8px 12px; border-radius: var(--radius-sm); font-size: 13px;\n  color: var(--text-secondary); cursor: pointer; transition: var(--transition);\n  display: flex; align-items: center; gap: 8px;\n}\n.user-menu-item:hover { background: var(--bg-hover); color: var(--text-primary); }\n.user-menu-item.danger { color: var(--red); }\n.user-menu-item.danger:hover { background: rgba(248,81,73,.1); }\n.user-menu-email { padding: 8px 12px 4px; font-size: 11px; color: var(--text-muted); font-family: var(--font-mono); border-bottom: 1px solid var(--border-soft); margin-bottom: 4px; word-break: break-all; }\n.user-pill-wrap { position: relative; }\n:root {\n  --blue:        #5B9BD5;\n  --blue-light:  #82b8e8;\n  --blue-dark:   #3a78b5;\n  --green:       #7DC142;\n  --green-light: #9fd664;\n  --green-dark:  #5da020;\n  --accent:      #4de0c0;\n  --purple:      #a78bfa;\n  --orange:      #e3b341;\n  --red:         #f85149;\n\n  --radius-sm:   6px;\n  --radius-md:   10px;\n  --radius-lg:   16px;\n  --radius-xl:   24px;\n\n  --shadow-sm:   0 2px 8px rgba(0,0,0,.18);\n  --shadow-md:   0 4px 20px rgba(0,0,0,.24);\n  --shadow-lg:   0 8px 40px rgba(0,0,0,.32);\n\n  \/* 3D card effect *\/\n  --card-3d-light: rgba(255,255,255,.08);\n  --card-3d-dark:  rgba(0,0,0,.45);\n  --card-3d-shine: rgba(255,255,255,.04);\n\n  --font-main:   'Exo 2', sans-serif;\n  --font-mono:   'JetBrains Mono', monospace;\n  --transition:  .22s cubic-bezier(.4,0,.2,1);\n}\n\n[data-theme=\"dark\"] {\n  --bg-base:     #0d1117;\n  --bg-surface:  #161b22;\n  --bg-card:     #1c2330;\n  --bg-elevated: #21262d;\n  --bg-overlay:  #2d333b;\n  --bg-hover:    #30363d;\n  --border:      rgba(91,155,213,.18);\n  --border-soft: rgba(255,255,255,.07);\n  --text-primary:   #e6edf3;\n  --text-secondary: #8b949e;\n  --text-muted:     #484f58;\n  --text-inverse:   #0d1117;\n  --input-bg:    #0d1117;\n  --scrollbar:   #30363d;\n  --kanban-bg:   #131920;\n  --chart-grid:  rgba(255,255,255,.06);\n}\n\n[data-theme=\"light\"] {\n  --bg-base:     #f0f4f8;\n  --bg-surface:  #ffffff;\n  --bg-card:     #ffffff;\n  --bg-elevated: #f7f9fc;\n  --bg-overlay:  #eef2f7;\n  --bg-hover:    #e8edf4;\n  --border:      rgba(91,155,213,.25);\n  --border-soft: rgba(0,0,0,.08);\n  --text-primary:   #1a2332;\n  --text-secondary: #4a5568;\n  --text-muted:     #a0aec0;\n  --text-inverse:   #ffffff;\n  --input-bg:    #f7f9fc;\n  --scrollbar:   #cbd5e0;\n  --kanban-bg:   #e8edf4;\n  --chart-grid:  rgba(0,0,0,.06);\n  --card-3d-light: rgba(255,255,255,.9);\n  --card-3d-dark:  rgba(0,0,0,.12);\n  --card-3d-shine: rgba(255,255,255,.6);\n}\n\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\nhtml { scroll-behavior: smooth; }\nbody {\n  font-family: var(--font-main);\n  background: var(--bg-base);\n  color: var(--text-primary);\n  min-height: 100vh;\n  font-size: 15px;\n  line-height: 1.5;\n  transition: background var(--transition), color var(--transition);\n}\n\n\/* \u2500\u2500\u2500 3D Card mixin (applied per component) \u2500\u2500\u2500 *\/\n.card-3d {\n  position: relative;\n  border: none !important;\n  background: var(--bg-card);\n  border-radius: var(--radius-lg);\n  box-shadow:\n    \/* top-left highlight *\/\n    -1px -1px 0 0 var(--card-3d-light),\n    \/* bottom-right shadow *\/\n    2px 3px 0 0 var(--card-3d-dark),\n    \/* ambient *\/\n    0 6px 24px rgba(0,0,0,.28),\n    0 1px 3px rgba(0,0,0,.18);\n  overflow: hidden;\n}\n.card-3d::before {\n  content: '';\n  position: absolute;\n  inset: 0;\n  border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 50%);\n  pointer-events: none;\n  z-index: 1;\n}\n.card-3d > * { position: relative; z-index: 2; }\n::-webkit-scrollbar { width: 6px; height: 6px; }\n::-webkit-scrollbar-track { background: transparent; }\n::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 99px; }\n\n\/* ============ LAYOUT ============ *\/\n.app-shell { display: grid; grid-template-rows: auto 1fr; min-height: 100vh; }\n.main-content {\n  max-width: 1600px;\n  margin: 0 auto;\n  padding: 0 20px 60px;\n  width: 100%;\n  \/* Sem overflow-x:hidden \u2014 evita cortar conte\u00fado leg\u00edtimo *\/\n  box-sizing: border-box;\n}\n\n\/* ============ HEADER ============ *\/\n.header {\n  background: var(--bg-surface);\n  border-bottom: 1px solid var(--border);\n  position: sticky; top: 0; z-index: 100;\n  backdrop-filter: blur(12px);\n}\n.header-inner {\n  max-width: 1600px; margin: 0 auto; padding: 0 20px;\n  display: flex; align-items: center; gap: 16px; height: 64px;\n}\n\n\/* ============ LOGO ============ *\/\n.logo-area {\n  display: flex; align-items: center; gap: 12px; flex-shrink: 0;\n  position: relative; cursor: pointer;\n}\n.logo-wrapper {\n  position: relative; display: flex; align-items: center; justify-content: center;\n}\n.logo-img-custom {\n  width: 36px;\n  height: 36px;\n  object-fit: contain;\n  border-radius: 4px;\n  display: block;\n}\n.logo-change-overlay {\n  position: absolute; inset: -4px; border-radius: 8px;\n  background: rgba(91,155,213,.15); border: 1.5px dashed var(--blue);\n  display: flex; align-items: center; justify-content: center;\n  opacity: 0; transition: opacity .2s;\n  font-size: 10px; color: var(--blue); font-weight: 700;\n  white-space: nowrap; gap: 4px;\n}\n.logo-wrapper:hover .logo-change-overlay { opacity: 1; }\n.logo-change-overlay svg { flex-shrink: 0; }\n\n.logo-text { display: flex; flex-direction: column; line-height: 1.1; }\n.logo-title { font-size: 19px; font-weight: 800; letter-spacing: -.3px; }\n.logo-title span:first-child { color: var(--blue); }\n.logo-title span:last-child  { color: var(--green); }\n.logo-sub { font-size: 11px; font-weight: 500; color: var(--text-secondary); letter-spacing: .5px; text-transform: uppercase; }\n\n.header-spacer { flex: 1; }\n.status-pill {\n  display: flex; align-items: center; gap: 6px; padding: 5px 12px;\n  border-radius: 99px; font-size: 12px; font-weight: 600; font-family: var(--font-mono);\n  border: 1px solid var(--border); background: var(--bg-elevated); color: var(--text-secondary);\n  transition: var(--transition);\n}\n.status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--text-muted); transition: var(--transition); }\n.status-pill.online  .status-dot { background: var(--green); box-shadow: 0 0 6px var(--green); }\n.status-pill.online  { color: var(--green); border-color: rgba(125,193,66,.3); }\n.status-pill.offline .status-dot { background: var(--red); box-shadow: 0 0 6px var(--red); }\n.status-pill.offline { color: var(--red); border-color: rgba(248,81,73,.3); }\n.status-pill.local   .status-dot { background: var(--orange); box-shadow: 0 0 6px var(--orange); }\n.status-pill.local   { color: var(--orange); border-color: rgba(227,179,65,.3); }\n\n.header-actions { display: flex; align-items: center; gap: 8px; }\n.theme-toggle { position: relative; width: 52px; height: 28px; cursor: pointer; }\n.theme-toggle input { display: none; }\n.theme-track {\n  position: absolute; inset: 0; border-radius: 99px; background: var(--bg-overlay);\n  border: 1px solid var(--border); transition: var(--transition);\n  display: flex; align-items: center; padding: 0 4px; justify-content: space-between; font-size: 12px;\n}\n.theme-knob {\n  position: absolute; top: 3px; left: 3px; width: 22px; height: 22px;\n  border-radius: 50%; background: linear-gradient(135deg, var(--blue), var(--green));\n  transition: transform var(--transition); box-shadow: var(--shadow-sm);\n  display: flex; align-items: center; justify-content: center; font-size: 11px;\n}\n[data-theme=\"light\"] .theme-knob { transform: translateX(24px); }\n\n\/* ============ BUTTONS ============ *\/\n.btn {\n  display: inline-flex; align-items: center; gap: 6px;\n  padding: 8px 16px; border-radius: var(--radius-md); font-family: var(--font-main);\n  font-size: 14px; font-weight: 600; cursor: pointer; border: none;\n  transition: var(--transition); white-space: nowrap; text-decoration: none;\n}\n.btn-primary { background: linear-gradient(135deg, var(--blue-dark), var(--blue)); color: #fff; box-shadow: 0 2px 12px rgba(91,155,213,.35); }\n.btn-primary:hover { background: linear-gradient(135deg, var(--blue), var(--blue-light)); box-shadow: 0 4px 20px rgba(91,155,213,.5); transform: translateY(-1px); }\n.btn-success { background: linear-gradient(135deg, var(--green-dark), var(--green)); color: #fff; box-shadow: 0 2px 12px rgba(125,193,66,.35); }\n.btn-success:hover { background: linear-gradient(135deg, var(--green), var(--green-light)); box-shadow: 0 4px 20px rgba(125,193,66,.5); transform: translateY(-1px); }\n.btn-outline { background: transparent; color: var(--text-secondary); border: 1px solid var(--border); }\n.btn-outline:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--blue); }\n.btn-ghost { background: transparent; color: var(--text-secondary); padding: 6px 10px; }\n.btn-ghost:hover { background: var(--bg-hover); color: var(--text-primary); }\n.btn-danger { background: rgba(248,81,73,.12); color: var(--red); border: 1px solid rgba(248,81,73,.25); }\n.btn-danger:hover { background: rgba(248,81,73,.22); }\n.btn-sm { padding: 5px 10px; font-size: 12px; }\n.btn-icon { padding: 7px; border-radius: var(--radius-sm); }\n\n\/* ============ TABS ============ *\/\n.section-tabs {\n  display: flex; gap: 2px;\n  padding: 20px 0 0; border-bottom: 1px solid var(--border-soft);\n  margin-bottom: 24px; overflow-x: auto; align-items: flex-end;\n}\n.tab-btn {\n  padding: 10px 18px; background: transparent; border: none; cursor: grab;\n  font-family: var(--font-main); font-size: 14px; font-weight: 600;\n  color: var(--text-secondary); border-bottom: 2px solid transparent;\n  transition: var(--transition); white-space: nowrap;\n  display: flex; align-items: center; gap: 7px;\n  border-radius: var(--radius-sm) var(--radius-sm) 0 0;\n  user-select: none; position: relative;\n}\n.tab-btn:hover { color: var(--text-primary); background: var(--bg-hover); }\n.tab-btn.active { color: var(--blue); border-bottom-color: var(--blue); background: rgba(91,155,213,.06); }\n.tab-btn.dragging { opacity: .4; cursor: grabbing; }\n.tab-btn.drag-over { background: rgba(91,155,213,.15); border-bottom-color: var(--blue-light); }\n.tab-drag-hint {\n  font-size: 10px; color: var(--text-muted); padding: 0 6px 2px;\n  display: flex; align-items: center; gap: 3px; flex-shrink: 0;\n}\n\n.tab-badge {\n  background: var(--bg-overlay); color: var(--text-secondary);\n  font-size: 11px; font-weight: 700; font-family: var(--font-mono);\n  padding: 1px 6px; border-radius: 99px; min-width: 20px; text-align: center;\n}\n.tab-btn.active .tab-badge { background: rgba(91,155,213,.18); color: var(--blue); }\n.tab-panel { display: none; }\n.tab-panel.active { display: block; }\n\n\/* ============ INDICATORS ============ *\/\n.indicators-grid {\n  display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n  gap: 12px; margin-bottom: 24px;\n}.ind-card {\n  background: var(--bg-card);\n  border-radius: var(--radius-lg); padding: 16px;\n  display: flex; flex-direction: column; gap: 8px;\n  transition: var(--transition); position: relative; overflow: hidden;\n  box-shadow:\n    -1px -1px 0 0 var(--card-3d-light),\n    2px 3px 0 0 var(--card-3d-dark),\n    0 6px 20px rgba(0,0,0,.22);\n}\n.ind-card::before {\n  content: '';\n  position: absolute; top: 0; left: 0; right: 0; height: 2px;\n  background: linear-gradient(90deg, var(--blue), var(--green)); opacity: 0; transition: var(--transition);\n  z-index: 2;\n}\n.ind-card::after {\n  content: '';\n  position: absolute; inset: 0;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 55%);\n  pointer-events: none; z-index: 1; border-radius: inherit;\n}\n.ind-card > * { position: relative; z-index: 3; }\n.ind-card:hover { transform: translateY(-3px); box-shadow: -1px -1px 0 0 var(--card-3d-light), 3px 5px 0 0 var(--card-3d-dark), 0 12px 32px rgba(0,0,0,.32); }\n.ind-card:hover::before { opacity: 1; }\n.ind-label { font-size: 12px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: .7px; }\n.ind-value { font-size: 29px; font-weight: 800; font-family: var(--font-mono); line-height: 1; }\n.ind-sub { font-size: 12px; color: var(--text-secondary); }\n.ind-total    .ind-value { color: var(--blue); }\n.ind-backlog  .ind-value { color: var(--text-secondary); }\n.ind-afazer   .ind-value { color: var(--orange); }\n.ind-andamento .ind-value { color: var(--blue-light); }\n.ind-revisao  .ind-value { color: var(--purple); }\n.ind-concluido .ind-value { color: var(--green); }\n.ind-vencidas  .ind-value { color: var(--red); }\n.ind-points   .ind-value { color: var(--accent); }\n\n\/* ============ FILTER BAR ============ *\/\n.filter-bar {\n  background: var(--bg-surface);\n  border-radius: var(--radius-lg); padding: 16px; margin-bottom: 20px;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 4px 16px rgba(0,0,0,.18);\n  position: relative; overflow: hidden;\n}\n.filter-bar::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%);\n  pointer-events: none; z-index: 0;\n}\n.filter-bar > * { position: relative; z-index: 1; }\n.filter-bar-header {\n  display: flex; align-items: center; justify-content: space-between;\n  margin-bottom: 12px; cursor: pointer;\n}\n.filter-title {\n  font-size: 13px; font-weight: 700; color: var(--text-secondary);\n  text-transform: uppercase; letter-spacing: .8px; display: flex; align-items: center; gap: 6px;\n}\n.filter-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 10px; }\n.filter-row-extra { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; align-items: center; }\n.filter-check { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 12px; color: var(--text-secondary); user-select: none; }\n.filter-check input { display: none; }\n.filter-check-box {\n  width: 16px; height: 16px; border-radius: 4px; border: 1.5px solid var(--border);\n  display: flex; align-items: center; justify-content: center; font-size: 10px; transition: var(--transition);\n}\n.filter-check input:checked + .filter-check-box { background: var(--blue); border-color: var(--blue); color: #fff; }\n\n\/* Active filter chips *\/\n.active-filters {\n  display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; min-height: 0;\n}\n.filter-chip {\n  display: inline-flex; align-items: center; gap: 5px;\n  padding: 3px 10px 3px 8px; border-radius: 99px;\n  font-size: 11px; font-weight: 600; background: rgba(91,155,213,.12);\n  border: 1px solid rgba(91,155,213,.3); color: var(--blue-light);\n  animation: chipIn .15s ease;\n}\n@keyframes chipIn { from { opacity:0; transform:scale(.9); } to { opacity:1; transform:scale(1); } }\n.filter-chip-remove { cursor: pointer; opacity: .6; font-size: 12px; transition: opacity .15s; }\n.filter-chip-remove:hover { opacity: 1; }\n\n\/* ============ FORM ELEMENTS ============ *\/\n.form-field { display: flex; flex-direction: column; gap: 5px; }\n.form-label { font-size: 12px; font-weight: 700; color: var(--text-secondary); text-transform: uppercase; letter-spacing: .6px; }\n.form-label .req { color: var(--red); margin-left: 2px; }\n.form-input, .form-select, .form-textarea {\n  background: var(--input-bg); border: 1px solid var(--border-soft);\n  border-radius: var(--radius-sm); color: var(--text-primary);\n  font-family: var(--font-main); font-size: 14px; padding: 9px 12px;\n  transition: var(--transition); width: 100%; outline: none; appearance: none;\n}\n.form-input::placeholder, .form-textarea::placeholder { color: var(--text-muted); }\n.form-input:focus, .form-select:focus, .form-textarea:focus {\n  border-color: var(--blue); box-shadow: 0 0 0 3px rgba(91,155,213,.15);\n}\n.form-textarea { resize: vertical; min-height: 80px; }\n.form-select {\n  background-image: url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 16 16'%3E%3Cpath fill='%238b949e' d='M4 6l4 4 4-4'\/%3E%3C\/svg%3E\");\n  background-repeat: no-repeat; background-position: right 10px center;\n  background-size: 16px; padding-right: 32px; cursor: pointer;\n}\n.form-card {\n  background: var(--bg-surface);\n  border-radius: var(--radius-xl); padding: 24px; margin-bottom: 24px;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 6px 22px rgba(0,0,0,.22);\n  position: relative; overflow: hidden;\n}\n.form-card::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%);\n  pointer-events: none; z-index: 0;\n}\n.form-card > * { position: relative; z-index: 1; }\n.form-card-header {\n  display: flex; align-items: center; justify-content: space-between;\n  margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border-soft);\n}\n.form-card-title {\n  font-size: 16px; font-weight: 700; color: var(--text-primary);\n  display: flex; align-items: center; gap: 8px;\n}\n.form-card-title span {\n  background: linear-gradient(135deg, var(--blue), var(--green));\n  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;\n}\n.form-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; margin-bottom: 14px; }\n.form-grid-wide { grid-column: 1 \/ -1; }\n.form-actions {\n  display: flex; gap: 10px; flex-wrap: wrap;\n  padding-top: 16px; border-top: 1px solid var(--border-soft); margin-top: 6px;\n}\n\n\/* ============ TASK CARDS ============ *\/\n.cards-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: 14px; }\n.task-card {\n  background: var(--bg-card);\n  border-radius: var(--radius-lg); padding: 16px;\n  transition: var(--transition); position: relative; overflow: hidden; cursor: default;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 4px 14px rgba(0,0,0,.2);\n}\n.task-card::before {\n  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;\n  border-radius: 3px 0 0 3px; background: var(--blue); transition: var(--transition); z-index: 2;\n}\n.task-card::after {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 50%);\n  pointer-events: none; z-index: 1;\n}\n.task-card > * { position: relative; z-index: 3; }\n.task-card:hover { transform: translateY(-3px); box-shadow: -1px -1px 0 0 var(--card-3d-light), 3px 5px 0 0 var(--card-3d-dark), 0 10px 28px rgba(0,0,0,.3); }\n.task-card.vencida::before { background: var(--red); }\n.task-card.impedimento::before { background: var(--orange); }\n.task-card.concluida { opacity: .78; }\n.task-card.concluida::before { background: var(--green); }\n.task-card-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; margin-bottom: 10px; }\n.task-title { font-size: 14px; font-weight: 700; color: var(--text-primary); line-height: 1.4; flex: 1; }\n.task-id { font-family: var(--font-mono); font-size: 10px; color: var(--text-muted); background: var(--bg-overlay); padding: 2px 6px; border-radius: 4px; flex-shrink: 0; }\n.task-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }\n.badge {\n  display: inline-flex; align-items: center; gap: 3px;\n  padding: 3px 8px; border-radius: 99px; font-size: 11px; font-weight: 700; border: 1px solid transparent;\n}\n.badge-backlog   { background: rgba(139,148,158,.15); color: #8b949e; border-color: rgba(139,148,158,.25); }\n.badge-afazer    { background: rgba(227,179,65,.15); color: var(--orange); border-color: rgba(227,179,65,.3); }\n.badge-andamento { background: rgba(91,155,213,.15); color: var(--blue-light); border-color: rgba(91,155,213,.3); }\n.badge-revisao   { background: rgba(167,139,250,.15); color: var(--purple); border-color: rgba(167,139,250,.3); }\n.badge-concluido { background: rgba(125,193,66,.15); color: var(--green); border-color: rgba(125,193,66,.3); }\n.badge-baixa    { background: rgba(125,193,66,.1); color: var(--green); border-color: rgba(125,193,66,.2); }\n.badge-media    { background: rgba(91,155,213,.1); color: var(--blue-light); border-color: rgba(91,155,213,.2); }\n.badge-alta     { background: rgba(227,179,65,.1); color: var(--orange); border-color: rgba(227,179,65,.2); }\n.badge-critica  { background: rgba(248,81,73,.1); color: var(--red); border-color: rgba(248,81,73,.2); }\n.badge-task      { background: rgba(91,155,213,.1); color: var(--blue); border-color: rgba(91,155,213,.2); }\n.badge-correcao       { background: rgba(248,81,73,.1); color: var(--red); border-color: rgba(248,81,73,.2); }\n.badge-melhoria  { background: rgba(125,193,66,.1); color: var(--green); border-color: rgba(125,193,66,.2); }\n.badge-demanda   { background: rgba(167,139,250,.1); color: var(--purple); border-color: rgba(167,139,250,.2); }\n.task-info-row { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 10px; font-size: 12px; color: var(--text-secondary); }\n.task-info-item { display: flex; align-items: center; gap: 4px; }\n.task-impedimento-alert {\n  background: rgba(227,179,65,.1); border: 1px solid rgba(227,179,65,.25);\n  border-radius: var(--radius-sm); padding: 7px 10px; font-size: 12px; color: var(--orange);\n  margin-bottom: 10px; display: flex; gap: 6px; align-items: flex-start;\n}\n.task-prazo-alert {\n  background: rgba(248,81,73,.1); border: 1px solid rgba(248,81,73,.25);\n  border-radius: var(--radius-sm); padding: 5px 10px; font-size: 12px; color: var(--red);\n  margin-bottom: 8px; display: flex; gap: 5px; align-items: center;\n}\n.task-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 12px; }\n.tag { background: var(--bg-overlay); border: 1px solid var(--border-soft); border-radius: 4px; padding: 2px 7px; font-size: 11px; color: var(--text-secondary); }\n.task-actions { display: flex; gap: 4px; flex-wrap: wrap; padding-top: 10px; border-top: 1px solid var(--border-soft); }\n\n\/* ============ KANBAN ============ *\/\n.kanban-board { display: grid; grid-template-columns: repeat(5, minmax(200px, 1fr)); gap: 12px; overflow-x: auto; padding-bottom: 8px; }\n.kanban-col {\n  background: var(--kanban-bg); border-radius: var(--radius-lg); padding: 12px; min-height: 200px;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 4px 14px rgba(0,0,0,.2);\n  position: relative; transition: var(--transition);\n}\n.kanban-col::after {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 50%);\n  pointer-events: none;\n}\n.kanban-col > * { position: relative; z-index: 1; }\n\/* Drop target highlight *\/\n.kanban-col.drag-over {\n  box-shadow: 0 0 0 2px var(--blue), -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 8px 24px rgba(91,155,213,.3);\n  background: rgba(91,155,213,.06);\n}\n.kanban-col-header {\n  display: flex; align-items: center; justify-content: space-between;\n  margin-bottom: 12px; padding-bottom: 10px; border-bottom: 2px solid var(--border-soft);\n}\n.kanban-col-title { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .7px; }\n.kanban-count {\n  font-family: var(--font-mono); font-size: 12px; font-weight: 700;\n  background: var(--bg-card); padding: 2px 8px; border-radius: 99px; color: var(--text-secondary);\n}\n.kanban-cards { display: flex; flex-direction: column; gap: 8px; min-height: 40px; }\n\/* Drop placeholder *\/\n.kanban-drop-placeholder {\n  height: 52px; border: 2px dashed var(--blue); border-radius: var(--radius-md);\n  background: rgba(91,155,213,.06); opacity: .7;\n  display: flex; align-items: center; justify-content: center;\n  font-size: 11px; color: var(--blue-light);\n}\n.kanban-card {\n  background: var(--bg-card);\n  border-radius: var(--radius-md); padding: 10px 12px; transition: var(--transition); cursor: grab;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 1px 2px 0 0 var(--card-3d-dark), 0 2px 6px rgba(0,0,0,.16);\n  position: relative; overflow: hidden;\n}\n.kanban-card::after {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 50%);\n  pointer-events: none;\n}\n.kanban-card > * { position: relative; z-index: 1; }\n.kanban-card:hover { box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 4px 0 0 var(--card-3d-dark), 0 8px 20px rgba(0,0,0,.26); transform: translateY(-2px); }\n.kanban-card.dragging { opacity: .35; cursor: grabbing; transform: rotate(1.5deg) scale(.98); }\n.kanban-card-title { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-bottom: 7px; line-height: 1.4; }\n.kanban-card-meta { display: flex; align-items: center; justify-content: space-between; font-size: 11px; color: var(--text-secondary); }\n.kanban-drag-hint {\n  font-size: 10px; color: var(--text-muted); text-align: center; padding: 6px 0 0;\n  letter-spacing: .3px; display: flex; align-items: center; justify-content: center; gap: 4px;\n}\n.kanban-col-backlog   .kanban-col-title { color: #8b949e; }\n.kanban-col-backlog   .kanban-col-header { border-color: rgba(139,148,158,.3); }\n.kanban-col-afazer    .kanban-col-title { color: var(--orange); }\n.kanban-col-afazer    .kanban-col-header { border-color: rgba(227,179,65,.4); }\n.kanban-col-andamento .kanban-col-title { color: var(--blue-light); }\n.kanban-col-andamento .kanban-col-header { border-color: rgba(91,155,213,.4); }\n.kanban-col-revisao   .kanban-col-title { color: var(--purple); }\n.kanban-col-revisao   .kanban-col-header { border-color: rgba(167,139,250,.4); }\n.kanban-col-concluido .kanban-col-title { color: var(--green); }\n.kanban-col-concluido .kanban-col-header { border-color: rgba(125,193,66,.4); }\n\n\/* ============ DASHBOARD TABLES ============ *\/\n.dash-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr)); gap: 16px; }\n.dash-section {\n  background: var(--bg-surface);\n  border-radius: var(--radius-lg); overflow: hidden;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 6px 22px rgba(0,0,0,.24);\n  position: relative;\n  display: flex; flex-direction: column;   \/* \u2190 equal-height columns *\/\n}\n.dash-section::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 40%);\n  pointer-events: none; z-index: 0;\n}\n.dash-section > * { position: relative; z-index: 1; }\n.dash-section-header {\n  padding: 14px 18px; background: var(--bg-elevated); border-bottom: 1px solid var(--border-soft);\n  font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .8px;\n  color: var(--text-secondary); display: flex; align-items: center; gap: 7px;\n  flex-shrink: 0;\n}\n\/* Wrapper that gives the table breathing room on all sides *\/\n.dash-table-wrap {\n  padding: 0 8px 8px;   \/* 8px side gap, 8px bottom gap *\/\n  flex: 1;              \/* fills remaining height *\/\n}\n.dash-table { width: 100%; border-collapse: collapse; }\n.dash-table th, .dash-table td { padding: 10px 10px; text-align: left; font-size: 13px; border-bottom: 1px solid var(--border-soft); }\n.dash-table th { font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .5px; font-size: 11px; }\n.dash-table td { color: var(--text-secondary); }\n.dash-table tr:last-child td { border-bottom: none; }\n.dash-table tr:hover td { background: var(--bg-hover); color: var(--text-primary); }\n\/* Rounded corners on first\/last rows *\/\n.dash-table tbody tr:first-child td:first-child { border-top-left-radius: 6px; }\n.dash-table tbody tr:first-child td:last-child  { border-top-right-radius: 6px; }\n.dash-table tbody tr:last-child  td:first-child { border-bottom-left-radius: 6px; }\n.dash-table tbody tr:last-child  td:last-child  { border-bottom-right-radius: 6px; }\n.dash-bar { display: flex; align-items: center; gap: 8px; }\n.dash-bar-track { flex: 1; height: 7px; background: var(--bg-overlay); border-radius: 99px; overflow: hidden; }\n.dash-bar-fill { height: 100%; border-radius: 99px; background: linear-gradient(90deg, var(--blue), var(--green)); transition: width .6s ease; }\n\n\/* ============ CHARTS ============ *\/\n.chart-card {\n  background: var(--bg-surface);\n  border-radius: var(--radius-lg); overflow: hidden;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 6px 22px rgba(0,0,0,.24);\n  position: relative;\n}\n.chart-card::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%);\n  pointer-events: none; z-index: 0;\n}\n.chart-card > * { position: relative; z-index: 1; }\n.chart-card-header {\n  padding: 14px 18px; background: var(--bg-elevated); border-bottom: 1px solid var(--border-soft);\n  display: flex; align-items: center; justify-content: space-between;\n}\n.chart-card-title { font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .8px; color: var(--text-secondary); display: flex; align-items: center; gap: 7px; }\n.chart-card-body { padding: 18px; position: relative; }\n.chart-canvas-wrap { position: relative; }\n.chart-canvas-wrap canvas { max-height: 240px; }\n\n\/* ============ BI SECTION ============ *\/\n.bi-toolbar {\n  background: var(--bg-surface);\n  border-radius: var(--radius-lg); padding: 18px; margin-bottom: 20px;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 6px 22px rgba(0,0,0,.22);\n  position: relative; overflow: hidden;\n}\n.bi-toolbar::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%);\n  pointer-events: none;\n}\n.bi-toolbar > * { position: relative; z-index: 1; }\n.bi-toolbar-title {\n  font-size: 13px; font-weight: 700; color: var(--text-secondary);\n  text-transform: uppercase; letter-spacing: .8px; margin-bottom: 14px;\n  display: flex; align-items: center; justify-content: space-between;\n}\n.bi-filter-builder {\n  display: flex; flex-wrap: wrap; gap: 8px; align-items: flex-end; margin-bottom: 12px;\n}\n.bi-filter-builder .form-field { min-width: 150px; flex: 1; }\n.bi-active-filters { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }\n\n.bi-charts-grid {\n  display: grid;\n  grid-template-columns: repeat(2, minmax(0, 1fr));\n  gap: 18px;\n  margin-bottom: 24px;\n}\n.bi-charts-grid .chart-card.full-width { grid-column: 1 \/ -1; }\n\n.bi-kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), 1fr)); gap: 14px; margin-bottom: 24px; }\n.bi-kpi {\n  background: var(--bg-card);\n  border-radius: var(--radius-lg); padding: 20px 18px; transition: var(--transition);\n  position: relative; overflow: hidden;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 6px 20px rgba(0,0,0,.22);\n}\n\n\/* Shine overlay *\/\n.bi-kpi::before {\n  content: '';\n  position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 55%);\n  pointer-events: none; z-index: 1;\n}\n\/* Accent bottom line *\/\n.bi-kpi::after {\n  content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 3px;\n  background: linear-gradient(90deg, var(--blue), var(--green));\n  transform: scaleX(0); transition: transform .3s ease; transform-origin: left;\n  z-index: 2;\n}\n.bi-kpi:hover::after { transform: scaleX(1); }\n.bi-kpi:hover {\n  transform: translateY(-3px);\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 3px 5px 0 0 var(--card-3d-dark), 0 12px 32px rgba(0,0,0,.3);\n}\n.bi-kpi > * { position: relative; z-index: 3; }\n\n\/* Subtle icon glow in background *\/\n.bi-kpi-icon {\n  position: absolute; right: 12px; top: 12px;\n  font-size: 32px; opacity: .07; pointer-events: none;\n  z-index: 0; line-height: 1;\n}\n.bi-kpi-label { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .7px; margin-bottom: 8px; font-weight: 700; }\n.bi-kpi-val { font-size: 30px; font-weight: 800; font-family: var(--font-mono); line-height: 1; margin-bottom: 6px; }\n.bi-kpi-sub { font-size: 12px; color: var(--text-muted); }\n.bi-kpi-trend {\n  display: inline-flex; align-items: center; gap: 3px;\n  font-size: 11px; font-weight: 700; margin-top: 6px;\n  padding: 2px 7px; border-radius: 99px;\n}\n.bi-kpi-trend.up   { background: rgba(125,193,66,.12); color: var(--green); }\n.bi-kpi-trend.down { background: rgba(248,81,73,.12);  color: var(--red); }\n.bi-kpi-trend.flat { background: rgba(91,155,213,.10); color: var(--blue-light); }\n\n.bi-kpi.kpi-blue   .bi-kpi-val { color: var(--blue); }\n.bi-kpi.kpi-green  .bi-kpi-val { color: var(--green); }\n.bi-kpi.kpi-orange .bi-kpi-val { color: var(--orange); }\n.bi-kpi.kpi-red    .bi-kpi-val { color: var(--red); }\n.bi-kpi.kpi-purple .bi-kpi-val { color: var(--purple); }\n.bi-kpi.kpi-accent .bi-kpi-val { color: var(--accent); }\n\n\/* Left accent stripe per color *\/\n.bi-kpi.kpi-blue   { border-left: 3px solid var(--blue); }\n.bi-kpi.kpi-green  { border-left: 3px solid var(--green); }\n.bi-kpi.kpi-orange { border-left: 3px solid var(--orange); }\n.bi-kpi.kpi-red    { border-left: 3px solid var(--red); }\n.bi-kpi.kpi-purple { border-left: 3px solid var(--purple); }\n.bi-kpi.kpi-accent { border-left: 3px solid var(--accent); }\n\n\/* ============ MODAL ============ *\/\n.modal-overlay {\n  position: fixed; inset: 0; background: rgba(0,0,0,.6); backdrop-filter: blur(4px);\n  z-index: 1000; display: flex; align-items: center; justify-content: center;\n  opacity: 0; pointer-events: none; transition: var(--transition);\n}\n.modal-overlay.active { opacity: 1; pointer-events: auto; }\n.modal-box {\n  background: var(--bg-surface); border: 1px solid var(--border);\n  border-radius: var(--radius-xl); padding: 28px; max-width: 420px; width: 90%;\n  transform: scale(.95); transition: var(--transition); box-shadow: var(--shadow-lg);\n}\n.modal-overlay.active .modal-box { transform: scale(1); }\n.modal-title { font-size: 16px; font-weight: 700; margin-bottom: 8px; color: var(--text-primary); }\n.modal-text { font-size: 13px; color: var(--text-secondary); margin-bottom: 24px; line-height: 1.6; }\n.modal-actions { display: flex; gap: 10px; justify-content: flex-end; }\n\n\/* ============ SETUP WIZARD ============ *\/\n.setup-overlay {\n  position: fixed; inset: 0; background: rgba(0,0,0,.8); backdrop-filter: blur(8px);\n  z-index: 2000; display: flex; align-items: center; justify-content: center;\n  transition: opacity .3s;\n}\n.setup-overlay.hidden { opacity: 0; pointer-events: none; }\n.setup-box {\n  background: var(--bg-surface); border: 1px solid var(--border);\n  border-radius: var(--radius-xl); padding: 32px; max-width: 520px; width: 92%;\n  box-shadow: var(--shadow-lg); transform: translateY(0); transition: transform .3s;\n}\n.setup-title {\n  font-size: 20px; font-weight: 800; margin-bottom: 6px;\n  background: linear-gradient(135deg, var(--blue), var(--green));\n  -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;\n}\n.setup-sub { font-size: 13px; color: var(--text-secondary); margin-bottom: 24px; }\n.setup-options { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 20px; }\n.setup-opt {\n  background: var(--bg-card); border: 2px solid var(--border-soft);\n  border-radius: var(--radius-lg); padding: 16px 12px;\n  text-align: center; cursor: pointer; transition: var(--transition);\n}\n.setup-opt:hover { border-color: var(--blue); background: var(--bg-hover); }\n.setup-opt.selected { border-color: var(--blue); background: rgba(91,155,213,.08); }\n.setup-opt-icon { font-size: 24px; margin-bottom: 8px; }\n.setup-opt-label { font-size: 12px; font-weight: 700; color: var(--text-secondary); }\n.setup-preview {\n  background: var(--bg-card); border: 1px solid var(--border-soft);\n  border-radius: var(--radius-md); padding: 16px; margin-bottom: 20px;\n  display: flex; align-items: center; gap: 12px;\n}\n.setup-preview-logo { width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; }\n.setup-logo-input { width: 100%; display: none; }\n.setup-section { margin-bottom: 20px; }\n.setup-section-title { font-size: 12px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .6px; margin-bottom: 10px; }\n.logo-upload-area {\n  border: 2px dashed var(--border); border-radius: var(--radius-md);\n  padding: 20px; text-align: center; cursor: pointer; transition: var(--transition);\n  font-size: 12px; color: var(--text-muted);\n}\n.logo-upload-area:hover { border-color: var(--blue); color: var(--blue); background: rgba(91,155,213,.05); }\n\n\/* ============ TOAST ============ *\/\n.toast-container { position: fixed; bottom: 24px; right: 24px; z-index: 9999; display: flex; flex-direction: column; gap: 8px; pointer-events: none; }\n.toast {\n  display: flex; align-items: center; gap: 10px;\n  padding: 12px 18px; border-radius: var(--radius-md); font-size: 13px; font-weight: 600;\n  min-width: 260px; max-width: 380px; animation: toastIn .3s ease; pointer-events: auto;\n  box-shadow: var(--shadow-lg); border: 1px solid transparent;\n}\n@keyframes toastIn  { from { opacity:0; transform:translateX(30px) scale(.95); } to { opacity:1; transform:translateX(0) scale(1); } }\n@keyframes toastOut { from { opacity:1; transform:translateX(0) scale(1); } to { opacity:0; transform:translateX(30px) scale(.95); } }\n.toast.removing { animation: toastOut .3s ease forwards; }\n.toast-success { background: var(--bg-card); border-color: rgba(125,193,66,.35); color: var(--green); }\n.toast-error   { background: var(--bg-card); border-color: rgba(248,81,73,.35); color: var(--red); }\n.toast-info    { background: var(--bg-card); border-color: rgba(91,155,213,.35); color: var(--blue-light); }\n\n\/* ============ MISC ============ *\/\n.section-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; flex-wrap: wrap; gap: 10px; }\n.section-title { font-size: 15px; font-weight: 700; color: var(--text-primary); display: flex; align-items: center; gap: 8px; }\n.sprint-display { font-family: var(--font-mono); font-size: 12px; font-weight: 600; background: rgba(91,155,213,.12); color: var(--blue-light); border: 1px solid rgba(91,155,213,.25); padding: 4px 10px; border-radius: 99px; }\n.empty-state { text-align: center; padding: 60px 24px; color: var(--text-muted); }\n.empty-state-icon { font-size: 48px; margin-bottom: 12px; opacity: .5; }\n.empty-state-text { font-size: 15px; margin-bottom: 4px; color: var(--text-secondary); }\n.empty-state-sub  { font-size: 13px; }\n.url-config-bar {\n  background: var(--bg-surface);\n  border-radius: var(--radius-lg);\n  padding: 14px 18px; margin-bottom: 20px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 4px 14px rgba(0,0,0,.18);\n  position: relative; overflow: hidden;\n}\n.url-config-bar::before {\n  content: ''; position: absolute; inset: 0; border-radius: inherit;\n  background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%);\n  pointer-events: none;\n}\n.url-config-bar label { font-size: 12px; font-weight: 700; color: var(--text-secondary); white-space: nowrap; }\n.url-config-bar .form-input { flex: 1; min-width: 280px; font-family: var(--font-mono); font-size: 12px; }\n.spinner { width: 16px; height: 16px; border: 2px solid rgba(255,255,255,.3); border-top-color: #fff; border-radius: 50%; animation: spin .6s linear infinite; display: inline-block; }\n@keyframes spin { to { transform: rotate(360deg); } }\n\n\/* ============ KANBAN POPUP ============ *\/\n.kanban-popup-overlay {\n  position: fixed; inset: 0; background: rgba(0,0,0,.55);\n  backdrop-filter: blur(6px); z-index: 500;\n  display: flex; align-items: center; justify-content: center;\n  opacity: 0; pointer-events: none; transition: opacity .2s;\n}\n.kanban-popup-overlay.active { opacity: 1; pointer-events: auto; }\n.kanban-popup {\n  background: var(--bg-surface); border-radius: var(--radius-xl);\n  width: min(480px, 92vw); max-height: 88vh; overflow-y: auto;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 3px 5px 0 0 var(--card-3d-dark), 0 24px 60px rgba(0,0,0,.45);\n  transform: scale(.94) translateY(12px); transition: transform .22s cubic-bezier(.34,1.56,.64,1);\n  position: relative;\n}\n.kanban-popup-overlay.active .kanban-popup { transform: scale(1) translateY(0); }\n.kanban-popup-header {\n  padding: 18px 20px 14px; border-bottom: 1px solid var(--border-soft);\n  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;\n}\n.kanban-popup-title { font-size: 15px; font-weight: 700; color: var(--text-primary); line-height: 1.4; flex: 1; }\n.kanban-popup-close {\n  width: 28px; height: 28px; border-radius: 50%; border: none; background: var(--bg-overlay);\n  color: var(--text-secondary); cursor: pointer; font-size: 14px; flex-shrink: 0;\n  display: flex; align-items: center; justify-content: center; transition: var(--transition);\n}\n.kanban-popup-close:hover { background: var(--red); color: #fff; }\n.kanban-popup-body { padding: 16px 20px 20px; }\n.kanban-popup-badges { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }\n.kanban-popup-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }\n.kanban-popup-field { display: flex; flex-direction: column; gap: 3px; }\n.kanban-popup-field-label { font-size: 10px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .6px; }\n.kanban-popup-field-val { font-size: 13px; color: var(--text-primary); }\n.kanban-popup-desc {\n  background: var(--bg-elevated); border-radius: var(--radius-md);\n  padding: 10px 12px; font-size: 12px; color: var(--text-secondary);\n  line-height: 1.6; margin-bottom: 14px;\n}\n.kanban-popup-actions { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 14px; border-top: 1px solid var(--border-soft); }\n.kanban-popup-hint { font-size: 10px; color: var(--text-muted); text-align: center; padding: 8px 0 0; width: 100%; }\n\n\/* ============ REPORT CARDS ============ *\/\n.relat-filter-bar {\n  background: var(--bg-surface); border-radius: var(--radius-lg);\n  padding: 14px 16px; margin-bottom: 20px;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 2px 3px 0 0 var(--card-3d-dark), 0 4px 14px rgba(0,0,0,.18);\n  position: relative; overflow: hidden;\n}\n.relat-filter-bar::before { content: ''; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(135deg, var(--card-3d-shine) 0%, transparent 45%); pointer-events: none; }\n.relat-filter-bar > * { position: relative; z-index: 1; }\n.relat-filter-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; }\n.relat-filter-row .form-field { min-width: min(160px, 100%); flex: 1; }\n.relat-grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fill, minmax(min(340px,100%),1fr)); }\n.relat-card {\n  border-radius: var(--radius-xl); overflow: hidden; position: relative;\n  box-shadow: -1px -1px 0 0 var(--card-3d-light), 3px 4px 0 0 var(--card-3d-dark), 0 8px 28px rgba(0,0,0,.28);\n  transition: transform .22s cubic-bezier(.34,1.2,.64,1), box-shadow .22s;\n}\n.relat-card:hover { transform: translateY(-4px); box-shadow: -1px -1px 0 0 var(--card-3d-light), 4px 6px 0 0 var(--card-3d-dark), 0 16px 40px rgba(0,0,0,.36); }\n.relat-card-header { padding: 16px 18px 14px; position: relative; overflow: hidden; }\n.relat-card-header::after { content: ''; position: absolute; inset: 0; background: linear-gradient(135deg,rgba(255,255,255,.12) 0%,transparent 55%); pointer-events: none; }\n.relat-card-icon { font-size: 28px; margin-bottom: 8px; line-height: 1; filter: drop-shadow(0 2px 4px rgba(0,0,0,.3)); }\n.relat-card-title { font-size: 13px; font-weight: 800; letter-spacing: .3px; text-transform: uppercase; opacity: .9; }\n.relat-card-subtitle { font-size: 11px; opacity: .65; margin-top: 2px; }\n.relat-card-body { background: var(--bg-surface); padding: 14px 16px 16px; }\n.relat-stat-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--border-soft); }\n.relat-stat-row:last-child { border-bottom: none; }\n.relat-stat-rank { width: 20px; font-size: 11px; font-weight: 800; color: var(--text-muted); text-align: center; flex-shrink: 0; }\n.relat-stat-label { flex: 1; font-size: 12px; color: var(--text-secondary); font-weight: 500; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.relat-stat-val { font-size: 13px; font-weight: 700; color: var(--text-primary); font-family: var(--font-mono); min-width: 28px; text-align: right; }\n.relat-stat-bar { width: 70px; flex-shrink: 0; }\n.relat-bar-track { height: 6px; background: var(--bg-overlay); border-radius: 99px; overflow: hidden; }\n.relat-bar-fill { height: 100%; border-radius: 99px; transition: width .6s ease; }\n.relat-badge { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: 99px; font-size: 11px; font-weight: 700; margin-top: 10px; }\n.relat-card.card-blue   .relat-card-header { background: linear-gradient(135deg,#1e4a8c,#3a78b5); color:#fff; }\n.relat-card.card-green  .relat-card-header { background: linear-gradient(135deg,#2d6a1a,#5da020); color:#fff; }\n.relat-card.card-red    .relat-card-header { background: linear-gradient(135deg,#8c1a1a,#c0392b); color:#fff; }\n.relat-card.card-purple .relat-card-header { background: linear-gradient(135deg,#4a1a8c,#7c3aed); color:#fff; }\n.relat-card.card-orange .relat-card-header { background: linear-gradient(135deg,#8c4a1a,#d97706); color:#fff; }\n.relat-card.card-teal   .relat-card-header { background: linear-gradient(135deg,#0e5c5c,#0d9488); color:#fff; }\n.relat-card.full { grid-column: 1\/-1; }\n\n\/* =============================================\n   RESPONSIVO \u2014 MOBILE FIRST\n   Abordagem correta: controle por elemento,\n   NUNCA overflow-x:hidden no html\/body\n============================================= *\/\n\n\/* Dashboard charts grid \u2014 responsivo *\/\n.dash-charts-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(min(340px, 100%), 1fr));\n  gap: 16px;\n  margin-bottom: 20px;\n}\n\n\/* \u2500\u2500 768px \u2014 tablet\/mobile \u2500\u2500 *\/\n.ftab-btn {\n  padding: 8px 16px; background: transparent; border: none; cursor: pointer;\n  font-family: var(--font-main); font-size: 13px; font-weight: 600;\n  color: var(--text-secondary); border-bottom: 2px solid transparent; transition: var(--transition);\n}\n.ftab-btn:hover { color: var(--text-primary); }\n.ftab-btn.ftab-active { color: var(--blue); border-bottom-color: var(--blue); }\n\n@media (max-width: 768px) {\n\n  \/* === HEADER === *\/\n  .header-inner { height: 56px; padding: 0 12px; gap: 8px; }\n  .logo-text { display: none; }\n  .status-pill .label { display: none; }\n  .status-pill { padding: 6px 8px; }\n  .btn-refresh-text { display: none; }\n  .user-name { display: none; }\n  .user-pill { padding: 4px 6px; }\n  .user-pill > svg { display: none; }\n\n  \/* === MAIN CONTENT === *\/\n  .main-content { padding: 0 12px 80px; width: 100%; }\n\n  \/* === URL CONFIG BAR === *\/\n  .url-config-bar { flex-direction: column; align-items: stretch; }\n  .url-config-bar .form-input { min-width: 0; width: 100%; }\n\n  \/* === TABS \u2014 scroll interno, n\u00e3o vaza para a p\u00e1gina === *\/\n  .section-tabs {\n    padding: 12px 0 0;\n    margin-bottom: 16px;\n    gap: 2px;\n    overflow-x: auto;          \/* scroll suave dentro da barra *\/\n    overflow-y: visible;\n    -webkit-overflow-scrolling: touch;\n    scrollbar-width: none;\n  }\n  .section-tabs::-webkit-scrollbar { display: none; }\n  .tab-btn { padding: 8px 12px; font-size: 12px; white-space: nowrap; flex-shrink: 0; }\n  .tab-drag-hint { display: none; }\n\n  \/* === INDICADORES === *\/\n  .indicators-grid { grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 16px; }\n  .ind-card { padding: 12px; }\n  .ind-value { font-size: 24px; }\n\n  \/* === DASHBOARD GRIDS === *\/\n  .dash-grid { grid-template-columns: 1fr; gap: 12px; }\n  .dash-charts-grid { grid-template-columns: 1fr; gap: 12px; }\n\n  \/* === CARDS GRID === *\/\n  .cards-grid { grid-template-columns: 1fr; gap: 10px; }\n  .task-actions { flex-wrap: wrap; gap: 4px; }\n\n  \/* === FILTER BAR === *\/\n  .filter-grid { grid-template-columns: 1fr 1fr; gap: 8px; }\n  .filter-bar { padding: 12px; }\n\n  \/* === FORM === *\/\n  .form-grid { grid-template-columns: 1fr; }\n  .form-card { padding: 16px; }\n  .form-card-header { flex-direction: column; align-items: flex-start; gap: 8px; }\n\n  \/* === KANBAN \u2014 coluna \u00fanica com nav no mobile === *\/\n  .kanban-board {\n    display: block;\n  }\n  \/* Cards verticais no mobile \u2014 empilhados, arrast\u00e1veis *\/\n  .kanban-col {\n    width: 100%;\n    margin-bottom: 0;\n  }\n  .kanban-cards {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n  }\n  \/* Cards menores no mobile mas com altura suficiente para arrastar *\/\n  .kanban-card {\n    touch-action: none; \/* permite arrastar no touch *\/\n  }\n  .kanban-mobile-nav {\n    display: flex; gap: 4px; overflow-x: auto; margin-bottom: 12px;\n    padding-bottom: 4px; scrollbar-width: none;\n  }\n  .kanban-mobile-nav::-webkit-scrollbar { display: none; }\n  .kmn-btn {\n    flex-shrink: 0; padding: 6px 12px; border-radius: 99px; border: 1px solid var(--border);\n    background: var(--bg-card); color: var(--text-secondary); font-size: 12px; font-weight: 600;\n    cursor: pointer; transition: var(--transition); font-family: var(--font-main);\n    display: flex; align-items: center; gap: 5px;\n  }\n  .kmn-btn.ativo { background: rgba(91,155,213,.15); color: var(--blue); border-color: rgba(91,155,213,.4); }\n  .kmn-count { background: var(--bg-overlay); border-radius: 99px; padding: 1px 6px; font-size: 10px; font-family: var(--font-mono); font-weight: 700; }\n  .kmn-btn.ativo .kmn-count { background: rgba(91,155,213,.2); color: var(--blue); }\n  .kanban-drag-hint { display: none; }\n  \/* Bot\u00f5es de a\u00e7\u00e3o dentro do card no mobile *\/\n  .kanban-card-actions-mobile {\n    display: flex; gap: 6px; margin-top: 8px; padding-top: 8px;\n    border-top: 1px solid var(--border-soft);\n  }\n  .kmn-action-btn {\n    flex: 1; padding: 6px 4px; border-radius: var(--radius-sm);\n    font-size: 11px; font-weight: 600; cursor: pointer; border: 1px solid var(--border);\n    background: var(--bg-overlay); color: var(--text-secondary);\n    font-family: var(--font-main); transition: var(--transition); text-align: center;\n  }\n  .kmn-action-btn:active { transform: scale(.96); }\n  .kmn-action-btn.avancar { background: rgba(91,155,213,.12); color: var(--blue); border-color: rgba(91,155,213,.3); }\n  .kmn-action-btn.voltar  { background: rgba(139,148,158,.1); color: var(--text-secondary); }\n  .kmn-action-btn.concluir { background: rgba(125,193,66,.12); color: var(--green); border-color: rgba(125,193,66,.3); }\n\n  \/* === BI CHARTS === *\/\n  .bi-charts-grid { grid-template-columns: 1fr; gap: 12px; }\n  .bi-kpis { grid-template-columns: repeat(2, 1fr); gap: 10px; }\n  .bi-kpi { padding: 14px 12px; }\n  .bi-kpi-val { font-size: 24px; }\n\n  \/* === BI FILTER \u2014 mobile vertical e justificado === *\/\n  .bi-toolbar { padding: 14px; }\n  .bi-toolbar-title { flex-direction: column; align-items: flex-start; gap: 8px; margin-bottom: 10px; }\n  .bi-filter-builder {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 8px;\n    align-items: end;\n  }\n  .bi-filter-builder .form-field { min-width: 0; }\n  .bi-filter-builder > button { grid-column: 1 \/ -1; width: 100%; justify-content: center; }\n  .bi-active-filters { flex-wrap: wrap; gap: 6px; }\n  .bi-filter-chip { flex-shrink: 0; }\n  \/* BI an\u00e1lises r\u00e1pidas no mobile *\/\n  .bi-quick-filters {\n    display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px;\n    padding-top: 10px; border-top: 1px solid var(--border-soft);\n  }\n  .bi-quick-btn {\n    padding: 5px 10px; border-radius: 99px; border: 1px solid var(--border);\n    background: var(--bg-card); color: var(--text-secondary); font-size: 11px;\n    font-weight: 600; cursor: pointer; transition: var(--transition); font-family: var(--font-main);\n  }\n  .bi-quick-btn:active { transform: scale(.96); }\n  .bi-quick-btn.ativo { background: rgba(91,155,213,.15); color: var(--blue); border-color: rgba(91,155,213,.3); }\n\n  \/* === SETUP WIZARD === *\/\n  .setup-box { padding: 24px 20px; }\n\n  \/* === AUTH === *\/\n  .auth-box { padding: 28px 20px; }\n\n  \/* === MODALS === *\/\n  .modal-box { padding: 20px; }\n\n  \/* === SECTION HEADER === *\/\n  .section-header { gap: 8px; }\n  .section-title { font-size: 14px; }\n\n  \/* === GRIDS INTERNOS \u2014 min-width:0 evita overflow sem cortar === *\/\n  .ind-card, .dash-section, .chart-card, .task-card,\n  .bi-kpi, .kanban-col, .form-card, .filter-bar {\n    min-width: 0;\n  }\n}\n\n\/* \u2500\u2500 480px \u2014 phones pequenos \u2500\u2500 *\/\n@media (max-width: 480px) {\n  .main-content { padding: 0 10px 80px; }\n  .indicators-grid { grid-template-columns: repeat(2, 1fr); gap: 6px; }\n  .ind-card { padding: 10px; }\n  .ind-label { font-size: 10px; }\n  .ind-value { font-size: 22px; }\n  .ind-sub { display: none; }\n  .filter-grid { grid-template-columns: 1fr; }\n  .bi-kpis { grid-template-columns: 1fr 1fr; gap: 8px; }\n  .tab-btn { padding: 7px 10px; font-size: 11px; }\n  .tab-badge { display: none; }\n}\n\n<\/style>\n<\/head>\n<body>\n\n<!-- ============================\n     AUTH OVERLAY \u2014 Google Login\n============================= -->\n<div class=\"auth-overlay hidden\" id=\"authOverlay\">\n  <div class=\"auth-box\">\n    <div class=\"auth-logo\">\n      <div style=\"width:52px;height:52px;border-radius:12px;background:linear-gradient(135deg,var(--blue),var(--green));display:flex;align-items:center;justify-content:center;font-size:22px;font-weight:900;color:#fff;letter-spacing:-1px;\">LT<\/div>\n    <\/div>\n    <div class=\"auth-title\">Link Task<\/div>\n    <div class=\"auth-sub\">Acesso restrito a contas Google autorizadas.<br>Fa\u00e7a login para continuar.<\/div>\n    <div class=\"auth-error\" id=\"authError\"><\/div>\n    <div class=\"auth-google-btn-wrap\" id=\"authGoogleBtnWrap\"><\/div>\n    <div style=\"font-size:11px;color:var(--text-muted);margin-top:8px;\">\n      Seus dados ficam no seu Google Sheets. Nenhuma informa\u00e7\u00e3o \u00e9 enviada a terceiros.\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- ============================\n     SETUP WIZARD (primeiro uso)\n============================= -->\n<div class=\"setup-overlay\" id=\"setupOverlay\">\n  <div class=\"setup-box\">\n    <div class=\"setup-title\">\ud83d\ude80 Configura\u00e7\u00e3o Inicial<\/div>\n    <div class=\"setup-sub\">Personalize o Link Task com a identidade visual da sua empresa.<\/div>\n\n    <div class=\"setup-section\">\n      <div class=\"setup-section-title\">Tipo de Logo<\/div>\n      <div class=\"setup-options\">\n        <div class=\"setup-opt selected\" id=\"optText\" onclick=\"selecionarTipoLogo('text')\">\n          <div class=\"setup-opt-icon\">\ud83c\udd71\ufe0f<\/div>\n          <div class=\"setup-opt-label\">Texto<\/div>\n        <\/div>\n        <div class=\"setup-opt\" id=\"optImage\" onclick=\"selecionarTipoLogo('image')\">\n          <div class=\"setup-opt-icon\">\ud83d\uddbc\ufe0f<\/div>\n          <div class=\"setup-opt-label\">Imagem<\/div>\n        <\/div>\n        <div class=\"setup-opt\" id=\"optDefault\" onclick=\"selecionarTipoLogo('default')\">\n          <div class=\"setup-opt-icon\">\u2b21<\/div>\n          <div class=\"setup-opt-label\">Padr\u00e3o<\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <!-- Config texto -->\n    <div id=\"setupTextSection\" class=\"setup-section\">\n      <div class=\"setup-section-title\">Configurar Texto<\/div>\n      <div style=\"display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:10px;\">\n        <div class=\"form-field\">\n          <label class=\"form-label\">T\u00edtulo<\/label>\n          <input class=\"form-input\" id=\"setupLogoP1\" value=\"\" placeholder=\"Ex: Link\" oninput=\"atualizarPreview()\">\n        <\/div>\n        <div class=\"form-field\">\n          <label class=\"form-label\">Subt\u00edtulo<\/label>\n          <input class=\"form-input\" id=\"setupLogoP2\" value=\"\" placeholder=\"Ex: Task\" oninput=\"atualizarPreview()\">\n        <\/div>\n      <\/div>\n      <div class=\"form-field\">\n        <label class=\"form-label\">Informativo<\/label>\n        <input class=\"form-input\" id=\"setupLogoSub\" value=\"\" placeholder=\"Ex: Painel de Gest\u00e3o de Tarefas\" oninput=\"atualizarPreview()\">\n      <\/div>\n    <\/div>\n\n    <!-- Config imagem -->\n    <div id=\"setupImageSection\" class=\"setup-section\" style=\"display:none;\">\n      <div class=\"setup-section-title\">Upload de Logo<\/div>\n      <div class=\"logo-upload-area\" onclick=\"document.getElementById('logoFileInput').click()\">\n        <div style=\"font-size:24px; margin-bottom:6px;\">\ud83d\udcc2<\/div>\n        <div>Clique para selecionar imagem<\/div>\n        <div style=\"font-size:11px; margin-top:4px;\">PNG, JPG, SVG ou WEBP (m\u00e1x 2MB)<\/div>\n      <\/div>\n      <input type=\"file\" id=\"logoFileInput\" accept=\"image\/*\" style=\"display:none\" onchange=\"carregarImagemLogo(this)\">\n      <div class=\"form-field\" style=\"margin-top:10px;\">\n        <label class=\"form-label\">Informativo<\/label>\n        <input class=\"form-input\" id=\"setupImgSub\" value=\"\" placeholder=\"Ex: Painel de Gest\u00e3o de Tarefas\" oninput=\"atualizarPreview()\">\n      <\/div>\n    <\/div>\n\n    <!-- Preview -->\n    <div class=\"setup-preview\">\n      <div class=\"setup-preview-logo\" id=\"setupPreviewLogo\">\n        <div style=\"width:40px;height:40px;border-radius:8px;background:linear-gradient(135deg,var(--blue),var(--green));display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:800;color:#fff;\">LT<\/div>\n      <\/div>\n      <div>\n        <div id=\"setupPreviewTitle\" style=\"font-size:17px;font-weight:800;letter-spacing:-.3px;\">\n          <span style=\"color:var(--blue)\">Link<\/span>&nbsp;<span style=\"color:var(--green)\">Task<\/span>\n        <\/div>\n        <div id=\"setupPreviewSub\" style=\"font-size:10px;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.5px;\">Painel de Gest\u00e3o de Tarefas<\/div>\n      <\/div>\n    <\/div>\n\n    <div style=\"display:flex; gap:10px; justify-content:flex-end;\">\n      <button class=\"btn btn-ghost\" onclick=\"pularSetup()\">Pular<\/button>\n      <button class=\"btn btn-success\" onclick=\"confirmarSetup()\">\u2713 Confirmar e Entrar<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- ============================\n     APP SHELL\n============================= -->\n<div class=\"app-shell\">\n\n  <header class=\"header\">\n    <div class=\"header-inner\">\n      <div class=\"logo-area\" onclick=\"abrirTrocaLogo()\">\n        <div class=\"logo-wrapper\" id=\"logoWrapper\">\n          <div id=\"logoContainer\">\n            <!-- Logo preenchido via JS \u2014 sem \u00edcone padr\u00e3o -->\n          <\/div>\n          <div class=\"logo-change-overlay\">\n            <svg width=\"11\" height=\"11\" viewBox=\"0 0 16 16\" fill=\"none\"><path d=\"M11 2l3 3-8 8H3v-3l8-8z\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linejoin=\"round\"\/><\/svg>\n            Trocar\n          <\/div>\n        <\/div>\n        <div class=\"logo-text\" id=\"logoTextArea\">\n          <div class=\"logo-title\" id=\"logoTitle\"><span>Link<\/span>&nbsp;<span>Task<\/span><\/div>\n          <div class=\"logo-sub\" id=\"logoSub\">Painel de Gest\u00e3o de Tarefas<\/div>\n        <\/div>\n      <\/div>\n\n      <div class=\"header-spacer\"><\/div>\n\n      <div id=\"statusPill\" class=\"status-pill local\">\n        <div class=\"status-dot\"><\/div>\n        <span class=\"label\" id=\"statusLabel\">Modo Local<\/span>\n      <\/div>\n\n      <button class=\"btn btn-outline btn-sm\" onclick=\"carregarTarefas()\" title=\"Recarregar tarefas\">\n        <svg width=\"13\" height=\"13\" viewBox=\"0 0 16 16\" fill=\"none\">\n          <path d=\"M13.7 2.3A8 8 0 1 0 15 8\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/>\n          <path d=\"M12 0l1.7 2.3L11 3.6\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\n        <\/svg>\n        <span class=\"btn-refresh-text\">Atualizar<\/span>\n      <\/button>\n\n      <label class=\"theme-toggle\" title=\"Alternar tema\">\n        <input type=\"checkbox\" id=\"themeToggle\" onchange=\"alternarTema(this.checked)\">\n        <div class=\"theme-track\"><span>\ud83c\udf19<\/span><span>\u2600\ufe0f<\/span><\/div>\n        <div class=\"theme-knob\" id=\"themeKnob\"><span id=\"themeIcon\">\ud83c\udf19<\/span><\/div>\n      <\/label>\n\n      <!-- User pill -->\n      <div class=\"user-pill-wrap\" id=\"userPillWrap\" style=\"display:none;\">\n        <div class=\"user-pill\" onclick=\"toggleUserMenu()\">\n          <div class=\"user-avatar-placeholder\" id=\"userAvatarEl\">?<\/div>\n          <span class=\"user-name\" id=\"userNameEl\">\u2014<\/span>\n          <svg width=\"10\" height=\"10\" viewBox=\"0 0 16 16\" fill=\"none\"><path d=\"M4 6l4 4 4-4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\"\/><\/svg>\n        <\/div>\n        <div class=\"user-menu\" id=\"userMenu\">\n          <div class=\"user-menu-email\" id=\"userEmailEl\">\u2014<\/div>\n          <div class=\"user-menu-item\" onclick=\"logout()\">\n            <svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\"><path d=\"M6 2H3a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h3M10 11l3-3-3-3M13 8H6\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\n            Sair\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/header>\n\n  <main>\n    <div class=\"main-content\">\n\n      <div id=\"urlConfigBar\" class=\"url-config-bar\" style=\"margin-top:20px;\">\n        <label>\ud83d\udd17 URL Apps Script:<\/label>\n        <input type=\"text\" class=\"form-input\" id=\"appsScriptUrl\"\n          placeholder=\"Cole aqui a URL do Web App (https:\/\/script.google.com\/...)\"\n          oninput=\"salvarUrl(this.value)\">\n        <button class=\"btn btn-primary btn-sm\" onclick=\"testarConexao()\">Testar Conex\u00e3o<\/button>\n        <button class=\"btn btn-ghost btn-sm\" onclick=\"document.getElementById('urlConfigBar').style.display='none'\">\u2715<\/button>\n      <\/div>\n\n      <!-- TABS \u2014 drag to reorder -->\n      <div class=\"section-tabs\" id=\"tabsContainer\">\n        <!-- gerado via JS para permitir reordena\u00e7\u00e3o -->\n      <\/div>\n\n      <!-- TAB: DASHBOARD -->\n      <div id=\"tab-dashboard\" class=\"tab-panel active\">\n        <div class=\"indicators-grid\" id=\"indicatorsGrid\">\n          <div class=\"ind-card ind-total\">\n            <div class=\"ind-label\">Total de Tarefas<\/div>\n            <div class=\"ind-value\" id=\"indTotal\">0<\/div>\n            <div class=\"ind-sub\">em todos os setores<\/div>\n          <\/div>\n          <div class=\"ind-card ind-backlog\">\n            <div class=\"ind-label\">Backlog<\/div>\n            <div class=\"ind-value\" id=\"indBacklog\">0<\/div>\n            <div class=\"ind-sub\">aguardando planejamento<\/div>\n          <\/div>\n          <div class=\"ind-card ind-afazer\">\n            <div class=\"ind-label\">A Fazer<\/div>\n            <div class=\"ind-value\" id=\"indAfazer\">0<\/div>\n            <div class=\"ind-sub\">planejadas para sprint<\/div>\n          <\/div>\n          <div class=\"ind-card ind-andamento\">\n            <div class=\"ind-label\">Em Andamento<\/div>\n            <div class=\"ind-value\" id=\"indAndamento\">0<\/div>\n            <div class=\"ind-sub\">em execu\u00e7\u00e3o agora<\/div>\n          <\/div>\n          <div class=\"ind-card ind-revisao\">\n            <div class=\"ind-label\">Em Revis\u00e3o<\/div>\n            <div class=\"ind-value\" id=\"indRevisao\">0<\/div>\n            <div class=\"ind-sub\">aguardando aprova\u00e7\u00e3o<\/div>\n          <\/div>\n          <div class=\"ind-card ind-concluido\">\n            <div class=\"ind-label\">Conclu\u00eddas<\/div>\n            <div class=\"ind-value\" id=\"indConcluido\">0<\/div>\n            <div class=\"ind-sub\">entregues com sucesso<\/div>\n          <\/div>\n          <div class=\"ind-card ind-vencidas\">\n            <div class=\"ind-label\">Vencidas<\/div>\n            <div class=\"ind-value\" id=\"indVencidas\">0<\/div>\n            <div class=\"ind-sub\">prazo ultrapassado<\/div>\n          <\/div>\n          <div class=\"ind-card ind-points\">\n            <div class=\"ind-label\">Story Points<\/div>\n            <div class=\"ind-value\" id=\"indPoints\">0<\/div>\n            <div class=\"ind-sub\" id=\"indPointsSub\">sprint atual<\/div>\n          <\/div>\n        <\/div>\n\n        <!-- Charts row -->\n        <div class=\"dash-charts-grid\">\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83d\udcca Status das Tarefas<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"chartStatus\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83c\udfaf Distribui\u00e7\u00e3o por Prioridade<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"chartPrioridade\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83c\udfe2 Tarefas por Setor<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"chartSetor\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83e\udde9 Tipos de Tarefa<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"chartTipo\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n\n        <!-- Tables -->\n        <div class=\"dash-grid\" id=\"dashGrid\"><\/div>\n      <\/div>\n\n      <!-- TAB: TAREFAS -->\n      <div id=\"tab-tarefas\" class=\"tab-panel\">\n        <div class=\"filter-bar\">\n          <div style=\"display:flex;gap:2px;margin-bottom:14px;border-bottom:1px solid var(--border-soft);\">\n            <button class=\"ftab-btn ftab-active\" id=\"ftabFiltrar\" onclick=\"ativarFTab('filtrar')\">\ud83d\udd0d Filtrar<\/button>\n            <button class=\"ftab-btn\" id=\"ftabOrdenar\" onclick=\"ativarFTab('ordenar')\">\u2195 Ordenar<\/button>\n            <div style=\"flex:1;\"><\/div>\n            <button class=\"btn btn-ghost btn-sm\" id=\"ftabLimparBtn\" onclick=\"limparFiltros()\" style=\"margin-bottom:2px;\">Limpar tudo<\/button>\n          <\/div>\n          <div id=\"ftabPainelFiltrar\">\n          <div class=\"filter-grid\">\n            <div class=\"form-field\">\n              <label class=\"form-label\">Busca livre<\/label>\n              <input type=\"text\" class=\"form-input\" id=\"filtBusca\" placeholder=\"T\u00edtulo, descri\u00e7\u00e3o, respons\u00e1vel...\" oninput=\"aplicarFiltros()\">\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Setor<\/label>\n              <select class=\"form-select\" id=\"filtSetor\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Todos os setores<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Sprint<\/label>\n              <select class=\"form-select\" id=\"filtSprint\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Todas as sprints<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Status<\/label>\n              <select class=\"form-select\" id=\"filtStatus\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Todos os status<\/option>\n                <option>Backlog<\/option><option>A Fazer<\/option>\n                <option>Em Andamento<\/option><option>Em Revis\u00e3o<\/option><option>Conclu\u00eddo<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Prioridade<\/label>\n              <select class=\"form-select\" id=\"filtPrioridade\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Todas<\/option>\n                <option>Baixa<\/option><option>M\u00e9dia<\/option><option>Alta<\/option><option>Cr\u00edtica<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Respons\u00e1vel<\/label>\n              <select class=\"form-select\" id=\"filtResponsavel\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Todos<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Tipo<\/label>\n              <select class=\"form-select\" id=\"filtTipo\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Todos<\/option>\n                <option>Task<\/option><option>Corre\u00e7\u00e3o<\/option><option>Melhoria<\/option><option>Demanda<\/option>\n              <\/select>\n            <\/div>\n          <\/div>\n          <div class=\"filter-row-extra\">\n            <label class=\"filter-check\">\n              <input type=\"checkbox\" id=\"filtVencidas\" onchange=\"aplicarFiltros()\">\n              <div class=\"filter-check-box\">\u2713<\/div>Apenas vencidas\n            <\/label>\n            <label class=\"filter-check\">\n              <input type=\"checkbox\" id=\"filtImpedimento\" onchange=\"aplicarFiltros()\">\n              <div class=\"filter-check-box\">\u2713<\/div>Com impedimento\n            <\/label>\n            <label class=\"filter-check\">\n              <input type=\"checkbox\" id=\"filtConcluidas\" onchange=\"aplicarFiltros()\">\n              <div class=\"filter-check-box\">\u2713<\/div>Apenas conclu\u00eddas\n            <\/label>\n          <\/div>\n          <!-- Active filter chips -->\n          <div class=\"active-filters\" id=\"activeFilterChips\"><\/div>\n          <\/div><!-- \/ftabPainelFiltrar -->\n          <div id=\"ftabPainelOrdenar\" style=\"display:none;\">\n            <div class=\"form-field\" style=\"max-width:340px;\">\n              <label class=\"form-label\">Ordenar por<\/label>\n              <select class=\"form-select\" id=\"sortCampo\" onchange=\"aplicarFiltros()\">\n                <option value=\"\">Padr\u00e3o (mais recente)<\/option>\n                <option value=\"titulo\">T\u00edtulo (A\u2192Z)<\/option>\n                <option value=\"titulo_desc\">T\u00edtulo (Z\u2192A)<\/option>\n                <option value=\"prioridade\">Prioridade (Cr\u00edtica\u2192Baixa)<\/option>\n                <option value=\"prioridade_asc\">Prioridade (Baixa\u2192Cr\u00edtica)<\/option>\n                <option value=\"status\">Status (fluxo)<\/option>\n                <option value=\"storyPoints\">Story Points (maior)<\/option>\n                <option value=\"storyPoints_asc\">Story Points (menor)<\/option>\n                <option value=\"prazo\">Data Inicial (pr\u00f3xima)<\/option>\n                <option value=\"prazo_desc\">Data Inicial (distante)<\/option>\n                <option value=\"responsavel\">Respons\u00e1vel (A\u2192Z)<\/option>\n                <option value=\"setor\">Setor (A\u2192Z)<\/option>\n                <option value=\"sprint\">Sprint<\/option>\n                <option value=\"criadoEm\">Cria\u00e7\u00e3o (recente)<\/option>\n                <option value=\"criadoEm_asc\">Cria\u00e7\u00e3o (antiga)<\/option>\n                <option value=\"dataConclusao\">Conclus\u00e3o (recente)<\/option>\n              <\/select>\n            <\/div>\n            <div id=\"sortIndicador\" style=\"margin-top:8px;font-size:12px;color:var(--text-secondary);display:none;\">\n              \u2195 <span id=\"sortIndicadorTxt\"><\/span>\n              <button class=\"btn btn-ghost btn-sm\" onclick=\"document.getElementById('sortCampo').value='';aplicarFiltros();\" style=\"padding:2px 8px;font-size:11px;margin-left:6px;\">\u2715 Remover<\/button>\n            <\/div>\n          <\/div><!-- \/ftabPainelOrdenar -->\n        <\/div>\n\n        <div class=\"section-header\">\n          <div class=\"section-title\">\n            \ud83d\udccb Tarefas <span class=\"sprint-display\" id=\"sprintDisplay\">\u2014<\/span>\n          <\/div>\n          <div style=\"display:flex;gap:8px;align-items:center;\">\n            <span style=\"font-size:12px;color:var(--text-muted)\" id=\"countDisplay\">0 tarefas<\/span>\n            <button class=\"btn btn-success btn-sm\" onclick=\"irParaNova()\">+ Nova Tarefa<\/button>\n          <\/div>\n        <\/div>\n        <div class=\"cards-grid\" id=\"cardsGrid\">\n          <div class=\"empty-state\" style=\"grid-column:1\/-1\">\n            <div class=\"empty-state-icon\">\ud83d\udccb<\/div>\n            <div class=\"empty-state-text\">Carregando tarefas...<\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <!-- TAB: KANBAN -->\n      <div id=\"tab-kanban\" class=\"tab-panel\">\n        <div class=\"section-header\">\n          <div class=\"section-title\">\ud83d\uddc2 Quadro Kanban<\/div>\n          <div style=\"display:flex;gap:8px;align-items:center;\">\n            <span style=\"font-size:12px;color:var(--text-muted)\" id=\"kanbanCountDisplay\"><\/span>\n            <button class=\"btn btn-ghost btn-sm\" onclick=\"limparFiltrosKanban()\">Limpar<\/button>\n          <\/div>\n        <\/div>\n\n        <!-- Filtros do Kanban -->\n        <div class=\"filter-bar\" style=\"margin-bottom:14px;\">\n          <div class=\"filter-bar-header\">\n            <div class=\"filter-title\">\ud83d\udd0d Filtros<\/div>\n          <\/div>\n          <div class=\"filter-grid\" style=\"grid-template-columns:repeat(auto-fill,minmax(min(160px,100%),1fr));\">\n            <div class=\"form-field\">\n              <label class=\"form-label\">Busca<\/label>\n              <input type=\"text\" class=\"form-input\" id=\"kfiltBusca\" placeholder=\"T\u00edtulo ou respons\u00e1vel...\" oninput=\"aplicarFiltrosKanban()\">\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Setor<\/label>\n              <select class=\"form-select\" id=\"kfiltSetor\" onchange=\"aplicarFiltrosKanban()\">\n                <option value=\"\">Todos<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Sprint<\/label>\n              <select class=\"form-select\" id=\"kfiltSprint\" onchange=\"aplicarFiltrosKanban()\">\n                <option value=\"\">Todas<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Prioridade<\/label>\n              <select class=\"form-select\" id=\"kfiltPrioridade\" onchange=\"aplicarFiltrosKanban()\">\n                <option value=\"\">Todas<\/option>\n                <option>Cr\u00edtica<\/option><option>Alta<\/option><option>M\u00e9dia<\/option><option>Baixa<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Respons\u00e1vel<\/label>\n              <select class=\"form-select\" id=\"kfiltResponsavel\" onchange=\"aplicarFiltrosKanban()\">\n                <option value=\"\">Todos<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Tipo<\/label>\n              <select class=\"form-select\" id=\"kfiltTipo\" onchange=\"aplicarFiltrosKanban()\">\n                <option value=\"\">Todos<\/option>\n                <option>Task<\/option><option>Corre\u00e7\u00e3o<\/option><option>Melhoria<\/option><option>Demanda<\/option>\n              <\/select>\n            <\/div>\n          <\/div>\n          <div class=\"active-filters\" id=\"kanbanActiveChips\"><\/div>\n        <\/div>\n\n        <!-- Mobile column nav -->\n        <div class=\"kanban-mobile-nav\" id=\"kanbanMobileNav\" style=\"display:none;\"><\/div>\n        <div class=\"kanban-board\" id=\"kanbanBoard\"><\/div>\n      <\/div>\n\n      <!-- TAB: NOVA TAREFA -->\n      <div id=\"tab-nova\" class=\"tab-panel\">\n        <div class=\"form-card\" id=\"taskFormCard\">\n          <div class=\"form-card-header\">\n            <div class=\"form-card-title\"><span id=\"formTitle\">\u2795 Nova Tarefa<\/span><\/div>\n            <button class=\"btn btn-ghost btn-sm\" id=\"cancelarEdicaoBtn\" style=\"display:none;\" onclick=\"cancelarEdicao()\">\u2715 Cancelar Edi\u00e7\u00e3o<\/button>\n          <\/div>\n          <form id=\"taskForm\" onsubmit=\"event.preventDefault(); salvarTarefa()\">\n            <div class=\"form-grid\">\n              <div class=\"form-field\">\n                <label class=\"form-label\">Setor <span class=\"req\">*<\/span><\/label>\n                <select class=\"form-select\" id=\"fSetor\" required>\n                  <option value=\"\">Selecione...<\/option>\n                  <option>Administracao<\/option><option>Comercial<\/option><option>Marketing<\/option>\n                  <option>TI<\/option><option>Financeiro<\/option><option>Operacoes<\/option><option>RH<\/option>\n                <\/select>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Sprint <span class=\"req\">*<\/span><\/label>\n                <input type=\"text\" class=\"form-input\" id=\"fSprint\" placeholder=\"Ex: Sprint 12\" required>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Respons\u00e1vel <span class=\"req\">*<\/span><\/label>\n                <input type=\"text\" class=\"form-input\" id=\"fResponsavel\" placeholder=\"Nome do respons\u00e1vel\" required>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Prioridade <span class=\"req\">*<\/span><\/label>\n                <select class=\"form-select\" id=\"fPrioridade\" required>\n                  <option value=\"\">Selecione...<\/option>\n                  <option>Baixa<\/option><option>M\u00e9dia<\/option><option>Alta<\/option><option>Cr\u00edtica<\/option>\n                <\/select>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Status <span class=\"req\">*<\/span><\/label>\n                <select class=\"form-select\" id=\"fStatus\" required>\n                  <option value=\"\">Selecione...<\/option>\n                  <option>Backlog<\/option><option>A Fazer<\/option>\n                  <option>Em Andamento<\/option><option>Em Revis\u00e3o<\/option><option>Conclu\u00eddo<\/option>\n                <\/select>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Tipo <span class=\"req\">*<\/span><\/label>\n                <select class=\"form-select\" id=\"fTipo\" required>\n                  <option value=\"\">Selecione...<\/option>\n                  <option>Task<\/option><option>Corre\u00e7\u00e3o<\/option><option>Melhoria<\/option><option>Demanda<\/option>\n                <\/select>\n              <\/div>\n            <\/div>\n            <div class=\"form-grid\" style=\"margin-bottom:14px;\">\n              <div class=\"form-field form-grid-wide\">\n                <label class=\"form-label\">T\u00edtulo <span class=\"req\">*<\/span><\/label>\n                <input type=\"text\" class=\"form-input\" id=\"fTitulo\" placeholder=\"Descreva a tarefa de forma objetiva\" required>\n              <\/div>\n            <\/div>\n            <div class=\"form-grid\">\n              <div class=\"form-field\">\n                <label class=\"form-label\">Story Points<\/label>\n                <input type=\"number\" class=\"form-input\" id=\"fStoryPoints\" placeholder=\"0\" min=\"0\" max=\"100\">\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Data Inicial<\/label>\n                <input type=\"date\" class=\"form-input\" id=\"fPrazo\">\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Data de Conclus\u00e3o<\/label>\n                <input type=\"date\" class=\"form-input\" id=\"fDataConclusao\">\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Tags<\/label>\n                <input type=\"text\" class=\"form-input\" id=\"fTags\" placeholder=\"tag1, tag2, tag3\">\n              <\/div>\n            <\/div>\n            <div class=\"form-grid\">\n              <div class=\"form-field form-grid-wide\">\n                <label class=\"form-label\">Descri\u00e7\u00e3o<\/label>\n                <textarea class=\"form-textarea\" id=\"fDescricao\" placeholder=\"Detalhes da tarefa, contexto e objetivos...\"><\/textarea>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Impedimento<\/label>\n                <textarea class=\"form-textarea\" id=\"fImpedimento\" placeholder=\"Descreva bloqueios ou impedimentos existentes...\" style=\"min-height:60px;\"><\/textarea>\n              <\/div>\n              <div class=\"form-field\">\n                <label class=\"form-label\">Crit\u00e9rio de Aceite<\/label>\n                <textarea class=\"form-textarea\" id=\"fCriterioAceite\" placeholder=\"Como saber que essa tarefa est\u00e1 pronta?\" style=\"min-height:60px;\"><\/textarea>\n              <\/div>\n            <\/div>\n            <div class=\"form-actions\">\n              <button type=\"submit\" class=\"btn btn-success\" id=\"submitBtn\">\u2713 Criar Tarefa<\/button>\n              <button type=\"button\" class=\"btn btn-outline\" onclick=\"resetarFormulario()\">\u21ba Limpar Formul\u00e1rio<\/button>\n            <\/div>\n          <\/form>\n        <\/div>\n      <\/div>\n\n      <!-- TAB: BI -->\n      <div id=\"tab-bi\" class=\"tab-panel\">\n        <div class=\"section-header\">\n          <div class=\"section-title\">\ud83d\udcca Business Intelligence<\/div>\n        <\/div>\n\n        <!-- Multi-filter BI -->\n        <div class=\"bi-toolbar\">\n          <div class=\"bi-toolbar-title\">\n            <span>\ud83c\udf9b\ufe0f Filtros de An\u00e1lise<\/span>\n            <button class=\"btn btn-ghost btn-sm\" onclick=\"limparFiltrosBI()\">Limpar todos<\/button>\n          <\/div>\n          <div class=\"bi-filter-builder\">\n            <div class=\"form-field\">\n              <label class=\"form-label\">Dimens\u00e3o<\/label>\n              <select class=\"form-select\" id=\"biDimensao\">\n                <option value=\"setor\">Setor<\/option>\n                <option value=\"sprint\">Sprint<\/option>\n                <option value=\"status\">Status<\/option>\n                <option value=\"prioridade\">Prioridade<\/option>\n                <option value=\"tipo\">Tipo<\/option>\n                <option value=\"responsavel\">Respons\u00e1vel<\/option>\n                <option value=\"setor_status\">Setor \u00d7 Status<\/option>\n                <option value=\"sprint_status\">Sprint \u00d7 Status<\/option>\n                <option value=\"responsavel_status\">Respons\u00e1vel \u00d7 Status<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Valor<\/label>\n              <select class=\"form-select\" id=\"biValor\">\n                <option value=\"\">Selecione...<\/option>\n              <\/select>\n            <\/div>\n            <button class=\"btn btn-primary btn-sm\" onclick=\"adicionarFiltroBI()\">+ Adicionar<\/button>\n          <\/div>\n          <!-- An\u00e1lises r\u00e1pidas \u2014 atalhos pr\u00e9-definidos -->\n          <div class=\"bi-quick-filters\" id=\"biQuickFilters\">\n            <span style=\"font-size:11px;color:var(--text-muted);width:100%;margin-bottom:2px;\">\u26a1 An\u00e1lises r\u00e1pidas:<\/span>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('status','Em Andamento')\">\ud83d\udd04 Em Andamento<\/button>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('status','Conclu\u00eddo')\">\u2705 Conclu\u00eddas<\/button>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('status','Backlog')\">\ud83d\udce5 Backlog<\/button>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('prioridade','Cr\u00edtica')\">\ud83d\udd34 Cr\u00edtica<\/button>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('prioridade','Alta')\">\ud83d\udfe0 Alta Prio.<\/button>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('tipo','Corre\u00e7\u00e3o')\">\ud83d\udd27 Bugs<\/button>\n            <button class=\"bi-quick-btn\" onclick=\"filtroRapidoBI('tipo','Melhoria')\">\u2728 Melhorias<\/button>\n          <\/div>\n          <div class=\"bi-active-filters\" id=\"biActiveFilters\">\n            <span style=\"font-size:11px;color:var(--text-muted);align-self:center;\">Nenhum filtro \u2014 mostrando todos os dados<\/span>\n          <\/div>\n        <\/div>\n\n        <!-- BI KPIs -->\n        <div class=\"bi-kpis\" id=\"biKpis\"><\/div>\n\n        <!-- BI Charts Grid -->\n        <div class=\"bi-charts-grid\" id=\"biChartsGrid\">\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83d\udcc8 Evolu\u00e7\u00e3o por Sprint<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"biChartSprint\" style=\"max-height:260px;\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83d\udc64 Story Points por Respons\u00e1vel<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"biChartResponsavel\" style=\"max-height:260px;\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card full-width\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83c\udfc6 Produtividade por Setor (Conclu\u00eddas vs Total)<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"biChartProdutividade\" style=\"max-height:280px;\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83c\udfaf Taxa de Conclus\u00e3o por Prioridade<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"biChartConclusao\" style=\"max-height:260px;\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n          <div class=\"chart-card\">\n            <div class=\"chart-card-header\">\n              <div class=\"chart-card-title\">\ud83d\udd34 Vencidas vs Em Dia<\/div>\n            <\/div>\n            <div class=\"chart-card-body\">\n              <div class=\"chart-canvas-wrap\"><canvas id=\"biChartVencidas\" style=\"max-height:260px;\"><\/canvas><\/div>\n            <\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n\n      <!-- TAB: RELAT\u00d3RIOS -->\n      <div id=\"tab-relatorios\" class=\"tab-panel\">\n        <div class=\"section-header\">\n          <div class=\"section-title\">\ud83d\udcc8 Relat\u00f3rios<\/div>\n          <button class=\"btn btn-ghost btn-sm\" onclick=\"limparFiltrosRelat()\">Limpar filtros<\/button>\n        <\/div>\n\n        <!-- Filtros dos relat\u00f3rios -->\n        <div class=\"relat-filter-bar\">\n          <div class=\"relat-filter-row\">\n            <div class=\"form-field\">\n              <label class=\"form-label\">Setor<\/label>\n              <select class=\"form-select\" id=\"rfiltSetor\" onchange=\"renderizarRelatorios()\">\n                <option value=\"\">Todos os setores<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Sprint<\/label>\n              <select class=\"form-select\" id=\"rfiltSprint\" onchange=\"renderizarRelatorios()\">\n                <option value=\"\">Todas as sprints<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Per\u00edodo<\/label>\n              <select class=\"form-select\" id=\"rfiltPeriodo\" onchange=\"renderizarRelatorios()\">\n                <option value=\"\">Todo o per\u00edodo<\/option>\n                <option value=\"7\">\u00daltimos 7 dias<\/option>\n                <option value=\"15\">\u00daltimos 15 dias<\/option>\n                <option value=\"30\">\u00daltimos 30 dias<\/option>\n                <option value=\"60\">\u00daltimos 60 dias<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Tipo<\/label>\n              <select class=\"form-select\" id=\"rfiltTipo\" onchange=\"renderizarRelatorios()\">\n                <option value=\"\">Todos os tipos<\/option>\n                <option>Task<\/option><option>Corre\u00e7\u00e3o<\/option><option>Melhoria<\/option><option>Demanda<\/option>\n              <\/select>\n            <\/div>\n            <div class=\"form-field\">\n              <label class=\"form-label\">Respons\u00e1vel<\/label>\n              <select class=\"form-select\" id=\"rfiltResponsavel\" onchange=\"renderizarRelatorios()\">\n                <option value=\"\">Todos<\/option>\n              <\/select>\n            <\/div>\n          <\/div>\n        <\/div>\n\n        <div class=\"relat-grid\" id=\"relatoriosGrid\"><\/div>\n      <\/div>\n\n    <\/div>\n  <\/main>\n<\/div>\n\n<!-- CONFIRM MODAL -->\n<!-- KANBAN POPUP -->\n<div class=\"kanban-popup-overlay\" id=\"kanbanPopupOverlay\" onclick=\"fecharKanbanPopup(event)\">\n  <div class=\"kanban-popup\" id=\"kanbanPopup\">\n    <div class=\"kanban-popup-header\">\n      <div class=\"kanban-popup-title\" id=\"kpTitulo\">\u2014<\/div>\n      <button class=\"kanban-popup-close\" onclick=\"fecharKanbanPopup()\">\u2715<\/button>\n    <\/div>\n    <div class=\"kanban-popup-body\">\n      <div class=\"kanban-popup-badges\" id=\"kpBadges\"><\/div>\n      <div class=\"kanban-popup-grid\" id=\"kpGrid\"><\/div>\n      <div class=\"kanban-popup-desc\" id=\"kpDesc\" style=\"display:none;\"><\/div>\n      <div id=\"kpImpedimento\" style=\"display:none;\" class=\"task-impedimento-alert\">\u26a0\ufe0f <span id=\"kpImpedimentoTxt\"><\/span><\/div>\n      <div class=\"kanban-popup-actions\">\n        <button class=\"btn btn-primary btn-sm\" onclick=\"editarDoPopup()\">\u270f\ufe0f Editar<\/button>\n        <button class=\"btn btn-success btn-sm\" id=\"kpConcluirBtn\" onclick=\"concluirDoPopup()\">\u2713 Concluir<\/button>\n        <button class=\"btn btn-outline btn-sm\" id=\"kpAvancarBtn\" onclick=\"avancarDoPopup()\">Avan\u00e7ar \u2192<\/button>\n        <button class=\"btn btn-danger btn-sm\" onclick=\"excluirDoPopup()\">\ud83d\uddd1 Excluir<\/button>\n      <\/div>\n      <div class=\"kanban-popup-hint\">Segure o card para arrastar \u00b7 Clique para ver detalhes<\/div>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div class=\"modal-overlay\" id=\"modalOverlay\">\n  <div class=\"modal-box\">\n    <div class=\"modal-title\" id=\"modalTitle\">Confirmar exclus\u00e3o<\/div>\n    <div class=\"modal-text\" id=\"modalText\">Tem certeza que deseja excluir esta tarefa?<\/div>\n    <div class=\"modal-actions\">\n      <button class=\"btn btn-outline\" onclick=\"fecharModal()\">Cancelar<\/button>\n      <button class=\"btn btn-danger\" id=\"modalConfirmBtn\" onclick=\"confirmarModal()\">Excluir<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- LOGO TROCA MODAL -->\n<div class=\"modal-overlay\" id=\"logoModalOverlay\">\n  <div class=\"modal-box\" style=\"max-width:500px;\">\n    <div class=\"modal-title\">\ud83d\uddbc\ufe0f Alterar Logo<\/div>\n    <div class=\"modal-text\" style=\"margin-bottom:16px;\">Escolha como deseja exibir o logo.<\/div>\n    <div class=\"setup-options\" style=\"margin-bottom:16px;\">\n      <div class=\"setup-opt\" id=\"logoOptText\" onclick=\"selecionarTipoLogoModal('text')\">\n        <div class=\"setup-opt-icon\">\ud83c\udd71\ufe0f<\/div><div class=\"setup-opt-label\">Texto<\/div>\n      <\/div>\n      <div class=\"setup-opt\" id=\"logoOptImage\" onclick=\"selecionarTipoLogoModal('image')\">\n        <div class=\"setup-opt-icon\">\ud83d\uddbc\ufe0f<\/div><div class=\"setup-opt-label\">Imagem<\/div>\n      <\/div>\n      <div class=\"setup-opt\" id=\"logoOptDefault\" onclick=\"selecionarTipoLogoModal('default')\">\n        <div class=\"setup-opt-icon\">\u2b21<\/div><div class=\"setup-opt-label\">Padr\u00e3o<\/div>\n      <\/div>\n    <\/div>\n    <div id=\"logoModalTextFields\">\n      <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:10px;\">\n        <div class=\"form-field\">\n          <label class=\"form-label\">T\u00edtulo<\/label>\n          <input class=\"form-input\" id=\"modalLogoP1\" value=\"\" placeholder=\"Ex: Link\">\n        <\/div>\n        <div class=\"form-field\">\n          <label class=\"form-label\">Subt\u00edtulo<\/label>\n          <input class=\"form-input\" id=\"modalLogoP2\" value=\"\" placeholder=\"Ex: Task\">\n        <\/div>\n      <\/div>\n      <div class=\"form-field\" style=\"margin-bottom:12px;\">\n        <label class=\"form-label\">Informativo<\/label>\n        <input class=\"form-input\" id=\"modalLogoSub\" value=\"\" placeholder=\"Ex: Painel de Gest\u00e3o de Tarefas\">\n      <\/div>\n    <\/div>\n    <div id=\"logoModalImageField\" style=\"display:none; margin-bottom:12px;\">\n      <div class=\"logo-upload-area\" onclick=\"document.getElementById('logoFileInputModal').click()\">\n        \ud83d\udcc2 Clique para upload de imagem\n      <\/div>\n      <input type=\"file\" id=\"logoFileInputModal\" accept=\"image\/*\" style=\"display:none\" onchange=\"carregarImagemLogoModal(this)\">\n      <div class=\"form-field\" style=\"margin-top:10px;\">\n        <label class=\"form-label\">Informativo<\/label>\n        <input class=\"form-input\" id=\"modalImgSub\" value=\"\" placeholder=\"Ex: Painel de Gest\u00e3o de Tarefas\">\n      <\/div>\n    <\/div>\n    <div class=\"modal-actions\">\n      <button class=\"btn btn-outline\" onclick=\"fecharLogoModal()\">Cancelar<\/button>\n      <button class=\"btn btn-success\" onclick=\"salvarLogoModal()\">\u2713 Aplicar<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div class=\"toast-container\" id=\"toastContainer\"><\/div>\n\n<script>\n'use strict';\n\n\/\/ =============================================\n\/\/ CONFIG\n\/\/ =============================================\nlet APPS_SCRIPT_URL = localStorage.getItem('bpolink_url') || '';\nconst SETORES = ['Administracao','Comercial','Marketing','TI','Financeiro','Operacoes','RH'];\nconst STATUS_ORDEM = ['Backlog','A Fazer','Em Andamento','Em Revis\u00e3o','Conclu\u00eddo'];\nconst STATUS_SLUG  = { 'Backlog':'backlog','A Fazer':'afazer','Em Andamento':'andamento','Em Revis\u00e3o':'revisao','Conclu\u00eddo':'concluido' };\n\n\/\/ \u2500\u2500 Auth \u2500\u2500\n\/\/ Client ID fixo \u2014 client_secret NUNCA vai no frontend\nconst FIXED_CLIENT_ID = '771505818358-8g12t36n0nhfgbbfvmfs0dujvqadmrf1.apps.googleusercontent.com';\nlet AUTH_CLIENT_ID  = FIXED_CLIENT_ID;\nlet authCredential  = null;\nlet authUser        = null;\n\n\/\/ BI filters store\nlet biFilters = [];\nlet biFilterType = 'text'; \/\/ active logo modal mode\nlet logoModalType = 'text';\n\n\/\/ Charts instances\nconst CHARTS = {};\n\n\/\/ Tab order\nconst TAB_DEFAULTS = [\n  { id: 'dashboard', label: '\ud83d\udcca Dashboard', badge: 'tabTotalBadge' },\n  { id: 'tarefas',   label: '\ud83d\udccb Tarefas',   badge: 'tabTarefasBadge' },\n  { id: 'kanban',    label: '\ud83d\uddc2 Kanban',     badge: 'tabKanbanBadge' },\n  { id: 'bi',        label: '\ud83d\udcc8 BI',         badge: null },\n  { id: 'nova',      label: '\u2795 Nova Tarefa', badge: null },\n  { id: 'relatorios',label: '\ud83d\udcc8 Relat\u00f3rios', badge: null },\n];\n\nlet tabOrder = JSON.parse(localStorage.getItem('bpolink_tabs') || 'null') || TAB_DEFAULTS.map(t => t.id);\n\nlet estado = {\n  tarefas: [],\n  tarefasFiltradas: [],\n  tarefaEmEdicao: null,\n  filtros: {},\n  modoIntegracao: false,\n  carregando: false,\n  modalCallback: null\n};\n\n\/\/ =============================================\n\/\/ INIT\n\/\/ =============================================\ndocument.addEventListener('DOMContentLoaded', () => {\n  \/\/ \u2500\u2500 Auth primeiro \u2500\u2500\n  const savedCred = sessionStorage.getItem('bpolink_credential');\n  const savedUser = sessionStorage.getItem('bpolink_user');\n\n  if (AUTH_CLIENT_ID && savedCred && savedUser) {\n    \/\/ Sess\u00e3o ainda v\u00e1lida \u2014 verifica expira\u00e7\u00e3o do JWT\n    try {\n      const payload = decodificarJWT_(savedCred);\n      if (payload.exp * 1000 > Date.now()) {\n        authCredential = savedCred;\n        authUser = JSON.parse(savedUser);\n        document.getElementById('authOverlay').classList.add('hidden');\n        iniciarApp_();\n        return;\n      }\n    } catch(e) { \/* token inv\u00e1lido, pede login *\/ }\n  }\n\n  \/\/ Sem sess\u00e3o v\u00e1lida \u2014 mostra tela de login\n  mostrarAuthOverlay_();\n});\n\nfunction mostrarAuthOverlay_() {\n  const overlay = document.getElementById('authOverlay');\n  overlay.classList.remove('hidden');\n  \/\/ Client ID j\u00e1 embutido \u2014 inicializa direto, sem pedir ao usu\u00e1rio\n  inicializarAuth();\n}\n\nfunction iniciarApp_() {\n  \/\/ Mostrar user pill no header\n  const wrap = document.getElementById('userPillWrap');\n  const nameEl  = document.getElementById('userNameEl');\n  const emailEl = document.getElementById('userEmailEl');\n  const avatarEl = document.getElementById('userAvatarEl');\n\n  if (authUser) {\n    nameEl.textContent  = authUser.name?.split(' ')[0] || authUser.email;\n    emailEl.textContent = authUser.email;\n    avatarEl.textContent = (authUser.name || authUser.email || '?').charAt(0).toUpperCase();\n    if (authUser.picture) {\n      avatarEl.innerHTML = `<img decoding=\"async\" src=\"${authUser.picture}\" class=\"user-avatar\" onerror=\"this.parentElement.textContent='${avatarEl.textContent}'\">`;\n    }\n    wrap.style.display = '';\n  }\n\n  \/\/ Setup wizard\n  const setupDone = localStorage.getItem('bpolink_setup_done');\n  if (!setupDone) {\n    document.getElementById('setupOverlay').classList.remove('hidden');\n  } else {\n    document.getElementById('setupOverlay').classList.add('hidden');\n    aplicarLogoSalvo();\n  }\n\n  \/\/ URL\n  const urlSalva = localStorage.getItem('bpolink_url');\n  if (urlSalva) { document.getElementById('appsScriptUrl').value = urlSalva; APPS_SCRIPT_URL = urlSalva; }\n\n  \/\/ Tema\n  const tema = localStorage.getItem('bpolink_tema') || 'dark';\n  document.documentElement.setAttribute('data-theme', tema);\n  if (tema === 'light') { document.getElementById('themeToggle').checked = true; document.getElementById('themeIcon').textContent = '\u2600\ufe0f'; }\n\n  \/\/ Render tabs\n  renderizarTabs();\n  popularFiltrosSetor();\n  carregarTarefas();\n\n  \/\/ BI dimension change\n  document.getElementById('biDimensao').addEventListener('change', atualizarValoresBiDimensao);\n  atualizarValoresBiDimensao();\n}\n\n\/\/ =============================================\n\/\/ TEMA\n\/\/ =============================================\nfunction alternarTema(isLight) {\n  const tema = isLight ? 'light' : 'dark';\n  document.documentElement.setAttribute('data-theme', tema);\n  localStorage.setItem('bpolink_tema', tema);\n  document.getElementById('themeIcon').textContent = isLight ? '\u2600\ufe0f' : '\ud83c\udf19';\n  setTimeout(() => { renderizarChartsGlobais(); renderizarChartsBI(); }, 100);\n}\n\n\/\/ =============================================\n\/\/ AUTH \u2014 Google Identity Services\n\/\/ =============================================\nfunction salvarClientId(val) {\n  \/\/ Mantido por compatibilidade mas n\u00e3o mais necess\u00e1rio\n  AUTH_CLIENT_ID = val.trim() || FIXED_CLIENT_ID;\n}\n\nfunction inicializarAuth() {\n  \/\/ Usa sempre o Client ID fixo\n  const clientId = FIXED_CLIENT_ID;\n  AUTH_CLIENT_ID = clientId;\n  ocultarAuthError_();\n\n  \/\/ Aguarda a biblioteca GIS carregar\n  if (typeof google === 'undefined' || !google.accounts) {\n    setTimeout(inicializarAuth, 400);\n    return;\n  }\n\n  google.accounts.id.initialize({\n    client_id: clientId,\n    callback: handleCredentialResponse_,\n    auto_select: true,\n    cancel_on_tap_outside: false,\n  });\n\n  google.accounts.id.renderButton(\n    document.getElementById('authGoogleBtnWrap'),\n    {\n      theme: document.documentElement.getAttribute('data-theme') === 'dark' ? 'filled_black' : 'outline',\n      size: 'large',\n      shape: 'pill',\n      width: 280,\n      text: 'signin_with',\n      locale: 'pt-BR'\n    }\n  );\n\n  \/\/ Tenta One Tap silencioso\n  google.accounts.id.prompt();\n}\n\nfunction handleCredentialResponse_(response) {\n  try {\n    const credential = response.credential;\n    const payload = decodificarJWT_(credential);\n\n    \/\/ Verificar expira\u00e7\u00e3o\n    if (payload.exp * 1000 < Date.now()) {\n      mostrarAuthError_('Token expirado. Tente novamente.');\n      return;\n    }\n\n    \/\/ Verificar email verificado\n    if (!payload.email_verified) {\n      mostrarAuthError_('Sua conta Google n\u00e3o tem e-mail verificado.');\n      return;\n    }\n\n    authCredential = credential;\n    authUser = {\n      name:    payload.name    || '',\n      email:   payload.email   || '',\n      picture: payload.picture || ''\n    };\n\n    \/\/ Persistir na sess\u00e3o (tab atual \u2014 expira ao fechar)\n    sessionStorage.setItem('bpolink_credential', credential);\n    sessionStorage.setItem('bpolink_user', JSON.stringify(authUser));\n\n    \/\/ Esconder overlay e iniciar app\n    document.getElementById('authOverlay').classList.add('hidden');\n    iniciarApp_();\n    mostrarToast(`Bem-vindo, ${authUser.name.split(' ')[0] || authUser.email}! \ud83d\udc4b`, 'success');\n\n  } catch(e) {\n    mostrarAuthError_('Erro ao processar login: ' + e.message);\n  }\n}\n\nfunction decodificarJWT_(token) {\n  const parts = token.split('.');\n  if (parts.length !== 3) throw new Error('Token JWT inv\u00e1lido');\n  let payload = parts[1].replace(\/-\/g, '+').replace(\/_\/g, '\/');\n  while (payload.length % 4) payload += '=';\n  return JSON.parse(atob(payload));\n}\n\nfunction logout() {\n  authCredential = null;\n  authUser = null;\n  sessionStorage.removeItem('bpolink_credential');\n  sessionStorage.removeItem('bpolink_user');\n\n  if (typeof google !== 'undefined' && google.accounts) {\n    google.accounts.id.disableAutoSelect();\n  }\n\n  \/\/ Reset header\n  document.getElementById('userPillWrap').style.display = 'none';\n  document.getElementById('userMenu').classList.remove('open');\n\n  \/\/ Volta para tela de login\n  mostrarAuthOverlay_();\n  mostrarToast('Sess\u00e3o encerrada.', 'info');\n}\n\nfunction toggleUserMenu() {\n  document.getElementById('userMenu').classList.toggle('open');\n}\n\n\/\/ Fecha menu ao clicar fora\ndocument.addEventListener('click', e => {\n  const wrap = document.getElementById('userPillWrap');\n  if (wrap && !wrap.contains(e.target)) {\n    document.getElementById('userMenu')?.classList.remove('open');\n  }\n});\n\nfunction mostrarAuthError_(msg) {\n  const el = document.getElementById('authError');\n  if (el) { el.textContent = msg; el.classList.add('show'); }\n}\nfunction ocultarAuthError_() {\n  const el = document.getElementById('authError');\n  if (el) el.classList.remove('show');\n}\n\n\/\/ =============================================\n\/\/ SETUP WIZARD\n\/\/ =============================================\nlet setupTipoLogo = 'text';\nlet setupImageData = null;\n\nfunction selecionarTipoLogo(tipo) {\n  setupTipoLogo = tipo;\n  ['text','image','default'].forEach(t => {\n    document.getElementById('opt' + t.charAt(0).toUpperCase() + t.slice(1)).classList.toggle('selected', t === tipo);\n  });\n  document.getElementById('setupTextSection').style.display  = tipo === 'text'    ? '' : 'none';\n  document.getElementById('setupImageSection').style.display = tipo === 'image'   ? '' : 'none';\n  atualizarPreview();\n}\n\nfunction atualizarPreview() {\n  const previewLogo  = document.getElementById('setupPreviewLogo');\n  const previewTitle = document.getElementById('setupPreviewTitle');\n  const previewSub   = document.getElementById('setupPreviewSub');\n\n  if (setupTipoLogo === 'text') {\n    const p1 = document.getElementById('setupLogoP1').value || 'Link';\n    const p2 = document.getElementById('setupLogoP2').value || 'Task';\n    const sub = document.getElementById('setupLogoSub').value || '';\n    previewTitle.innerHTML = `<span style=\"color:var(--blue)\">${esc(p1)}<\/span>&nbsp;<span style=\"color:var(--green)\">${esc(p2)}<\/span>`;\n    previewSub.textContent = sub;\n    previewLogo.innerHTML = `<div style=\"width:40px;height:40px;border-radius:8px;background:linear-gradient(135deg,var(--blue),var(--green));display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:800;color:#fff;\">${esc(p1.charAt(0))}${esc(p2.charAt(0))}<\/div>`;\n  } else if (setupTipoLogo === 'image' && setupImageData) {\n    previewTitle.textContent = '';\n    previewSub.textContent = document.getElementById('setupImgSub').value || '';\n    previewLogo.innerHTML = `<img decoding=\"async\" src=\"${setupImageData}\" style=\"height:40px;max-width:120px;object-fit:contain;border-radius:4px;\">`;\n  } else {\n    previewTitle.innerHTML = `<span style=\"color:var(--blue)\">Link<\/span>&nbsp;<span style=\"color:var(--green)\">Task<\/span>`;\n    previewSub.textContent = 'Painel de Gest\u00e3o de Tarefas';\n    previewLogo.innerHTML = `<div style=\"width:40px;height:40px;border-radius:8px;background:linear-gradient(135deg,var(--blue),var(--green));display:flex;align-items:center;justify-content:center;font-size:15px;font-weight:800;color:#fff;\">LT<\/div>`;\n  }\n}\n\nfunction carregarImagemLogo(input) {\n  const file = input.files[0];\n  if (!file) return;\n  if (file.size > 2 * 1024 * 1024) { mostrarToast('Imagem muito grande (m\u00e1x 2MB)', 'error'); return; }\n  const reader = new FileReader();\n  reader.onload = e => { setupImageData = e.target.result; atualizarPreview(); };\n  reader.readAsDataURL(file);\n}\n\nfunction confirmarSetup() {\n  const config = {\n    tipo: setupTipoLogo,\n    p1: document.getElementById('setupLogoP1')?.value || 'Link',\n    p2: document.getElementById('setupLogoP2')?.value || 'Task',\n    sub: setupTipoLogo === 'image'\n         ? (document.getElementById('setupImgSub')?.value || '')\n         : (document.getElementById('setupLogoSub')?.value || 'Painel de Gest\u00e3o de Tarefas'),\n    imageData: setupTipoLogo === 'image' ? setupImageData : null\n  };\n  localStorage.setItem('bpolink_logo', JSON.stringify(config));\n  localStorage.setItem('bpolink_setup_done', '1');\n  document.getElementById('setupOverlay').classList.add('hidden');\n  aplicarLogoSalvo();\n  mostrarToast('Configura\u00e7\u00e3o salva!', 'success');\n}\n\nfunction pularSetup() {\n  localStorage.setItem('bpolink_setup_done', '1');\n  document.getElementById('setupOverlay').classList.add('hidden');\n  aplicarLogoSalvo();\n}\n\nfunction aplicarLogoSalvo() {\n  const raw = localStorage.getItem('bpolink_logo');\n  if (!raw) return;\n  const cfg = JSON.parse(raw);\n  aplicarLogo(cfg);\n}\n\nfunction aplicarLogo(cfg) {\n  const container = document.getElementById('logoContainer');\n  const textArea  = document.getElementById('logoTextArea');\n  const titleEl   = document.getElementById('logoTitle');\n  const subEl     = document.getElementById('logoSub');\n\n  if (cfg.tipo === 'text') {\n    container.innerHTML = `<div style=\"width:34px;height:34px;border-radius:8px;background:linear-gradient(135deg,var(--blue),var(--green));display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:800;color:#fff;\">${esc(cfg.p1.charAt(0))}${esc(cfg.p2.charAt(0))}<\/div>`;\n    titleEl.innerHTML   = `<span>${esc(cfg.p1)}<\/span>&nbsp;<span>${esc(cfg.p2)}<\/span>`;\n    subEl.textContent   = cfg.sub;\n    textArea.style.display = '';\n  } else if (cfg.tipo === 'image' && cfg.imageData) {\n    container.innerHTML = `<img decoding=\"async\" src=\"${cfg.imageData}\" class=\"logo-img-custom\" style=\"width:36px;height:36px;object-fit:contain;\" alt=\"Logo\">`;\n    titleEl.innerHTML   = '';\n    subEl.textContent   = cfg.sub || '';\n    textArea.style.display = cfg.sub ? '' : 'none';\n  } else {\n    \/\/ default \u2014 sem \u00edcone, s\u00f3 texto\n    container.innerHTML = '';\n    titleEl.innerHTML   = `<span>Link<\/span>&nbsp;<span>Task<\/span>`;\n    subEl.textContent   = 'Painel de Gest\u00e3o de Tarefas';\n    textArea.style.display = '';\n  }\n}\n\n\/\/ =============================================\n\/\/ LOGO MODAL (hover change)\n\/\/ =============================================\nfunction abrirTrocaLogo() {\n  const raw = localStorage.getItem('bpolink_logo');\n  const cfg = raw ? JSON.parse(raw) : { tipo: 'default', p1: 'Link', p2: 'Task', sub: 'Painel de Gest\u00e3o de Tarefas' };\n  logoModalType = cfg.tipo || 'default';\n\n  document.getElementById('modalLogoP1').value  = cfg.p1 || 'Link';\n  document.getElementById('modalLogoP2').value  = cfg.p2 || 'Task';\n  document.getElementById('modalLogoSub').value = cfg.sub || 'Painel de Gest\u00e3o de Tarefas';\n  document.getElementById('modalImgSub').value  = cfg.sub || '';\n\n  atualizarLogoModalUI();\n  document.getElementById('logoModalOverlay').classList.add('active');\n}\n\nfunction selecionarTipoLogoModal(tipo) {\n  logoModalType = tipo;\n  atualizarLogoModalUI();\n}\n\nfunction atualizarLogoModalUI() {\n  ['text','image','default'].forEach(t => {\n    const el = document.getElementById('logoOpt' + t.charAt(0).toUpperCase() + t.slice(1));\n    if (el) el.classList.toggle('selected', t === logoModalType);\n  });\n  document.getElementById('logoModalTextFields').style.display  = logoModalType === 'text'  ? '' : 'none';\n  document.getElementById('logoModalImageField').style.display  = logoModalType === 'image' ? '' : 'none';\n}\n\nfunction carregarImagemLogoModal(input) {\n  const file = input.files[0];\n  if (!file) return;\n  if (file.size > 2 * 1024 * 1024) { mostrarToast('Imagem muito grande (m\u00e1x 2MB)', 'error'); return; }\n  const reader = new FileReader();\n  reader.onload = e => {\n    const raw = localStorage.getItem('bpolink_logo');\n    const cfg = raw ? JSON.parse(raw) : {};\n    cfg.imageData = e.target.result;\n    localStorage.setItem('bpolink_logo', JSON.stringify(cfg));\n    mostrarToast('Imagem carregada!', 'success');\n  };\n  reader.readAsDataURL(file);\n}\n\nfunction salvarLogoModal() {\n  const raw = localStorage.getItem('bpolink_logo');\n  const existing = raw ? JSON.parse(raw) : {};\n  const cfg = {\n    tipo: logoModalType,\n    p1: document.getElementById('modalLogoP1').value || 'Link',\n    p2: document.getElementById('modalLogoP2').value || 'Task',\n    sub: logoModalType === 'image'\n         ? document.getElementById('modalImgSub').value\n         : document.getElementById('modalLogoSub').value,\n    imageData: existing.imageData || null\n  };\n  localStorage.setItem('bpolink_logo', JSON.stringify(cfg));\n  fecharLogoModal();\n  aplicarLogo(cfg);\n  mostrarToast('Logo atualizado!', 'success');\n}\n\nfunction fecharLogoModal() {\n  document.getElementById('logoModalOverlay').classList.remove('active');\n}\n\ndocument.getElementById('logoModalOverlay').addEventListener('click', function(e) {\n  if (e.target === this) fecharLogoModal();\n});\n\n\/\/ =============================================\n\/\/ TABS \u2014 drag to reorder\n\/\/ =============================================\nlet dragSrcTab = null;\n\nfunction renderizarTabs() {\n  const container = document.getElementById('tabsContainer');\n  const firstActive = tabOrder[0];\n\n  container.innerHTML = tabOrder.map(id => {\n    const def = TAB_DEFAULTS.find(t => t.id === id);\n    if (!def) return '';\n    const badgeHtml = def.badge ? `<span class=\"tab-badge\" id=\"${def.badge}\">0<\/span>` : '';\n    return `<button class=\"tab-btn${id === firstActive ? ' active' : ''}\" \n      data-tab=\"${id}\"\n      draggable=\"true\"\n      onclick=\"ativarTab('${id}', this)\"\n      ondragstart=\"onTabDragStart(event, this)\"\n      ondragover=\"onTabDragOver(event, this)\"\n      ondragleave=\"onTabDragLeave(event, this)\"\n      ondrop=\"onTabDrop(event, this)\"\n      ondragend=\"onTabDragEnd(event)\"\n      title=\"Arraste para reordenar\">\n      ${def.label}${badgeHtml}\n    <\/button>`;\n  }).join('') + `<div class=\"tab-drag-hint\">\u283f arraste para reordenar<\/div>`;\n\n  \/\/ activate first tab panel\n  document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));\n  const firstPanel = document.getElementById('tab-' + firstActive);\n  if (firstPanel) firstPanel.classList.add('active');\n}\n\nfunction onTabDragStart(e, el) {\n  dragSrcTab = el;\n  el.classList.add('dragging');\n  e.dataTransfer.effectAllowed = 'move';\n  e.dataTransfer.setData('text\/plain', el.dataset.tab);\n}\nfunction onTabDragOver(e, el) {\n  e.preventDefault();\n  e.dataTransfer.dropEffect = 'move';\n  if (el !== dragSrcTab && el.classList.contains('tab-btn')) el.classList.add('drag-over');\n}\nfunction onTabDragLeave(e, el) { el.classList.remove('drag-over'); }\nfunction onTabDrop(e, el) {\n  e.preventDefault();\n  if (el === dragSrcTab || !el.classList.contains('tab-btn')) return;\n  el.classList.remove('drag-over');\n  const srcId  = dragSrcTab.dataset.tab;\n  const dstId  = el.dataset.tab;\n  const si = tabOrder.indexOf(srcId);\n  const di = tabOrder.indexOf(dstId);\n  if (si < 0 || di < 0) return;\n  tabOrder.splice(si, 1);\n  tabOrder.splice(di, 0, srcId);\n  localStorage.setItem('bpolink_tabs', JSON.stringify(tabOrder));\n  renderizarTabs();\n  atualizarBadgesTabs();\n  mostrarToast('Ordem das abas salva!', 'info');\n}\nfunction onTabDragEnd(e) {\n  document.querySelectorAll('.tab-btn').forEach(b => { b.classList.remove('dragging'); b.classList.remove('drag-over'); });\n  dragSrcTab = null;\n}\n\nfunction ativarTab(id, btn) {\n  document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));\n  document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));\n  const panel = document.getElementById('tab-' + id);\n  if (panel) panel.classList.add('active');\n  if (btn) btn.classList.add('active');\n  if (id === 'kanban')    { popularFiltrosKanban(); renderizarKanban(); aplicarFiltrosKanban(); }\n  if (id === 'relatorios') { popularFiltrosRelat(); renderizarRelatorios(); }\n  if (id === 'dashboard') { renderizarDashboard(); renderizarChartsGlobais(); }\n  if (id === 'bi')        { renderizarChartsBI(); renderizarBIKpis(); }\n}\n\nfunction irParaNova() {\n  const btn = document.querySelector('[data-tab=\"nova\"]');\n  ativarTab('nova', btn);\n}\n\n\/\/ =============================================\n\/\/ URL & CONEX\u00c3O\n\/\/ =============================================\nfunction salvarUrl(val) { APPS_SCRIPT_URL = val.trim(); localStorage.setItem('bpolink_url', APPS_SCRIPT_URL); }\n\nasync function testarConexao() {\n  if (!APPS_SCRIPT_URL) { mostrarToast('Cole a URL do Apps Script primeiro', 'error'); return; }\n  atualizarStatus('loading');\n  try {\n    const data = await gasGet_('health');\n    if (data.ok) {\n      estado.modoIntegracao = true;\n      atualizarStatus('online');\n      mostrarToast('Conectado ao Google Sheets!', 'success');\n      await carregarTarefas();\n    } else throw new Error(data.message || 'Resposta inv\u00e1lida');\n  } catch(e) { atualizarStatus('offline'); estado.modoIntegracao = false; mostrarToast('Erro: ' + e.message, 'error'); }\n}\n\nfunction atualizarStatus(modo) {\n  const pill  = document.getElementById('statusPill');\n  const label = document.getElementById('statusLabel');\n  pill.className = 'status-pill';\n  if (modo === 'online')  { pill.classList.add('online');  label.textContent = 'Online'; }\n  if (modo === 'offline') { pill.classList.add('offline'); label.textContent = 'Offline'; }\n  if (modo === 'local')   { pill.classList.add('local');   label.textContent = 'Modo Local'; }\n  if (modo === 'loading') { label.textContent = 'Conectando...'; }\n}\n\n\/\/ =============================================\n\/\/ DADOS\n\/\/ =============================================\nasync function carregarTarefas() {\n  estado.carregando = true;\n  if (APPS_SCRIPT_URL && estado.modoIntegracao) {\n    try {\n      const data = await gasGet_('listTasks');\n      if (data.ok) { estado.tarefas = data.data || []; atualizarStatus('online'); }\n      else throw new Error(data.message);\n    } catch(e) { mostrarToast('Erro ao carregar: ' + e.message, 'error'); atualizarStatus('offline'); carregarDadosDemo(); }\n  } else { carregarDadosDemo(); }\n  estado.carregando = false;\n  aplicarFiltros();\n  atualizarBadgesTabs();\n  renderizarDashboard();\n  renderizarChartsGlobais();\n  popularFiltrosDinamicos();\n  popularFiltrosKanban();\n  atualizarValoresBiDimensao();\n  renderizarBIKpis();\n  renderizarChartsBI();\n}\n\nfunction carregarDadosDemo() {\n  atualizarStatus('local');\n  const hoje  = new Date().toISOString().split('T')[0];\n  const ontem = new Date(Date.now()-86400000).toISOString().split('T')[0];\n  const ante  = new Date(Date.now()-172800000).toISOString().split('T')[0];\n  estado.tarefas = [\n    { id:'T001',setor:'TI',sprint:'Sprint 1',titulo:'Configurar ambiente Docker',responsavel:'Carlos Silva',prioridade:'Alta',status:'Em Andamento',tipo:'Task',storyPoints:5,prazo:hoje,descricao:'Criar containers Docker.',tags:'docker,infra',impedimento:'',criadoEm:ontem,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'docker-compose up funciona' },\n    { id:'T002',setor:'Comercial',sprint:'Sprint 1',titulo:'Atualizar proposta comercial V2',responsavel:'Ana Paula',prioridade:'Cr\u00edtica',status:'A Fazer',tipo:'Demanda',storyPoints:3,prazo:hoje,descricao:'Revis\u00e3o da proposta.',tags:'comercial,proposta',impedimento:'',criadoEm:ontem,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T003',setor:'Marketing',sprint:'Sprint 1',titulo:'Campanha de Lan\u00e7amento Q2',responsavel:'Beatriz Lopes',prioridade:'Alta',status:'Em Revis\u00e3o',tipo:'Demanda',storyPoints:8,prazo:ante,descricao:'Campanha completa.',tags:'marketing,campanha',impedimento:'Aguardando aprova\u00e7\u00e3o.',criadoEm:ante,atualizadoEm:ontem,dataConclusao:'',criterioAceite:'Materiais aprovados' },\n    { id:'T004',setor:'TI',sprint:'Sprint 1',titulo:'Corrigir bug de autentica\u00e7\u00e3o',responsavel:'Carlos Silva',prioridade:'Cr\u00edtica',status:'Conclu\u00eddo',tipo:'Corre\u00e7\u00e3o',storyPoints:2,prazo:ante,descricao:'Login falhando em mobile.',tags:'bug,auth',impedimento:'',criadoEm:ante,atualizadoEm:ontem,dataConclusao:ontem,criterioAceite:'Login funcionando' },\n    { id:'T005',setor:'RH',sprint:'Sprint 2',titulo:'Onboarding novo colaborador',responsavel:'Fernanda Costa',prioridade:'M\u00e9dia',status:'A Fazer',tipo:'Task',storyPoints:3,prazo:'',descricao:'Processo de integra\u00e7\u00e3o.',tags:'rh,onboarding',impedimento:'',criadoEm:ontem,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T006',setor:'Financeiro',sprint:'Sprint 2',titulo:'Fechar DRE do m\u00eas',responsavel:'Ricardo Mendes',prioridade:'Alta',status:'Backlog',tipo:'Task',storyPoints:5,prazo:'',descricao:'Demonstra\u00e7\u00e3o de resultado.',tags:'financeiro,dre',impedimento:'Aguardando dados.',criadoEm:hoje,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T007',setor:'TI',sprint:'Sprint 2',titulo:'Migrar banco para PostgreSQL',responsavel:'Pedro Alves',prioridade:'Alta',status:'Backlog',tipo:'Melhoria',storyPoints:13,prazo:'',descricao:'Migra\u00e7\u00e3o de MySQL.',tags:'banco,infra',impedimento:'',criadoEm:hoje,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T008',setor:'Comercial',sprint:'Sprint 2',titulo:'Pipeline de vendas Q2',responsavel:'Ana Paula',prioridade:'Alta',status:'Em Andamento',tipo:'Demanda',storyPoints:5,prazo:hoje,descricao:'Estruturar funil.',tags:'comercial,pipeline',impedimento:'',criadoEm:ante,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T009',setor:'Marketing',sprint:'Sprint 2',titulo:'Redesign do site institucional',responsavel:'Beatriz Lopes',prioridade:'M\u00e9dia',status:'A Fazer',tipo:'Melhoria',storyPoints:8,prazo:'',descricao:'Novo layout.',tags:'marketing,design',impedimento:'',criadoEm:hoje,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T010',setor:'TI',sprint:'Sprint 1',titulo:'API de integra\u00e7\u00e3o Sheets',responsavel:'Pedro Alves',prioridade:'Alta',status:'Conclu\u00eddo',tipo:'Task',storyPoints:8,prazo:ante,descricao:'Integra\u00e7\u00e3o Google.',tags:'api,sheets',impedimento:'',criadoEm:ante,atualizadoEm:ontem,dataConclusao:ontem,criterioAceite:'CRUD funcionando' },\n    { id:'T011',setor:'Operacoes',sprint:'Sprint 2',titulo:'Mapeamento de processos BPO',responsavel:'Marcos Dias',prioridade:'M\u00e9dia',status:'Em Andamento',tipo:'Task',storyPoints:5,prazo:'',descricao:'Documentar fluxos.',tags:'processos,bpo',impedimento:'',criadoEm:ontem,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n    { id:'T012',setor:'Administracao',sprint:'Sprint 2',titulo:'Renova\u00e7\u00e3o de contratos fornecedores',responsavel:'Julia Santos',prioridade:'Baixa',status:'Backlog',tipo:'Task',storyPoints:2,prazo:'',descricao:'Revisar contratos.',tags:'admin,contratos',impedimento:'',criadoEm:hoje,atualizadoEm:hoje,dataConclusao:'',criterioAceite:'' },\n  ];\n}\n\n\/\/ =============================================\n\/\/ CRUD\n\/\/ =============================================\nasync function salvarTarefa() {\n  const campos = ['fSetor','fSprint','fResponsavel','fPrioridade','fStatus','fTipo','fTitulo'];\n  for (const id of campos) {\n    if (!document.getElementById(id).value) { mostrarToast('Preencha todos os campos obrigat\u00f3rios', 'error'); return; }\n  }\n  const tarefa = {\n    id:           estado.tarefaEmEdicao?.id || gerarId(),\n    setor:        document.getElementById('fSetor').value,\n    sprint:       document.getElementById('fSprint').value.trim(),\n    responsavel:  document.getElementById('fResponsavel').value.trim(),\n    prioridade:   document.getElementById('fPrioridade').value,\n    status:       document.getElementById('fStatus').value,\n    tipo:         document.getElementById('fTipo').value,\n    titulo:       document.getElementById('fTitulo').value.trim(),\n    storyPoints:  parseInt(document.getElementById('fStoryPoints').value) || 0,\n    prazo:        document.getElementById('fPrazo').value,\n    dataConclusao:document.getElementById('fDataConclusao').value,\n    tags:         document.getElementById('fTags').value.trim(),\n    descricao:    document.getElementById('fDescricao').value.trim(),\n    impedimento:  document.getElementById('fImpedimento').value.trim(),\n    criterioAceite: document.getElementById('fCriterioAceite').value.trim(),\n    criadoEm:     estado.tarefaEmEdicao?.criadoEm || new Date().toISOString().split('T')[0],\n    atualizadoEm: new Date().toISOString().split('T')[0]\n  };\n\n  const btn = document.getElementById('submitBtn');\n  btn.disabled = true;\n  btn.innerHTML = '<span class=\"spinner\"><\/span> Salvando...';\n\n  if (APPS_SCRIPT_URL && estado.modoIntegracao) {\n    try {\n      const action = estado.tarefaEmEdicao ? 'updateTask' : 'createTask';\n      \/\/ \u2705 Tudo via GET \u2014 nunca dispara CORS preflight\n      const data = await gasGet_(action, { tarefa });\n      if (!data.ok) throw new Error(data.message);\n    } catch(e) { mostrarToast('Erro ao salvar: ' + e.message, 'error'); btn.disabled = false; btn.innerHTML = '\u2713 ' + (estado.tarefaEmEdicao ? 'Atualizar' : 'Criar') + ' Tarefa'; return; }\n  }\n\n  if (estado.tarefaEmEdicao) {\n    const idx = estado.tarefas.findIndex(t => t.id === tarefa.id);\n    if (idx >= 0) estado.tarefas[idx] = tarefa;\n    mostrarToast('Tarefa atualizada!', 'success');\n  } else {\n    estado.tarefas.unshift(tarefa);\n    mostrarToast('Tarefa criada!', 'success');\n  }\n\n  resetarFormulario();\n  aplicarFiltros();\n  renderizarDashboard();\n  renderizarChartsGlobais();\n  renderizarBIKpis();\n  renderizarChartsBI();\n  atualizarBadgesTabs();\n  popularFiltrosDinamicos();\n  btn.disabled = false;\n  btn.innerHTML = '\u2713 Criar Tarefa';\n}\n\nfunction editarTarefa(id) {\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t) return;\n  estado.tarefaEmEdicao = t;\n  document.getElementById('fSetor').value        = t.setor;\n  document.getElementById('fSprint').value       = t.sprint;\n  document.getElementById('fResponsavel').value  = t.responsavel;\n  document.getElementById('fPrioridade').value   = t.prioridade;\n  document.getElementById('fStatus').value       = t.status;\n  document.getElementById('fTipo').value         = t.tipo;\n  document.getElementById('fTitulo').value       = t.titulo;\n  document.getElementById('fStoryPoints').value  = t.storyPoints || '';\n  document.getElementById('fPrazo').value        = t.prazo || '';\n  document.getElementById('fDataConclusao').value= t.dataConclusao || '';\n  document.getElementById('fTags').value         = t.tags || '';\n  document.getElementById('fDescricao').value    = t.descricao || '';\n  document.getElementById('fImpedimento').value  = t.impedimento || '';\n  document.getElementById('fCriterioAceite').value = t.criterioAceite || '';\n  document.getElementById('formTitle').innerHTML = '\u270f\ufe0f Editando: ' + esc(t.titulo.substring(0,40));\n  document.getElementById('submitBtn').innerHTML = '\u2713 Atualizar Tarefa';\n  document.getElementById('cancelarEdicaoBtn').style.display = '';\n  const btn = document.querySelector('[data-tab=\"nova\"]');\n  ativarTab('nova', btn);\n}\n\nfunction cancelarEdicao() {\n  estado.tarefaEmEdicao = null;\n  resetarFormulario();\n}\n\nfunction resetarFormulario() {\n  estado.tarefaEmEdicao = null;\n  document.getElementById('taskForm').reset();\n  document.getElementById('formTitle').innerHTML = '\u2795 Nova Tarefa';\n  document.getElementById('submitBtn').innerHTML = '\u2713 Criar Tarefa';\n  document.getElementById('cancelarEdicaoBtn').style.display = 'none';\n}\n\nfunction excluirTarefa(id) {\n  abrirModal('Excluir tarefa', 'Tem certeza? Esta a\u00e7\u00e3o n\u00e3o pode ser desfeita.', async () => {\n    if (APPS_SCRIPT_URL && estado.modoIntegracao) {\n      try {\n        const data = await gasGet_('deleteTask', { id });\n        if (!data.ok) throw new Error(data.message);\n      } catch(e) { mostrarToast('Erro ao excluir: ' + e.message, 'error'); return; }\n    }\n    estado.tarefas = estado.tarefas.filter(t => t.id !== id);\n    aplicarFiltros();\n    renderizarDashboard();\n    renderizarChartsGlobais();\n    atualizarBadgesTabs();\n    mostrarToast('Tarefa exclu\u00edda', 'success');\n  });\n}\n\nasync function duplicarTarefa(id) {\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t) return;\n  const nova = { ...t, id: gerarId(), titulo: '[C\u00f3pia] ' + t.titulo, status: 'Backlog', criadoEm: new Date().toISOString().split('T')[0], dataConclusao: '' };\n\n  if (APPS_SCRIPT_URL && estado.modoIntegracao) {\n    try {\n      const data = await gasGet_('duplicateTask', { id });\n      if (!data.ok) throw new Error(data.message);\n      if (data.data?.id) nova.id = data.data.id;\n    } catch(e) {\n      mostrarToast('Erro ao duplicar: ' + e.message, 'error');\n      return;\n    }\n  }\n\n  estado.tarefas.unshift(nova);\n  aplicarFiltros(); renderizarDashboard(); renderizarChartsGlobais(); atualizarBadgesTabs();\n  mostrarToast('Tarefa duplicada', 'success');\n}\n\nasync function avancarStatus(id) {\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t) return;\n  const idx = STATUS_ORDEM.indexOf(t.status);\n  if (idx >= STATUS_ORDEM.length - 1) return;\n  t.status = STATUS_ORDEM[idx + 1];\n  t.atualizadoEm = new Date().toISOString().split('T')[0];\n  await sincronizarTarefa_(t);\n  aplicarFiltros(); renderizarDashboard(); renderizarChartsGlobais(); atualizarBadgesTabs();\n}\n\nasync function voltarStatus(id) {\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t) return;\n  const idx = STATUS_ORDEM.indexOf(t.status);\n  if (idx <= 0) return;\n  t.status = STATUS_ORDEM[idx - 1];\n  t.atualizadoEm = new Date().toISOString().split('T')[0];\n  await sincronizarTarefa_(t);\n  aplicarFiltros(); renderizarDashboard(); renderizarChartsGlobais(); atualizarBadgesTabs();\n}\n\nasync function concluirTarefa(id) {\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t) return;\n  t.status = 'Conclu\u00eddo';\n  t.dataConclusao = new Date().toISOString().split('T')[0];\n  t.atualizadoEm  = new Date().toISOString().split('T')[0];\n  await sincronizarTarefa_(t);\n  aplicarFiltros(); renderizarDashboard(); renderizarChartsGlobais(); atualizarBadgesTabs();\n  mostrarToast('Tarefa conclu\u00edda! \u2713', 'success');\n}\n\n\/\/ \u2500\u2500\u2500 Helper central: todas as chamadas ao Apps Script via GET \u2500\u2500\u2500\n\/\/ GET nunca dispara CORS preflight \u2014 solu\u00e7\u00e3o definitiva para Apps Script\nasync function gasGet_(action, params = {}) {\n  \/\/ Inclui o credential Google para valida\u00e7\u00e3o no servidor\n  const requestBody = { action, ...params };\n  if (authCredential) requestBody.credential = authCredential;\n\n  const payload = encodeURIComponent(JSON.stringify(requestBody));\n  const url = `${APPS_SCRIPT_URL}?payload=${payload}`;\n  const resp = await fetch(url, { redirect: 'follow' });\n  const text = await resp.text();\n  try {\n    const data = JSON.parse(text);\n    \/\/ Se servidor retornar 401, pede novo login\n    if (data.code === 401) {\n      mostrarToast('Sess\u00e3o expirada. Fa\u00e7a login novamente.', 'error');\n      setTimeout(logout, 1500);\n      throw new Error('N\u00e3o autorizado');\n    }\n    return data;\n  } catch(e) {\n    if (e.message === 'N\u00e3o autorizado') throw e;\n    throw new Error('Resposta inv\u00e1lida: ' + text.substring(0, 120));\n  }\n}\n\n\/\/ \u2500\u2500\u2500 Helper: envia updateTask ao backend \u2500\u2500\u2500\nasync function sincronizarTarefa_(tarefa) {\n  if (!APPS_SCRIPT_URL || !estado.modoIntegracao) return;\n  try {\n    const data = await gasGet_('updateTask', { tarefa });\n    if (!data.ok) throw new Error(data.message);\n  } catch(e) {\n    mostrarToast('Sync: ' + e.message, 'error');\n  }\n}\n\n\/\/ =============================================\n\/\/ FILTROS\n\/\/ =============================================\nfunction popularFiltrosSetor() {\n  const sel = document.getElementById('filtSetor');\n  SETORES.forEach(s => { const o = document.createElement('option'); o.value = s; o.textContent = s; sel.appendChild(o); });\n}\n\nfunction popularFiltrosDinamicos() {\n  const sprints = [...new Set(estado.tarefas.map(t => t.sprint).filter(Boolean))].sort();\n  const selSprint = document.getElementById('filtSprint');\n  const valSprint = selSprint.value;\n  selSprint.innerHTML = '<option value=\"\">Todas as sprints<\/option>';\n  sprints.forEach(s => { const o = document.createElement('option'); o.value = s; o.textContent = s; selSprint.appendChild(o); });\n  if (valSprint) selSprint.value = valSprint;\n\n  const resps = [...new Set(estado.tarefas.map(t => t.responsavel).filter(Boolean))].sort();\n  const selResp = document.getElementById('filtResponsavel');\n  const valResp = selResp.value;\n  selResp.innerHTML = '<option value=\"\">Todos<\/option>';\n  resps.forEach(r => { const o = document.createElement('option'); o.value = r; o.textContent = r; selResp.appendChild(o); });\n  if (valResp) selResp.value = valResp;\n}\n\nfunction ativarFTab(tab) {\n  document.getElementById('ftabPainelFiltrar').style.display = tab==='filtrar'?'':'none';\n  document.getElementById('ftabPainelOrdenar').style.display = tab==='ordenar'?'':'none';\n  document.getElementById('ftabFiltrar').classList.toggle('ftab-active', tab==='filtrar');\n  document.getElementById('ftabOrdenar').classList.toggle('ftab-active', tab==='ordenar');\n  document.getElementById('ftabLimparBtn').textContent = tab==='filtrar'?'Limpar tudo':'Remover ordem';\n  document.getElementById('ftabLimparBtn').onclick = tab==='filtrar' ? ()=>limparFiltros() : ()=>{document.getElementById('sortCampo').value='';aplicarFiltros();};\n}\n\nfunction aplicarFiltros() {\n  const busca       = document.getElementById('filtBusca')?.value?.toLowerCase() || '';\n  const setor       = document.getElementById('filtSetor')?.value || '';\n  const sprint      = document.getElementById('filtSprint')?.value || '';\n  const status      = document.getElementById('filtStatus')?.value || '';\n  const prioridade  = document.getElementById('filtPrioridade')?.value || '';\n  const responsavel = document.getElementById('filtResponsavel')?.value || '';\n  const tipo        = document.getElementById('filtTipo')?.value || '';\n  const soVencidas  = document.getElementById('filtVencidas')?.checked || false;\n  const soImpedimento = document.getElementById('filtImpedimento')?.checked || false;\n  const soConcluidas  = document.getElementById('filtConcluidas')?.checked || false;\n  const hoje = new Date().toISOString().split('T')[0];\n\n  estado.tarefasFiltradas = estado.tarefas.filter(t => {\n    if (busca && !(t.titulo?.toLowerCase().includes(busca) || t.descricao?.toLowerCase().includes(busca) || t.responsavel?.toLowerCase().includes(busca) || t.tags?.toLowerCase().includes(busca))) return false;\n    if (setor       && t.setor      !== setor)       return false;\n    if (sprint      && t.sprint     !== sprint)       return false;\n    if (status      && t.status     !== status)       return false;\n    if (prioridade  && t.prioridade !== prioridade)   return false;\n    if (responsavel && t.responsavel!== responsavel)  return false;\n    if (tipo        && t.tipo       !== tipo)         return false;\n    if (soVencidas   && !(t.prazo && t.prazo < hoje && t.status !== 'Conclu\u00eddo')) return false;\n    if (soImpedimento && !t.impedimento) return false;\n    if (soConcluidas  && t.status !== 'Conclu\u00eddo')    return false;\n    return true;\n  });\n\n  \/\/ Ordena\u00e7\u00e3o\n  const _sc = document.getElementById('sortCampo')?.value || '';\n  if (_sc) {\n    const _po = {'Cr\u00edtica':0,'Alta':1,'M\u00e9dia':2,'Baixa':3};\n    estado.tarefasFiltradas.sort((a,b) => {\n      if(_sc==='titulo') return (a.titulo||'').localeCompare(b.titulo||'','pt-BR');\n      if(_sc==='titulo_desc') return (b.titulo||'').localeCompare(a.titulo||'','pt-BR');\n      if(_sc==='prioridade') return (_po[a.prioridade]??9)-(_po[b.prioridade]??9);\n      if(_sc==='prioridade_asc') return (_po[b.prioridade]??9)-(_po[a.prioridade]??9);\n      if(_sc==='status') return STATUS_ORDEM.indexOf(a.status)-STATUS_ORDEM.indexOf(b.status);\n      if(_sc==='storyPoints') return (Number(b.storyPoints)||0)-(Number(a.storyPoints)||0);\n      if(_sc==='storyPoints_asc') return (Number(a.storyPoints)||0)-(Number(b.storyPoints)||0);\n      if(_sc==='prazo') return (a.prazo||'9999').localeCompare(b.prazo||'9999');\n      if(_sc==='prazo_desc') return (b.prazo||'0000').localeCompare(a.prazo||'0000');\n      if(_sc==='responsavel') return (a.responsavel||'').localeCompare(b.responsavel||'','pt-BR');\n      if(_sc==='setor') return (a.setor||'').localeCompare(b.setor||'','pt-BR');\n      if(_sc==='sprint') return (a.sprint||'').localeCompare(b.sprint||'','pt-BR');\n      if(_sc==='criadoEm') return new Date(b.criadoEm||0)-new Date(a.criadoEm||0);\n      if(_sc==='criadoEm_asc') return new Date(a.criadoEm||0)-new Date(b.criadoEm||0);\n      if(_sc==='dataConclusao') return (b.dataConclusao||'0').localeCompare(a.dataConclusao||'0');\n      return 0;\n    });\n  }\n  const _labels = {titulo:'T\u00edtulo A\u2192Z',titulo_desc:'T\u00edtulo Z\u2192A',prioridade:'Prioridade',prioridade_asc:'Prioridade \u2191',status:'Status',storyPoints:'Pontos (maior)',storyPoints_asc:'Pontos (menor)',prazo:'Data Inicial',prazo_desc:'Data Inicial \u2193',responsavel:'Respons\u00e1vel',setor:'Setor',sprint:'Sprint',criadoEm:'Cria\u00e7\u00e3o (rec)',criadoEm_asc:'Cria\u00e7\u00e3o (ant)',dataConclusao:'Conclus\u00e3o (rec)'};\n  const _indEl=document.getElementById('sortIndicador'), _indTxt=document.getElementById('sortIndicadorTxt');\n  if(_indEl&&_indTxt){if(_sc){_indEl.style.display='';_indTxt.textContent=_labels[_sc]||_sc;}else _indEl.style.display='none';}\n\n  renderizarCards();\n  renderizarKanban();\n  atualizarChipsAtivos();\n\n  const sprintEl = document.getElementById('sprintDisplay');\n  if (sprintEl) sprintEl.textContent = sprint || 'Todas';\n  const countEl = document.getElementById('countDisplay');\n  if (countEl) countEl.textContent = `${estado.tarefasFiltradas.length} tarefa${estado.tarefasFiltradas.length !== 1 ? 's' : ''}`;\n}\n\nfunction atualizarChipsAtivos() {\n  const container = document.getElementById('activeFilterChips');\n  if (!container) return;\n  const chips = [];\n  const add = (id, label, val) => { if (val) chips.push({ id, label: `${label}: ${val}` }); };\n  add('filtSetor',       'Setor',       document.getElementById('filtSetor')?.value);\n  add('filtSprint',      'Sprint',      document.getElementById('filtSprint')?.value);\n  add('filtStatus',      'Status',      document.getElementById('filtStatus')?.value);\n  add('filtPrioridade',  'Prioridade',  document.getElementById('filtPrioridade')?.value);\n  add('filtResponsavel', 'Respons\u00e1vel', document.getElementById('filtResponsavel')?.value);\n  add('filtTipo',        'Tipo',        document.getElementById('filtTipo')?.value);\n  const busca = document.getElementById('filtBusca')?.value;\n  if (busca) chips.push({ id:'filtBusca', label:`Busca: \"${busca}\"` });\n  if (document.getElementById('filtVencidas')?.checked)    chips.push({ id:'filtVencidas', label:'Apenas vencidas' });\n  if (document.getElementById('filtImpedimento')?.checked) chips.push({ id:'filtImpedimento', label:'Com impedimento' });\n  if (document.getElementById('filtConcluidas')?.checked)  chips.push({ id:'filtConcluidas', label:'Apenas conclu\u00eddas' });\n\n  container.innerHTML = chips.map(c =>\n    `<div class=\"filter-chip\">${esc(c.label)}<span class=\"filter-chip-remove\" onclick=\"removerChip('${c.id}')\">\u2715<\/span><\/div>`\n  ).join('');\n}\n\nfunction removerChip(id) {\n  const el = document.getElementById(id);\n  if (!el) return;\n  if (el.type === 'checkbox') el.checked = false;\n  else el.value = '';\n  aplicarFiltros();\n}\n\nfunction limparFiltros() {\n  ['filtBusca','filtSetor','filtSprint','filtStatus','filtPrioridade','filtResponsavel','filtTipo'].forEach(id => { const el = document.getElementById(id); if(el) el.value = ''; });\n  ['filtVencidas','filtImpedimento','filtConcluidas'].forEach(id => { const el = document.getElementById(id); if(el) el.checked = false; });\n  aplicarFiltros();\n}\n\n\/\/ =============================================\n\/\/ RENDER CARDS\n\/\/ =============================================\nfunction renderizarCards() {\n  const grid = document.getElementById('cardsGrid');\n  if (!grid) return;\n  if (!estado.tarefasFiltradas.length) {\n    grid.innerHTML = `<div class=\"empty-state\" style=\"grid-column:1\/-1\"><div class=\"empty-state-icon\">\ud83d\udd0d<\/div><div class=\"empty-state-text\">Nenhuma tarefa encontrada<\/div><div class=\"empty-state-sub\">Ajuste os filtros ou crie uma nova tarefa.<\/div><\/div>`;\n    return;\n  }\n  grid.innerHTML = estado.tarefasFiltradas.map(t => criarCardHTML(t)).join('');\n}\n\nfunction criarCardHTML(t) {\n  const hoje = new Date().toISOString().split('T')[0];\n  const isVencida   = t.prazo && t.prazo < hoje && t.status !== 'Conclu\u00eddo';\n  const isImpedido  = !!t.impedimento;\n  const isConcluida = t.status === 'Conclu\u00eddo';\n  const statusSlug  = STATUS_SLUG[t.status] || 'backlog';\n  const prioSlug    = (t.prioridade || '').toLowerCase().replace('\u00e9','e');\n  const tipoSlug    = (t.tipo || '').toLowerCase();\n  const tags = (t.tags || '').split(',').map(x => x.trim()).filter(Boolean);\n  const tagsHtml = tags.length ? `<div class=\"task-tags\">${tags.map(tg => `<span class=\"tag\">${esc(tg)}<\/span>`).join('')}<\/div>` : '';\n  const idxStatus = STATUS_ORDEM.indexOf(t.status);\n  return `<div class=\"task-card${isVencida?' vencida':''}${isImpedido?' impedimento':''}${isConcluida?' concluida':''}\" id=\"card-${t.id}\">\n    <div class=\"task-card-header\"><div class=\"task-title\">${esc(t.titulo)}<\/div><span class=\"task-id\">${esc(t.id)}<\/span><\/div>\n    <div class=\"task-meta\"><span class=\"badge badge-${statusSlug}\">${esc(t.status)}<\/span><span class=\"badge badge-${prioSlug}\">${esc(t.prioridade)}<\/span><span class=\"badge badge-${tipoSlug}\">${esc(t.tipo)}<\/span><\/div>\n    <div class=\"task-info-row\">\n      <div class=\"task-info-item\">\ud83d\udc64 ${esc(t.responsavel)}<\/div>\n      <div class=\"task-info-item\">\ud83c\udfe2 ${esc(t.setor)}<\/div>\n      <div class=\"task-info-item\">\ud83c\udfc3 ${esc(t.sprint)}<\/div>\n      ${t.storyPoints > 0 ? `<div class=\"task-info-item\">\u26a1 ${t.storyPoints} pts<\/div>` : ''}\n      ${t.prazo && !isVencida ? `<div class=\"task-info-item\">\ud83d\udcc5 In\u00edcio: ${formatarData(t.prazo)}<\/div>` : ''}\n      ${isConcluida && t.dataConclusao ? `<div class=\"task-info-item\" style=\"color:var(--green)\">\u2713 ${formatarData(t.dataConclusao)}<\/div>` : ''}\n    <\/div>\n    ${isVencida ? `<div class=\"task-prazo-alert\">\ud83d\udd34 Data inicial: ${formatarData(t.prazo)}<\/div>` : ''}\n    ${isImpedido ? `<div class=\"task-impedimento-alert\">\u26a0\ufe0f <span>${esc(t.impedimento.substring(0,80))}${t.impedimento.length>80?'...':''}<\/span><\/div>` : ''}\n    ${tagsHtml}\n    <div class=\"task-actions\">\n      <button class=\"btn btn-outline btn-sm btn-icon\" title=\"Editar\" onclick=\"editarTarefa('${t.id}')\">\u270f\ufe0f<\/button>\n      <button class=\"btn btn-outline btn-sm btn-icon\" title=\"Duplicar\" onclick=\"duplicarTarefa('${t.id}')\">\u29c9<\/button>\n      <button class=\"btn btn-danger btn-sm btn-icon\" title=\"Excluir\" onclick=\"excluirTarefa('${t.id}')\">\ud83d\uddd1<\/button>\n      ${idxStatus > 0 ? `<button class=\"btn btn-outline btn-sm\" onclick=\"voltarStatus('${t.id}')\">\u2190 Voltar<\/button>` : ''}\n      ${idxStatus < STATUS_ORDEM.length-1 ? `<button class=\"btn btn-primary btn-sm\" onclick=\"avancarStatus('${t.id}')\">Avan\u00e7ar \u2192<\/button>` : ''}\n      ${t.status !== 'Conclu\u00eddo' ? `<button class=\"btn btn-success btn-sm\" onclick=\"concluirTarefa('${t.id}')\">\u2713 Concluir<\/button>` : ''}\n    <\/div><\/div>`;\n}\n\n\/\/ =============================================\n\/\/ KANBAN \u2014 Filtros\n\/\/ =============================================\nfunction popularFiltrosKanban() {\n  \/\/ Setor\n  const selSetor = document.getElementById('kfiltSetor');\n  if (selSetor && selSetor.options.length === 1) {\n    SETORES.forEach(s => { const o = document.createElement('option'); o.value = s; o.textContent = s; selSetor.appendChild(o); });\n  }\n  \/\/ Sprints din\u00e2micas\n  const sprints = [...new Set(estado.tarefas.map(t => t.sprint).filter(Boolean))].sort();\n  const selSprint = document.getElementById('kfiltSprint');\n  if (selSprint) {\n    const val = selSprint.value;\n    selSprint.innerHTML = '<option value=\"\">Todas<\/option>';\n    sprints.forEach(s => { const o = document.createElement('option'); o.value = s; o.textContent = s; selSprint.appendChild(o); });\n    if (val) selSprint.value = val;\n  }\n  \/\/ Respons\u00e1veis din\u00e2micos\n  const resps = [...new Set(estado.tarefas.map(t => t.responsavel).filter(Boolean))].sort();\n  const selResp = document.getElementById('kfiltResponsavel');\n  if (selResp) {\n    const val = selResp.value;\n    selResp.innerHTML = '<option value=\"\">Todos<\/option>';\n    resps.forEach(r => { const o = document.createElement('option'); o.value = r; o.textContent = r; selResp.appendChild(o); });\n    if (val) selResp.value = val;\n  }\n}\n\nfunction getTarefasKanban() {\n  const busca      = document.getElementById('kfiltBusca')?.value?.toLowerCase() || '';\n  const setor      = document.getElementById('kfiltSetor')?.value || '';\n  const sprint     = document.getElementById('kfiltSprint')?.value || '';\n  const prioridade = document.getElementById('kfiltPrioridade')?.value || '';\n  const responsavel= document.getElementById('kfiltResponsavel')?.value || '';\n  const tipo       = document.getElementById('kfiltTipo')?.value || '';\n\n  return estado.tarefas.filter(t => {\n    if (busca && !(t.titulo?.toLowerCase().includes(busca) || t.responsavel?.toLowerCase().includes(busca))) return false;\n    if (setor       && t.setor       !== setor)       return false;\n    if (sprint      && t.sprint      !== sprint)      return false;\n    if (prioridade  && t.prioridade  !== prioridade)  return false;\n    if (responsavel && t.responsavel !== responsavel) return false;\n    if (tipo        && t.tipo        !== tipo)         return false;\n    return true;\n  });\n}\n\nfunction aplicarFiltrosKanban() {\n  atualizarChipsKanban();\n  renderizarKanban();\n  const total = getTarefasKanban().length;\n  const el = document.getElementById('kanbanCountDisplay');\n  if (el) el.textContent = `${total} tarefa${total !== 1 ? 's' : ''}`;\n}\n\nfunction atualizarChipsKanban() {\n  const container = document.getElementById('kanbanActiveChips');\n  if (!container) return;\n  const chips = [];\n  const add = (id, label, val) => { if (val) chips.push({ id, label: `${label}: ${val}` }); };\n  add('kfiltSetor',       'Setor',       document.getElementById('kfiltSetor')?.value);\n  add('kfiltSprint',      'Sprint',      document.getElementById('kfiltSprint')?.value);\n  add('kfiltPrioridade',  'Prioridade',  document.getElementById('kfiltPrioridade')?.value);\n  add('kfiltResponsavel', 'Respons\u00e1vel', document.getElementById('kfiltResponsavel')?.value);\n  add('kfiltTipo',        'Tipo',        document.getElementById('kfiltTipo')?.value);\n  const busca = document.getElementById('kfiltBusca')?.value;\n  if (busca) chips.push({ id: 'kfiltBusca', label: `Busca: \"${busca}\"` });\n  container.innerHTML = chips.map(c =>\n    `<div class=\"filter-chip\">${esc(c.label)}<span class=\"filter-chip-remove\" onclick=\"removerChipKanban('${c.id}')\">\u2715<\/span><\/div>`\n  ).join('');\n}\n\nfunction removerChipKanban(id) {\n  const el = document.getElementById(id);\n  if (el) el.value = '';\n  aplicarFiltrosKanban();\n}\n\nfunction limparFiltrosKanban() {\n  ['kfiltBusca','kfiltSetor','kfiltSprint','kfiltPrioridade','kfiltResponsavel','kfiltTipo']\n    .forEach(id => { const el = document.getElementById(id); if (el) el.value = ''; });\n  aplicarFiltrosKanban();\n}\n\n\/\/ =============================================\n\/\/ KANBAN \u2014 Drag & Drop + Mobile Nav\n\/\/ =============================================\nlet kanbanDragId = null;\nlet kanbanColunaAtiva = 'Em Andamento'; \/\/ coluna padr\u00e3o no mobile\n\nfunction isMobile() { return window.innerWidth <= 768; }\n\nfunction renderizarKanban() {\n  const board = document.getElementById('kanbanBoard');\n  if (!board) return;\n  const tarefasBase = getTarefasKanban();\n  const mobile = isMobile();\n\n  \/\/ Renderiza colunas\n  board.innerHTML = STATUS_ORDEM.map(status => {\n    const slug = STATUS_SLUG[status];\n    const tarefasCol = tarefasBase.filter(t => t.status === status);\n    const isAtiva = status === kanbanColunaAtiva;\n\n    const cards = tarefasCol.map(t => {\n      const prioSlug = (t.prioridade || '').toLowerCase().replace('\u00e9','e');\n      const hoje = new Date().toISOString().split('T')[0];\n      const isVencida = t.prazo && t.prazo < hoje && t.status !== 'Conclu\u00eddo';\n      const idxStatus = STATUS_ORDEM.indexOf(t.status);\n\n      \/\/ Bot\u00f5es de a\u00e7\u00e3o r\u00e1pida para mobile\n      const mobileActions = mobile ? `\n        <div class=\"kanban-card-actions-mobile\">\n          ${idxStatus > 0 ? `<button class=\"kmn-action-btn voltar\" onclick=\"event.stopPropagation();voltarStatus('${t.id}')\">\u2190 Voltar<\/button>` : ''}\n          ${idxStatus < STATUS_ORDEM.length-1 ? `<button class=\"kmn-action-btn avancar\" onclick=\"event.stopPropagation();avancarStatus('${t.id}')\">Avan\u00e7ar \u2192<\/button>` : ''}\n          ${t.status !== 'Conclu\u00eddo' ? `<button class=\"kmn-action-btn concluir\" onclick=\"event.stopPropagation();concluirTarefa('${t.id}')\">\u2713<\/button>` : ''}\n        <\/div>` : '';\n\n      return `<div class=\"kanban-card\"\n          draggable=\"true\"\n          data-id=\"${t.id}\"\n          ondragstart=\"onKanbanDragStart(event,'${t.id}')\"\n          ondragend=\"onKanbanDragEnd(event)\"\n          onclick=\"abrirKanbanPopup('${t.id}', event)\"\n          onmousedown=\"iniciarLongPress('${t.id}')\"\n          onmouseup=\"cancelarLongPress()\"\n          onmouseleave=\"cancelarLongPress()\"\n          ontouchstart=\"iniciarLongPress('${t.id}')\"\n          ontouchend=\"cancelarLongPress()\"\n          ontouchmove=\"cancelarLongPress()\">\n          <div class=\"kanban-card-title\">${esc(t.titulo)}<\/div>\n          <div class=\"kanban-card-meta\">\n            <span class=\"badge badge-${prioSlug}\" style=\"font-size:10px;\">${esc(t.prioridade)}<\/span>\n            <span style=\"font-size:11px;\">\u26a1 ${t.storyPoints||0}<\/span>\n          <\/div>\n          <div style=\"margin-top:6px;font-size:11px;color:var(--text-muted);display:flex;align-items:center;justify-content:space-between;\">\n            <span>\ud83d\udc64 ${esc(t.responsavel)}<\/span>\n            ${isVencida ? `<span style=\"color:var(--red);font-size:10px;\">\ud83d\udd34<\/span>` : ''}\n          <\/div>\n          ${mobileActions}\n        <\/div>`;\n    }).join('');\n\n    const empty = !tarefasCol.length\n      ? `<div style=\"text-align:center;padding:24px 12px;font-size:12px;color:var(--text-muted);line-height:1.6;\">\n           Sem tarefas<br><span style=\"font-size:10px;opacity:.6;\">${mobile ? 'Toque em + Nova Tarefa para adicionar' : 'Arraste cards aqui'}<\/span>\n         <\/div>` : '';\n\n    \/\/ Mobile: mostra s\u00f3 a coluna ativa\n    const mobileHidden = mobile && !isAtiva ? '' : '';\n    const classes = `kanban-col kanban-col-${slug}${mobile && isAtiva ? ' kanban-col-ativo' : ''}`;\n\n    return `<div class=\"${classes}\"\n        data-status=\"${status}\"\n        ondragover=\"onKanbanDragOver(event,this)\"\n        ondragleave=\"onKanbanDragLeave(event,this)\"\n        ondrop=\"onKanbanDrop(event,this,'${status}')\">\n        <div class=\"kanban-col-header\">\n          <div class=\"kanban-col-title\">${status}<\/div>\n          <span class=\"kanban-count\">${tarefasCol.length}<\/span>\n        <\/div>\n        <div class=\"kanban-cards\" id=\"kcards-${slug}\">${cards}${empty}<\/div>\n      <\/div>`;\n  }).join('') + (mobile ? '' :\n    `<div class=\"kanban-drag-hint\" style=\"grid-column:1\/-1;\">\n       \u283f Arraste os cards entre colunas para mudar o status\n     <\/div>`);\n\n  \/\/ Mobile nav\n  const nav = document.getElementById('kanbanMobileNav');\n  if (nav) {\n    if (mobile) {\n      nav.style.display = 'flex';\n      nav.innerHTML = STATUS_ORDEM.map(status => {\n        const slug = STATUS_SLUG[status];\n        const count = tarefasBase.filter(t => t.status === status).length;\n        const isAtiva = status === kanbanColunaAtiva;\n        return `<button class=\"kmn-btn${isAtiva ? ' ativo' : ''}\" onclick=\"mudarColunaKanban('${status}')\">\n          ${status} <span class=\"kmn-count\">${count}<\/span>\n        <\/button>`;\n      }).join('');\n    } else {\n      nav.style.display = 'none';\n    }\n  }\n\n  \/\/ No mobile aplica visibilidade via classe\n  if (mobile) {\n    board.querySelectorAll('.kanban-col').forEach(col => {\n      col.style.display = col.dataset.status === kanbanColunaAtiva ? 'block' : 'none';\n    });\n  }\n}\n\nfunction mudarColunaKanban(status) {\n  kanbanColunaAtiva = status;\n  renderizarKanban();\n}\n\nfunction onKanbanDragStart(e, id) {\n  kanbanDragId = id;\n  _isDragging = true;\n  cancelarLongPress();\n  e.dataTransfer.effectAllowed = 'move';\n  e.dataTransfer.setData('text\/plain', id);\n  requestAnimationFrame(() => {\n    const el = e.target.closest('.kanban-card');\n    if (el) el.classList.add('dragging');\n  });\n}\n\nfunction onKanbanDragEnd(e) {\n  kanbanDragId = null;\n  setTimeout(() => { _isDragging = false; }, 100); \/\/ pequeno delay para evitar popup p\u00f3s-drag\n  document.querySelectorAll('.kanban-card.dragging').forEach(el => el.classList.remove('dragging'));\n  document.querySelectorAll('.kanban-col.drag-over').forEach(el => el.classList.remove('drag-over'));\n  document.querySelectorAll('.kanban-drop-placeholder').forEach(el => el.remove());\n}\n\nfunction onKanbanDragOver(e, col) {\n  e.preventDefault();\n  e.dataTransfer.dropEffect = 'move';\n  if (!col.classList.contains('drag-over')) {\n    col.classList.add('drag-over');\n    const cards = col.querySelector('.kanban-cards');\n    if (cards && !cards.querySelector('.kanban-drop-placeholder')) {\n      const ph = document.createElement('div');\n      ph.className = 'kanban-drop-placeholder';\n      ph.textContent = '\u2193 Soltar aqui';\n      cards.appendChild(ph);\n    }\n  }\n}\n\nfunction onKanbanDragLeave(e, col) {\n  if (!col.contains(e.relatedTarget)) {\n    col.classList.remove('drag-over');\n    col.querySelectorAll('.kanban-drop-placeholder').forEach(el => el.remove());\n  }\n}\n\nasync function onKanbanDrop(e, col, novoStatus) {\n  e.preventDefault();\n  col.classList.remove('drag-over');\n  col.querySelectorAll('.kanban-drop-placeholder').forEach(el => el.remove());\n\n  const id = e.dataTransfer.getData('text\/plain') || kanbanDragId;\n  if (!id) return;\n\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t || t.status === novoStatus) return;\n\n  const statusAntigo = t.status;\n  t.status = novoStatus;\n  t.atualizadoEm = new Date().toISOString().split('T')[0];\n  if (novoStatus === 'Conclu\u00eddo' && !t.dataConclusao) t.dataConclusao = new Date().toISOString().split('T')[0];\n  if (statusAntigo === 'Conclu\u00eddo' && novoStatus !== 'Conclu\u00eddo') t.dataConclusao = '';\n\n  renderizarKanban();\n  atualizarBadgesTabs();\n  renderizarDashboard();\n  renderizarChartsGlobais();\n  mostrarToast(`\"${t.titulo.substring(0,28)}\u2026\" \u2192 ${novoStatus}`, 'success');\n  await sincronizarTarefa_(t);\n}\n\n\/\/ Re-render kanban on resize to switch between grid and mobile mode\nwindow.addEventListener('resize', () => {\n  if (document.getElementById('tab-kanban')?.classList.contains('active')) {\n    renderizarKanban();\n  }\n});\n\n\/\/ =============================================\n\/\/ DASHBOARD \u2014 indicadores + tabelas\n\/\/ =============================================\nfunction renderizarDashboard() {\n  const t = estado.tarefas;\n  if (!t.length) return;\n  const hoje = new Date().toISOString().split('T')[0];\n  const counts = {};\n  STATUS_ORDEM.forEach(s => counts[s] = t.filter(x => x.status === s).length);\n  const vencidas = t.filter(x => x.prazo && x.prazo < hoje && x.status !== 'Conclu\u00eddo').length;\n  const points   = t.filter(x => x.status !== 'Conclu\u00eddo').reduce((a,x) => a+(Number(x.storyPoints)||0), 0);\n\n  document.getElementById('indTotal').textContent     = t.length;\n  document.getElementById('indBacklog').textContent   = counts['Backlog']      || 0;\n  document.getElementById('indAfazer').textContent    = counts['A Fazer']      || 0;\n  document.getElementById('indAndamento').textContent = counts['Em Andamento'] || 0;\n  document.getElementById('indRevisao').textContent   = counts['Em Revis\u00e3o']   || 0;\n  document.getElementById('indConcluido').textContent = counts['Conclu\u00eddo']    || 0;\n  document.getElementById('indVencidas').textContent  = vencidas;\n  document.getElementById('indPoints').textContent    = points;\n  atualizarBadgesTabs();\n\n  const dashGrid = document.getElementById('dashGrid');\n  if (!dashGrid) return;\n  dashGrid.innerHTML = '';\n  dashGrid.className = 'relat-grid'; \/\/ usa o mesmo grid dos relat\u00f3rios\n\n  \/\/ Helper reutilizado do relat\u00f3rios\n  function mkDashCard(colorClass, icon, titulo, subtitulo, linhas) {\n    const maxVal = Math.max(...linhas.map(l => l.val || 0), 1);\n    const statsHtml = linhas.map((l, i) => {\n      const pct = Math.round(((l.val || 0) \/ maxVal) * 100);\n      const fill = l.color || 'linear-gradient(90deg,var(--blue),var(--green))';\n      return `<div class=\"relat-stat-row\">\n        <div class=\"relat-stat-rank\">${l.rank !== undefined ? l.rank : (i + 1)}<\/div>\n        <div class=\"relat-stat-label\" title=\"${esc(l.label)}\">${esc(l.label)}<\/div>\n        ${l.extra ? `<div style=\"font-size:10px;color:var(--text-muted);white-space:nowrap;\">${esc(l.extra)}<\/div>` : ''}\n        <div class=\"relat-stat-val\">${l.val ?? '\u2014'}<\/div>\n        <div class=\"relat-stat-bar\"><div class=\"relat-bar-track\"><div class=\"relat-bar-fill\" style=\"width:${pct}%;background:${fill}\"><\/div><\/div><\/div>\n      <\/div>`;\n    }).join('');\n    const card = document.createElement('div');\n    card.className = `relat-card ${colorClass}`;\n    card.innerHTML = `\n      <div class=\"relat-card-header\">\n        <div class=\"relat-card-icon\">${icon}<\/div>\n        <div class=\"relat-card-title\">${titulo}<\/div>\n        <div class=\"relat-card-subtitle\">${subtitulo}<\/div>\n      <\/div>\n      <div class=\"relat-card-body\">${statsHtml}<\/div>`;\n    return card;\n  }\n\n  \/\/ \u2500\u2500 Card 1: Por Setor \u2500\u2500\n  const setorLinhas = SETORES.map(s => {\n    const tt = t.filter(x => x.setor === s);\n    if (!tt.length) return null;\n    const conc = tt.filter(x => x.status === 'Conclu\u00eddo').length;\n    const taxa = Math.round((conc \/ tt.length) * 100);\n    const fill = taxa >= 70 ? 'linear-gradient(90deg,var(--green-dark),var(--green))'\n               : taxa >= 40 ? 'linear-gradient(90deg,#b45309,var(--orange))'\n               :              'linear-gradient(90deg,#991b1b,var(--red))';\n    return { label: s, val: tt.length, extra: `${conc} conclu\u00eddas \u00b7 ${taxa}%`, color: fill };\n  }).filter(Boolean).sort((a,b) => b.val - a.val);\n  dashGrid.appendChild(mkDashCard('card-blue', '\ud83c\udfe2', 'Por Setor', 'Volume e conclus\u00e3o por \u00e1rea', setorLinhas));\n\n  \/\/ \u2500\u2500 Card 2: Por Status \u2500\u2500\n  const statusColors = {\n    'Backlog':'#6b7280','A Fazer':'#d97706','Em Andamento':'#3a78b5','Em Revis\u00e3o':'#7c3aed','Conclu\u00eddo':'#5da020'\n  };\n  const statusLinhas = STATUS_ORDEM.map(s => {\n    const n = counts[s] || 0;\n    const pct = t.length ? Math.round((n \/ t.length) * 100) : 0;\n    return n ? { label: s, val: n, extra: `${pct}%`, color: `linear-gradient(90deg,${statusColors[s]},${statusColors[s]}99)` } : null;\n  }).filter(Boolean);\n  dashGrid.appendChild(mkDashCard('card-teal', '\ud83d\udcca', 'Por Status', 'Distribui\u00e7\u00e3o atual do fluxo', statusLinhas));\n\n  \/\/ \u2500\u2500 Card 3: Por Respons\u00e1vel \u2500\u2500\n  const resps = [...new Set(t.map(x => x.responsavel).filter(Boolean))];\n  const medals = ['\ud83e\udd47','\ud83e\udd48','\ud83e\udd49'];\n  const respLinhas = resps.map(r => {\n    const tt  = t.filter(x => x.responsavel === r);\n    const pts = tt.reduce((a, x) => a + (Number(x.storyPoints) || 0), 0);\n    const conc= tt.filter(x => x.status === 'Conclu\u00eddo').length;\n    return { label: r, val: tt.length, extra: `${conc} conclu\u00eddas \u00b7 ${pts}pts`, color: 'linear-gradient(90deg,var(--blue-dark),var(--blue))' };\n  }).sort((a,b) => b.val - a.val).slice(0, 8);\n  respLinhas.forEach((l, i) => { l.rank = medals[i] || (i + 1); });\n  dashGrid.appendChild(mkDashCard('card-green', '\ud83d\udc64', 'Por Respons\u00e1vel', 'Tarefas por pessoa', respLinhas));\n\n  \/\/ \u2500\u2500 Card 4: Por Prioridade \u2500\u2500\n  const prioColors = { 'Cr\u00edtica':'#c0392b','Alta':'#d97706','M\u00e9dia':'#3a78b5','Baixa':'#5da020' };\n  const prioLinhas = ['Cr\u00edtica','Alta','M\u00e9dia','Baixa'].map(p => {\n    const n = t.filter(x => x.prioridade === p).length;\n    return n ? { label: p, val: n, color: `linear-gradient(90deg,${prioColors[p]},${prioColors[p]}99)` } : null;\n  }).filter(Boolean);\n  dashGrid.appendChild(mkDashCard('card-orange', '\ud83c\udfaf', 'Por Prioridade', 'Criticidade das tarefas abertas', prioLinhas));\n}\n\nfunction criarTabelaDash(titulo, colunas, linhas, total) {\n  const section = document.createElement('div');\n  section.className = 'dash-section';\n  const header = `<div class=\"dash-section-header\">${titulo}<\/div>`;\n  if (!linhas.length) {\n    section.innerHTML = header + '<div style=\"padding:20px 26px;text-align:center;color:var(--text-muted);font-size:12px;\">Sem dados<\/div>';\n    return section;\n  }\n  const thead = `<thead><tr>${colunas.map(c=>`<th>${c}<\/th>`).join('')}${total?'<th>Bar<\/th>':''}<\/tr><\/thead>`;\n  const tbody = linhas.map(row => {\n    const pct = total ? Math.round((row[1]\/total)*100) : 0;\n    const tds = row.map(cell => `<td>${esc(String(cell))}<\/td>`).join('');\n    const barTd = total ? `<td><div class=\"dash-bar\"><div class=\"dash-bar-track\"><div class=\"dash-bar-fill\" style=\"width:${pct}%\"><\/div><\/div><span style=\"font-size:10px;color:var(--text-muted);min-width:28px\">${pct}%<\/span><\/div><\/td>` : '';\n    return `<tr>${tds}${barTd}<\/tr>`;\n  }).join('');\n  section.innerHTML = header + `<div class=\"dash-table-wrap\"><table class=\"dash-table\">${thead}<tbody>${tbody}<\/tbody><\/table><\/div>`;\n  return section;\n}\n\n\/\/ =============================================\n\/\/ CHARTS \u2014 Dashboard Global\n\/\/ =============================================\nfunction getChartColors() {\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n  return {\n    gridColor: isDark ? 'rgba(255,255,255,.06)' : 'rgba(0,0,0,.06)',\n    labelColor: isDark ? '#8b949e' : '#6b7280',\n    tickColor: isDark ? '#484f58' : '#9ca3af',\n  };\n}\n\nfunction destroyChart(id) { if (CHARTS[id]) { CHARTS[id].destroy(); delete CHARTS[id]; } }\n\nfunction renderizarChartsGlobais() {\n  const t = estado.tarefas;\n  if (!t.length) return;\n  const cc = getChartColors();\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n\n  const tooltipCfg = {\n    backgroundColor: isDark ? '#1c2330' : '#fff',\n    titleColor: isDark ? '#e6edf3' : '#1a2332',\n    bodyColor: isDark ? '#8b949e' : '#4a5568',\n    borderColor: isDark ? 'rgba(91,155,213,.3)' : 'rgba(91,155,213,.25)',\n    borderWidth: 1, padding: 10, cornerRadius: 8, displayColors:true, boxWidth:10, boxHeight:10\n  };\n\n  \/\/ Chart Status (Donut)\n  destroyChart('chartStatus');\n  const ctxS = document.getElementById('chartStatus');\n  if (ctxS) {\n    const statusColors = ['rgba(139,148,158,.8)','rgba(227,179,65,.8)','rgba(91,155,213,.8)','rgba(167,139,250,.8)','rgba(125,193,66,.8)'];\n    const counts = STATUS_ORDEM.map(s=>t.filter(x=>x.status===s).length);\n    CHARTS['chartStatus'] = new Chart(ctxS, {\n      type:'doughnut',\n      data:{ labels:STATUS_ORDEM, datasets:[{ data:counts, backgroundColor:statusColors, hoverBackgroundColor:['#8b949e','#e3b341','#5B9BD5','#a78bfa','#7DC142'], borderColor: isDark?'#1c2330':'#f7f9fc', borderWidth:3, hoverOffset:8 }]},\n      options:{ responsive:true, maintainAspectRatio:true, cutout:'60%', animation:{duration:800,animateRotate:true,animateScale:true},\n        plugins:{ legend:{ position:'right', labels:{ color:cc.labelColor, font:{size:12}, padding:14, boxWidth:12 } }, tooltip: tooltipCfg }\n      }\n    });\n  }\n\n  \/\/ Chart Prioridade (Bar)\n  destroyChart('chartPrioridade');\n  const ctxP = document.getElementById('chartPrioridade');\n  if (ctxP) {\n    const prios = ['Cr\u00edtica','Alta','M\u00e9dia','Baixa'];\n    const pCounts = prios.map(p=>t.filter(x=>x.prioridade===p).length);\n    const pColors = ['rgba(248,81,73,.8)','rgba(227,179,65,.8)','rgba(91,155,213,.8)','rgba(125,193,66,.8)'];\n    const pBorders= ['#f85149','#e3b341','#5B9BD5','#7DC142'];\n    CHARTS['chartPrioridade'] = new Chart(ctxP, {\n      type:'bar',\n      data:{ labels:prios, datasets:[{ label:'Tarefas', data:pCounts, backgroundColor:pColors, borderColor:pBorders, borderWidth:2, borderRadius:8, borderSkipped:false }] },\n      options:{ responsive:true, maintainAspectRatio:true, animation:{duration:700,easing:'easeOutBack'},\n        plugins:{ legend:{display:false}, tooltip: tooltipCfg },\n        scales:{ x:{ ticks:{color:cc.labelColor,font:{size:12}}, grid:{color:cc.gridColor} }, y:{ ticks:{color:cc.labelColor,font:{size:12},stepSize:1}, grid:{color:cc.gridColor}, beginAtZero:true, min:0 } }\n      }\n    });\n  }\n\n  \/\/ Chart Setor (Horizontal Bar) with gradient\n  destroyChart('chartSetor');\n  const ctxSt = document.getElementById('chartSetor');\n  if (ctxSt) {\n    const setoresData = SETORES.map(s=>t.filter(x=>x.setor===s).length);\n    CHARTS['chartSetor'] = new Chart(ctxSt, {\n      type:'bar',\n      data:{ labels:SETORES, datasets:[{ label:'Tarefas', data:setoresData, backgroundColor:'rgba(91,155,213,.72)', borderColor:'#5B9BD5', borderWidth:2, borderRadius:6, borderSkipped:false }]},\n      options:{ indexAxis:'y', responsive:true, maintainAspectRatio:true, animation:{duration:800,easing:'easeInOutCubic'},\n        plugins:{ legend:{display:false}, tooltip: tooltipCfg },\n        scales:{ x:{ ticks:{color:cc.labelColor,font:{size:12},stepSize:1}, grid:{color:cc.gridColor}, beginAtZero:true, min:0 }, y:{ ticks:{color:cc.labelColor,font:{size:12}}, grid:{display:false} } }\n      }\n    });\n  }\n\n  \/\/ Chart Tipo (Doughnut)\n  destroyChart('chartTipo');\n  const ctxT = document.getElementById('chartTipo');\n  if (ctxT) {\n    const tipos = ['Task','Corre\u00e7\u00e3o','Melhoria','Demanda'];\n    const tCounts = tipos.map(tp=>t.filter(x=>x.tipo===tp).length);\n    CHARTS['chartTipo'] = new Chart(ctxT, {\n      type:'doughnut',\n      data:{ labels:tipos, datasets:[{ data:tCounts, backgroundColor:['rgba(91,155,213,.8)','rgba(248,81,73,.8)','rgba(125,193,66,.8)','rgba(167,139,250,.8)'], hoverBackgroundColor:['#5B9BD5','#f85149','#7DC142','#a78bfa'], borderColor: isDark?'#1c2330':'#f7f9fc', borderWidth:3, hoverOffset:8 }]},\n      options:{ responsive:true, maintainAspectRatio:true, cutout:'60%', animation:{duration:800,animateRotate:true},\n        plugins:{ legend:{ position:'right', labels:{ color:cc.labelColor, font:{size:12}, padding:14, boxWidth:12 } }, tooltip: tooltipCfg }\n      }\n    });\n  }\n}\n\n\/\/ =============================================\n\/\/ BI \u2014 Multi-filter + Charts\n\/\/ =============================================\nfunction atualizarValoresBiDimensao() {\n  const dim = document.getElementById('biDimensao')?.value;\n  const sel = document.getElementById('biValor');\n  if (!sel) return;\n  sel.innerHTML = '<option value=\"\">Selecione...<\/option>';\n  let values = [];\n  if (dim === 'setor')       values = SETORES;\n  else if (dim === 'sprint') values = [...new Set(estado.tarefas.map(t=>t.sprint).filter(Boolean))].sort();\n  else if (dim === 'status') values = STATUS_ORDEM;\n  else if (dim === 'prioridade') values = ['Cr\u00edtica','Alta','M\u00e9dia','Baixa'];\n  else if (dim === 'tipo')   values = ['Task','Corre\u00e7\u00e3o','Melhoria','Demanda'];\n  else if (dim === 'responsavel') values = [...new Set(estado.tarefas.map(t=>t.responsavel).filter(Boolean))].sort();\n  values.forEach(v => { const o = document.createElement('option'); o.value = v; o.textContent = v; sel.appendChild(o); });\n}\n\nfunction adicionarFiltroBI() {\n  const dim = document.getElementById('biDimensao').value;\n  const val = document.getElementById('biValor').value;\n  if (!val) { mostrarToast('Selecione um valor para o filtro', 'error'); return; }\n  \/\/ avoid duplicate\n  if (biFilters.some(f => f.dim === dim && f.val === val)) { mostrarToast('Filtro j\u00e1 adicionado', 'info'); return; }\n  biFilters.push({ dim, val });\n  renderizarChipsBIAtivos();\n  renderizarBIKpis();\n  renderizarChartsBI();\n}\n\nfunction removerFiltroBI(idx) {\n  biFilters.splice(idx, 1);\n  renderizarChipsBIAtivos();\n  renderizarBIKpis();\n  renderizarChartsBI();\n}\n\nfunction limparFiltrosBI() {\n  biFilters = [];\n  renderizarChipsBIAtivos();\n  renderizarBIKpis();\n  renderizarChartsBI();\n  \/\/ Remove ativo dos quick buttons\n  document.querySelectorAll('.bi-quick-btn').forEach(b => b.classList.remove('ativo'));\n}\n\n\/\/ Aplica um filtro r\u00e1pido pr\u00e9-definido (toggle)\nfunction filtroRapidoBI(dim, val) {\n  const idx = biFilters.findIndex(f => f.dim === dim && f.val === val);\n  if (idx >= 0) {\n    biFilters.splice(idx, 1); \/\/ remove se j\u00e1 estava\n  } else {\n    \/\/ Remove outros filtros da mesma dimens\u00e3o antes de adicionar\n    biFilters = biFilters.filter(f => f.dim !== dim);\n    biFilters.push({ dim, val });\n  }\n  renderizarChipsBIAtivos();\n  renderizarBIKpis();\n  renderizarChartsBI();\n  \/\/ Atualiza visual dos quick buttons\n  document.querySelectorAll('.bi-quick-btn').forEach(b => {\n    const isAtivo = biFilters.some(f => b.textContent.includes(val) && f.val === val);\n    b.classList.toggle('ativo', isAtivo);\n  });\n}\n\nfunction renderizarChipsBIAtivos() {\n  const container = document.getElementById('biActiveFilters');\n  if (!container) return;\n  if (!biFilters.length) {\n    container.innerHTML = '<span style=\"font-size:11px;color:var(--text-muted);align-self:center;\">Nenhum filtro aplicado \u2014 mostrando todos os dados<\/span>';\n    return;\n  }\n  const dimLabels = { setor:'Setor', sprint:'Sprint', status:'Status', prioridade:'Prioridade', tipo:'Tipo', responsavel:'Respons\u00e1vel' };\n  container.innerHTML = biFilters.map((f,i) =>\n    `<div class=\"filter-chip\">${dimLabels[f.dim]}: ${esc(f.val)}<span class=\"filter-chip-remove\" onclick=\"removerFiltroBI(${i})\">\u2715<\/span><\/div>`\n  ).join('');\n}\n\nfunction getTarefasBI() {\n  if (!biFilters.length) return estado.tarefas;\n  return estado.tarefas.filter(t =>\n    biFilters.every(f => {\n      if (f.dim === 'setor')       return t.setor === f.val;\n      if (f.dim === 'sprint')      return t.sprint === f.val;\n      if (f.dim === 'status')      return t.status === f.val;\n      if (f.dim === 'prioridade')  return t.prioridade === f.val;\n      if (f.dim === 'tipo')        return t.tipo === f.val;\n      if (f.dim === 'responsavel') return t.responsavel === f.val;\n      return true;\n    })\n  );\n}\n\nfunction renderizarBIKpis() {\n  const container = document.getElementById('biKpis');\n  if (!container) return;\n  const t = getTarefasBI();\n  const all = estado.tarefas;\n  const hoje = new Date().toISOString().split('T')[0];\n  const total     = t.length;\n  const conc      = t.filter(x=>x.status==='Conclu\u00eddo').length;\n  const taxa      = total ? Math.round((conc\/total)*100) : 0;\n  const pts       = t.reduce((a,x)=>a+(Number(x.storyPoints)||0),0);\n  const venc      = t.filter(x=>x.prazo&&x.prazo<hoje&&x.status!=='Conclu\u00eddo').length;\n  const andamento = t.filter(x=>x.status==='Em Andamento').length;\n  const impede    = t.filter(x=>x.impedimento).length;\n\n  \/\/ Simple trend vs all data\n  const taxaAll   = all.length ? Math.round((all.filter(x=>x.status==='Conclu\u00eddo').length\/all.length)*100) : 0;\n  const trendTaxa = biFilters.length ? (taxa > taxaAll ? 'up' : taxa < taxaAll ? 'down' : 'flat') : 'flat';\n  const trendVenc = biFilters.length ? (venc < all.filter(x=>x.prazo&&x.prazo<hoje&&x.status!=='Conclu\u00eddo').length ? 'up' : 'down') : 'flat';\n\n  const kpis = [\n    { cls:'kpi-blue',   label:'Total Tarefas',   val:total,    sub:'no filtro atual',       icon:'\ud83d\udccb', trend:null },\n    { cls:'kpi-green',  label:'Taxa Conclus\u00e3o',  val:taxa+'%', sub:`${conc} de ${total} conclu\u00eddas`, icon:'\u2705', trend: biFilters.length ? { dir: trendTaxa, label: trendTaxa==='up'?'acima da m\u00e9dia':'abaixo da m\u00e9dia' } : null },\n    { cls:'kpi-accent', label:'Story Points',    val:pts,      sub:'pontos totais acumulados', icon:'\u26a1', trend:null },\n    { cls:'kpi-orange', label:'Em Andamento',    val:andamento,sub:'tarefas ativas agora',  icon:'\ud83d\udd04', trend:null },\n    { cls:'kpi-red',    label:'Vencidas',        val:venc,     sub:'prazo expirado',         icon:'\ud83d\udd34', trend: biFilters.length ? { dir: trendVenc, label: trendVenc==='up'?'melhor que m\u00e9dia':'aten\u00e7\u00e3o' } : null },\n    { cls:'kpi-purple', label:'Com Impedimento', val:impede,   sub:'tarefas bloqueadas',     icon:'\u26a0\ufe0f', trend:null },\n  ];\n\n  container.innerHTML = kpis.map(k => {\n    const trendHtml = k.trend ? `<div class=\"bi-kpi-trend ${k.trend.dir}\">${k.trend.dir==='up'?'\u2191':k.trend.dir==='down'?'\u2193':'\u2192'} ${esc(k.trend.label)}<\/div>` : '';\n    return `<div class=\"bi-kpi ${k.cls}\">\n      <div class=\"bi-kpi-icon\">${k.icon}<\/div>\n      <div class=\"bi-kpi-label\">${k.label}<\/div>\n      <div class=\"bi-kpi-val\">${k.val}<\/div>\n      <div class=\"bi-kpi-sub\">${k.sub}<\/div>\n      ${trendHtml}\n    <\/div>`;\n  }).join('');\n}\n\nfunction renderizarChartsBI() {\n  const t = getTarefasBI();\n  const cc = getChartColors();\n  const isDark = document.documentElement.getAttribute('data-theme') === 'dark';\n\n  const tooltipPlugin = {\n    backgroundColor: isDark ? '#1c2330' : '#fff',\n    titleColor: isDark ? '#e6edf3' : '#1a2332',\n    bodyColor: isDark ? '#8b949e' : '#4a5568',\n    borderColor: isDark ? 'rgba(91,155,213,.3)' : 'rgba(91,155,213,.25)',\n    borderWidth: 1,\n    padding: 10,\n    cornerRadius: 8,\n    displayColors: true,\n    boxWidth: 10, boxHeight: 10,\n  };\n\n  const baseScales = {\n    x: { ticks:{ color:cc.labelColor, font:{size:12} }, grid:{ color:cc.gridColor } },\n    y: { ticks:{ color:cc.labelColor, font:{size:12}, stepSize:1 }, grid:{ color:cc.gridColor }, beginAtZero:true, min:0 }\n  };\n  const baseLegend = { labels:{ color:cc.labelColor, font:{size:12}, padding:16, boxWidth:12 } };\n\n  if (!t.length) return;\n\n  \/\/ \u2500\u2500 Sprint line with gradient fill \u2500\u2500\n  destroyChart('biChartSprint');\n  const ctxSp = document.getElementById('biChartSprint');\n  if (ctxSp) {\n    const sprints = [...new Set(estado.tarefas.map(x=>x.sprint).filter(Boolean))].sort();\n    const totais  = sprints.map(s=>t.filter(x=>x.sprint===s).length);\n    const concl   = sprints.map(s=>t.filter(x=>x.sprint===s&&x.status==='Conclu\u00eddo').length);\n\n    const gradBlue = ctxSp.getContext('2d').createLinearGradient(0,0,0,260);\n    gradBlue.addColorStop(0, 'rgba(91,155,213,.4)');\n    gradBlue.addColorStop(1, 'rgba(91,155,213,.02)');\n\n    const gradGreen = ctxSp.getContext('2d').createLinearGradient(0,0,0,260);\n    gradGreen.addColorStop(0, 'rgba(125,193,66,.35)');\n    gradGreen.addColorStop(1, 'rgba(125,193,66,.02)');\n\n    CHARTS['biChartSprint'] = new Chart(ctxSp, {\n      type:'line',\n      data:{ labels:sprints, datasets:[\n        { label:'Total', data:totais, borderColor:'#5B9BD5', backgroundColor: gradBlue, tension:.42, fill:true, pointBackgroundColor:'#5B9BD5', pointRadius:5, pointHoverRadius:7, borderWidth:2.5 },\n        { label:'Conclu\u00eddas', data:concl, borderColor:'#7DC142', backgroundColor: gradGreen, tension:.42, fill:true, pointBackgroundColor:'#7DC142', pointRadius:5, pointHoverRadius:7, borderWidth:2.5 }\n      ]},\n      options:{ responsive:true, maintainAspectRatio:true, animation:{ duration:800, easing:'easeInOutQuart' },\n        plugins:{ legend:{ labels:{ ...baseLegend.labels } }, tooltip: tooltipPlugin },\n        scales: baseScales\n      }\n    });\n  }\n\n  \/\/ \u2500\u2500 Story Points por Respons\u00e1vel (gradient horizontal bars) \u2500\u2500\n  destroyChart('biChartResponsavel');\n  const ctxR = document.getElementById('biChartResponsavel');\n  if (ctxR) {\n    const resps = [...new Set(t.map(x=>x.responsavel).filter(Boolean))].sort();\n    const pts = resps.map(r=>t.filter(x=>x.responsavel===r).reduce((a,x)=>a+(Number(x.storyPoints)||0),0));\n    const maxPts = Math.max(...pts, 1);\n    const colors = pts.map(p => {\n      const ratio = p \/ maxPts;\n      const r1 = Math.round(77 + ratio * (91-77));\n      const g1 = Math.round(224 - ratio * (224-155));\n      const b1 = Math.round(192 - ratio * (192-213));\n      return `rgba(${r1},${g1},${b1},0.75)`;\n    });\n    CHARTS['biChartResponsavel'] = new Chart(ctxR, {\n      type:'bar',\n      data:{ labels:resps, datasets:[{ label:'Story Points', data:pts, backgroundColor: colors, borderColor:'rgba(77,224,192,.9)', borderWidth:1.5, borderRadius:6, borderSkipped:false }] },\n      options:{ indexAxis:'y', responsive:true, maintainAspectRatio:true, animation:{ duration:700, easing:'easeOutBack' },\n        plugins:{ legend:{display:false}, tooltip: tooltipPlugin },\n        scales:{ x:{ ticks:{ color:cc.labelColor, font:{size:12}, stepSize:1 }, grid:{ color:cc.gridColor }, beginAtZero:true, min:0 }, y:{ ticks:{ color:cc.labelColor, font:{size:12} }, grid:{display:false} } }\n      }\n    });\n  }\n\n  \/\/ \u2500\u2500 Produtividade por Setor (stacked + rounded) \u2500\u2500\n  destroyChart('biChartProdutividade');\n  const ctxProd = document.getElementById('biChartProdutividade');\n  if (ctxProd) {\n    const setores = SETORES.filter(s=>t.some(x=>x.setor===s));\n    const conclData = setores.map(s=>t.filter(x=>x.setor===s&&x.status==='Conclu\u00eddo').length);\n    const abertData = setores.map(s=>t.filter(x=>x.setor===s&&x.status!=='Conclu\u00eddo').length);\n    CHARTS['biChartProdutividade'] = new Chart(ctxProd, {\n      type:'bar',\n      data:{ labels:setores, datasets:[\n        { label:'Conclu\u00eddas', data:conclData, backgroundColor:'rgba(125,193,66,.78)', borderColor:'rgba(125,193,66,1)', borderWidth:1, borderRadius:{topLeft:5,topRight:5}, borderSkipped:'bottom' },\n        { label:'Em aberto',  data:abertData, backgroundColor:'rgba(91,155,213,.58)', borderColor:'rgba(91,155,213,.8)', borderWidth:1, borderRadius:0, borderSkipped:'bottom' }\n      ]},\n      options:{ responsive:true, maintainAspectRatio:true, animation:{ duration:900, easing:'easeInOutCubic' },\n        scales:{ x:{ stacked:true, ticks:{ color:cc.labelColor, font:{size:12} }, grid:{ color:cc.gridColor } }, y:{ stacked:true, ticks:{ color:cc.labelColor, font:{size:12}, stepSize:1 }, grid:{ color:cc.gridColor }, beginAtZero:true, min:0 } },\n        plugins:{ legend:{ labels:{ ...baseLegend.labels } }, tooltip: tooltipPlugin }\n      }\n    });\n  }\n\n  \/\/ \u2500\u2500 Taxa de Conclus\u00e3o por Prioridade (polar area style) \u2500\u2500\n  destroyChart('biChartConclusao');\n  const ctxC = document.getElementById('biChartConclusao');\n  if (ctxC) {\n    const prios = ['Cr\u00edtica','Alta','M\u00e9dia','Baixa'];\n    const taxas = prios.map(p => {\n      const tt = t.filter(x=>x.prioridade===p);\n      return tt.length ? Math.round((tt.filter(x=>x.status==='Conclu\u00eddo').length\/tt.length)*100) : 0;\n    });\n    const barColors = ['rgba(248,81,73,.75)','rgba(227,179,65,.75)','rgba(91,155,213,.75)','rgba(125,193,66,.75)'];\n    const barBorders = ['#f85149','#e3b341','#5B9BD5','#7DC142'];\n    CHARTS['biChartConclusao'] = new Chart(ctxC, {\n      type:'bar',\n      data:{ labels:prios, datasets:[{ label:'% Conclu\u00eddas', data:taxas, backgroundColor: barColors, borderColor: barBorders, borderWidth:2, borderRadius:8, borderSkipped:false }] },\n      options:{ responsive:true, maintainAspectRatio:true, animation:{ duration:750, easing:'easeOutElastic' },\n        plugins:{ legend:{display:false}, tooltip:{ ...tooltipPlugin, callbacks:{ label: ctx => ` ${ctx.raw}% conclu\u00eddo` } } },\n        scales:{ x:{ ticks:{ color:cc.labelColor, font:{size:12} }, grid:{ color:cc.gridColor } }, y:{ ticks:{ color:cc.labelColor, font:{size:12}, callback:v=>v+'%', stepSize:10 }, grid:{ color:cc.gridColor }, beginAtZero:true, max:100 } }\n      }\n    });\n  }\n\n  \/\/ \u2500\u2500 Vencidas vs Em dia (doughnut aprimorado) \u2500\u2500\n  destroyChart('biChartVencidas');\n  const ctxV = document.getElementById('biChartVencidas');\n  if (ctxV) {\n    const hoje = new Date().toISOString().split('T')[0];\n    const venc  = t.filter(x=>x.prazo&&x.prazo<hoje&&x.status!=='Conclu\u00eddo').length;\n    const emDia = t.filter(x=>(!x.prazo||x.prazo>=hoje)&&x.status!=='Conclu\u00eddo').length;\n    const conc2 = t.filter(x=>x.status==='Conclu\u00eddo').length;\n    CHARTS['biChartVencidas'] = new Chart(ctxV, {\n      type:'doughnut',\n      data:{ labels:['Vencidas','Em dia','Conclu\u00eddas'], datasets:[{\n        data:[venc,emDia,conc2],\n        backgroundColor:['rgba(248,81,73,.8)','rgba(91,155,213,.8)','rgba(125,193,66,.8)'],\n        hoverBackgroundColor:['#f85149','#5B9BD5','#7DC142'],\n        borderColor: isDark ? '#1c2330' : '#f7f9fc',\n        borderWidth:3, hoverOffset:8\n      }]},\n      options:{ responsive:true, maintainAspectRatio:true,\n        animation:{ duration:800, animateRotate:true, animateScale:true },\n        cutout:'62%',\n        plugins:{ legend:{ position:'right', labels:{ color:cc.labelColor, font:{size:12}, padding:14, boxWidth:12 } }, tooltip: tooltipPlugin }\n      }\n    });\n  }\n}\n\n\/\/ =============================================\n\/\/ KANBAN POPUP \u2014 clique simples visualiza,\n\/\/                long press (600ms) abre edi\u00e7\u00e3o\n\/\/ =============================================\nlet _longPressTimer = null;\nlet _longPressId    = null;\nlet _popupTarefaId  = null;\nlet _isDragging     = false;\n\nfunction iniciarLongPress(id) {\n  _longPressId = id;\n  _longPressTimer = setTimeout(() => {\n    if (!_isDragging) {\n      fecharKanbanPopup();\n      editarTarefa(id);\n    }\n  }, 600);\n}\nfunction cancelarLongPress() {\n  clearTimeout(_longPressTimer);\n  _longPressTimer = null;\n}\n\nfunction abrirKanbanPopup(id, e) {\n  if (_isDragging) return; \/\/ foi drag, n\u00e3o clique\n  cancelarLongPress();\n  const t = estado.tarefas.find(x => x.id === id);\n  if (!t) return;\n  _popupTarefaId = id;\n\n  const statusSlug = STATUS_SLUG[t.status] || 'backlog';\n  const prioSlug   = (t.prioridade || '').toLowerCase().replace('\u00e9','e');\n  const tipoSlug   = (t.tipo || '').toLowerCase().normalize('NFD').replace(\/[\\u0300-\\u036f]\/g,'').replace(\/[^a-z]\/g,'');\n  const idxStatus  = STATUS_ORDEM.indexOf(t.status);\n  const hoje = new Date().toISOString().split('T')[0];\n  const isVencida = t.prazo && t.prazo < hoje && t.status !== 'Conclu\u00eddo';\n\n  document.getElementById('kpTitulo').textContent = t.titulo;\n\n  document.getElementById('kpBadges').innerHTML = `\n    <span class=\"badge badge-${statusSlug}\">${esc(t.status)}<\/span>\n    <span class=\"badge badge-${prioSlug}\">${esc(t.prioridade)}<\/span>\n    <span class=\"badge badge-${tipoSlug}\">${esc(t.tipo)}<\/span>\n    ${isVencida ? `<span class=\"badge\" style=\"background:rgba(248,81,73,.15);color:var(--red);border-color:rgba(248,81,73,.3);\">\ud83d\udd34 Vencida<\/span>` : ''}\n  `;\n\n  document.getElementById('kpGrid').innerHTML = [\n    t.responsavel ? `<div class=\"kanban-popup-field\"><div class=\"kanban-popup-field-label\">Respons\u00e1vel<\/div><div class=\"kanban-popup-field-val\">\ud83d\udc64 ${esc(t.responsavel)}<\/div><\/div>` : '',\n    t.setor       ? `<div class=\"kanban-popup-field\"><div class=\"kanban-popup-field-label\">Setor<\/div><div class=\"kanban-popup-field-val\">\ud83c\udfe2 ${esc(t.setor)}<\/div><\/div>` : '',\n    t.sprint      ? `<div class=\"kanban-popup-field\"><div class=\"kanban-popup-field-label\">Sprint<\/div><div class=\"kanban-popup-field-val\">\ud83c\udfc3 ${esc(t.sprint)}<\/div><\/div>` : '',\n    t.storyPoints ? `<div class=\"kanban-popup-field\"><div class=\"kanban-popup-field-label\">Story Points<\/div><div class=\"kanban-popup-field-val\">\u26a1 ${t.storyPoints} pts<\/div><\/div>` : '',\n    t.prazo       ? `<div class=\"kanban-popup-field\"><div class=\"kanban-popup-field-label\">Data Inicial<\/div><div class=\"kanban-popup-field-val\">\ud83d\udcc5 ${formatarData(t.prazo)}<\/div><\/div>` : '',\n    t.dataConclusao ? `<div class=\"kanban-popup-field\"><div class=\"kanban-popup-field-label\">Conclu\u00eddo em<\/div><div class=\"kanban-popup-field-val\" style=\"color:var(--green)\">\u2713 ${formatarData(t.dataConclusao)}<\/div><\/div>` : '',\n  ].join('');\n\n  const descEl = document.getElementById('kpDesc');\n  if (t.descricao) { descEl.textContent = t.descricao; descEl.style.display = ''; }\n  else descEl.style.display = 'none';\n\n  const impEl = document.getElementById('kpImpedimento');\n  if (t.impedimento) { document.getElementById('kpImpedimentoTxt').textContent = t.impedimento; impEl.style.display = ''; }\n  else impEl.style.display = 'none';\n\n  document.getElementById('kpConcluirBtn').style.display = t.status === 'Conclu\u00eddo' ? 'none' : '';\n  document.getElementById('kpAvancarBtn').style.display  = idxStatus >= STATUS_ORDEM.length-1 ? 'none' : '';\n\n  document.getElementById('kanbanPopupOverlay').classList.add('active');\n}\n\nfunction fecharKanbanPopup(e) {\n  if (e && e.target !== document.getElementById('kanbanPopupOverlay')) return;\n  document.getElementById('kanbanPopupOverlay').classList.remove('active');\n  _popupTarefaId = null;\n}\n\nfunction editarDoPopup()   { const id = _popupTarefaId; fecharKanbanPopup(); editarTarefa(id); }\nfunction concluirDoPopup() { const id = _popupTarefaId; fecharKanbanPopup(); concluirTarefa(id); }\nfunction avancarDoPopup()  { const id = _popupTarefaId; fecharKanbanPopup(); avancarStatus(id); }\nfunction excluirDoPopup()  { const id = _popupTarefaId; fecharKanbanPopup(); excluirTarefa(id); }\n\n\/\/ =============================================\n\/\/ RELAT\u00d3RIOS \u2014 filtros\n\/\/ =============================================\nfunction popularFiltrosRelat() {\n  const selSetor  = document.getElementById('rfiltSetor');\n  const selSprint = document.getElementById('rfiltSprint');\n  const selResp   = document.getElementById('rfiltResponsavel');\n  if (!selSetor || !selSprint) return;\n\n  if (selSetor.options.length === 1) {\n    SETORES.forEach(s => { const o = document.createElement('option'); o.value = s; o.textContent = s; selSetor.appendChild(o); });\n  }\n  const sprints = [...new Set(estado.tarefas.map(t=>t.sprint).filter(Boolean))].sort();\n  const valSp = selSprint.value;\n  selSprint.innerHTML = '<option value=\"\">Todas as sprints<\/option>';\n  sprints.forEach(s => { const o = document.createElement('option'); o.value = s; o.textContent = s; selSprint.appendChild(o); });\n  if (valSp) selSprint.value = valSp;\n\n  if (selResp) {\n    const resps = [...new Set(estado.tarefas.map(t=>t.responsavel).filter(Boolean))].sort();\n    const valR = selResp.value;\n    selResp.innerHTML = '<option value=\"\">Todos<\/option>';\n    resps.forEach(r => { const o = document.createElement('option'); o.value = r; o.textContent = r; selResp.appendChild(o); });\n    if (valR) selResp.value = valR;\n  }\n}\n\nfunction getTarefasRelat() {\n  const setor      = document.getElementById('rfiltSetor')?.value      || '';\n  const sprint     = document.getElementById('rfiltSprint')?.value     || '';\n  const periodo    = document.getElementById('rfiltPeriodo')?.value    || '';\n  const tipo       = document.getElementById('rfiltTipo')?.value       || '';\n  const responsavel= document.getElementById('rfiltResponsavel')?.value|| '';\n\n  return estado.tarefas.filter(t => {\n    if (setor       && t.setor       !== setor)       return false;\n    if (sprint      && t.sprint      !== sprint)      return false;\n    if (tipo        && t.tipo        !== tipo)         return false;\n    if (responsavel && t.responsavel !== responsavel) return false;\n    if (periodo) {\n      const limite = new Date();\n      limite.setDate(limite.getDate() - Number(periodo));\n      if (new Date(t.criadoEm || 0) < limite) return false;\n    }\n    return true;\n  });\n}\n\nfunction limparFiltrosRelat() {\n  ['rfiltSetor','rfiltSprint','rfiltPeriodo','rfiltTipo','rfiltResponsavel'].forEach(id => {\n    const el = document.getElementById(id); if (el) el.value = '';\n  });\n  renderizarRelatorios();\n}\n\n\/\/ =============================================\n\/\/ RELAT\u00d3RIOS \u2014 render com cards refinados\n\/\/ =============================================\nfunction renderizarRelatorios() {\n  popularFiltrosRelat();\n  const grid = document.getElementById('relatoriosGrid');\n  if (!grid) return;\n  const t = getTarefasRelat();\n  if (!t.length) {\n    grid.innerHTML = '<div class=\"empty-state\"><div class=\"empty-state-icon\">\ud83d\udcc8<\/div><div class=\"empty-state-text\">Nenhum dado para os filtros selecionados<\/div><\/div>';\n    return;\n  }\n  grid.innerHTML = '';\n  const hoje = new Date().toISOString().split('T')[0];\n\n  \/\/ \u2500\u2500 Helper: cria card refinado \u2500\u2500\n  function mkCard(colorClass, icon, titulo, subtitulo, linhas, fullWidth) {\n    const maxVal = Math.max(...linhas.map(l => l.val || 0), 1);\n    const statsHtml = linhas.map((l, i) => {\n      const pct = Math.round(((l.val||0) \/ maxVal) * 100);\n      const fillColor = l.color || 'linear-gradient(90deg,var(--blue),var(--green))';\n      return `<div class=\"relat-stat-row\">\n        <div class=\"relat-stat-rank\">${l.rank !== undefined ? l.rank : (i+1)}<\/div>\n        <div class=\"relat-stat-label\" title=\"${esc(l.label)}\">${esc(l.label)}<\/div>\n        ${l.extra ? `<div style=\"font-size:10px;color:var(--text-muted);white-space:nowrap;\">${esc(l.extra)}<\/div>` : ''}\n        <div class=\"relat-stat-val\">${l.val ?? '\u2014'}<\/div>\n        ${l.showBar !== false ? `<div class=\"relat-stat-bar\"><div class=\"relat-bar-track\"><div class=\"relat-bar-fill\" style=\"width:${pct}%;background:${fillColor}\"><\/div><\/div><\/div>` : ''}\n      <\/div>`;\n    }).join('');\n    const card = document.createElement('div');\n    card.className = `relat-card ${colorClass}${fullWidth ? ' full' : ''}`;\n    card.innerHTML = `\n      <div class=\"relat-card-header\">\n        <div class=\"relat-card-icon\">${icon}<\/div>\n        <div class=\"relat-card-title\">${titulo}<\/div>\n        <div class=\"relat-card-subtitle\">${subtitulo}<\/div>\n      <\/div>\n      <div class=\"relat-card-body\">${statsHtml}<\/div>`;\n    return card;\n  }\n\n  \/\/ \u2500\u2500 1. Podium de Produtividade \u2500\u2500\n  const resps = [...new Set(t.map(x=>x.responsavel).filter(Boolean))];\n  const podium = resps.map(r => {\n    const tt  = t.filter(x=>x.responsavel===r);\n    const conc= tt.filter(x=>x.status==='Conclu\u00eddo').length;\n    const pts = tt.filter(x=>x.status==='Conclu\u00eddo').reduce((a,x)=>a+(Number(x.storyPoints)||0),0);\n    const taxa= tt.length ? Math.round((conc\/tt.length)*100) : 0;\n    return { label: r, val: conc, extra: `${taxa}% \u00b7 ${pts}pts`, color: 'linear-gradient(90deg,var(--green-dark),var(--green))' };\n  }).sort((a,b) => b.val - a.val).slice(0, 8);\n  const medals = ['\ud83e\udd47','\ud83e\udd48','\ud83e\udd49'];\n  podium.forEach((p, i) => p.rank = medals[i] || (i+1));\n  grid.appendChild(mkCard('card-green','\ud83c\udfc6','Produtividade','Tarefas conclu\u00eddas por respons\u00e1vel', podium));\n\n  \/\/ \u2500\u2500 2. Health por Setor \u2500\u2500\n  const setorHealth = SETORES\n    .map(s => {\n      const tt   = t.filter(x=>x.setor===s); if (!tt.length) return null;\n      const conc = tt.filter(x=>x.status==='Conclu\u00eddo').length;\n      const taxa = Math.round((conc\/tt.length)*100);\n      const imp  = tt.filter(x=>x.impedimento).length;\n      const color = taxa >= 70 ? 'linear-gradient(90deg,var(--green-dark),var(--green))'\n                  : taxa >= 40 ? 'linear-gradient(90deg,#b45309,var(--orange))'\n                  :              'linear-gradient(90deg,#991b1b,var(--red))';\n      return { label: s, val: taxa, extra: `${tt.length} tarefas \u00b7 ${imp} imp.`, color, showBar: true };\n    }).filter(Boolean).sort((a,b)=>b.val-a.val);\n  grid.appendChild(mkCard('card-blue','\ud83c\udfe5','Sa\u00fade por Setor','Taxa de conclus\u00e3o (%) por \u00e1rea', setorHealth));\n\n  \/\/ \u2500\u2500 3. Distribui\u00e7\u00e3o de Bugs \u2500\u2500\n  const bugs = t.filter(x=>x.tipo==='Corre\u00e7\u00e3o');\n  if (bugs.length) {\n    const bugPorSetor = SETORES.map(s => {\n      const n = bugs.filter(x=>x.setor===s).length;\n      return n ? { label: s, val: n, color: 'linear-gradient(90deg,#991b1b,var(--red))' } : null;\n    }).filter(Boolean).sort((a,b)=>b.val-a.val);\n    grid.appendChild(mkCard('card-red','\ud83d\udd27','Bugs por Setor',`${bugs.length} bugs no total`, bugPorSetor));\n  }\n\n  \/\/ \u2500\u2500 4. Backlog vs Execu\u00e7\u00e3o \u2500\u2500\n  const fluxo = STATUS_ORDEM.map(s => {\n    const n = t.filter(x=>x.status===s).length;\n    const colors = { 'Backlog':'#6b7280', 'A Fazer':'#d97706', 'Em Andamento':'#3a78b5', 'Em Revis\u00e3o':'#7c3aed', 'Conclu\u00eddo':'#5da020' };\n    return { label: s, val: n, color: `linear-gradient(90deg,${colors[s]},${colors[s]}99)`, showBar: true };\n  }).filter(x=>x.val>0);\n  grid.appendChild(mkCard('card-teal','\ud83c\udf0a','Fluxo do Trabalho','Distribui\u00e7\u00e3o atual por status', fluxo));\n\n  \/\/ \u2500\u2500 5. Velocidade por Sprint \u2500\u2500\n  const sprints = [...new Set(t.map(x=>x.sprint).filter(Boolean))].sort();\n  if (sprints.length > 1) {\n    const velocidade = sprints.slice(-6).map(s => {\n      const tt  = t.filter(x=>x.sprint===s);\n      const pts = tt.filter(x=>x.status==='Conclu\u00eddo').reduce((a,x)=>a+(Number(x.storyPoints)||0),0);\n      return { label: s, val: pts, extra: `${tt.filter(x=>x.status==='Conclu\u00eddo').length} tarefas`, color: 'linear-gradient(90deg,var(--blue-dark),var(--blue))' };\n    });\n    grid.appendChild(mkCard('card-purple','\u26a1','Velocidade por Sprint','Story Points entregues', velocidade));\n  }\n\n  \/\/ \u2500\u2500 6. Alertas \u2014 Tarefas Cr\u00edticas sem Andamento \u2500\u2500\n  const criticas = t.filter(x => x.prioridade === 'Cr\u00edtica' && x.status !== 'Conclu\u00eddo')\n    .map(x => ({ label: x.titulo.substring(0,32), val: null, extra: x.responsavel || '\u2014', showBar: false, rank: x.status === 'Backlog' ? '\ud83d\udd34' : '\ud83d\udfe0' }));\n  if (criticas.length) {\n    grid.appendChild(mkCard('card-orange','\ud83d\udea8','Alertas Cr\u00edticos',`${criticas.length} tarefas cr\u00edticas em aberto`, criticas.slice(0,6)));\n  }\n\n  \/\/ \u2500\u2500 7. Efici\u00eancia \u2014 prazo vs conclus\u00e3o (completo) \u2500\u2500\n  const eficiencia = resps.map(r => {\n    const tt      = t.filter(x=>x.responsavel===r);\n    const comPrazo= tt.filter(x=>x.prazo);\n    const noPrazo = comPrazo.filter(x=>x.status==='Conclu\u00eddo'&&x.dataConclusao&&x.dataConclusao<=x.prazo).length;\n    const eff     = comPrazo.length ? Math.round((noPrazo\/comPrazo.length)*100) : null;\n    if (eff === null) return null;\n    return { label: r, val: eff, extra: `${noPrazo}\/${comPrazo.length} no prazo`, color: eff>=80?'linear-gradient(90deg,var(--green-dark),var(--green))':eff>=50?'linear-gradient(90deg,#b45309,var(--orange))':'linear-gradient(90deg,#991b1b,var(--red))' };\n  }).filter(Boolean).sort((a,b)=>b.val-a.val);\n  if (eficiencia.length) {\n    grid.appendChild(mkCard('card-teal','\ud83c\udfaf','Efici\u00eancia de Prazo','% entregues dentro do prazo (Data Inicial)', eficiencia));\n  }\n\n  \/\/ \u2500\u2500 8. Tipos de tarefa \u2500\u2500\n  const tiposData = ['Task','Corre\u00e7\u00e3o','Melhoria','Demanda'].map(tp => {\n    const n    = t.filter(x=>x.tipo===tp).length; if (!n) return null;\n    const conc = t.filter(x=>x.tipo===tp&&x.status==='Conclu\u00eddo').length;\n    const colors = { Task:'#3a78b5', 'Corre\u00e7\u00e3o':'#c0392b', Melhoria:'#5da020', Demanda:'#7c3aed' };\n    return { label: tp, val: n, extra: `${conc} conclu\u00eddas`, color: `linear-gradient(90deg,${colors[tp]},${colors[tp]}88)` };\n  }).filter(Boolean).sort((a,b)=>b.val-a.val);\n  grid.appendChild(mkCard('card-purple','\ud83e\udde9','Mix de Trabalho','Tipos de tarefas no per\u00edodo', tiposData));\n}\n\n\/\/ =============================================\n\/\/ BADGES\n\/\/ =============================================\nfunction atualizarBadgesTabs() {\n  const total    = estado.tarefas.length;\n  const filtradas= estado.tarefasFiltradas.length || total;\n  const el1 = document.getElementById('tabTotalBadge');\n  const el2 = document.getElementById('tabTarefasBadge');\n  const el3 = document.getElementById('tabKanbanBadge');\n  if (el1) el1.textContent = total;\n  if (el2) el2.textContent = filtradas;\n  if (el3) el3.textContent = total;\n}\n\n\/\/ =============================================\n\/\/ MODAL\n\/\/ =============================================\nfunction abrirModal(titulo, texto, callback, textoBtn) {\n  document.getElementById('modalTitle').textContent = titulo;\n  document.getElementById('modalText').textContent  = texto;\n  if (textoBtn) document.getElementById('modalConfirmBtn').textContent = textoBtn;\n  estado.modalCallback = callback;\n  document.getElementById('modalOverlay').classList.add('active');\n}\nfunction fecharModal() { document.getElementById('modalOverlay').classList.remove('active'); estado.modalCallback = null; }\nfunction confirmarModal() { if (estado.modalCallback) estado.modalCallback(); fecharModal(); }\ndocument.getElementById('modalOverlay').addEventListener('click', function(e) { if (e.target === this) fecharModal(); });\n\n\/\/ =============================================\n\/\/ TOAST\n\/\/ =============================================\nfunction mostrarToast(msg, tipo='info') {\n  const container = document.getElementById('toastContainer');\n  const icons = { success:'\u2713', error:'\u2715', info:'\u2139' };\n  const toast = document.createElement('div');\n  toast.className = `toast toast-${tipo}`;\n  toast.innerHTML = `<span style=\"font-size:15px;\">${icons[tipo]||'\u2139'}<\/span><span>${esc(msg)}<\/span>`;\n  container.appendChild(toast);\n  setTimeout(() => { toast.classList.add('removing'); setTimeout(() => toast.remove(), 300); }, 3500);\n}\n\n\/\/ =============================================\n\/\/ UTILS\n\/\/ =============================================\nfunction gerarId() { return 'T'+Date.now().toString(36).toUpperCase()+Math.random().toString(36).substr(2,3).toUpperCase(); }\nfunction esc(str) { if(!str) return ''; return String(str).replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;').replace(\/\"\/g,'&quot;'); }\nfunction formatarData(iso) { if(!iso) return ''; const [y,m,d]=iso.split('-'); return `${d}\/${m}\/${y}`; }\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Link Task \u2014 Painel Scrum LT Link Task Acesso restrito a contas Google autorizadas.Fa\u00e7a login para continuar. Seus dados ficam no seu Google Sheets. Nenhuma informa\u00e7\u00e3o \u00e9 enviada a terceiros. \ud83d\ude80 Configura\u00e7\u00e3o Inicial Personalize o Link Task com a identidade visual da sua empresa. Tipo de Logo \ud83c\udd71\ufe0f Texto \ud83d\uddbc\ufe0f Imagem \u2b21 Padr\u00e3o Configurar Texto [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-6","page","type-page","status-publish","hentry"],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=\/wp\/v2\/pages\/6","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6"}],"version-history":[{"count":113,"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=\/wp\/v2\/pages\/6\/revisions"}],"predecessor-version":[{"id":127,"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=\/wp\/v2\/pages\/6\/revisions\/127"}],"wp:attachment":[{"href":"https:\/\/bpo.link-ceo.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}