<?php
/**
 * 1MZ For Artists — Projects admin page (v2: full-screen, live chat, anexos)
 *
 * Substitui a UI da função onemz_mostrar_pagina_projetos.
 * Carregado pelo plugin principal antes de admin-views.php.
 *
 * @package 1MZ_For_Artists
 * @since 1.5.193
 */

if ( ! defined( 'ABSPATH' ) ) exit;

/* ============================================================================
 * CSS + JS específicos da página
 * ============================================================================ */
function rmbz_projects_v2_styles() {
    ?>
    <style>
    /* Reset wp-admin: aproveitar largura toda. WP injecta `#wpcontent { padding-left: 20px }`
       que limita a 1200px nalguns ecrãs — quebramos isso para a página de projetos. */
    body.toplevel_page_rmbz-projetos.rmbz-pjv2-fullscreen #wpcontent,
    body.rmbz-dashboard_page_rmbz-projetos.rmbz-pjv2-fullscreen #wpcontent {
        padding-left: 0 !important;
        background: #f3f4f6;
    }
    body.rmbz-pjv2-fullscreen #wpbody-content {
        padding-bottom: 0 !important;
    }

    .rmbz-pjv2 {
        font-family: "Roboto", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
        color: #1a1a1f;
        line-height: 1.5;
        margin: 0;
        padding: 0;
        background: #f3f4f6;
        min-height: calc(100vh - 32px);
    }
    .rmbz-pjv2 *, .rmbz-pjv2 *::before, .rmbz-pjv2 *::after { box-sizing: border-box; }

    /* ── PAGE LIST (todos os projetos) ───────────────────────────────────── */
    .rmbz-pjv2-list-wrap { padding: 20px 24px; }
    .rmbz-pjv2-list-head {
        display: flex; justify-content: space-between; align-items: flex-end;
        gap: 16px; margin-bottom: 20px; flex-wrap: wrap;
    }
    .rmbz-pjv2-list-head h1 {
        margin: 0; font-size: 26px; font-weight: 700; color: #1a1a1f;
        letter-spacing: -0.02em;
        display: flex; align-items: center; gap: 10px;
    }
    .rmbz-pjv2-list-head .sub {
        margin: 4px 0 0 0; color: #5f6368; font-size: 14px;
    }
    .rmbz-pjv2-list-toolbar {
        display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
        background: #fff; padding: 14px 16px; border: 1px solid #ebecf0;
        border-radius: 12px; margin-bottom: 14px;
    }
    .rmbz-pjv2-search {
        flex: 1; min-width: 280px; position: relative;
        background: #f3f4f6; border: 1px solid #ebecf0; border-radius: 28px;
        transition: 0.15s;
    }
    .rmbz-pjv2-search:focus-within {
        background: #fff; border-color: #1a1a1f;
        box-shadow: 0 0 0 3px rgba(26,26,31,0.08);
    }
    .rmbz-pjv2-search input {
        width: 100%; padding: 12px 16px 12px 44px;
        border: none; background: transparent; font-size: 14px; outline: none;
    }
    .rmbz-pjv2-search::before {
        content: ""; position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
        width: 18px; height: 18px;
        background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%235f6368'><path d='M15.5 14h-.79l-.28-.27a6.5 6.5 0 0 0 1.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 0 0-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 0 0 5.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14z'/></svg>") center/contain no-repeat;
    }
    .rmbz-pjv2-filters { display: flex; gap: 6px; flex-wrap: wrap; }
    .rmbz-pjv2-filter {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 8px 14px; border: 1px solid #d8dae0; background: #fff;
        border-radius: 8px; font-size: 13px; font-weight: 500;
        cursor: pointer; color: #1a1a1f; font-family: inherit;
    }
    .rmbz-pjv2-filter:hover { background: #f9fafb; }
    .rmbz-pjv2-filter.is-active {
        background: #1a1a1f; color: #fff; border-color: #1a1a1f;
    }
    .rmbz-pjv2-filter .count {
        background: rgba(0,0,0,0.08); padding: 1px 7px; border-radius: 999px;
        font-size: 11px; font-weight: 600; min-width: 20px; text-align: center;
    }
    .rmbz-pjv2-filter.is-active .count { background: rgba(255,255,255,0.22); }
    .rmbz-pjv2-filter--rejected {
        color: #991b1b; border-color: #fecaca; background: #fff7f7;
    }
    .rmbz-pjv2-filter--rejected:hover { background: #fee2e2; }
    .rmbz-pjv2-filter--rejected.is-active {
        color: #fff; border-color: #991b1b; background: #991b1b;
    }
    .rmbz-pjv2-filter--cancelled {
        color: #9a3412; border-color: #fed7aa; background: #fffaf5;
    }
    .rmbz-pjv2-filter--cancelled:hover { background: #ffedd5; }
    .rmbz-pjv2-filter--cancelled.is-active {
        color: #fff; border-color: #9a3412; background: #9a3412;
    }

    /* [1.5.200] Filtro "Mensagens novas" — visual alerta */
    .rmbz-pjv2-filter--alert {
        border-color: #ef4444;
        color: #991b1b;
        background: #fee2e2;
    }
    .rmbz-pjv2-filter--alert:hover { background: #fecaca; }
    .rmbz-pjv2-filter--alert.is-active {
        background: #ef4444; color: #fff; border-color: #ef4444;
    }
    .rmbz-pjv2-filter--alert .count { background: rgba(0,0,0,0.10); }
    .rmbz-pjv2-filter--alert.is-active .count { background: rgba(255,255,255,0.28); }

    .rmbz-pjv2-grid {
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
        gap: 14px;
    }
    .rmbz-pjv2-card {
        background: #fff; border: 1px solid #ebecf0; border-radius: 14px;
        padding: 16px; transition: 0.15s; cursor: pointer;
        display: flex; flex-direction: column; gap: 12px;
        position: relative; /* para o badge unread */
    }
    .rmbz-pjv2-card:hover {
        border-color: #d8dae0;
        box-shadow: 0 6px 16px rgba(0,0,0,0.06), 0 1px 3px rgba(0,0,0,0.04);
        transform: translateY(-1px);
    }
    .rmbz-pjv2-card.is-new { background: #fffbeb; border-color: #fde68a; }
    .rmbz-pjv2-card.has-unread {
        border-color: #ef4444;
        box-shadow: 0 0 0 1px #ef4444;
    }
    .rmbz-pjv2-card.has-unread.is-new {
        /* combinação: novo + mensagem nova — fica com aro vermelho mas fundo amarelo */
        border-color: #ef4444;
    }
    .rmbz-pjv2-card-unread {
        position: absolute;
        top: -8px; right: -8px;
        background: #ef4444; color: #fff;
        font-size: 11px; font-weight: 700;
        min-width: 22px; height: 22px;
        padding: 0 7px;
        border-radius: 999px;
        display: inline-flex; align-items: center; justify-content: center;
        box-shadow: 0 2px 6px rgba(239,68,68,0.4);
        animation: rmbzPjv2Pulse 2s ease-in-out infinite;
        z-index: 2;
    }
    @keyframes rmbzPjv2Pulse {
        0%, 100% { transform: scale(1); }
        50%      { transform: scale(1.08); }
    }
    .rmbz-pjv2-btn-badge {
        background: rgba(255,255,255,0.25);
        color: #fff;
        font-size: 10px; font-weight: 700;
        min-width: 18px; height: 18px;
        padding: 0 6px;
        margin-left: 6px;
        border-radius: 999px;
        display: inline-flex; align-items: center; justify-content: center;
    }

    .rmbz-pjv2-card-head {
        display: flex; gap: 12px; align-items: flex-start;
    }
    .rmbz-pjv2-card-avatar {
        width: 44px; height: 44px; border-radius: 50%;
        background: linear-gradient(135deg, #1a1a1f, #3a3a45);
        color: #f0b90b; font-weight: 700; font-size: 16px;
        display: flex; align-items: center; justify-content: center;
        flex-shrink: 0;
    }
    .rmbz-pjv2-card-id { flex: 1; min-width: 0; }
    .rmbz-pjv2-card-title {
        font-size: 15px; font-weight: 600; margin: 0;
        color: #1a1a1f;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .rmbz-pjv2-card-artist {
        font-size: 12px; color: #5f6368; margin-top: 2px;
    }

    .rmbz-pjv2-status {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 4px 11px; border-radius: 999px;
        font-size: 11px; font-weight: 600;
        text-transform: uppercase; letter-spacing: 0.4px;
        border: 1px solid transparent;
    }
    .rmbz-pjv2-status .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
    .rmbz-pjv2-status--pending_review { background: #fef3c7; color: #92400e; border-color: #fde68a; }
    .rmbz-pjv2-status--pre-production { background: #dbeafe; color: #1e40af; border-color: #bfdbfe; }
    .rmbz-pjv2-status--kyc_review     { background: #fed7aa; color: #9a3412; border-color: #fdba74; }
    .rmbz-pjv2-status--filming        { background: #e0f2fe; color: #075985; border-color: #bae6fd; }
    .rmbz-pjv2-status--editing        { background: #ede9fe; color: #5b21b6; border-color: #ddd6fe; }
    .rmbz-pjv2-status--done           { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
    .rmbz-pjv2-status--correction     { background: #fed7aa; color: #9a3412; border-color: #fdba74; }
    .rmbz-pjv2-status--rejected       { background: #fee2e2; color: #991b1b; border-color: #fca5a5; }

    /* [1.6.118.24] Idade do projeto */
    .rmbz-pjv2-age {
        display: inline-flex; align-items: center; gap: 4px;
        padding: 3px 9px; border-radius: 999px;
        font-size: 11px; font-weight: 600;
        background: #f1f3f5; color: #5f6368;
        border: 1px solid #ebecf0;
    }
    .rmbz-pjv2-age--warn   { background: #fef3c7; color: #92400e; border-color: #fde68a; }
    .rmbz-pjv2-age--urgent { background: #fee2e2; color: #991b1b; border-color: #fca5a5; }

    /* [1.6.118.24] Online / Offline pill */
    .rmbz-pjv2-online {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 3px 10px; border-radius: 999px;
        font-size: 11px; font-weight: 700;
        background: #d1fae5; color: #065f46;
        border: 1px solid #6ee7b7;
    }
    .rmbz-pjv2-online .pulse {
        width: 8px; height: 8px; background: #10b981;
        border-radius: 50%;
        box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.5);
        animation: rmbz-pjv2-pulse 2s infinite;
    }
    @keyframes rmbz-pjv2-pulse {
        0%   { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
        70%  { box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
        100% { box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
    }
    .rmbz-pjv2-offline {
        display: inline-flex; align-items: center; gap: 4px;
        padding: 3px 9px; border-radius: 999px;
        font-size: 11px; font-weight: 500;
        background: #f1f3f5; color: #5f6368;
    }

    .rmbz-pjv2-card-meta {
        display: flex; gap: 14px; flex-wrap: wrap; align-items: center;
        font-size: 12px; color: #5f6368;
    }
    .rmbz-pjv2-card-meta strong { color: #1a1a1f; font-weight: 600; }
    .rmbz-pjv2-card-meta .paid-y { color: #065f46; font-weight: 600; }
    .rmbz-pjv2-card-meta .paid-n { color: #991b1b; font-weight: 600; }

    .rmbz-pjv2-card-foot {
        display: flex; gap: 6px; margin-top: auto;
    }

    /* Botões da lista */
    .rmbz-pjv2-btn {
        display: inline-flex; align-items: center; justify-content: center;
        gap: 6px; padding: 8px 14px; border-radius: 8px;
        font-size: 12px; font-weight: 500; cursor: pointer;
        text-decoration: none; transition: 0.15s; font-family: inherit;
        border: 1px solid transparent;
    }
    .rmbz-pjv2-btn--primary { background: #1a1a1f; color: #fff; flex: 1; }
    .rmbz-pjv2-btn--primary:hover { background: #2c3338; color: #fff; transform: translateY(-1px); }
    .rmbz-pjv2-btn--primary .ico { color: #f0b90b; }
    .rmbz-pjv2-btn--outline { background: #fff; border-color: #ebecf0; color: #1a1a1f; }
    .rmbz-pjv2-btn--outline:hover { background: #f9fafb; }
    /* [1.5.239] Botão eliminar — mais visível e melhor proporcionado.
       Antes era branco com borda clara e quase desaparecia ao lado do
       botão preto "Gerir & Chat". Agora: fundo vermelho suave sólido,
       largura mínima e ícone maior. */
    .rmbz-pjv2-btn--danger {
        background: #fef2f2; border-color: #f3b4b4; color: #b91c1c;
        min-width: 44px; font-size: 14px; font-weight: 600;
    }
    .rmbz-pjv2-btn--danger:hover {
        background: #dc2626; border-color: #dc2626; color: #fff;
        transform: translateY(-1px);
    }

    /* [1.5.239] Modal de confirmação de eliminação de projeto */
    .rmbz-pjv2-delmodal-overlay {
        display: none; position: fixed; inset: 0; z-index: 99999;
        background: rgba(15, 15, 20, 0.55);
        align-items: center; justify-content: center; padding: 20px;
    }
    .rmbz-pjv2-delmodal-overlay.is-open { display: flex; }
    .rmbz-pjv2-delmodal {
        background: #fff; border-radius: 14px; max-width: 420px; width: 100%;
        padding: 22px; box-shadow: 0 20px 60px rgba(0,0,0,.3);
        font-family: inherit;
    }
    .rmbz-pjv2-delmodal h3 {
        margin: 0 0 6px; font-size: 17px; color: #1a1a1f;
    }
    .rmbz-pjv2-delmodal .sub {
        margin: 0 0 14px; font-size: 13px; color: #6b7280; line-height: 1.5;
    }
    .rmbz-pjv2-delmodal .target {
        background: #f9fafb; border: 1px solid #ededf0; border-radius: 8px;
        padding: 10px 12px; margin-bottom: 14px; font-size: 13px;
    }
    .rmbz-pjv2-delmodal .target strong { color: #1a1a1f; }
    .rmbz-pjv2-delmodal label {
        display: block; font-size: 12px; font-weight: 600;
        color: #374151; margin-bottom: 6px;
    }
    .rmbz-pjv2-delmodal input[type=text] {
        width: 100%; box-sizing: border-box; padding: 9px 11px;
        border: 1px solid #d1d5db; border-radius: 8px; font-size: 14px;
        font-family: inherit;
    }
    .rmbz-pjv2-delmodal input[type=text].mismatch { border-color: #f3b4b4; }
    .rmbz-pjv2-delmodal input[type=text].match { border-color: #86efac; }
    .rmbz-pjv2-delmodal .hint {
        font-size: 11px; margin: 6px 0 0; min-height: 14px;
    }
    .rmbz-pjv2-delmodal .hint.err { color: #b91c1c; }
    .rmbz-pjv2-delmodal .hint.ok  { color: #15803d; }
    .rmbz-pjv2-delmodal-actions {
        display: flex; gap: 10px; margin-top: 18px;
    }
    .rmbz-pjv2-delmodal-actions button,
    .rmbz-pjv2-delmodal-actions a {
        flex: 1; padding: 9px 14px; border-radius: 8px; font-size: 13px;
        font-weight: 600; cursor: pointer; text-align: center;
        text-decoration: none; border: 1px solid transparent;
        font-family: inherit;
    }
    .rmbz-pjv2-delmodal-cancel {
        background: #fff; border-color: #d1d5db; color: #374151;
    }
    .rmbz-pjv2-delmodal-cancel:hover { background: #f9fafb; }
    .rmbz-pjv2-delmodal-confirm {
        background: #dc2626; color: #fff;
    }
    .rmbz-pjv2-delmodal-confirm:hover { background: #b91c1c; }
    .rmbz-pjv2-delmodal-confirm[aria-disabled="true"] {
        background: #e5e7eb; color: #9ca3af; cursor: not-allowed;
        pointer-events: none;
    }

    /* ──────────────────────────────────────────────────────────────────────
     * PAGE DETAIL — FULL SCREEN, 3 colunas (esq=ficha, meio=chat, dir=gestão)
     * ────────────────────────────────────────────────────────────────────── */
    .rmbz-pjv2-detail {
        display: grid;
        /* [1.6.366] Linha "alert" no topo (avisos de subscrição). Quando não há
           aviso, o div .rmbz-pjv2-alert fica vazio → linha auto de 0px. */
        grid-template-rows: auto auto 1fr;
        /* [1.6.118.37] Coluna "manage" (orçamento) precisava de mais espaço — tabela tem 7
           colunas no modo misto. Aumentei manage para 460-520px e dei ao chat minmax(0, 1fr)
           sem cap superior — chat continua flexível mas já não monopoliza o ecrã. */
        /* [1.5.398] Coluna side alargada (280-300 → 360-400) para caber o bloco
           "Transferência de Projeto" sem encurtar os campos. */
        grid-template-columns: minmax(360px, 400px) minmax(0, 1fr) minmax(460px, 520px);
        grid-template-areas:
            "alert  alert  alert"
            "topbar topbar topbar"
            "side   chat   manage";
        height: calc(100vh - 32px);
        background: #f3f4f6;
        overflow: hidden;
    }
    /* [1.6.366] Banner de aviso ocupa a sua própria linha (não desalinha o grid).
       line-height:0 colapsa a linha quando está vazio (só espaços do template);
       os banners têm o seu próprio line-height inline. */
    .rmbz-pjv2-alert { grid-area: alert; line-height: 0; }
    .rmbz-pjv2-alert > div { line-height: 1.45; }
    @media (max-width: 1380px) {
        /* [1.6.118.37] Antes era 1280px. Subi o breakpoint porque com manage maior
           o layout 3-col precisa de mais ecrã para respirar. */
        .rmbz-pjv2-detail {
            grid-template-rows: auto auto 1fr auto;
            grid-template-columns: minmax(0, 1fr) minmax(420px, 480px);
            grid-template-areas:
                "alert  alert"
                "topbar topbar"
                "chat   manage"
                "side   side";
        }
        .rmbz-pjv2-side { max-height: 380px; overflow-y: auto; }
    }
    @media (max-width: 880px) {
        .rmbz-pjv2-detail {
            grid-template-rows: none;
            grid-template-columns: 1fr;
            grid-template-areas: "alert" "topbar" "chat" "manage" "side";
            height: auto;
        }
        .rmbz-pjv2-side { max-height: none; }
    }

    .rmbz-pjv2-topbar {
        grid-area: topbar;
        background: #fff; border-bottom: 1px solid #ebecf0;
        padding: 12px 20px;
        display: flex; align-items: center; gap: 16px;
        box-shadow: 0 1px 3px rgba(0,0,0,0.04);
        z-index: 5;
    }
    .rmbz-pjv2-topbar .back {
        display: inline-flex; align-items: center; gap: 8px;
        padding: 7px 14px; border-radius: 999px;
        background: #f3f4f6; border: 1px solid #ebecf0; color: #1a1a1f;
        font-size: 13px; font-weight: 500; text-decoration: none;
    }
    .rmbz-pjv2-topbar .back:hover { background: #ebecf0; }

    .rmbz-pjv2-topbar .titlebar {
        flex: 1; min-width: 0;
        display: flex; align-items: center; gap: 14px;
    }
    .rmbz-pjv2-topbar .titlebar .icon-wrap {
        width: 42px; height: 42px; border-radius: 10px;
        background: linear-gradient(135deg, #1a1a1f, #3a3a45);
        display: flex; align-items: center; justify-content: center;
        color: #f0b90b; font-size: 20px;
    }
    .rmbz-pjv2-topbar .titlebar .meta { min-width: 0; flex: 1; }
    .rmbz-pjv2-topbar .titlebar h1 {
        margin: 0; font-size: 17px; font-weight: 700; color: #1a1a1f;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .rmbz-pjv2-topbar .titlebar .who {
        font-size: 12px; color: #5f6368;
        display: flex; gap: 10px; align-items: center; flex-wrap: wrap;
    }
    .rmbz-pjv2-topbar .titlebar .who code {
        background: #f3f4f6; padding: 1px 6px; border-radius: 4px;
        font-size: 11px; font-family: "Roboto Mono", monospace;
    }

    .rmbz-pjv2-topbar .actions {
        display: flex; gap: 8px; align-items: center;
    }

    /* ── Coluna esq: ficha do projeto + audio demo */
    .rmbz-pjv2-side {
        grid-area: side;
        background: #fff; border-right: 1px solid #ebecf0;
        padding: 18px; overflow-y: auto;
    }
    .rmbz-pjv2-side h3 {
        margin: 0 0 12px 0; font-size: 12px; font-weight: 600;
        color: #5f6368; text-transform: uppercase; letter-spacing: 0.5px;
        display: flex; align-items: center; gap: 8px;
    }
    .rmbz-pjv2-side h3 .ico {
        width: 22px; height: 22px;
        display: inline-flex; align-items: center; justify-content: center;
        background: #f3f4f6; border-radius: 6px; font-size: 12px;
    }
    .rmbz-pjv2-side-block + .rmbz-pjv2-side-block {
        margin-top: 18px; padding-top: 18px; border-top: 1px solid #ebecf0;
    }
    .rmbz-pjv2-side .row {
        display: flex; justify-content: space-between; gap: 10px;
        padding: 6px 0; font-size: 13px;
    }
    .rmbz-pjv2-side .row .k { color: #5f6368; font-size: 12px; font-weight: 500; }
    .rmbz-pjv2-side .row .v { color: #1a1a1f; font-weight: 500; text-align: right; }
    .rmbz-pjv2-side .pitch {
        background: #f3f4f6; border: 1px solid #ebecf0; border-radius: 10px;
        padding: 12px; font-size: 13px; line-height: 1.55; color: #1a1a1f;
        white-space: pre-wrap;
        max-height: 220px; overflow-y: auto;
    }
    .rmbz-pjv2-side audio { width: 100%; height: 36px; }
    .rmbz-pjv2-side .demo-actions {
        display: flex; gap: 6px; margin-top: 8px;
    }

    /* [1.6.118.23] CONTEXTO DO ARTISTA — saldo + VIP */
    .rmbz-pjv2-context-block .rmbz-pjv2-ctx-row {
        padding: 10px 12px; background: #f7f7fb; border-radius: 10px;
        margin-bottom: 8px; border: 1px solid #ebecf0;
    }
    .rmbz-pjv2-context-block .ctx-label {
        font-size: 11px; text-transform: uppercase; font-weight: 700;
        color: #5f6368; letter-spacing: 0.3px; margin-bottom: 4px;
    }
    .rmbz-pjv2-context-block .ctx-value {
        font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums;
        line-height: 1.2;
    }
    .rmbz-pjv2-context-block .ctx-value.ok      { color: #047857; }
    .rmbz-pjv2-context-block .ctx-value.partial { color: #b45309; }
    .rmbz-pjv2-context-block .ctx-value.empty   { color: #b91c1c; }
    .rmbz-pjv2-context-block .ctx-hint {
        font-size: 11px; color: #5f6368; margin-top: 4px; line-height: 1.4;
    }
    .rmbz-pjv2-context-block .ctx-hint strong { color: #1d2327; }
    .rmbz-pjv2-context-block .rmbz-pjv2-ctx-link {
        display: block; text-align: center; padding: 8px 12px;
        background: #1d2327; color: #f0b90b; border-radius: 8px;
        font-size: 12px; font-weight: 700; text-transform: uppercase;
        letter-spacing: 0.5px; text-decoration: none; margin-top: 4px;
        transition: 0.15s;
    }
    .rmbz-pjv2-context-block .rmbz-pjv2-ctx-link:hover {
        background: #2c2c34; color: #f0b90b; transform: translateY(-1px);
    }

    /* [1.6.118.23] OUTROS PROJETOS — track record */
    .rmbz-pjv2-other-projects h3 .count-badge {
        margin-left: auto; padding: 2px 9px; background: #1d2327;
        color: #f0b90b; border-radius: 10px; font-size: 11px; font-weight: 700;
    }
    .rmbz-pjv2-other-projects h3 {
        display: flex; align-items: center; gap: 6px;
    }
    .rmbz-pjv2-other-projects .op-summary {
        display: flex; gap: 12px; font-size: 12px; margin-bottom: 10px;
        padding: 8px 10px; background: #f7f7fb; border-radius: 8px;
    }
    .rmbz-pjv2-other-projects .op-ok  { color: #047857; font-weight: 600; }
    .rmbz-pjv2-other-projects .op-rej { color: #991b1b; font-weight: 600; }
    .rmbz-pjv2-other-projects .op-list {
        list-style: none; padding: 0; margin: 0;
    }
    .rmbz-pjv2-other-projects .op-list li {
        margin-bottom: 6px;
    }
    .rmbz-pjv2-other-projects .op-list a {
        display: block; padding: 8px 10px; background: #fff;
        border: 1px solid #ebecf0; border-radius: 8px;
        text-decoration: none; color: inherit; transition: 0.15s;
    }
    .rmbz-pjv2-other-projects .op-list a:hover {
        border-color: #1d2327; background: #fbfbfc; transform: translateX(2px);
    }
    .rmbz-pjv2-other-projects .op-title {
        font-size: 13px; font-weight: 600; color: #1d2327;
        margin-bottom: 4px; line-height: 1.3;
    }
    .rmbz-pjv2-other-projects .op-meta {
        display: flex; gap: 6px; align-items: center; flex-wrap: wrap;
        font-size: 11px;
    }
    .rmbz-pjv2-other-projects .op-status {
        padding: 2px 7px; border-radius: 6px; font-weight: 600;
        font-size: 10px; text-transform: uppercase; letter-spacing: 0.3px;
    }
    .rmbz-pjv2-other-projects .op-status-pending_review { background: #fef3c7; color: #92400e; }
    .rmbz-pjv2-other-projects .op-status-pre-production { background: #dbeafe; color: #1e40af; }
    .rmbz-pjv2-other-projects .op-status-kyc_review     { background: #ede9fe; color: #5b21b6; }
    .rmbz-pjv2-other-projects .op-status-filming        { background: #fed7aa; color: #9a3412; }
    .rmbz-pjv2-other-projects .op-status-editing        { background: #fde68a; color: #92400e; }
    .rmbz-pjv2-other-projects .op-status-done           { background: #d1fae5; color: #065f46; }
    .rmbz-pjv2-other-projects .op-status-correction     { background: #fde2e7; color: #9d174d; }
    .rmbz-pjv2-other-projects .op-status-rejected       { background: #fee2e2; color: #991b1b; }
    .rmbz-pjv2-other-projects .op-cost {
        color: #1e40af; font-weight: 700; font-variant-numeric: tabular-nums;
    }
    .rmbz-pjv2-other-projects .op-paid.paid   { color: #047857; }
    .rmbz-pjv2-other-projects .op-paid.unpaid { color: #b91c1c; }
    .rmbz-pjv2-other-projects .op-more {
        text-align: center; font-size: 11px; color: #5f6368;
        padding: 6px; font-style: italic;
    }
    .rmbz-pjv2-side .demo-actions a {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 7px 12px; background: #1a1a1f; color: #fff;
        border-radius: 8px; font-size: 12px; font-weight: 500;
        text-decoration: none;
    }
    .rmbz-pjv2-side .demo-actions a .ico { color: #f0b90b; }
    .rmbz-pjv2-side .demo-actions a:hover { background: #2c3338; color: #fff; }

    /* ───────────────────────────────────────────────────────────────
     * COLUNA CENTRAL — CHAT LIVE
     * ─────────────────────────────────────────────────────────────── */
    .rmbz-pjv2-chat {
        grid-area: chat;
        display: flex; flex-direction: column;
        background: #f3f4f6;
        min-height: 0;
    }
    .rmbz-pjv2-chat-head {
        background: #fff; border-bottom: 1px solid #ebecf0;
        padding: 12px 20px;
        display: flex; align-items: center; gap: 14px;
        flex-wrap: wrap;
    }
    .rmbz-pjv2-chat-head .title {
        font-size: 14px; font-weight: 600; color: #1a1a1f;
        display: flex; align-items: center; gap: 8px;
        flex: 1; min-width: 0;
    }
    .rmbz-pjv2-chat-head .title .ico {
        width: 24px; height: 24px;
        display: inline-flex; align-items: center; justify-content: center;
        background: #f3f4f6; border-radius: 6px; font-size: 13px;
    }
    .rmbz-pjv2-chat-head .live-dot {
        display: inline-flex; align-items: center; gap: 6px;
        font-size: 11px; color: #5f6368; font-weight: 500;
        text-transform: uppercase; letter-spacing: 0.4px;
    }
    .rmbz-pjv2-chat-head .live-dot::before {
        content: ""; width: 8px; height: 8px; border-radius: 50%;
        background: #10b981;
        animation: rmbz-live-pulse 2s ease-in-out infinite;
    }
    @keyframes rmbz-live-pulse {
        0%, 100% { opacity: 1; transform: scale(1); }
        50%      { opacity: 0.6; transform: scale(0.85); }
    }

    /* Toggle anexos do artista (interruptor MD3) */
    .rmbz-pjv2-attach-toggle {
        display: inline-flex; align-items: center; gap: 10px;
        padding: 6px 12px; border-radius: 999px;
        background: #f3f4f6; border: 1px solid #ebecf0;
        cursor: pointer; transition: 0.15s; user-select: none;
        font-family: inherit;
    }
    .rmbz-pjv2-attach-toggle:hover { background: #ebecf0; }
    .rmbz-pjv2-attach-toggle .switch {
        width: 36px; height: 20px; border-radius: 999px;
        background: #d1d5db; position: relative; transition: 0.2s;
    }
    .rmbz-pjv2-attach-toggle .switch::after {
        content: ""; position: absolute; left: 2px; top: 2px;
        width: 16px; height: 16px; border-radius: 50%;
        background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.20);
        transition: 0.2s;
    }
    .rmbz-pjv2-attach-toggle.is-on .switch { background: #10b981; }
    .rmbz-pjv2-attach-toggle.is-on .switch::after { left: 18px; }
    .rmbz-pjv2-attach-toggle .label {
        font-size: 12px; font-weight: 500; color: #1a1a1f;
    }
    .rmbz-pjv2-attach-toggle .label .hint {
        display: block; font-size: 10px; color: #5f6368; font-weight: 400;
    }

    /* [1.6.118.24] Filtros do chat */
    .rmbz-pjv2-chat-filters {
        display: flex; gap: 4px; padding: 8px 18px;
        background: #fbfbfc; border-bottom: 1px solid #ebecf0;
    }
    .rmbz-pjv2-cf-btn {
        background: transparent; border: 1px solid transparent;
        padding: 4px 10px; border-radius: 999px;
        font-size: 11px; font-weight: 600; color: #5f6368;
        cursor: pointer; font-family: inherit; transition: 0.15s;
    }
    .rmbz-pjv2-cf-btn:hover { background: #f1f3f5; color: #1a1a1f; }
    .rmbz-pjv2-cf-btn.is-active {
        background: #1a1a1f; color: #f0b90b; border-color: #1a1a1f;
    }

    /* Filtros aplicados via data-attr no stream — esconde mensagens não-correspondentes */
    .rmbz-pjv2-chat-stream[data-chat-filter="artist"] .rmbz-pjv2-msg:not(.rmbz-pjv2-msg--artist) { display: none; }
    .rmbz-pjv2-chat-stream[data-chat-filter="admin"]  .rmbz-pjv2-msg:not(.rmbz-pjv2-msg--admin)  { display: none; }
    .rmbz-pjv2-chat-stream[data-chat-filter="system"] .rmbz-pjv2-msg:not(.rmbz-pjv2-msg--system) { display: none; }

    /* [1.6.118.24] Preview embed do contrato */
    .rmbz-pjv2-contract-preview {
        position: relative; margin-top: 10px;
        background: #fff; border: 1px solid #ebecf0;
        border-radius: 10px; overflow: hidden;
    }
    .rmbz-pjv2-contract-preview iframe {
        width: 100%; height: 380px; border: none; display: block;
    }
    .rmbz-pjv2-contract-preview--img {
        text-align: center; padding: 8px;
    }
    .rmbz-pjv2-contract-preview--img img {
        max-width: 100%; max-height: 380px; display: inline-block;
        border-radius: 6px;
    }
    .rmbz-pjv2-contract-preview-zoom {
        position: absolute; top: 8px; right: 8px;
        background: rgba(0,0,0,0.7); color: #fff;
        width: 32px; height: 32px; border-radius: 8px;
        display: inline-flex; align-items: center; justify-content: center;
        font-size: 14px; text-decoration: none; backdrop-filter: blur(4px);
        transition: 0.15s;
    }
    .rmbz-pjv2-contract-preview-zoom:hover {
        background: #000; color: #f0b90b; transform: scale(1.05);
    }

    /* Stream */
    .rmbz-pjv2-chat-stream {
        flex: 1; overflow-y: auto; padding: 14px 18px;
        scroll-behavior: smooth;
        display: flex; flex-direction: column; gap: 8px;
        background: #f3f4f6;
    }
    .rmbz-pjv2-chat-empty {
        margin: auto; text-align: center; color: #5f6368;
        font-size: 13px;
    }
    .rmbz-pjv2-chat-empty .icon {
        font-size: 38px; opacity: 0.4; margin-bottom: 10px;
    }

    .rmbz-pjv2-msg {
        display: flex; gap: 8px; max-width: 70%;
        align-items: flex-end;
        position: relative;
    }
    .rmbz-pjv2-msg--artist { align-self: flex-start; }
    .rmbz-pjv2-msg--admin  { align-self: flex-end; flex-direction: row-reverse; }
    .rmbz-pjv2-msg--system {
        align-self: center; max-width: 90%; opacity: 0.85;
    }
    .rmbz-pjv2-msg--system .bubble {
        background: #fff; border: 1px dashed #d8dae0; color: #5f6368;
        font-size: 11px; padding: 5px 12px; text-align: center;
        border-radius: 999px;
    }
    .rmbz-pjv2-msg--system .avatar { display: none; }

    .rmbz-pjv2-msg .avatar {
        width: 26px; height: 26px; border-radius: 50%; flex-shrink: 0;
        display: flex; align-items: center; justify-content: center;
        font-size: 11px; font-weight: 700;
    }
    .rmbz-pjv2-msg--artist .avatar {
        background: linear-gradient(135deg, #6b7280, #4b5563); color: #fff;
    }
    .rmbz-pjv2-msg--admin .avatar {
        background: linear-gradient(135deg, #1a1a1f, #3a3a45); color: #f0b90b;
    }

    .rmbz-pjv2-msg .bubble {
        padding: 8px 12px; border-radius: 12px;
        font-size: 13px; line-height: 1.45;
        background: #fff; border: 1px solid #ebecf0;
        color: #1a1a1f; word-wrap: break-word; word-break: break-word;
        min-width: 0;
        box-shadow: 0 1px 2px rgba(0,0,0,0.04);
    }
    .rmbz-pjv2-msg--artist .bubble { border-bottom-left-radius: 4px; }
    .rmbz-pjv2-msg--admin .bubble {
        background: #1a1a1f; color: #fff; border-color: #1a1a1f;
        border-bottom-right-radius: 4px;
    }
    .rmbz-pjv2-msg--admin .bubble a { color: #f0b90b; }
    .rmbz-pjv2-msg .bubble .meta {
        font-size: 10px; opacity: 0.6; margin-top: 4px;
        display: flex; gap: 8px; align-items: center;
    }
    .rmbz-pjv2-msg .bubble .meta .edited { font-style: italic; }
    .rmbz-pjv2-msg .bubble .meta .actions {
        display: none; gap: 8px;
    }
    .rmbz-pjv2-msg--admin .bubble:hover .meta .actions { display: inline-flex; }
    .rmbz-pjv2-msg .bubble .meta .actions a {
        color: inherit; opacity: 0.8; cursor: pointer; text-decoration: underline;
    }

    /* Anexos */
    .rmbz-pjv2-att {
        display: block; margin-top: 8px;
        border-radius: 10px; overflow: hidden;
        background: rgba(0,0,0,0.05);
    }
    .rmbz-pjv2-msg--admin .rmbz-pjv2-att { background: rgba(255,255,255,0.10); }
    .rmbz-pjv2-att img {
        display: block; max-width: 100%; max-height: 280px;
        object-fit: cover; cursor: zoom-in;
    }
    .rmbz-pjv2-att audio { width: 100%; min-width: 240px; height: 36px; display: block; }
    .rmbz-pjv2-att video { display: block; max-width: 100%; max-height: 280px; }
    .rmbz-pjv2-att-file {
        display: flex; align-items: center; gap: 10px;
        padding: 10px 14px; text-decoration: none; color: inherit;
        font-size: 13px;
    }
    .rmbz-pjv2-att-file .ico {
        width: 36px; height: 36px; border-radius: 8px;
        background: rgba(0,0,0,0.10);
        display: flex; align-items: center; justify-content: center;
        font-size: 18px; flex-shrink: 0;
    }
    .rmbz-pjv2-msg--admin .rmbz-pjv2-att-file .ico { background: rgba(255,255,255,0.18); }
    .rmbz-pjv2-att-file .name {
        flex: 1; min-width: 0; font-weight: 500;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .rmbz-pjv2-att-file .size { font-size: 11px; opacity: 0.7; }

    /* Composer */
    .rmbz-pjv2-chat-composer {
        background: #fff; border-top: 1px solid #ebecf0;
        padding: 10px 16px;
    }
    .rmbz-pjv2-composer-preview {
        margin-bottom: 8px; padding: 8px 12px;
        background: #f3f4f6; border-radius: 8px;
        display: none; align-items: center; gap: 10px;
        font-size: 12px;
    }
    .rmbz-pjv2-composer-preview.is-show { display: flex; }
    .rmbz-pjv2-composer-preview .ico {
        width: 30px; height: 30px; border-radius: 7px;
        background: #1a1a1f; color: #f0b90b;
        display: flex; align-items: center; justify-content: center;
        font-size: 14px; flex-shrink: 0;
    }
    .rmbz-pjv2-composer-preview .name { flex: 1; min-width: 0; font-weight: 500;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .rmbz-pjv2-composer-preview .size { font-size: 11px; color: #5f6368; }
    .rmbz-pjv2-composer-preview .remove {
        cursor: pointer; background: transparent; border: none;
        color: #991b1b; font-size: 18px; padding: 4px 8px;
    }
    .rmbz-pjv2-composer-preview.is-uploading {
        opacity: 0.7; pointer-events: none;
    }
    .rmbz-pjv2-composer-preview .progress {
        background: #ebecf0; border-radius: 3px; height: 4px;
        overflow: hidden; width: 100px;
    }
    .rmbz-pjv2-composer-preview .progress .bar {
        height: 100%; background: #10b981; transition: width 0.2s;
    }

    .rmbz-pjv2-composer-row {
        display: flex; gap: 8px; align-items: flex-end;
    }
    .rmbz-pjv2-composer-attach {
        display: inline-flex; align-items: center; justify-content: center;
        width: 36px; height: 36px; border-radius: 50%;
        background: #f3f4f6; border: 1px solid #ebecf0; color: #1a1a1f;
        cursor: pointer; font-size: 16px; flex-shrink: 0;
        transition: 0.15s; font-family: inherit;
    }
    .rmbz-pjv2-composer-attach:hover { background: #ebecf0; }
    .rmbz-pjv2-composer-input {
        flex: 1; min-width: 0;
        padding: 9px 14px; border: 1px solid #ebecf0; border-radius: 20px;
        background: #f3f4f6; font-size: 13px; outline: none; line-height: 1.4;
        font-family: inherit; resize: none;
        max-height: 100px; min-height: 36px;
    }
    .rmbz-pjv2-composer-input:focus {
        background: #fff; border-color: #1a1a1f;
        box-shadow: 0 0 0 3px rgba(26,26,31,0.06);
    }
    .rmbz-pjv2-composer-send {
        display: inline-flex; align-items: center; justify-content: center;
        width: 36px; height: 36px; border-radius: 50%;
        background: #1a1a1f; color: #f0b90b; border: none;
        cursor: pointer; font-size: 16px; flex-shrink: 0;
        transition: 0.15s; font-family: inherit;
    }
    .rmbz-pjv2-composer-send:hover { background: #2c3338; }
    .rmbz-pjv2-composer-send:disabled {
        background: #d1d5db; color: #9ca3af; cursor: not-allowed;
    }

    /* ───────────────────────────────────────────────────────────────
     * COLUNA DIREITA — GESTÃO (estado, contrato, etc.)
     * ─────────────────────────────────────────────────────────────── */
    .rmbz-pjv2-manage {
        grid-area: manage;
        background: #fff; border-left: 1px solid #ebecf0;
        padding: 18px; overflow-y: auto;
    }
    .rmbz-pjv2-manage h3 {
        margin: 0 0 12px 0; font-size: 12px; font-weight: 600;
        color: #5f6368; text-transform: uppercase; letter-spacing: 0.5px;
        display: flex; align-items: center; gap: 8px;
    }
    .rmbz-pjv2-manage h3 .ico {
        width: 22px; height: 22px;
        display: inline-flex; align-items: center; justify-content: center;
        background: #f3f4f6; border-radius: 6px; font-size: 12px;
    }
    .rmbz-pjv2-manage-block + .rmbz-pjv2-manage-block {
        margin-top: 18px; padding-top: 18px; border-top: 1px solid #ebecf0;
    }

    .rmbz-pjv2-state-pills {
        display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px;
    }
    .rmbz-pjv2-state-pill {
        display: inline-flex; align-items: center; gap: 6px;
        padding: 8px 12px; border: 1px solid #d8dae0; background: #fff;
        border-radius: 8px; font-size: 12px; font-weight: 500;
        cursor: pointer; color: #1a1a1f; font-family: inherit;
    }
    .rmbz-pjv2-state-pill:hover { background: #f3f4f6; }
    .rmbz-pjv2-state-pill.is-active {
        background: #1a1a1f; color: #fff; border-color: #1a1a1f;
    }

    /* [1.6.118.21] Quick actions — aprovar/rejeitar/correção */
    .rmbz-pjv2-quick-actions {
        background: linear-gradient(135deg, #fef9e7 0%, #fff8e1 100%);
        border: 1px solid #f0d676;
        border-radius: 12px;
        padding: 14px 16px;
        margin-bottom: 14px;
    }
    .rmbz-pjv2-quick-actions .qa-title {
        font-size: 12px; font-weight: 700; text-transform: uppercase;
        color: #1d2327; letter-spacing: 0.5px; margin-bottom: 10px;
    }
    .rmbz-pjv2-quick-actions .qa-buttons {
        display: grid; grid-template-columns: 1fr; gap: 8px;
    }
    .rmbz-pjv2-quick-actions .qa-btn {
        display: flex; flex-direction: column; align-items: flex-start;
        padding: 10px 14px; border: 1px solid; border-radius: 8px;
        background: #fff; cursor: pointer; font-family: inherit;
        font-size: 14px; font-weight: 700; text-align: left;
        transition: 0.15s; line-height: 1.2;
    }
    .rmbz-pjv2-quick-actions .qa-btn .qa-sub {
        font-size: 11px; font-weight: 500; opacity: 0.7; margin-top: 3px;
        text-transform: none; letter-spacing: 0;
    }
    .rmbz-pjv2-quick-actions .qa-btn:hover { transform: translateY(-1px); }
    .rmbz-pjv2-quick-actions .qa-approve {
        color: #047857; border-color: #10b981;
    }
    .rmbz-pjv2-quick-actions .qa-approve:hover {
        background: #10b981; color: #fff; border-color: #047857;
    }
    .rmbz-pjv2-quick-actions .qa-approve.is-selected {
        background: #10b981; color: #fff; border-color: #047857; box-shadow: 0 2px 8px rgba(16, 185, 129, 0.3);
    }
    .rmbz-pjv2-quick-actions .qa-correction {
        color: #b45309; border-color: #f59e0b;
    }
    .rmbz-pjv2-quick-actions .qa-correction:hover {
        background: #f59e0b; color: #fff; border-color: #b45309;
    }
    .rmbz-pjv2-quick-actions .qa-correction.is-selected {
        background: #f59e0b; color: #fff; border-color: #b45309; box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);
    }
    .rmbz-pjv2-quick-actions .qa-reject {
        color: #991b1b; border-color: #ef4444;
    }
    .rmbz-pjv2-quick-actions .qa-reject:hover {
        background: #ef4444; color: #fff; border-color: #991b1b;
    }
    .rmbz-pjv2-quick-actions .qa-reject.is-selected {
        background: #ef4444; color: #fff; border-color: #991b1b; box-shadow: 0 2px 8px rgba(239, 68, 68, 0.3);
    }
    /* [1.6.118.24] qa-info (azul) — usado em mudanças de fluxo neutras */
    .rmbz-pjv2-quick-actions .qa-info {
        color: #1e40af; border-color: #3b82f6;
    }
    .rmbz-pjv2-quick-actions .qa-info:hover {
        background: #3b82f6; color: #fff; border-color: #1e40af;
    }
    .rmbz-pjv2-quick-actions .qa-info.is-selected {
        background: #3b82f6; color: #fff; border-color: #1e40af; box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
    }
    /* qa-final (info-only — para estados rejected/done) */
    .rmbz-pjv2-qa-final {
        background: #f7f7fb !important;
        border-color: #ebecf0 !important;
    }
    .rmbz-pjv2-qa-final .qa-title {
        color: #5f6368 !important;
    }
    .rmbz-pjv2-quick-actions .qa-hint {
        font-size: 11px; color: #5f6368; margin: 10px 0 0 0; line-height: 1.4;
    }
    .rmbz-pjv2-quick-actions .qa-hint strong { color: #1d2327; }

    /* [1.6.118.22] Estado de pagamento inteligente */
    .rmbz-pjv2-payment-state {
        border-radius: 10px;
        padding: 14px 16px;
        border: 1px solid;
    }
    .rmbz-pjv2-payment-state.paid-full {
        background: linear-gradient(135deg, #d1fae5 0%, #ecfdf5 100%);
        border-color: #6ee7b7;
    }
    .rmbz-pjv2-payment-state.paid-part {
        background: linear-gradient(135deg, #fef3c7 0%, #fffbeb 100%);
        border-color: #fcd34d;
    }
    .rmbz-pjv2-payment-state.paid-none {
        background: linear-gradient(135deg, #fee2e2 0%, #fef2f2 100%);
        border-color: #fca5a5;
    }
    .rmbz-pjv2-payment-state .ps-header {
        display: flex; align-items: center; justify-content: space-between;
        margin-bottom: 8px;
    }
    .rmbz-pjv2-payment-state .ps-badge {
        font-weight: 800; font-size: 14px;
    }
    .rmbz-pjv2-payment-state.paid-full .ps-badge { color: #047857; }
    .rmbz-pjv2-payment-state.paid-part .ps-badge { color: #b45309; }
    .rmbz-pjv2-payment-state.paid-none .ps-badge { color: #b91c1c; }
    .rmbz-pjv2-payment-state .ps-pct {
        font-weight: 800; font-size: 18px; font-variant-numeric: tabular-nums;
    }
    .rmbz-pjv2-payment-state.paid-full .ps-pct { color: #047857; }
    .rmbz-pjv2-payment-state.paid-part .ps-pct { color: #b45309; }
    .rmbz-pjv2-payment-state.paid-none .ps-pct { color: #b91c1c; }
    .rmbz-pjv2-payment-state .ps-bar {
        background: rgba(0,0,0,0.08); height: 6px; border-radius: 3px;
        overflow: hidden; margin-bottom: 10px;
    }
    .rmbz-pjv2-payment-state .ps-bar-fill {
        height: 100%; border-radius: 3px; transition: width 0.3s;
    }
    .rmbz-pjv2-payment-state.paid-full .ps-bar-fill { background: linear-gradient(90deg, #10b981, #059669); }
    .rmbz-pjv2-payment-state.paid-part .ps-bar-fill { background: linear-gradient(90deg, #f59e0b, #d97706); }
    .rmbz-pjv2-payment-state.paid-none .ps-bar-fill { background: linear-gradient(90deg, #ef4444, #dc2626); }
    .rmbz-pjv2-payment-state .ps-desc {
        font-size: 12px; line-height: 1.4; opacity: 0.85; margin-bottom: 10px;
    }
    .rmbz-pjv2-payment-state.paid-full .ps-desc { color: #065f46; }
    .rmbz-pjv2-payment-state.paid-part .ps-desc { color: #92400e; }
    .rmbz-pjv2-payment-state.paid-none .ps-desc { color: #991b1b; }
    .rmbz-pjv2-payment-state .ps-numbers {
        display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
        background: rgba(255,255,255,0.6); padding: 8px 10px; border-radius: 8px;
    }
    .rmbz-pjv2-payment-state .ps-num {
        display: flex; flex-direction: column; gap: 2px;
    }
    .rmbz-pjv2-payment-state .ps-num .label {
        font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px;
        font-weight: 600; opacity: 0.7;
    }
    .rmbz-pjv2-payment-state .ps-num .value {
        font-weight: 700; font-size: 13px; font-variant-numeric: tabular-nums;
        color: #1d2327;
    }
    .rmbz-pjv2-payment-state .ps-num .value.paid  { color: #047857; }
    .rmbz-pjv2-payment-state .ps-num .value.falta { color: #b91c1c; }

    .rmbz-pjv2-field {
        margin-bottom: 12px;
    }
    .rmbz-pjv2-field label {
        display: block; font-size: 12px; font-weight: 600;
        color: #1a1a1f; margin-bottom: 5px;
    }
    .rmbz-pjv2-field input[type="text"],
    .rmbz-pjv2-field input[type="url"],
    .rmbz-pjv2-field textarea,
    .rmbz-pjv2-field select {
        width: 100%; padding: 9px 12px; border: 1px solid #d8dae0;
        border-radius: 8px; font-size: 13px; font-family: inherit;
        background: #fff; color: #1a1a1f;
    }
    .rmbz-pjv2-field input:focus, .rmbz-pjv2-field textarea:focus, .rmbz-pjv2-field select:focus {
        outline: none; border-color: #1a1a1f;
        box-shadow: 0 0 0 3px rgba(26,26,31,0.06);
    }

    .rmbz-pjv2-rejbox {
        padding: 14px; border-radius: 10px;
        background: #fef2f2; border: 1px solid #fca5a5;
        margin-bottom: 12px;
    }
    .rmbz-pjv2-rejbox--correction {
        background: #fff7ed; border-color: #fdba74;
    }

    .rmbz-pjv2-save {
        display: inline-flex; align-items: center; justify-content: center;
        gap: 8px; width: 100%; padding: 12px 18px;
        background: #1a1a1f; color: #fff; border: none;
        border-radius: 10px; font-size: 14px; font-weight: 600;
        cursor: pointer; font-family: inherit;
        box-shadow: 0 1px 3px rgba(26,26,31,0.18);
    }
    .rmbz-pjv2-save:hover { background: #2c3338; }
    .rmbz-pjv2-save .ico { color: #f0b90b; }

    /* ── Artist card (sidebar esq) ── */
    .rmbz-pjv2-artist-card {
        display: flex; flex-direction: column; gap: 10px;
    }
    .rmbz-pjv2-artist-head {
        display: flex; gap: 10px; align-items: center;
    }
    .rmbz-pjv2-artist-avatar {
        width: 38px; height: 38px; border-radius: 50%;
        background: linear-gradient(135deg, #1a1a1f, #3a3a45);
        color: #f0b90b; font-weight: 700; font-size: 14px;
        display: flex; align-items: center; justify-content: center;
        flex-shrink: 0;
    }
    .rmbz-pjv2-artist-head .name {
        font-size: 14px; font-weight: 600; color: #1a1a1f;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .rmbz-pjv2-artist-head .sub {
        font-size: 11px; color: #5f6368;
    }
    .rmbz-pjv2-artist-badges {
        display: flex; flex-wrap: wrap; gap: 5px;
    }
    .rmbz-pjv2-artist-badge {
        display: inline-flex; align-items: center; gap: 4px;
        padding: 3px 8px; border-radius: 6px;
        font-size: 10px; font-weight: 600; text-transform: uppercase;
        letter-spacing: 0.3px;
    }
    .rmbz-pjv2-artist-badge--banned { background: #fee2e2; color: #991b1b; }
    .rmbz-pjv2-artist-badge--creator { background: #d1fae5; color: #065f46; }
    .rmbz-pjv2-artist-balance {
        background: #1a1a1f; color: #f0b90b;
        padding: 7px 11px; border-radius: 8px;
        font-size: 13px; font-weight: 600;
        display: flex; justify-content: space-between; align-items: center;
    }
    .rmbz-pjv2-artist-balance .lab { font-size: 10px; opacity: 0.75; font-weight: 500; }
    .rmbz-pjv2-artist-stats {
        display: grid; grid-template-columns: repeat(2, 1fr);
        gap: 6px;
    }
    .rmbz-pjv2-artist-stat {
        background: #f7f7fb; border-radius: 6px; padding: 6px 8px;
    }
    .rmbz-pjv2-artist-stat .n { font-size: 14px; font-weight: 700; color: #1a1a1f; line-height: 1.1; }
    .rmbz-pjv2-artist-stat .l { font-size: 10px; color: #5f6368; text-transform: uppercase; letter-spacing: 0.3px; }
    .rmbz-pjv2-artist-stat.is-good .n { color: #065f46; }
    .rmbz-pjv2-artist-stat.is-bad .n { color: #991b1b; }
    .rmbz-pjv2-artist-stat.is-warn .n { color: #9a3412; }

    /* ── Recommendations (sidebar esq) ── */
    .rmbz-pjv2-rec {
        display: flex; gap: 8px; align-items: flex-start;
        padding: 8px 10px; border-radius: 8px; margin-bottom: 6px;
        font-size: 12px; line-height: 1.4;
        border: 1px solid; background: #fff;
    }
    .rmbz-pjv2-rec .ico { flex-shrink: 0; font-size: 14px; }
    .rmbz-pjv2-rec--info  { background: #eff6ff; border-color: #bfdbfe; color: #1e40af; }
    .rmbz-pjv2-rec--warn  { background: #fff7ed; border-color: #fdba74; color: #9a3412; }
    .rmbz-pjv2-rec--alert { background: #fef2f2; border-color: #fca5a5; color: #991b1b; }

    /* ── Change log (sidebar dir) — [1.5.407] M3 Expressive ── */
    .rmbz-pjv2-log-empty {
        font-size: 12px; color: #8a8794; padding: 14px;
        background: #f6f4fb; border-radius: 14px; text-align: center;
    }
    /* Timeline suave: linha lilás + pontos tonais com anel */
    .rmbz-pjv2-log-list {
        position: relative;
        padding-left: 22px;
    }
    .rmbz-pjv2-log-list::before {
        content: ""; position: absolute; left: 6px; top: 10px; bottom: 10px;
        width: 2px; border-radius: 2px; background: #ece8f5;
    }
    .rmbz-pjv2-log-entry {
        position: relative; font-size: 12px;
        padding: 9px 0 11px 0; line-height: 1.5;
    }
    .rmbz-pjv2-log-entry + .rmbz-pjv2-log-entry { border-top: 1px solid #f3f1f9; }
    .rmbz-pjv2-log-entry::before {
        content: ""; position: absolute;
        left: -20px; top: 14px;
        width: 8px; height: 8px;
        border-radius: 50%;
        background: #c9c2dd;
        box-shadow: 0 0 0 4px #f3f1f9;
    }
    .rmbz-pjv2-log-entry--admin::before  { background: #3d2a66; box-shadow: 0 0 0 4px #ece5fb; }
    .rmbz-pjv2-log-entry--artist::before { background: #2563eb; box-shadow: 0 0 0 4px #e3ecfd; }
    .rmbz-pjv2-log-entry--system::before { background: #d9a606; box-shadow: 0 0 0 4px #fdf3d7; }

    .rmbz-pjv2-log-entry .ts {
        color: #9ca3af; font-size: 10px; font-weight: 600;
        font-variant-numeric: tabular-nums; letter-spacing: .3px;
        display: block; margin-bottom: 4px;
    }
    .rmbz-pjv2-log-entry .what { color: #1a1a1f; font-weight: 600; }
    .rmbz-pjv2-log-entry .who {
        display: inline-block; padding: 2px 10px;
        background: #ece5fb; color: #3d2a66;
        border-radius: 99px; font-size: 9px;
        font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px;
        margin-right: 6px; vertical-align: 1px;
    }
    .rmbz-pjv2-log-entry--artist .who { background: #e3ecfd; color: #1d4ed8; }
    .rmbz-pjv2-log-entry--system .who { background: #fdf3d7; color: #92400e; }
    /* Diff em chips tonais (antes → depois) em vez de riscado */
    .rmbz-pjv2-log-entry .diff {
        display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
        margin-top: 7px; font-size: 11px;
    }
    .rmbz-pjv2-log-entry .diff .from,
    .rmbz-pjv2-log-entry .diff .to {
        display: inline-block; padding: 4px 10px; border-radius: 99px;
        max-width: 100%; word-break: break-word; line-height: 1.4;
    }
    .rmbz-pjv2-log-entry .diff .from { background: #fdf1f0; color: #8c1d18; text-decoration: line-through; text-decoration-thickness: 1px; opacity: .85; }
    .rmbz-pjv2-log-entry .diff .arrow { color: #b3aec6; font-weight: 700; }
    .rmbz-pjv2-log-entry .diff .to { background: #e6f4ea; color: #0d5c34; font-weight: 700; }

    /* Botão "Ver tudo" como pill tonal */
    #rmbz-pjv2-history-open.button {
        border: 0 !important; background: #ece5fb !important; color: #3d2a66 !important;
        border-radius: 99px !important; font-weight: 700 !important; font-size: 11px !important;
        padding: 3px 14px !important; box-shadow: none !important;
    }
    #rmbz-pjv2-history-open.button:hover { background: #e0d5f7 !important; }

    /* [1.5.373] Modal de histórico completo */
    .rmbz-pjv2-histmodal { display: none; position: fixed; inset: 0; z-index: 100050; }
    .rmbz-pjv2-histmodal.is-show { display: block; }
    .rmbz-pjv2-histmodal__backdrop {
        position: absolute; inset: 0; background: rgba(15,18,25,0.55);
        backdrop-filter: blur(2px); animation: rmbzHistFade .15s ease;
    }
    @keyframes rmbzHistFade { from { opacity: 0; } to { opacity: 1; } }
    .rmbz-pjv2-histmodal__panel {
        position: relative; margin: 5vh auto 0; width: min(640px, 94vw);
        max-height: 86vh; display: flex; flex-direction: column;
        background: #fff; border-radius: 24px; overflow: hidden;
        box-shadow: 0 24px 70px rgba(0,0,0,0.35);
        animation: rmbzHistPop .18s cubic-bezier(.2,.9,.3,1.2);
    }
    @keyframes rmbzHistPop { from { transform: translateY(14px) scale(.98); opacity: 0; } to { transform: none; opacity: 1; } }
    .rmbz-pjv2-histmodal__head {
        display: flex; align-items: center; justify-content: space-between;
        padding: 16px 20px; border-bottom: 1px solid #ece8f5;
        background: linear-gradient(135deg,#f6f2ff,#fff);
    }
    .rmbz-pjv2-histmodal__head h3 { margin: 0; font-size: 16px; font-weight: 800; color: #1a1a1f; letter-spacing: -.01em; }
    .rmbz-pjv2-histmodal__x {
        border: 0; background: #ece5fb; color: #3d2a66; width: 34px; height: 34px;
        border-radius: 99px; font-size: 20px; line-height: 1; cursor: pointer;
    }
    .rmbz-pjv2-histmodal__x:hover { background: #e0d5f7; color: #1a1a1f; }
    .rmbz-pjv2-histmodal__body { padding: 16px 20px; overflow-y: auto; }

    /* ── Budget table (orçamento por localização) — [1.5.409] M3 espaçoso ──
       A coluna direita é estreita → a tabela ganha largura mínima e o
       CONTENTOR faz scroll horizontal, em vez de esmagar os inputs. */
    .rmbz-pjv2-budget-scroll { overflow-x: auto; margin: 0 -4px; padding: 0 4px; }
    .rmbz-pjv2-budget-table {
        width: 100%; min-width: 560px; border-collapse: separate; border-spacing: 0 6px;
        font-size: 12px; margin-bottom: 8px;
    }
    .rmbz-pjv2-budget-table th {
        text-align: left; padding: 4px 8px;
        font-size: 10px; font-weight: 800;
        color: #5b3e70; text-transform: uppercase; letter-spacing: 0.6px;
    }
    .rmbz-pjv2-budget-table td {
        padding: 7px 5px; vertical-align: middle;
        background: #faf9fd; border-top: 1px solid #ece8f5; border-bottom: 1px solid #ece8f5;
    }
    .rmbz-pjv2-budget-table tr td:first-child { border-left: 1px solid #ece8f5; border-radius: 12px 0 0 12px; padding-left: 8px; }
    .rmbz-pjv2-budget-table tr td:last-child  { border-right: 1px solid #ece8f5; border-radius: 0 12px 12px 0; padding-right: 8px; }
    /* Larguras mínimas — categoria e item deixam de ficar encolhidos */
    .rmbz-pjv2-budget-table td:nth-child(1) { min-width: 110px; }
    .rmbz-pjv2-budget-table td:nth-child(2) { min-width: 150px; }
    .rmbz-pjv2-budget-table td:nth-child(3) { min-width: 92px; }
    .rmbz-pjv2-budget-table input[type="text"],
    .rmbz-pjv2-budget-table input[type="number"],
    .rmbz-pjv2-budget-table select {
        width: 100%; padding: 8px 12px;
        border: 1px solid #d9d2e8; border-radius: 10px;
        font-size: 12px; background: #fff; font-family: inherit;
        min-height: 34px; box-sizing: border-box;
    }
    /* [1.6.118.38] Forçar selects do orçamento a manterem-se numa linha. Sem isto,
       o select com emoji + arrow pode quebrar verticalmente em colunas estreitas. */
    .rmbz-pjv2-budget-table select {
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        line-height: 1.2;
        appearance: auto;
        -webkit-appearance: menulist;
    }
    .rmbz-pjv2-budget-table .rmbz-pjv2-checked-select {
        min-width: 56px;
        padding: 8px 4px;
        text-align: center;
    }
    /* [1.6.118.39] Span estático na coluna Status quando item não é checkable */
    .rmbz-pjv2-status-static {
        text-align: center;
        font-size: 14px;
        color: #b0b3b9;
        padding: 8px 0;
        display: block;
    }
    .rmbz-pjv2-budget-table input:focus,
    .rmbz-pjv2-budget-table select:focus {
        outline: none; border-color: #7b5bd6; box-shadow: 0 0 0 3px rgba(123,91,214,.15);
    }
    .rmbz-pjv2-row-del {
        background: #fdf1f0; color: #8c1d18;
        border: 0; border-radius: 99px;
        cursor: pointer; width: 30px; height: 30px; font-size: 13px; font-weight: 700;
        font-family: inherit; line-height: 1;
        flex: 0 0 auto;
    }
    .rmbz-pjv2-row-del:hover { background: #f9dedc; }
    /* [1.5.409] Variante com TEXTO ("Remover local") — pill, nunca esmagada. */
    .rmbz-pjv2-loc-del {
        width: auto; height: auto;
        padding: 8px 16px; font-size: 12px;
        white-space: nowrap;
    }
    .rmbz-pjv2-row-add {
        background: #ece5fb; color: #3d2a66;
        border: 0; border-radius: 99px;
        padding: 9px 18px; font-size: 12px; font-weight: 700;
        cursor: pointer; font-family: inherit;
    }
    .rmbz-pjv2-row-add:hover { background: #ebecf0; }
    .rmbz-pjv2-budget-foot {
        display: flex; justify-content: space-between; align-items: center;
        margin-top: 6px; padding-top: 8px; border-top: 1px solid #ebecf0;
    }
    .rmbz-pjv2-total { font-size: 12px; color: #5f6368; }
    .rmbz-pjv2-total strong { color: #1a1a1f; font-size: 14px; }
    .rmbz-pjv2-budget-loc {
        background: #fffbeb; border: 1px solid #fde68a; border-radius: 10px;
        padding: 12px; margin-bottom: 10px;
    }
    .rmbz-pjv2-budget-loc-head {
        display: flex; gap: 8px; align-items: center; margin-bottom: 8px;
    }
    .rmbz-pjv2-budget-loc-head input {
        flex: 1; min-width: 0; padding: 8px 12px; border: 1px solid #fcd34d;
        border-radius: 10px; font-size: 13px; font-weight: 600;
        font-family: inherit;
    }

    /* ── KYC / Contract boxes ── */
    .rmbz-pjv2-kyc-box {
        padding: 12px; border-radius: 10px; border: 1px solid;
    }
    .rmbz-pjv2-kyc-box .title {
        font-size: 13px; font-weight: 600; margin: 0 0 8px 0;
    }
    .rmbz-pjv2-kyc-box .row {
        margin: 4px 0; font-size: 12px;
    }
    .rmbz-pjv2-kyc-box .row .k { color: #5f6368; }
    .rmbz-pjv2-kyc-box--pending {
        background: #fffbeb; border-color: #fde68a;
    }
    .rmbz-pjv2-kyc-box--pending .title { color: #92400e; }
    .rmbz-pjv2-kyc-box--ok {
        background: #d1fae5; border-color: #a7f3d0;
    }
    .rmbz-pjv2-kyc-box--ok .title { color: #065f46; }
    .rmbz-pjv2-kyc-box--reject {
        background: #fef2f2; border-color: #fca5a5;
    }
    .rmbz-pjv2-kyc-box--reject .title { color: #991b1b; }
    .rmbz-pjv2-kyc-box--wait {
        background: #eff6ff; border-color: #bfdbfe;
    }
    .rmbz-pjv2-kyc-box--wait .title { color: #1e40af; }

    .rmbz-pjv2-kyc-actions {
        display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap;
    }
    .rmbz-pjv2-kyc-photo-btn {
        display: inline-block; padding: 6px 12px;
        background: #1a1a1f; color: #f0b90b;
        border-radius: 6px; font-size: 12px; font-weight: 600;
        text-decoration: none;
    }
    .rmbz-pjv2-kyc-photo-btn:hover { background: #2c3338; color: #f0b90b; }

    .rmbz-pjv2-kyc-textarea {
        width: 100%; padding: 8px 10px;
        border: 1px solid #d8dae0; border-radius: 6px;
        font-size: 12px; font-family: inherit;
        resize: vertical; min-height: 50px;
    }
    .rmbz-pjv2-file-input {
        font-size: 11px; width: 100%;
        padding: 6px; border: 1px solid #d8dae0; border-radius: 6px;
        background: #f7f7fb; font-family: inherit;
    }
    .rmbz-pjv2-btn-success,
    .rmbz-pjv2-btn-danger,
    .rmbz-pjv2-btn-outline,
    .rmbz-pjv2-btn-primary-full {
        display: inline-flex; align-items: center; justify-content: center;
        gap: 6px; padding: 7px 14px;
        border-radius: 6px; font-size: 12px; font-weight: 600;
        text-decoration: none; cursor: pointer; border: 1px solid transparent;
        font-family: inherit;
    }
    .rmbz-pjv2-btn-success { background: #10b981; color: #fff; }
    .rmbz-pjv2-btn-success:hover { background: #059669; color: #fff; }
    .rmbz-pjv2-btn-danger { background: #ef4444; color: #fff; }
    .rmbz-pjv2-btn-danger:hover { background: #dc2626; color: #fff; }
    .rmbz-pjv2-btn-outline { background: #fff; border-color: #d8dae0; color: #1a1a1f; }
    .rmbz-pjv2-btn-outline:hover { background: #f7f7fb; color: #1a1a1f; }
    .rmbz-pjv2-btn-primary-full {
        background: #1a1a1f; color: #f0b90b;
        width: 100%; margin-top: 6px; padding: 9px 14px;
    }
    .rmbz-pjv2-btn-primary-full:hover { background: #2c3338; color: #f0b90b; }

    /* Toast */
    .rmbz-pjv2-toast {
        position: fixed; bottom: 28px; left: 50%;
        transform: translateX(-50%) translateY(12px);
        background: #1a1a1f; color: #fff;
        padding: 12px 22px; border-radius: 999px;
        font-size: 13px; font-weight: 500;
        box-shadow: 0 8px 24px rgba(0,0,0,0.22);
        z-index: 99999; opacity: 0;
        transition: 0.2s; pointer-events: none;
    }
    .rmbz-pjv2-toast.is-show {
        opacity: 1; transform: translateX(-50%) translateY(0);
    }
    .rmbz-pjv2-toast .ico { color: #f0b90b; margin-right: 6px; }
    .rmbz-pjv2-toast.is-error { background: #991b1b; }
    .rmbz-pjv2-toast.is-error .ico { color: #fca5a5; }

    /* Lightbox para imagens */
    .rmbz-pjv2-lightbox {
        position: fixed; inset: 0;
        background: rgba(0,0,0,0.85);
        display: none; align-items: center; justify-content: center;
        padding: 30px; z-index: 99998;
        cursor: zoom-out;
    }
    .rmbz-pjv2-lightbox.is-show { display: flex; }
    .rmbz-pjv2-lightbox img {
        max-width: 100%; max-height: 100%;
        border-radius: 12px;
        box-shadow: 0 20px 60px rgba(0,0,0,0.5);
    }
    </style>
    <?php
}

/* ============================================================================
 * PAGE ROUTER — substitui onemz_mostrar_pagina_projetos
 * ============================================================================ */
function rmbz_pjv2_render_page() {
    global $wpdb;

    // adicionar classe ao body para o reset fullbleed
    add_filter( 'admin_body_class', function( $c ) {
        return $c . ' rmbz-pjv2-fullscreen';
    } );

    rmbz_projects_v2_styles();

    // Auto-limpeza (igual à versão antiga)
    $table_projects = $wpdb->prefix . 'rmbz_artist_projects';
    $rejeitados = $wpdb->get_results( "SELECT id, demo_mp3_url, extra_data FROM {$table_projects} WHERE production_status = 'rejected'" );
    foreach ( $rejeitados as $pr ) {
        $ext = ! empty( $pr->extra_data ) ? json_decode( $pr->extra_data, true ) : [];
        if ( isset( $ext['rejected_at'] ) ) {
            $dias = floor( ( time() - strtotime( $ext['rejected_at'] ) ) / 86400 );
            if ( $dias >= 30 ) {
                if ( function_exists( 'rmbz_destruir_ficheiro_fisico' ) ) {
                    rmbz_destruir_ficheiro_fisico( $pr->demo_mp3_url );
                    if ( ! empty( $ext['contract_url'] ) ) rmbz_destruir_ficheiro_fisico( $ext['contract_url'] );
                    if ( ! empty( $ext['final_video_url'] ) ) rmbz_destruir_ficheiro_fisico( $ext['final_video_url'] );
                }
                $wpdb->delete( $table_projects, [ 'id' => $pr->id ] );
            }
        }
    }

    if ( isset( $_GET['action'] ) && $_GET['action'] === 'edit' && isset( $_GET['id'] ) ) {
        rmbz_pjv2_render_detail( absint( $_GET['id'] ) );
    } elseif ( isset( $_GET['action'] ) && $_GET['action'] === 'team' ) {
        rmbz_pjv2_render_team_manager();
    } else {
        rmbz_pjv2_render_list();
    }
}

/* ============================================================================
 * LIST
 * ============================================================================ */
function rmbz_pjv2_render_list() {
    global $wpdb;
    $table_projects = $wpdb->prefix . 'rmbz_artist_projects';
    $table_wallets  = $wpdb->prefix . 'rmbz_wallets';
    $table_chat     = $wpdb->prefix . 'rmbz_project_chat_messages';

    // [1.5.200] LEFT JOIN com count de mensagens não-lidas pelo admin.
    // Subquery para evitar GROUP BY pesado na tabela principal.
    $projetos = $wpdb->get_results( "
        SELECT p.*, w.user_nome,
               COALESCE(c.unread_count, 0) AS unread_count
        FROM {$table_projects} p
        LEFT JOIN {$table_wallets} w ON p.artist_telemovel = w.user_telemovel
        LEFT JOIN (
            SELECT project_id, COUNT(id) AS unread_count
            FROM {$table_chat}
            WHERE read_by_admin = 0 AND author_type = 'artist' AND is_deleted = 0
            GROUP BY project_id
        ) c ON c.project_id = p.id
        ORDER BY p.contract_date DESC, p.id DESC
    " );

    // Contagens
    $status_meta = [
        'pending_review' => [ 'label' => 'Em Avaliação',  'icon' => '⏱' ],
        'pre-production' => [ 'label' => 'Aprovado',       'icon' => '✓' ],
        'kyc_review'     => [ 'label' => 'KYC Pendente',   'icon' => '🪪' ],
        'filming'        => [ 'label' => 'Filmagem',       'icon' => '🎥' ],
        'editing'        => [ 'label' => 'Edição',         'icon' => '✂' ],
        'done'           => [ 'label' => 'Concluído',      'icon' => '🚀' ],
        'correction'     => [ 'label' => 'Correção',       'icon' => '✎' ],
        'rejected'       => [ 'label' => 'Rejeitado',      'icon' => '✕' ],
        'cancelled_no_confirmation' => [ 'label' => 'Cancelado por Prazo', 'icon' => '⏱' ],
    ];
    $counts = [ 'all' => 0, 'unread' => 0 ];
    foreach ( array_keys( $status_meta ) as $k ) $counts[ $k ] = 0;
    foreach ( $projetos as $p ) {
        $counts['all']++;
        $s = $p->production_status ?: 'pending_review';
        if ( isset( $counts[ $s ] ) ) $counts[ $s ]++;
        if ( ! empty( $p->unread_count ) && (int) $p->unread_count > 0 ) {
            $counts['unread']++;
        }
    }
    ?>
    <div class="rmbz-pjv2">
        <div class="rmbz-pjv2-list-wrap">
            <div class="rmbz-pjv2-list-head">
                <div>
                    <h1>🎥 Projetos & Videoclipes</h1>
                    <p class="sub">Avalie candidaturas, acompanhe produções e converse ao vivo com os artistas.</p>
                </div>
            </div>

            <?php
            // [1.6.118.89] Abas de navegação — Projetos | Equipas & Pessoas
            $tab_projetos = admin_url( 'admin.php?page=rmbz-projetos' );
            $tab_equipas  = admin_url( 'admin.php?page=rmbz-projetos&action=team' );
            ?>
            <div style="display:flex; gap:4px; border-bottom:2px solid #e8eaed; margin:0 0 16px;">
                <a href="<?php echo esc_url( $tab_projetos ); ?>" style="padding:10px 18px; font-weight:600; font-size:14px; text-decoration:none; color:#f0b90b; border-bottom:3px solid #f0b90b; margin-bottom:-2px;">📁 Projetos</a>
                <a href="<?php echo esc_url( $tab_equipas ); ?>" style="padding:10px 18px; font-weight:600; font-size:14px; text-decoration:none; color:#5f6368; border-bottom:3px solid transparent; margin-bottom:-2px;">🎥 Equipas &amp; Pessoas</a>
            </div>

            <div class="rmbz-pjv2-list-toolbar">
                <div class="rmbz-pjv2-search">
                    <input type="text" id="rmbz-pjv2-q" placeholder="Pesquisar por artista, música, telemóvel…" autocomplete="off">
                </div>
                <div class="rmbz-pjv2-filters" role="tablist">
                    <button type="button" class="rmbz-pjv2-filter is-active" data-status="all">
                        Todos <span class="count"><?php echo (int) $counts['all']; ?></span>
                    </button>
                    <?php if ( $counts['unread'] > 0 ): ?>
                    <button type="button" class="rmbz-pjv2-filter rmbz-pjv2-filter--alert" data-status="unread">
                        💬 Mensagens novas <span class="count"><?php echo (int) $counts['unread']; ?></span>
                    </button>
                    <?php endif; ?>
                    <?php
                    $always_visible_filters = [ 'rejected', 'cancelled_no_confirmation' ];
                    foreach ( $status_meta as $k => $m ):
                        if ( $counts[ $k ] === 0 && ! in_array( $k, $always_visible_filters, true ) ) continue;
                        $filter_class = '';
                        if ( $k === 'rejected' ) $filter_class = ' rmbz-pjv2-filter--rejected';
                        if ( $k === 'cancelled_no_confirmation' ) $filter_class = ' rmbz-pjv2-filter--cancelled';
                    ?>
                        <button type="button" class="rmbz-pjv2-filter<?php echo esc_attr( $filter_class ); ?>" data-status="<?php echo esc_attr( $k ); ?>">
                            <?php echo esc_html( $m['label'] ); ?> <span class="count"><?php echo (int) $counts[ $k ]; ?></span>
                        </button>
                    <?php endforeach; ?>
                </div>
            </div>

            <?php if ( empty( $projetos ) ): ?>
                <div style="background:#fff;padding:60px 20px;text-align:center;border-radius:14px;border:1px solid #ebecf0;color:#5f6368;">
                    <div style="font-size:48px;opacity:0.4;margin-bottom:10px;">🎬</div>
                    <p style="margin:0;font-weight:600;font-size:15px;">Nenhum projeto ainda.</p>
                    <p style="margin:5px 0 0 0;font-size:13px;">Quando um artista candidatar-se para um videoclipe, aparece aqui.</p>
                </div>
            <?php else: ?>
                <div class="rmbz-pjv2-grid" id="rmbz-pjv2-grid">
                    <?php foreach ( $projetos as $p ):
                        $st = $p->production_status ?: 'pending_review';
                        $sm = $status_meta[ $st ] ?? [ 'label' => strtoupper( $st ), 'icon' => '·' ];
                        $is_new = $st === 'pending_review';
                        $unread = (int) ( $p->unread_count ?? 0 );
                        $nome = $p->user_nome ?: 'N/A';
                        $initials = '';
                        foreach ( array_slice( preg_split( '/\s+/', trim( $nome ) ), 0, 2 ) as $w ) {
                            if ( $w !== '' ) $initials .= mb_strtoupper( mb_substr( $w, 0, 1 ) );
                        }
                        if ( $initials === '' ) $initials = '?';
                        $search = strtolower( implode( ' ', array_filter( [ $nome, $p->project_title, $p->artist_telemovel, $p->music_producer ] ) ) );
                        $edit_url = admin_url( 'admin.php?page=rmbz-projetos&action=edit&id=' . $p->id );
                        $del_url  = wp_nonce_url( admin_url( 'admin-post.php?action=onemz_delete_project&project_id=' . $p->id ), 'onemz_delete_project_' . $p->id );
                        $card_classes = 'rmbz-pjv2-card';
                        if ( $is_new ) $card_classes .= ' is-new';
                        if ( $unread > 0 ) $card_classes .= ' has-unread';
                    ?>
                    <div class="<?php echo esc_attr( $card_classes ); ?>"
                         data-status="<?php echo esc_attr( $st ); ?>"
                         data-search="<?php echo esc_attr( $search ); ?>"
                         data-unread="<?php echo (int) $unread; ?>"
                         onclick="if(!event.target.closest('a,button'))window.location.href='<?php echo esc_url( $edit_url ); ?>'">
                        <?php if ( $unread > 0 ): ?>
                        <div class="rmbz-pjv2-card-unread" title="<?php echo esc_attr( $unread ); ?> mensagem(s) por ler">
                            <?php echo $unread > 99 ? '99+' : (int) $unread; ?>
                        </div>
                        <?php endif; ?>
                        <div class="rmbz-pjv2-card-head">
                            <div class="rmbz-pjv2-card-avatar"><?php echo esc_html( $initials ); ?></div>
                            <div class="rmbz-pjv2-card-id">
                                <p class="rmbz-pjv2-card-title"><?php echo esc_html( $p->project_title ?: '(sem título)' ); ?></p>
                                <div class="rmbz-pjv2-card-artist">👤 <?php echo esc_html( $nome ); ?> · <?php echo esc_html( $p->artist_telemovel ); ?></div>
                            </div>
                        </div>
                        <span class="rmbz-pjv2-status rmbz-pjv2-status--<?php echo esc_attr( $st ); ?>" style="align-self:flex-start;">
                            <span class="dot"></span><?php echo esc_html( $sm['icon'] . ' ' . $sm['label'] ); ?>
                        </span>
                        <?php
                            // [1.5.410] Estado de pagamento AO VIVO no card (não a coluna
                            // is_paid, que fica velha quando a vistoria/orçamento muda) —
                            // mesma conta do painel "Pagamento" do detalhe.
                            $rm_cost  = function_exists( 'rmbz_calc_project_obligatory_cost' )
                                ? (float) rmbz_calc_project_obligatory_cost( $p )
                                : (float) $p->scenario_cost;
                            if ( $rm_cost <= 0 ) $rm_cost = (float) $p->scenario_cost;
                            $rm_paid  = (float) $p->amount_paid;
                            $rm_falta = max( 0, $rm_cost - $rm_paid );
                            $rm_full  = ( $rm_cost > 0 && $rm_falta <= 0.01 );
                        ?>
                        <div class="rmbz-pjv2-card-meta">
                            <span>💰 <strong><?php echo number_format( $rm_cost, 0, ',', '.' ); ?> MT</strong></span>
                            <?php if ( $rm_full ): ?>
                                <span class="paid-y">✓ Pago</span>
                            <?php elseif ( $rm_paid > 0 ): ?>
                                <span class="paid-n">⏳ Falta <?php echo number_format( $rm_falta, 0, ',', '.' ); ?> MT</span>
                            <?php else: ?>
                                <span class="paid-n">✗ Não pago</span>
                            <?php endif; ?>
                            <?php if ( $p->contract_date ): ?>
                                <span style="margin-left:auto;font-size:11px;color:#9ca3af;"><?php echo esc_html( date( 'd/m/y', strtotime( $p->contract_date ) ) ); ?></span>
                            <?php endif; ?>
                        </div>
                        <div class="rmbz-pjv2-card-foot">
                            <a href="<?php echo esc_url( $edit_url ); ?>" class="rmbz-pjv2-btn rmbz-pjv2-btn--primary">
                                <span class="ico">💬</span> Gerir & Chat
                                <?php if ( $unread > 0 ): ?>
                                <span class="rmbz-pjv2-btn-badge"><?php echo $unread > 99 ? '99+' : (int) $unread; ?></span>
                                <?php endif; ?>
                            </a>
                            <a href="<?php echo esc_url( $del_url ); ?>"
                               class="rmbz-pjv2-btn rmbz-pjv2-btn--danger rmbz-pjv2-del-trigger"
                               data-del-url="<?php echo esc_url( $del_url ); ?>"
                               data-tel="<?php echo esc_attr( $p->artist_telemovel ); ?>"
                               data-artist="<?php echo esc_attr( $p->user_nome ?: 'Artista' ); ?>"
                               data-project="<?php echo esc_attr( $p->project_title ?: ( 'Projeto #' . $p->id ) ); ?>"
                               title="Apagar projeto">🗑 Eliminar</a>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>
            <?php endif; ?>
        </div>
    </div>

    <?php /* [1.5.239] Modal de confirmação de eliminação de projeto.
             Único para a página — preenchido dinamicamente pelo JS. */ ?>
    <div class="rmbz-pjv2-delmodal-overlay" id="rmbz-pjv2-delmodal">
        <div class="rmbz-pjv2-delmodal" role="dialog" aria-modal="true"
             aria-labelledby="rmbz-pjv2-delmodal-title">
            <h3 id="rmbz-pjv2-delmodal-title">Eliminar projeto definitivamente?</h3>
            <p class="sub">
                Esta acção não pode ser desfeita. O projeto e o seu ficheiro
                são apagados de forma permanente.
            </p>
            <div class="target">
                Projeto: <strong id="rmbz-pjv2-delmodal-project">—</strong><br>
                Artista: <strong id="rmbz-pjv2-delmodal-artist">—</strong>
            </div>
            <label for="rmbz-pjv2-delmodal-input">
                Para confirmar, escreve o número de telemóvel do artista:
            </label>
            <input type="text" id="rmbz-pjv2-delmodal-input"
                   autocomplete="off" inputmode="tel"
                   placeholder="Ex: 258..." />
            <p class="hint" id="rmbz-pjv2-delmodal-hint"></p>
            <div class="rmbz-pjv2-delmodal-actions">
                <button type="button" class="rmbz-pjv2-delmodal-cancel"
                        id="rmbz-pjv2-delmodal-cancel">Cancelar</button>
                <a href="#" class="rmbz-pjv2-delmodal-confirm"
                   id="rmbz-pjv2-delmodal-confirm" aria-disabled="true">
                    Eliminar
                </a>
            </div>
        </div>
    </div>

    <script>
    /* [1.5.239] Lógica do modal de eliminação — confirma com o telemóvel. */
    (function(){
        var overlay = document.getElementById('rmbz-pjv2-delmodal');
        if ( ! overlay ) return;
        var elProject = document.getElementById('rmbz-pjv2-delmodal-project');
        var elArtist  = document.getElementById('rmbz-pjv2-delmodal-artist');
        var input     = document.getElementById('rmbz-pjv2-delmodal-input');
        var hint      = document.getElementById('rmbz-pjv2-delmodal-hint');
        var btnCancel = document.getElementById('rmbz-pjv2-delmodal-cancel');
        var btnOk     = document.getElementById('rmbz-pjv2-delmodal-confirm');
        var expectedTel = '';
        var baseDelUrl  = '';

        // Só dígitos — para comparar telemóveis ignorando +, espaços, etc.
        function digits(s){ return ( s || '' ).replace(/\D/g, ''); }

        function close(){
            overlay.classList.remove('is-open');
            input.value = '';
            hint.textContent = '';
            input.className = '';
            btnOk.setAttribute('aria-disabled', 'true');
            btnOk.removeAttribute('href');
        }

        function validate(){
            var typed = digits(input.value);
            var want  = digits(expectedTel);
            if ( typed === '' ) {
                input.className = '';
                hint.textContent = '';
                hint.className = 'hint';
                btnOk.setAttribute('aria-disabled', 'true');
                btnOk.removeAttribute('href');
                return;
            }
            // Match: igual, OU os últimos 9 dígitos batem certo (tolera
            // o número estar com/sem indicativo +258).
            var ok = ( typed === want ) ||
                     ( typed.length >= 9 && want.length >= 9 &&
                       typed.slice(-9) === want.slice(-9) );
            if ( ok ) {
                input.className = 'match';
                hint.textContent = '✓ Número confirmado.';
                hint.className = 'hint ok';
                btnOk.setAttribute('aria-disabled', 'false');
                // Acrescenta o telemovel confirmado ao URL — o servidor
                // revalida (defesa extra, caso o JS seja contornado).
                btnOk.href = baseDelUrl + '&confirm_tel=' +
                             encodeURIComponent( typed );
            } else {
                input.className = 'mismatch';
                hint.textContent = 'O número não corresponde a este artista.';
                hint.className = 'hint err';
                btnOk.setAttribute('aria-disabled', 'true');
                btnOk.removeAttribute('href');
            }
        }

        // Abrir o modal a partir de qualquer botão eliminar.
        document.querySelectorAll('.rmbz-pjv2-del-trigger').forEach(function(a){
            a.addEventListener('click', function(e){
                e.preventDefault();
                e.stopPropagation();
                expectedTel = a.getAttribute('data-tel') || '';
                baseDelUrl  = a.getAttribute('data-del-url') || '';
                elProject.textContent = a.getAttribute('data-project') || '—';
                elArtist.textContent  = a.getAttribute('data-artist') || '—';
                overlay.classList.add('is-open');
                input.focus();
            });
        });

        input.addEventListener('input', validate);
        btnCancel.addEventListener('click', close);
        overlay.addEventListener('click', function(e){
            if ( e.target === overlay ) close();
        });
        document.addEventListener('keydown', function(e){
            if ( e.key === 'Escape' && overlay.classList.contains('is-open') ) {
                close();
            }
        });
        // Bloquear clique no Eliminar enquanto desactivado.
        btnOk.addEventListener('click', function(e){
            if ( btnOk.getAttribute('aria-disabled') === 'true' ) {
                e.preventDefault();
            }
        });
    })();
    </script>

    <script>
    /* Filtros e pesquisa da lista de projetos. */
    (function(){
        var q = document.getElementById('rmbz-pjv2-q');
        var cards = document.querySelectorAll('#rmbz-pjv2-grid .rmbz-pjv2-card');
        var filters = document.querySelectorAll('.rmbz-pjv2-filter');
        var curStatus = 'all', curQ = '';
        function apply() {
            cards.forEach(function(c){
                var sOK;
                if (curStatus === 'all') {
                    sOK = true;
                } else if (curStatus === 'unread') {
                    // Caso especial: filtra por contador, não por status
                    sOK = (parseInt(c.dataset.unread || '0', 10) > 0);
                } else {
                    sOK = (c.dataset.status === curStatus);
                }
                var qOK = !curQ || (c.dataset.search || '').indexOf(curQ) !== -1;
                c.style.display = (sOK && qOK) ? '' : 'none';
            });
        }
        if (q) q.addEventListener('input', function(){ curQ = q.value.trim().toLowerCase(); apply(); });
        filters.forEach(function(b){
            b.addEventListener('click', function(){
                filters.forEach(function(x){ x.classList.remove('is-active'); });
                b.classList.add('is-active'); curStatus = b.dataset.status; apply();
            });
        });
    })();
    </script>
    <?php
}

/* ============================================================================
 * [1.6.118.114] CONTADOR de prazo automático (cron de cancelamento)
 * ============================================================================ */
/**
 * Offset do fuso do site em segundos, robusto.
 * Deriva-o do próprio WordPress: current_time('timestamp') devolve a hora
 * LOCAL do site (como epoch), e time() devolve UTC. A diferença é o offset
 * real, seja qual for a forma como o fuso está configurado (gmt_offset ou
 * timezone_string). É a fonte de verdade mais fiável.
 */
function rmbz_pjv2_site_offset_secs() {
    // current_time('timestamp') = epoch + offset; time() = epoch UTC.
    $local = (int) current_time( 'timestamp' );      // hora local "fingida" em epoch
    $utc   = (int) current_time( 'timestamp', true ); // epoch UTC real
    $diff  = $local - $utc;

    // Sanidade: offsets do mundo vão de -12h a +14h.
    if ( $diff >= -12 * HOUR_IN_SECONDS && $diff <= 14 * HOUR_IN_SECONDS ) {
        return $diff;
    }

    // Fallback: gmt_offset, depois timezone_string.
    $gmt = get_option( 'gmt_offset', '' );
    if ( $gmt !== '' && $gmt !== null ) {
        return (int) round( (float) $gmt * HOUR_IN_SECONDS );
    }
    $tz_string = get_option( 'timezone_string', '' );
    if ( $tz_string ) {
        try {
            $tz  = new DateTimeZone( $tz_string );
            return $tz->getOffset( new DateTime( 'now', $tz ) );
        } catch ( Exception $e ) {
            return 0;
        }
    }
    return 0;
}
/**
 * Devolve o HTML de um prazo automático activo:
 *   1) localização, depois de o admin enviar opções válidas;
 *   2) confirmação das datas de gravação.
 * Devolve '' se não há prazo activo.
 *
 * Espelha a lógica do cron (includes/filming-cron.php) para o admin ver o
 * mesmo que vai acontecer automaticamente.
 */
function rmbz_pjv2_render_countdown( $extra, $status ) {
    if ( ! is_array( $extra ) ) return '';

    // Só faz sentido em estados de produção activa
    // Em filming a produção já começou; nunca ameaçar apagar o projecto por
    // falta de confirmação de uma etapa anterior.
    $active = [ 'pre-production', 'kyc_review' ];
    if ( ! in_array( $status, $active, true ) ) return '';

    $now = time(); // UTC puro do PHP — sempre fiável
    $box = null; // ['kind','label','deadline_ts','hint','danger']

    // LOCALIZAÇÃO: 2 dias depois de o admin guardar opções válidas.
    $location_deadline = function_exists( 'rmbz_filming_location_deadline_ts' )
        ? rmbz_filming_location_deadline_ts( $extra )
        : 0;
    if ( $location_deadline > 0 ) {
        $box = [
            'kind'  => 'Escolha de localização',
            'label' => 'Falta o artista escolher a localização',
            'deadline_ts' => $location_deadline,
            'hint'  => 'Se não escolher até ao fim do prazo, o projecto é cancelado, fica visível ao artista por 24h e a demo é removida após 30 dias.',
        ];
    }

    // DATAS: até ao início, se ainda não confirmou nem propôs novas datas.
    $start = isset( $extra['filming_start'] ) ? (string) $extra['filming_start'] : '';
    $confirmed = ! empty( $extra['filming_confirmed_by_artist'] );
    $proposed  = ! empty( $extra['filming_proposed_by_artist'] );
    if ( $start !== '' && ! $confirmed && ! $proposed ) {
        // Mesma fonte de verdade do cron: fim do dia de início ou 24h
        // após a última definição das datas, o que ocorrer mais tarde.
        $deadline_utc = function_exists( 'rmbz_filming_confirmation_deadline_ts' )
            ? rmbz_filming_confirmation_deadline_ts( $extra )
            : 0;
        if ( $deadline_utc > 0 && ( ! $box || $deadline_utc < $box['deadline_ts'] ) ) {
            $box = [
                'kind'  => 'Confirmação de datas',
                'label' => 'Falta o artista confirmar as datas de gravação',
                'deadline_ts' => $deadline_utc,
                'hint'  => 'Se não confirmar ou propuser outras datas até ao fim do prazo, o projecto é cancelado, fica visível por 24h e a demo é removida após 30 dias.',
            ];
        }
    }

    if ( ! $box ) return '';

    $remaining = $box['deadline_ts'] - $now;
    $overdue   = $remaining <= 0;

    // Formatar tempo restante
    if ( $overdue ) {
        $time_txt = 'Prazo terminado — será cancelado na próxima verificação';
        $color = '#d93025'; $bg = '#fce8e6'; $border = '#d93025';
    } else {
        $days  = floor( $remaining / DAY_IN_SECONDS );
        $hours = floor( ( $remaining % DAY_IN_SECONDS ) / HOUR_IN_SECONDS );
        if ( $days >= 1 ) {
            $time_txt = sprintf( '%dd %dh restantes', $days, $hours );
        } else {
            $mins = floor( ( $remaining % HOUR_IN_SECONDS ) / 60 );
            $time_txt = sprintf( '%dh %dmin restantes', $hours, $mins );
        }
        // Cor: < 24h = vermelho, senão amarelo
        if ( $remaining < DAY_IN_SECONDS ) {
            $color = '#d93025'; $bg = '#fce8e6'; $border = '#f0b90b';
        } else {
            $color = '#92400e'; $bg = '#fff8e1'; $border = '#f0b90b';
        }
    }

    ob_start();
    // [1.6.118.114] Data limite legível no fuso do site.
    // Usamos gmdate + offset EXPLÍCITO sobre o timestamp UTC. Assim não
    // dependemos do comportamento do date_i18n nem da config de fuso do
    // servidor (que pode mostrar UTC cru).
    $deadline_fmt = gmdate( 'd/m/Y \à\s H:i', $box['deadline_ts'] + rmbz_pjv2_site_offset_secs() );
    ?>
    <div style="background:<?php echo $bg; ?>; border:1px solid <?php echo $border; ?>; border-radius:10px; padding:12px 14px; margin:0 0 14px;">
        <div style="display:flex; align-items:center; gap:8px;">
            <span style="font-size:18px;">⏳</span>
            <div style="flex:1;">
                <div style="font-size:11px; text-transform:uppercase; letter-spacing:0.4px; color:#5f6368; font-weight:600;">Contagem automática: <?php echo esc_html( $box['kind'] ); ?></div>
                <div style="font-size:15px; font-weight:700; color:<?php echo $color; ?>;"><?php echo esc_html( $time_txt ); ?></div>
                <div style="font-size:12px; color:#5f6368; margin-top:2px;">📅 Prazo: <strong><?php echo esc_html( $deadline_fmt ); ?></strong></div>
            </div>
        </div>
        <p style="margin:8px 0 0; font-size:12px; color:#5f6368;">
            <?php echo esc_html( $box['label'] ); ?>. <?php echo esc_html( $box['hint'] ); ?>
        </p>
    </div>
    <?php
    return ob_get_clean();
}

/* ============================================================================
 * DETAIL — full screen
 * ============================================================================ */
function rmbz_pjv2_render_detail( $proj_id ) {
    global $wpdb;

    // CRÍTICO: emitir window.rmbzChatConfig ANTES de qualquer markup.
    // Não confiamos em admin_print_footer_scripts (frágil em alguns ambientes).
    if ( function_exists( 'rmbz_pchat_emit_inline_config' ) ) {
        rmbz_pchat_emit_inline_config( $proj_id );
    }

    $table_projects = $wpdb->prefix . 'rmbz_artist_projects';
    $table_wallets  = $wpdb->prefix . 'rmbz_wallets';

    $p = $wpdb->get_row( $wpdb->prepare(
        "SELECT p.*, w.user_nome, w.user_email, w.balance AS artist_balance
         FROM {$table_projects} p
         LEFT JOIN {$table_wallets} w ON p.artist_telemovel = w.user_telemovel
         WHERE p.id = %d", $proj_id
    ) );
    if ( ! $p ) {
        echo '<div class="rmbz-pjv2" style="padding:40px;">Projeto não encontrado.</div>';
        return;
    }
    $extra    = ! empty( $p->extra_data ) ? json_decode( $p->extra_data, true ) : [];
    $detalhes = ! empty( $p->scenario_details ) ? json_decode( $p->scenario_details, true ) : [];
    $artist_nm = $p->user_nome ?: 'Artista';
    $back_url = admin_url( 'admin.php?page=rmbz-projetos' );

    // [1.6.118.56] Snippet para limpar parâmetros feios da URL (msg=, updated=)
    // depois dos redirects de POST. Mostra a mensagem como toast bonito e
    // substitui a URL via history.replaceState (sem reload).
    ?>
    <script>
    (function() {
        var url = new URL(window.location.href);
        var msg = url.searchParams.get('msg');
        var updated = url.searchParams.get('updated');
        var teamGate = url.searchParams.get('team_gate'); // [1.6.118.98]
        var feeApplied = url.searchParams.get('fee_applied'); // [1.6.118.100]

        if (!msg && !updated && !teamGate && !feeApplied) return;

        // Toast simples — slides in do topo, desaparece em 5s
        var toast = document.createElement('div');
        var isBlock = teamGate === '1';
        var isFee = feeApplied !== null && parseInt(feeApplied, 10) > 0;
        toast.style.cssText = 'position:fixed; top:50px; right:20px; z-index:99999; '
            + 'background:#1a1a1a; color:#fff; padding:14px 20px; border-left:4px solid '
            + (isBlock ? '#d93025' : (isFee ? '#34a853' : '#f0b90b')) + '; '
            + 'border-radius:6px; box-shadow:0 6px 20px rgba(0,0,0,0.35); font-size:14px; '
            + 'max-width:420px; opacity:0; transform:translateY(-10px); '
            + 'transition:all 0.3s ease;';
        toast.textContent = isBlock
            ? '⛔ Guardado, mas NÃO avançou para filmagens: falta equipa essencial. Vê o aviso na secção Equipa.'
            : (isFee
                ? '✅ Taxa de vistoria adicionada ao orçamento (' + feeApplied + ' item' + (parseInt(feeApplied,10) > 1 ? 's' : '') + ').'
                : (msg || 'Alterações guardadas com sucesso.'));
        document.body.appendChild(toast);

        // Animação entrada
        setTimeout(function() {
            toast.style.opacity = '1';
            toast.style.transform = 'translateY(0)';
        }, 50);

        // Animação saída + remoção (gate fica mais tempo)
        setTimeout(function() {
            toast.style.opacity = '0';
            toast.style.transform = 'translateY(-10px)';
            setTimeout(function() { toast.remove(); }, 350);
        }, isBlock ? 9000 : 5000);

        // Limpar URL
        url.searchParams.delete('msg');
        url.searchParams.delete('updated');
        url.searchParams.delete('team_gate');
        url.searchParams.delete('fee_applied');
        window.history.replaceState({}, document.title, url.toString());
    })();
    </script>
    <?php

    // [1.6.118.23] VIP activo. NOTA: tabela rmbz_subscriptions NÃO tem
    // coluna `plan_id` — só id, user_telemovel, start_date, end_date,
    // last_payment_amount, status. Usar só campos existentes.
    $table_subs = $wpdb->prefix . 'rmbz_subscriptions';
    $vip_active = $wpdb->get_row( $wpdb->prepare(
        "SELECT id, start_date, end_date, last_payment_amount FROM {$table_subs}
         WHERE user_telemovel = %s AND status = 'active' AND end_date > NOW()
         ORDER BY end_date DESC LIMIT 1",
        $p->artist_telemovel
    ) );

    // [1.6.118.23] Outros projetos deste artista (excluindo o actual)
    $outros_projetos = $wpdb->get_results( $wpdb->prepare(
        "SELECT id, project_title, production_status, contract_date, scenario_cost, is_paid
         FROM {$table_projects}
         WHERE artist_telemovel = %s AND id != %d
         ORDER BY contract_date DESC, id DESC
         LIMIT 5",
        $p->artist_telemovel, $proj_id
    ) );
    $outros_total = (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$table_projects}
         WHERE artist_telemovel = %s AND id != %d",
        $p->artist_telemovel, $proj_id
    ) );
    $outros_concluidos = (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$table_projects}
         WHERE artist_telemovel = %s AND id != %d AND production_status = 'done'",
        $p->artist_telemovel, $proj_id
    ) );
    $outros_rejeitados = (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$table_projects}
         WHERE artist_telemovel = %s AND id != %d AND production_status = 'rejected'",
        $p->artist_telemovel, $proj_id
    ) );

    // Avatar iniciais
    $initials = '';
    foreach ( array_slice( preg_split( '/\s+/', trim( $artist_nm ) ), 0, 2 ) as $w ) {
        if ( $w !== '' ) $initials .= mb_strtoupper( mb_substr( $w, 0, 1 ) );
    }
    if ( $initials === '' ) $initials = '?';

    $status_meta = [
        'pending_review' => [ 'label' => 'Em Avaliação' ],
        'pre-production' => [ 'label' => 'Aprovado' ],
        'kyc_review'     => [ 'label' => 'KYC Pendente' ],
        'filming'        => [ 'label' => 'Filmagem' ],
        'editing'        => [ 'label' => 'Edição' ],
        'done'           => [ 'label' => 'Concluído' ],
        'correction'     => [ 'label' => 'Correção' ],
        'rejected'       => [ 'label' => 'Rejeitado' ],
        'cancelled_no_confirmation' => [ 'label' => 'Cancelado por Prazo' ],
    ];
    $cur = $p->production_status ?: 'pending_review';
    $can_attach = ! empty( $extra['artist_can_attach'] );

    // [1.6.118.24] Idade do projeto — usado em topbar
    $age_label = '';
    $age_class = 'ok';
    $age_days  = 0;
    $created_for_age = $p->contract_date ?: ( $extra['created_at'] ?? null );
    if ( $created_for_age ) {
        $created_ts = is_numeric( $created_for_age ) ? (int) $created_for_age : strtotime( $created_for_age );
        if ( $created_ts > 0 ) {
            $age_seconds = max( 0, time() - $created_ts );
            $age_days = floor( $age_seconds / 86400 );
            $age_hours = floor( $age_seconds / 3600 );

            if ( $age_seconds < 3600 )            $age_label = 'agora mesmo';
            elseif ( $age_hours < 24 )            $age_label = 'há ' . $age_hours . 'h';
            elseif ( $age_days === 1 )            $age_label = 'há 1 dia';
            elseif ( $age_days < 30 )             $age_label = 'há ' . $age_days . ' dias';
            elseif ( $age_days < 365 )            $age_label = 'há ' . floor( $age_days / 30 ) . ' mês(es)';
            else                                  $age_label = 'há ' . floor( $age_days / 365 ) . ' ano(s)';

            // Urgência: pendente há muito tempo é problema
            if ( $cur === 'pending_review' ) {
                if ( $age_days >= 7 )      $age_class = 'urgent';
                elseif ( $age_days >= 3 )  $age_class = 'warn';
            }
        }
    }

    // [1.6.118.24] Estado online do artista — vem de extra_data['last_seen'] na wallet
    $artist_online = false;
    $artist_last_seen_label = '';
    $wallet_extra_row = $wpdb->get_var( $wpdb->prepare(
        "SELECT extra_data FROM {$table_wallets} WHERE user_telemovel = %s LIMIT 1",
        $p->artist_telemovel
    ) );
    if ( $wallet_extra_row ) {
        $we = json_decode( $wallet_extra_row, true );
        if ( is_array( $we ) && ! empty( $we['last_seen'] ) ) {
            $last_seen_ts = (int) $we['last_seen'];
            $diff = time() - $last_seen_ts;
            if ( $diff < 300 ) {       // < 5 min
                $artist_online = true;
            } else {
                if ( $diff < 3600 )       $artist_last_seen_label = 'há ' . floor( $diff / 60 ) . ' min';
                elseif ( $diff < 86400 )  $artist_last_seen_label = 'há ' . floor( $diff / 3600 ) . 'h';
                elseif ( $diff < 86400*7 ) $artist_last_seen_label = 'há ' . floor( $diff / 86400 ) . ' dia(s)';
                else                       $artist_last_seen_label = wp_date( 'd/m/Y', $last_seen_ts );
            }
        }
    }
    ?>
    <div class="rmbz-pjv2">
        <div class="rmbz-pjv2-detail">
            <div class="rmbz-pjv2-alert">
            <?php
            // [1.6.318/1.6.381] Autorização da equipa: a PRODUÇÃO (filmagem/edição)
            // exige subscrição ativa. Sem ela, a equipa NÃO está autorizada a
            // produzir até o artista renovar. A produção começa na filmagem.
            $rmbz_prod_states = function_exists( 'rmbz_project_inprogress_states' )
                ? rmbz_project_inprogress_states() : [ 'filming', 'editing' ];
            $rmbz_in_prod = in_array( $cur, $rmbz_prod_states, true );
            if ( $rmbz_in_prod ) {
                // [1.6.332/1.6.380] Multa por atraso — calculada/persistida.
                $rmbz_fine = function_exists( 'rmbz_project_overdue_info' )
                    ? rmbz_project_overdue_info( $p->artist_telemovel ) : [ 'overdue' => false ];
                $rmbz_fine_on     = ( ! empty( $rmbz_fine['overdue'] ) && ! empty( $rmbz_fine['enabled'] ) );
                $rmbz_fine_unit   = ( isset( $rmbz_fine['unit'] ) && $rmbz_fine['unit'] === 'hour' );
                $rmbz_fine_frozen = ! empty( $rmbz_fine['frozen'] );
                $rmbz_fine_amt    = isset( $rmbz_fine['amount'] ) ? (float) $rmbz_fine['amount'] : 0.0;
                $rmbz_clear_url   = wp_nonce_url(
                    admin_url( 'admin-post.php?action=rmbz_clear_project_fine&project_id=' . (int) $p->id ),
                    'rmbz_clear_fine_' . (int) $p->id
                );
                ?>
                <style>
                    @keyframes rmbzFineRise { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
                    @keyframes rmbzFinePulse { 0%,100% { transform:scale(1); } 50% { transform:scale(1.10); } }
                    @keyframes rmbzFineHalo { 0%,100% { box-shadow:0 0 0 0 rgba(217,48,37,.30); } 50% { box-shadow:0 0 0 12px rgba(217,48,37,0); } }
                    @keyframes rmbzFineGlow { 0%,100% { text-shadow:0 0 0 rgba(217,48,37,0); } 50% { text-shadow:0 0 18px rgba(217,48,37,.45); } }
                    .rmbz-fineban{
                        max-width:560px; margin:24px auto 18px; text-align:center;
                        background:linear-gradient(160deg,#fff6f5 0%,#fdeceb 100%);
                        border:1px solid rgba(217,48,37,.28); border-radius:22px;
                        padding:24px 26px 22px; box-shadow:0 10px 30px rgba(217,48,37,.10);
                        animation:rmbzFineRise .45s cubic-bezier(.2,.9,.3,1.1) both;
                    }
                    .rmbz-fineban__icon{
                        width:60px; height:60px; margin:0 auto 14px; border-radius:20px;
                        display:flex; align-items:center; justify-content:center; font-size:30px;
                        background:rgba(217,48,37,.12); animation:rmbzFinePulse 1.8s ease-in-out infinite, rmbzFineHalo 1.8s ease-in-out infinite;
                    }
                    .rmbz-fineban__title{ margin:0 0 6px; font-size:18px; font-weight:800; color:#8a1c12; letter-spacing:-.2px; }
                    .rmbz-fineban__desc{ margin:0 auto; max-width:460px; font-size:13.5px; line-height:1.55; color:#7a3b34; }
                    .rmbz-fineban__fine{
                        margin:18px auto 0; padding:16px; border-radius:16px;
                        background:#fff; border:1px solid rgba(217,48,37,.22);
                    }
                    .rmbz-fineban__fine-label{ display:block; font-size:11px; font-weight:700; letter-spacing:1px; text-transform:uppercase; color:#d93025; opacity:.85; }
                    .rmbz-fineban__amount{
                        display:block; margin:4px 0 2px; font-size:34px; font-weight:900; color:#d93025; line-height:1.1;
                        animation:rmbzFineGlow 2.2s ease-in-out infinite;
                    }
                    .rmbz-fineban__meta{ display:block; font-size:12px; color:#9a564f; }
                    .rmbz-fineban__tag{
                        display:inline-block; margin-top:10px; font-size:11px; font-weight:600;
                        color:#8a1c12; background:rgba(217,48,37,.10); padding:4px 12px; border-radius:99px;
                    }
                    .rmbz-fineban__pay{
                        display:inline-block; margin-top:12px; font-size:13px; font-weight:700;
                        color:#fff !important; background:#1a8a4a; padding:9px 18px; border-radius:10px;
                        text-decoration:none; box-shadow:0 4px 12px rgba(26,138,74,.28);
                    }
                    .rmbz-fineban__pay:hover{ background:#157a40; color:#fff; }
                    .rmbz-fineban--warn{ background:#fff7e6; border-color:rgba(240,185,11,.45); box-shadow:0 8px 24px rgba(240,185,11,.12); }
                    .rmbz-fineban--warn .rmbz-fineban__icon{ background:rgba(240,185,11,.18); animation:rmbzFineRise .45s both; }
                    .rmbz-fineban--warn .rmbz-fineban__title{ color:#7a5b00; }
                    .rmbz-fineban--warn .rmbz-fineban__desc{ color:#7a5b15; }
                </style>
                <?php if ( ! $vip_active ): ?>
                    <div class="rmbz-fineban">
                        <div class="rmbz-fineban__icon">⛔</div>
                        <h3 class="rmbz-fineban__title">Subscrição do artista expirada</h3>
                        <p class="rmbz-fineban__desc">
                            A equipa <strong>não está autorizada</strong> a produzir este videoclipe até o artista renovar a subscrição (com permissão de vídeo). Não avances com filmagens/edição enquanto estiver assim.
                        </p>
                        <?php if ( $rmbz_fine_on ): ?>
                            <div class="rmbz-fineban__fine">
                                <span class="rmbz-fineban__fine-label">💸 Multa a acumular</span>
                                <span class="rmbz-fineban__amount"><?php echo esc_html( number_format( $rmbz_fine_amt, 2, ',', '.' ) ); ?> MT</span>
                                <span class="rmbz-fineban__meta">
                                    <?php echo (int) $rmbz_fine['units']; ?> <?php echo $rmbz_fine_unit ? 'hora(s)' : 'dia(s)'; ?> de atraso ×
                                    <?php echo esc_html( number_format( (float) $rmbz_fine['rate'], 2, ',', '.' ) ); ?> MT/<?php echo $rmbz_fine_unit ? 'hora' : 'dia'; ?>
                                    <?php if ( ! empty( $rmbz_fine['carry'] ) && (float) $rmbz_fine['carry'] > 0 ) : ?>
                                        + <?php echo esc_html( number_format( (float) $rmbz_fine['carry'], 2, ',', '.' ) ); ?> MT de dívida anterior
                                    <?php endif; ?>
                                </span>
                                <span class="rmbz-fineban__tag">Fica guardada mesmo que o artista renove — só sai quando for paga</span>
                                <?php if ( $rmbz_fine_amt > 0 ): ?>
                                    <div><a class="rmbz-fineban__pay" href="<?php echo esc_url( $rmbz_clear_url ); ?>" onclick="return confirm('Marcar a multa de <?php echo esc_js( number_format( $rmbz_fine_amt, 2, ',', '.' ) ); ?> MT como PAGA e limpar a dívida deste projeto?');">✓ Marcar multa como paga</a></div>
                                <?php endif; ?>
                            </div>
                        <?php endif; ?>
                    </div>
                <?php elseif ( $rmbz_fine_on && $rmbz_fine_frozen && $rmbz_fine_amt > 0 ): ?>
                    <div class="rmbz-fineban">
                        <div class="rmbz-fineban__icon">💸</div>
                        <h3 class="rmbz-fineban__title">Multa pendente neste projeto</h3>
                        <p class="rmbz-fineban__desc">
                            O artista <strong>renovou o VIP</strong>, mas ficou uma <strong>multa por atraso por pagar</strong>. A equipa só deve continuar a produção depois de esta multa ser resolvida.
                        </p>
                        <div class="rmbz-fineban__fine">
                            <span class="rmbz-fineban__fine-label">💸 Multa pendente</span>
                            <span class="rmbz-fineban__amount"><?php echo esc_html( number_format( $rmbz_fine_amt, 2, ',', '.' ) ); ?> MT</span>
                            <span class="rmbz-fineban__meta">
                                <?php echo (int) $rmbz_fine['units']; ?> <?php echo $rmbz_fine_unit ? 'hora(s)' : 'dia(s)'; ?> de atraso ×
                                <?php echo esc_html( number_format( (float) $rmbz_fine['rate'], 2, ',', '.' ) ); ?> MT/<?php echo $rmbz_fine_unit ? 'hora' : 'dia'; ?> · congelada
                            </span>
                            <div><a class="rmbz-fineban__pay" href="<?php echo esc_url( $rmbz_clear_url ); ?>" onclick="return confirm('Marcar a multa de <?php echo esc_js( number_format( $rmbz_fine_amt, 2, ',', '.' ) ); ?> MT como PAGA e libertar a equipa para continuar?');">✓ Marcar multa como paga</a></div>
                        </div>
                    </div>
                <?php else:
                    $rmbz_vip_days_left = max( 0, (int) ceil( ( strtotime( $vip_active->end_date ) - time() ) / 86400 ) );
                    if ( $rmbz_vip_days_left <= 7 ) { ?>
                        <div style="background:#fef7e0;border-left:4px solid #f0b90b;color:#5f4b15;padding:14px 18px;border-radius:8px;margin-bottom:16px;font-size:14px;line-height:1.45;">
                            ⚠ A subscrição do artista expira em <strong><?php echo (int) $rmbz_vip_days_left; ?> dia(s)</strong>. Avisa-o para renovar — sem subscrição ativa a produção não pode continuar.
                        </div>
                    <?php }
                endif;

                // [1.5.410] 🔎 DIAGNÓSTICO DA MULTA — explica porta a porta
                // porque a multa está (ou não) a contar neste artista/projeto.
                if ( function_exists( 'rmbz_project_fine_diagnose' ) ) :
                    $rmbz_fine_diag = rmbz_project_fine_diagnose( $p->artist_telemovel, (int) $p->id );
                ?>
                    <details style="max-width:560px; margin:0 auto 16px; background:#fff; border:1px solid #e8e6ef; border-radius:16px; padding:12px 16px;">
                        <summary style="cursor:pointer; font-size:12px; font-weight:800; color:#5b3e70;">🔎 Diagnóstico da multa (porque conta / não conta)</summary>
                        <div style="margin-top:10px; display:flex; flex-direction:column; gap:6px; text-align:left;">
                            <?php foreach ( $rmbz_fine_diag as $rmbz_fd ) : ?>
                                <div style="font-size:12px; line-height:1.5; color:#3a3744;">
                                    <?php echo $rmbz_fd['ok'] === null ? 'ℹ️' : ( $rmbz_fd['ok'] ? '✅' : '⛔' ); ?>
                                    <?php echo esc_html( $rmbz_fd['label'] ); ?>
                                </div>
                            <?php endforeach; ?>
                        </div>
                    </details>
                <?php endif;
            }
            ?>
            </div><!-- /.rmbz-pjv2-alert -->
            <!-- TOPBAR ─────────────────────────────────────────────── -->
            <div class="rmbz-pjv2-topbar">
                <a class="back" href="<?php echo esc_url( $back_url ); ?>">← Voltar</a>
                <div class="titlebar">
                    <div class="icon-wrap">🎥</div>
                    <div class="meta">
                        <h1><?php echo esc_html( $p->project_title ?: '(sem título)' ); ?></h1>
                        <div class="who">
                            <span>👤 <strong style="color:#1a1a1f;"><?php echo esc_html( $artist_nm ); ?></strong></span>
                            <code><?php echo esc_html( $p->artist_telemovel ); ?></code>
                            <span class="rmbz-pjv2-status rmbz-pjv2-status--<?php echo esc_attr( $cur ); ?>" style="font-size:10px;padding:3px 9px;">
                                <span class="dot"></span><?php echo esc_html( $status_meta[ $cur ]['label'] ?? $cur ); ?>
                            </span>
                            <?php if ( $age_label !== '' ): ?>
                                <span class="rmbz-pjv2-age rmbz-pjv2-age--<?php echo esc_attr( $age_class ); ?>" title="Idade do projeto">
                                    🕒 <?php echo esc_html( $age_label ); ?>
                                </span>
                            <?php endif; ?>
                            <?php if ( $artist_online ): ?>
                                <span class="rmbz-pjv2-online" title="Artista interagiu há &lt; 5 min">
                                    <span class="pulse"></span> Online agora
                                </span>
                            <?php elseif ( $artist_last_seen_label !== '' ): ?>
                                <span class="rmbz-pjv2-offline" title="Última actividade do artista">
                                    ⚪ Visto <?php echo esc_html( $artist_last_seen_label ); ?>
                                </span>
                            <?php endif; ?>
                        </div>
                    </div>
                </div>
            </div>

            <!-- COLUNA ESQ: FICHA ──────────────────────────────────── -->
            <aside class="rmbz-pjv2-side">
                <?php // [1.5.439] Desistir do projeto — botão + modal com a
                      // compilação (pedir ao artista com conselho da IA, ou
                      // desistência forçada). Ver includes/project-giveup.php. ?>
                <?php if ( function_exists( 'rmbz_giveup_admin_sideblock' ) ) rmbz_giveup_admin_sideblock( $p, $extra ); ?>

                <!-- Bloco: ARTISTA (preenchido por AJAX /info) -->
                <div class="rmbz-pjv2-side-block" id="rmbz-pjv2-artist-block" style="display:none;">
                    <h3><span class="ico">👤</span> Artista</h3>
                    <div class="rmbz-pjv2-artist-card" id="rmbz-pjv2-artist-card"></div>
                </div>

                <!-- Bloco: RECOMENDAÇÕES (preenchido por AJAX /info) -->
                <div class="rmbz-pjv2-side-block" id="rmbz-pjv2-recs-block" style="display:none;">
                    <h3><span class="ico">💡</span> Recomendações</h3>
                    <div id="rmbz-pjv2-recs-list"></div>
                </div>

                <div class="rmbz-pjv2-side-block">
                    <h3><span class="ico">📝</span> Candidatura</h3>
                    <div class="row"><span class="k">Música</span><span class="v"><?php echo esc_html( $p->project_title ); ?></span></div>
                    <div class="row"><span class="k">Produtor</span><span class="v"><?php echo esc_html( $p->music_producer ?: '—' ); ?></span></div>
                    <?php /* [1.5.398] Participação (feat). [1.5.401] + estado do consentimento. */
                    if ( ! empty( $extra['feat']['name'] ) ) : ?>
                    <div class="row"><span class="k">🎤 Feat</span><span class="v"><?php
                        echo esc_html( $extra['feat']['name'] );
                        echo ! empty( $extra['feat']['has_account'] ) && ! empty( $extra['feat']['tel'] )
                            ? ' · conta: ' . esc_html( $extra['feat']['tel'] )
                            : ' · sem conta 1MZ';
                        $rmbz_fc = $extra['feat']['consent']['status'] ?? '';
                        $rmbz_fc_forced = ! empty( $extra['feat']['consent']['forced_by_admin'] );
                        if ( $rmbz_fc === 'pending' )  echo ' · <strong style="color:#b45309;">⏳ à espera da resposta do participante</strong>';
                        if ( $rmbz_fc === 'accepted' ) echo $rmbz_fc_forced
                            ? ' · <strong style="color:#1a8a4a;">✅ aceite (definida pela equipa)</strong>'
                            : ' · <strong style="color:#1a8a4a;">✅ aceitou a participação</strong>';
                        if ( $rmbz_fc === 'declined' ) echo ' · <strong style="color:#b3261e;">❌ recusou — projeto cancelado</strong>';
                    ?></span></div>
                    <?php endif; ?>
                    <?php /* [1.5.403] Admin define/altera/remove a participação (forçada ou com aceitação). */ ?>
                    <details style="margin-top:8px;">
                        <summary style="cursor:pointer; font-size:12px; font-weight:700; color:#6b5320;">🎤 <?php echo empty( $extra['feat']['name'] ) ? 'Definir participação…' : 'Alterar participação…'; ?></summary>
                        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="margin-top:8px; background:#fdf6e3; border:1px solid #e8c56a; border-radius:10px; padding:10px;">
                            <input type="hidden" name="action" value="rmbz_feat_admin_set">
                            <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                            <?php wp_nonce_field( 'rmbz_feat_admin_set_' . (int) $proj_id ); ?>
                            <input type="text" name="feat_name" placeholder="Nome artístico do participante" value="<?php echo esc_attr( (string) ( $extra['feat']['name'] ?? '' ) ); ?>" style="width:100%; margin-bottom:6px;">
                            <label style="display:flex; gap:6px; align-items:center; font-size:12px; margin-bottom:6px;">
                                <input type="checkbox" name="feat_has_account" value="1" <?php checked( ! empty( $extra['feat']['has_account'] ) ); ?>> Tem conta 1MZ For Artists
                            </label>
                            <input type="text" name="feat_tel" placeholder="Número da conta dele" value="<?php echo esc_attr( (string) ( $extra['feat']['tel'] ?? '' ) ); ?>" style="width:100%; margin-bottom:8px;">
                            <div style="font-size:12px; margin-bottom:8px;">
                                <label style="display:block; margin-bottom:4px;"><input type="radio" name="feat_mode" value="forced" checked> <strong>Forçada</strong> — fica aceite JÁ, o participante não precisa de aceitar (é só informado).</label>
                                <label style="display:block;"><input type="radio" name="feat_mode" value="consent"> <strong>Com aceitação</strong> — o participante recebe o convite (termos); se recusar, o projeto é cancelado.</label>
                            </div>
                            <div style="display:flex; gap:8px;">
                                <button type="submit" class="button button-primary" style="flex:1;">Guardar participação</button>
                                <?php if ( ! empty( $extra['feat']['name'] ) ) : ?>
                                    <button type="submit" name="feat_remove" value="1" class="button" style="color:#b3261e;" onclick="return confirm('Remover a participação deste projeto?');">Remover</button>
                                <?php endif; ?>
                            </div>
                        </form>
                    </details>
                    <div class="row"><span class="k">Nível</span><span class="v"><?php echo esc_html( strtoupper( $p->scenario_type ?: '—' ) ); ?></span></div>
                    <div class="row"><span class="k">Orçado</span><span class="v"><?php echo number_format( (float) $p->scenario_cost, 2, ',', '.' ); ?> MT</span></div>
                </div>

                <?php /* [1.6.118.23] CONTEXTO DO ARTISTA — ajuda decisão de aprovar/rejeitar */ ?>
                <div class="rmbz-pjv2-side-block rmbz-pjv2-context-block">
                    <h3><span class="ico">💼</span> Contexto do Artista</h3>

                    <?php
                    // Saldo
                    $balance = (float) ( $p->artist_balance ?? 0 );
                    $cost    = (float) $p->scenario_cost;
                    $has_enough = ( $cost > 0 && $balance >= $cost );
                    $balance_pct = $cost > 0 ? min( 100, round( ( $balance / $cost ) * 100 ) ) : 0;
                    ?>

                    <div class="rmbz-pjv2-ctx-row">
                        <div class="ctx-label">💼 Carteira do artista</div>
                        <div class="ctx-value <?php echo $has_enough ? 'ok' : ( $balance > 0 ? 'partial' : 'empty' ); ?>">
                            <?php echo number_format( $balance, 2, ',', '.' ); ?> MT
                        </div>
                        <?php if ( $cost > 0 ): ?>
                            <div class="ctx-hint">
                                <?php if ( $has_enough ): ?>
                                    ✓ Tem fundos para pagar este projecto
                                <?php elseif ( $balance > 0 ): ?>
                                    ⚠ Cobre <?php echo $balance_pct; ?>% do projecto (falta <?php echo number_format( $cost - $balance, 2, ',', '.' ); ?> MT)
                                <?php else: ?>
                                    ✗ Carteira vazia — precisa depositar
                                <?php endif; ?>
                            </div>
                        <?php endif; ?>
                    </div>

                    <div class="rmbz-pjv2-ctx-row">
                        <div class="ctx-label">💎 Estatuto VIP</div>
                        <div class="ctx-value <?php echo $vip_active ? 'ok' : 'empty'; ?>">
                            <?php if ( $vip_active ): ?>
                                ✓ VIP Activo
                            <?php else: ?>
                                ✗ Sem VIP
                            <?php endif; ?>
                        </div>
                        <?php if ( $vip_active ): ?>
                            <div class="ctx-hint">
                                <?php
                                $vip_days = max( 0, ceil( ( strtotime( $vip_active->end_date ) - time() ) / 86400 ) );
                                ?>
                                <strong><?php echo $vip_days; ?> dia(s)</strong> restantes
                                · pagou <?php echo number_format( (float) $vip_active->last_payment_amount, 2, ',', '.' ); ?> MT
                            </div>
                        <?php else: ?>
                            <div class="ctx-hint">⚠ Artista sem subscrição activa</div>
                        <?php endif; ?>
                    </div>

                    <?php
                    // Link directo perfil artista
                    $perfil_url = admin_url( 'admin.php?page=rmbz-historico-utilizador&user_id=' . urlencode( $p->artist_telemovel ) );
                    ?>
                    <a href="<?php echo esc_url( $perfil_url ); ?>" class="rmbz-pjv2-ctx-link" target="_blank" rel="noopener">
                        Abrir perfil completo →
                    </a>
                </div>

                <?php /* [1.6.118.23] HISTÓRICO DE PROJETOS — track record */ ?>
                <?php if ( $outros_total > 0 ): ?>
                <div class="rmbz-pjv2-side-block rmbz-pjv2-other-projects">
                    <h3>
                        <span class="ico">📋</span> Outros Projetos do Artista
                        <span class="count-badge"><?php echo $outros_total; ?></span>
                    </h3>

                    <div class="op-summary">
                        <span class="op-ok">✓ <?php echo $outros_concluidos; ?> concluído(s)</span>
                        <?php if ( $outros_rejeitados > 0 ): ?>
                            <span class="op-rej">✗ <?php echo $outros_rejeitados; ?> rejeitado(s)</span>
                        <?php endif; ?>
                    </div>

                    <ul class="op-list">
                        <?php foreach ( $outros_projetos as $op ):
                            $op_st = $op->production_status ?: 'pending_review';
                            $op_meta = $status_meta[ $op_st ] ?? [ 'label' => $op_st ];
                            $op_url  = admin_url( 'admin.php?page=rmbz-projetos&action=edit&id=' . $op->id );
                        ?>
                            <li>
                                <a href="<?php echo esc_url( $op_url ); ?>">
                                    <div class="op-title"><?php echo esc_html( mb_substr( $op->project_title ?: '(sem título)', 0, 30 ) ); ?></div>
                                    <div class="op-meta">
                                        <span class="op-status op-status-<?php echo esc_attr( $op_st ); ?>"><?php echo esc_html( $op_meta['label'] ); ?></span>
                                        <span class="op-cost"><?php echo number_format( (float) $op->scenario_cost, 0, ',', '.' ); ?> MT</span>
                                        <span class="op-paid <?php echo $op->is_paid ? 'paid' : 'unpaid'; ?>"><?php echo $op->is_paid ? '✓' : '✗'; ?></span>
                                    </div>
                                </a>
                            </li>
                        <?php endforeach; ?>
                    </ul>
                    <?php if ( $outros_total > count( $outros_projetos ) ): ?>
                        <div class="op-more">
                            + <?php echo ( $outros_total - count( $outros_projetos ) ); ?> mais
                        </div>
                    <?php endif; ?>
                </div>
                <?php endif; ?>

                <?php if ( ! empty( $p->demo_mp3_url ) ): ?>
                <div class="rmbz-pjv2-side-block">
                    <h3><span class="ico">🎧</span> Demo do artista</h3>
                    <audio controls preload="none"><source src="<?php echo esc_url( $p->demo_mp3_url ); ?>"></audio>
                    <div class="demo-actions">
                        <a href="<?php echo esc_url( $p->demo_mp3_url ); ?>" download><span class="ico">📥</span> Baixar áudio</a>
                    </div>
                </div>
                <?php endif; ?>

                <?php if ( ! empty( $p->project_pitch ) ): ?>
                <div class="rmbz-pjv2-side-block">
                    <h3><span class="ico">💡</span> Pitch do artista</h3>
                    <div class="pitch"><?php echo esc_html( $p->project_pitch ); ?></div>
                </div>
                <?php endif; ?>

                    <?php /* [1.5.398] Transferência de projeto entre artistas (forçada / com aceitação). */
                    $rmbz_tr = is_array( $extra ) && ! empty( $extra['transfer_request'] ) && is_array( $extra['transfer_request'] ) ? $extra['transfer_request'] : null;
                    $rmbz_tr_artists = $wpdb->get_results(
                        "SELECT user_telemovel, user_nome FROM {$table_wallets}
                         WHERE (extra_data NOT LIKE '%\"deleted_at\"%' OR extra_data IS NULL)
                         ORDER BY user_nome ASC LIMIT 500"
                    );
                    ?>
                    <div class="rmbz-pjv2-side-block" style="border:1px solid #f0d9b8; background:#fffdf7; border-radius:12px; padding:14px 16px; box-sizing:border-box;">
                        <h3><span class="ico">🔁</span> Transferência de Projeto
                            <span style="font-weight:400; font-size:11px; color:#5f6368; margin-left:6px;">(quando a música pertence a outro artista)</span>
                        </h3>
                        <datalist id="rmbz-tr-artists">
                            <?php foreach ( (array) $rmbz_tr_artists as $ta ) :
                                if ( (string) $ta->user_telemovel === (string) $p->artist_telemovel ) continue; ?>
                                <option value="<?php echo esc_attr( $ta->user_telemovel ); ?>"><?php echo esc_html( ( $ta->user_nome ?: 'Sem nome' ) . ' — ' . $ta->user_telemovel ); ?></option>
                            <?php endforeach; ?>
                        </datalist>

                        <?php if ( $rmbz_tr && ( $rmbz_tr['status'] ?? '' ) === 'pending' ) : ?>
                            <div style="background:#fbe7be; color:#5b3e00; border-radius:10px; padding:12px 14px; font-size:13px;">
                                ⏳ <strong>Pedido enviado ao artista</strong> — aguarda aceitação
                                (<?php echo esc_html( $rmbz_tr['requested_at'] ?? '' ); ?>).
                                <?php if ( ! empty( $rmbz_tr['reason'] ) ) : ?><br>Motivo: <?php echo esc_html( $rmbz_tr['reason'] ); ?><?php endif; ?>
                            </div>
                            <p style="margin-top:10px;">
                                <a class="button" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=rmbz_project_transfer_cancel&project_id=' . (int) $p->id ), 'rmbz_project_transfer_cancel_' . (int) $p->id ) ); ?>"
                                   onclick="return confirm('Cancelar o pedido de transferência?');">✖ Cancelar pedido</a>
                            </p>

                        <?php elseif ( $rmbz_tr && ( $rmbz_tr['status'] ?? '' ) === 'accepted' ) : ?>
                            <div style="background:#c7f2df; color:#053f2f; border-radius:10px; padding:12px 14px; font-size:13px; margin-bottom:10px;">
                                ✅ <strong>O artista aceitou a transferência</strong>
                                (<?php echo esc_html( $rmbz_tr['accepted_at'] ?? '' ); ?>).
                                <?php if ( ! empty( $rmbz_tr['suggested_name'] ) || ! empty( $rmbz_tr['suggested_tel'] ) ) : ?>
                                    <br>👤 <strong>Sugeriu como novo dono:</strong>
                                    <?php echo esc_html( trim( ( $rmbz_tr['suggested_name'] ?? '' ) . ' — ' . ( $rmbz_tr['suggested_tel'] ?? '' ), ' —' ) ); ?>
                                    <br><span style="opacity:.8;">Confirma na lista abaixo (podes escolher outro se a sugestão estiver errada).</span>
                                <?php endif; ?>
                            </div>
                            <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
                                <input type="hidden" name="action" value="rmbz_project_transfer_finalize">
                                <input type="hidden" name="project_id" value="<?php echo (int) $p->id; ?>">
                                <?php wp_nonce_field( 'rmbz_project_transfer_finalize_' . (int) $p->id ); ?>
                                <div class="rmbz-pjv2-field">
                                    <label>Novo dono do projeto (pré-preenchido com a sugestão do artista)</label>
                                    <input type="text" name="target_tel" list="rmbz-tr-artists" required
                                           value="<?php echo esc_attr( $rmbz_tr['suggested_tel'] ?? '' ); ?>"
                                           placeholder="Escreve para procurar na lista de artistas…" style="width:100%;">
                                </div>
                                <button type="submit" class="button button-primary"
                                        onclick="return confirm('Transferir o projeto para este artista? O contrato/KYC do dono antigo serão limpos.');">
                                    🔁 Transferir agora
                                </button>
                                <a class="button" style="margin-left:6px;" href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=rmbz_project_transfer_cancel&project_id=' . (int) $p->id ), 'rmbz_project_transfer_cancel_' . (int) $p->id ) ); ?>">✖ Cancelar</a>
                            </form>

                        <?php else : ?>
                            <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
                                <input type="hidden" name="action" value="rmbz_project_transfer">
                                <input type="hidden" name="project_id" value="<?php echo (int) $p->id; ?>">
                                <?php wp_nonce_field( 'rmbz_project_transfer_' . (int) $p->id ); ?>
                                <div style="display:flex; gap:14px; flex-wrap:wrap; margin-bottom:8px;">
                                    <label style="font-size:12px;"><input type="radio" name="transfer_mode" value="consent" checked> 🤝 Com aceitação do artista <span style="color:#5f6368;">(o artista atual tem de aceitar)</span></label>
                                    <label style="font-size:12px;"><input type="radio" name="transfer_mode" value="forced"> ⚡ Forçada <span style="color:#5f6368;">(muda já, sem o artista saber)</span></label>
                                </div>
                                <div class="rmbz-pjv2-field">
                                    <label>Novo dono (obrigatório na forçada; na "com aceitação" podes escolher depois)</label>
                                    <input type="text" name="target_tel" list="rmbz-tr-artists"
                                           placeholder="Escreve para procurar na lista de artistas…" style="width:100%;">
                                </div>
                                <div class="rmbz-pjv2-field">
                                    <label>Motivo (o artista vê no pedido; opcional)</label>
                                    <input type="text" name="transfer_reason" placeholder="Ex: a música pertence a outro artista" style="width:100%;">
                                </div>
                                <details style="margin:8px 0;">
                                    <summary style="cursor:pointer; font-size:12px; font-weight:600; color:#4c3fd6;">✏️ Alterações na transferência (nível, título, pitch) — opcional</summary>
                                    <div style="display:flex; gap:10px; flex-wrap:wrap; margin-top:8px;">
                                        <div class="rmbz-pjv2-field" style="flex:1; min-width:180px;">
                                            <label>Novo título</label>
                                            <input type="text" name="new_title" value="" placeholder="<?php echo esc_attr( $p->project_title ); ?>" style="width:100%;">
                                        </div>
                                        <div class="rmbz-pjv2-field" style="flex:1; min-width:180px;">
                                            <label>Novo nível (cenário)</label>
                                            <input type="text" name="new_scenario" value="" placeholder="<?php echo esc_attr( $p->scenario_type ); ?>" style="width:100%;">
                                        </div>
                                    </div>
                                    <div class="rmbz-pjv2-field">
                                        <label>Novo pitch do artista</label>
                                        <textarea name="new_pitch" rows="3" placeholder="(vazio = manter o pitch atual)"></textarea>
                                    </div>
                                </details>
                                <button type="submit" class="button button-primary"
                                        onclick="var f=this.form; if(f.transfer_mode.value==='forced'){ if(!f.target_tel.value.trim()){alert('Na transferência forçada tens de escolher o novo dono.');return false;} return confirm('Transferência FORÇADA: o projeto muda de dono JÁ, sem o artista atual saber. Continuar?'); } return confirm('Enviar pedido de transferência ao artista?');">
                                    🔁 Iniciar transferência
                                </button>
                                <p style="font-size:11px;color:#8a6d3b;margin:8px 0 0 0;">
                                    Na transferência o contrato/KYC do dono antigo são limpos — o novo dono terá de assinar/validar de novo.
                                </p>
                            </form>
                        <?php endif; ?>
                    </div>



                <?php if ( ! empty( $p->project_link_opt ) ): ?>
                <div class="rmbz-pjv2-side-block">
                    <h3><span class="ico">🔗</span> Referência</h3>
                    <a href="<?php echo esc_url( $p->project_link_opt ); ?>" target="_blank" rel="noopener"
                       style="display:block;padding:10px;background:#f3f4f6;border-radius:8px;font-size:13px;color:#1a1a1f;text-decoration:none;word-break:break-all;">
                        ↗ Abrir link
                    </a>
                </div>
                <?php endif; ?>
            </aside>

            <!-- COLUNA CENTRO: CHAT ────────────────────────────────── -->
            <main class="rmbz-pjv2-chat" id="rmbz-pjv2-chat">
                <div class="rmbz-pjv2-chat-head">
                    <div class="title">
                        <span class="ico">💬</span> Conversa
                        <span class="live-dot" title="Atualiza em tempo real (3s)">Live</span>
                    </div>
                    <button type="button"
                            class="rmbz-pjv2-attach-toggle <?php echo $can_attach ? 'is-on' : ''; ?>"
                            id="rmbz-pjv2-toggle-attach"
                            aria-pressed="<?php echo $can_attach ? 'true' : 'false'; ?>">
                        <span class="switch" aria-hidden="true"></span>
                        <span class="label">
                            Anexos do artista
                            <span class="hint"><?php echo $can_attach ? 'Permitido' : 'Bloqueado'; ?></span>
                        </span>
                    </button>
                </div>

                <?php /* [1.6.118.24] Filtros do chat — filtra mensagens visíveis por autor */ ?>
                <div class="rmbz-pjv2-chat-filters" id="rmbz-pjv2-chat-filters">
                    <button type="button" class="rmbz-pjv2-cf-btn is-active" data-filter="all">
                        Todos
                    </button>
                    <button type="button" class="rmbz-pjv2-cf-btn" data-filter="artist">
                        👤 Artista
                    </button>
                    <button type="button" class="rmbz-pjv2-cf-btn" data-filter="admin">
                        🛡 Admin
                    </button>
                    <button type="button" class="rmbz-pjv2-cf-btn" data-filter="system">
                        ⚙ Sistema
                    </button>
                    <button type="button" class="rmbz-pjv2-cf-btn" id="rmbz-pjv2-sound-toggle"
                            title="Som de novas mensagens" style="margin-left:auto;">🔔</button>
                </div>

                <div class="rmbz-pjv2-chat-stream" id="rmbz-pjv2-stream">
                    <div class="rmbz-pjv2-chat-empty" id="rmbz-pjv2-empty">
                        <div class="icon">💬</div>
                        <p style="margin:0;">A carregar conversa…</p>
                    </div>
                </div>

                <?php if ( in_array( $cur, [ 'rejected', 'cancelled_no_confirmation' ], true ) ) : ?>
                <?php // Chat bloqueado — o servidor também recusa o envio (code project_locked). ?>
                <div class="rmbz-pjv2-chat-composer" style="display:flex;align-items:center;justify-content:center;gap:8px;padding:14px;color:#8a8f98;font-size:13px;">
                    <span aria-hidden="true">🔒</span>
                    <span>Chat desativado — o projeto foi <?php echo $cur === 'rejected' ? 'rejeitado' : 'cancelado por prazo'; ?>.</span>
                </div>
                <?php else : ?>
                <div class="rmbz-pjv2-chat-composer">
                    <div class="rmbz-pjv2-composer-preview" id="rmbz-pjv2-preview">
                        <div class="ico" id="rmbz-pjv2-preview-ico">📎</div>
                        <div style="flex:1;min-width:0;">
                            <div class="name" id="rmbz-pjv2-preview-name">arquivo.png</div>
                            <div class="size" id="rmbz-pjv2-preview-size">0 KB</div>
                        </div>
                        <div class="progress" style="display:none;" id="rmbz-pjv2-preview-progress-wrap"><div class="bar" id="rmbz-pjv2-preview-progress"></div></div>
                        <button type="button" class="remove" id="rmbz-pjv2-preview-remove" aria-label="Remover">×</button>
                    </div>
                    <div class="rmbz-pjv2-composer-row">
                        <input type="file" id="rmbz-pjv2-file" style="display:none;" accept="image/*,audio/*,video/mp4,video/webm,video/quicktime,application/pdf">
                        <button type="button" class="rmbz-pjv2-composer-attach" id="rmbz-pjv2-attach-btn" title="Anexar (imagem, áudio, vídeo, PDF)">📎</button>
                        <textarea id="rmbz-pjv2-input" class="rmbz-pjv2-composer-input" rows="1" placeholder="Escreva uma mensagem…"></textarea>
                        <button type="button" class="rmbz-pjv2-composer-send" id="rmbz-pjv2-send" disabled aria-label="Enviar">➤</button>
                    </div>
                </div>
                <?php endif; ?>
            </main>

            <!-- COLUNA DIREITA: GESTÃO ─────────────────────────────── -->
            <aside class="rmbz-pjv2-manage">
                <form id="rmbz-pjv2-form" method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>">
                    <input type="hidden" name="action" value="onemz_admin_update_project">
                    <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                    <input type="hidden" name="production_status" id="rmbz-pjv2-prod-status" value="<?php echo esc_attr( $cur ); ?>">
                    <?php wp_nonce_field( 'onemz_update_project_nonce' ); ?>

                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">🚦</span> Estado da produção</h3>

                        <?php
                        // [1.6.118.114] Contador de prazo automático (cron):
                        //   - localização (2 dias após o admin enviar opções válidas)
                        //   - confirmação de datas (até ao início)
                        // Mostra ao admin que a contagem está activa e quanto falta.
                        echo rmbz_pjv2_render_countdown( $extra, $cur );
                        ?>

                        <?php // [1.6.118.24] Acções rápidas contextuais — diferentes por estado.
                        if ( $cur === 'pending_review' ): ?>
                            <div class="rmbz-pjv2-quick-actions">
                                <div class="qa-title">⚡ Decidir sobre este pedido</div>
                                <div class="qa-buttons">
                                    <button type="button" class="qa-btn qa-approve" data-target-status="pre-production">
                                        ✅ Aprovar
                                        <span class="qa-sub">passa a Aprovado (desbloqueia)</span>
                                    </button>
                                    <button type="button" class="qa-btn qa-correction" data-target-status="correction">
                                        ⚠️ Pedir Correções
                                        <span class="qa-sub">artista revê e re-submete</span>
                                    </button>
                                    <button type="button" class="qa-btn qa-reject" data-target-status="rejected">
                                        ❌ Rejeitar
                                        <span class="qa-sub">cancela definitivamente</span>
                                    </button>
                                </div>
                                <p class="qa-hint">Atalho rápido — depois clica em <strong>"Guardar alterações"</strong> em baixo para aplicar.</p>
                            </div>

                        <?php elseif ( $cur === 'pre-production' ): ?>
                            <div class="rmbz-pjv2-quick-actions">
                                <div class="qa-title">⚡ Avançar produção</div>
                                <div class="qa-buttons">
                                    <button type="button" class="qa-btn qa-approve" data-target-status="kyc_review">
                                        🪪 Pedir KYC
                                        <span class="qa-sub">artista precisa enviar documento</span>
                                    </button>
                                    <button type="button" class="qa-btn qa-info" data-target-status="filming">
                                        🎥 Iniciar Filmagem
                                        <span class="qa-sub">marcar início de produção</span>
                                    </button>
                                </div>
                                <p class="qa-hint">Próximos passos típicos depois da aprovação.</p>
                            </div>

                        <?php elseif ( $cur === 'kyc_review' ): ?>
                            <div class="rmbz-pjv2-quick-actions">
                                <div class="qa-title">⚡ Depois do KYC</div>
                                <div class="qa-buttons">
                                    <button type="button" class="qa-btn qa-info" data-target-status="filming">
                                        🎥 Iniciar Filmagem
                                        <span class="qa-sub">KYC validado, começar produção</span>
                                    </button>
                                    <button type="button" class="qa-btn qa-correction" data-target-status="correction">
                                        ⚠️ Documentos incompletos
                                        <span class="qa-sub">pedir novos documentos</span>
                                    </button>
                                </div>
                            </div>

                        <?php elseif ( $cur === 'filming' ): ?>
                            <div class="rmbz-pjv2-quick-actions">
                                <div class="qa-title">⚡ Próximos passos</div>
                                <div class="qa-buttons">
                                    <button type="button" class="qa-btn qa-info" data-target-status="editing">
                                        ✂ Em Edição
                                        <span class="qa-sub">filmagens completas, montar vídeo</span>
                                    </button>
                                </div>
                            </div>

                        <?php elseif ( $cur === 'editing' ): ?>
                            <div class="rmbz-pjv2-quick-actions">
                                <div class="qa-title">⚡ Finalizar projeto</div>
                                <div class="qa-buttons">
                                    <button type="button" class="qa-btn qa-approve" data-target-status="done">
                                        🚀 Concluir
                                        <span class="qa-sub">vídeo entregue, projeto fechado</span>
                                    </button>
                                </div>
                                <p class="qa-hint">Antes de concluir, preencha os links HD/YouTube em "Entrega final" em baixo.</p>
                            </div>

                        <?php elseif ( $cur === 'correction' ): ?>
                            <div class="rmbz-pjv2-quick-actions">
                                <div class="qa-title">⚡ Depois da correção</div>
                                <div class="qa-buttons">
                                    <button type="button" class="qa-btn qa-approve" data-target-status="pre-production">
                                        ✅ Aceitar correções
                                        <span class="qa-sub">retomar para Aprovado</span>
                                    </button>
                                    <button type="button" class="qa-btn qa-reject" data-target-status="rejected">
                                        ❌ Rejeitar definitivamente
                                        <span class="qa-sub">correções insuficientes</span>
                                    </button>
                                </div>
                            </div>

                        <?php elseif ( $cur === 'rejected' || $cur === 'done' ): ?>
                            <div class="rmbz-pjv2-quick-actions rmbz-pjv2-qa-final">
                                <div class="qa-title">
                                    <?php echo $cur === 'done' ? '🚀 Projecto Concluído' : '✕ Projecto Rejeitado'; ?>
                                </div>
                                <p class="qa-hint" style="margin:4px 0 0;">
                                    <?php if ( $cur === 'done' ): ?>
                                        Este projeto está finalizado. Para reabrir, use os pills em baixo.
                                    <?php else: ?>
                                        Este projeto foi rejeitado. Para reabrir, use os pills em baixo.
                                    <?php endif; ?>
                                </p>
                            </div>
                        <?php endif; ?>

                        <div class="rmbz-pjv2-state-pills" id="rmbz-pjv2-state-pills">
                            <?php foreach ( $status_meta as $k => $m ):
                                $active = ( $cur === $k );
                            ?>
                                <button type="button" class="rmbz-pjv2-state-pill <?php echo $active ? 'is-active' : ''; ?>" data-status="<?php echo esc_attr( $k ); ?>">
                                    <?php echo esc_html( $m['label'] ); ?>
                                </button>
                            <?php endforeach; ?>
                        </div>

                        <div class="rmbz-pjv2-rejbox <?php echo $cur === 'correction' ? 'rmbz-pjv2-rejbox--correction' : ''; ?>" id="rmbz-pjv2-rejbox" style="display:<?php echo in_array( $cur, [ 'rejected', 'correction' ], true ) ? 'block' : 'none'; ?>;">
                            <div class="rmbz-pjv2-field">
                                <label id="rmbz-pjv2-rejlabel">
                                    <?php echo $cur === 'correction' ? '✉ Instruções para correção (irá no email):' : '✉ Motivo da rejeição (irá no email):'; ?>
                                </label>
                                <textarea name="rejection_reason" rows="3" placeholder="Escreva aqui…"></textarea>
                            </div>
                        </div>
                    </div>

                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">💰</span> Pagamento</h3>
                        <?php
                        // [1.6.118.62] Detecção inteligente do estado de pagamento.
                        // BUG FIX: antes usava scenario_cost (bruto) — agora usa
                        // obligatory_cost (o que o artista realmente paga à 1MZ
                        // depois de assumir items negociáveis). Sem isto, um projecto
                        // com items assumidos mostrava "33% pago / faltam 6.000" quando
                        // na verdade já estava 100% pago.
                        //
                        // Usa a mesma função single-source-of-truth da API/form-handler.
                        $cost = function_exists( 'rmbz_calc_project_obligatory_cost' )
                            ? (float) rmbz_calc_project_obligatory_cost( $p )
                            : (float) $p->scenario_cost; // fallback defensivo
                        $paid     = (float) $p->amount_paid;
                        $is_full  = ( $cost > 0 && $paid >= ( $cost - 0.01 ) );
                        $is_part  = ( $paid > 0 && $paid < ( $cost - 0.01 ) );
                        $is_none  = ( $paid <= 0 );
                        $pct_pago = $cost > 0 ? min( 100, round( ( $paid / $cost ) * 100 ) ) : 0;
                        $falta    = max( 0, $cost - $paid );

                        // [1.6.118.62] scenario_cost bruto — só para mostrar contexto
                        // ("de um orçamento total de X") quando difere do obligatory.
                        $cost_bruto = (float) $p->scenario_cost;
                        $tem_assumidos = ( $cost_bruto > $cost + 0.01 );

                        // Estado calculado (auto)
                        $auto_state_class = $is_full ? 'paid-full' : ( $is_part ? 'paid-part' : 'paid-none' );
                        $auto_state_label = $is_full
                            ? '✅ Totalmente Pago'
                            : ( $is_part
                                ? '⚠️ Parcialmente Pago'
                                : '❌ Sem Pagamentos' );
                        $auto_state_desc  = $is_full
                            ? 'O artista pagou o valor total devido à 1MZ. Pronto para avançar.'
                            : ( $is_part
                                ? sprintf( 'Falta receber %s MT do total de %s MT a pagar à 1MZ.',
                                    number_format( $falta, 2, ',', '.' ),
                                    number_format( $cost, 2, ',', '.' ) )
                                : ( $cost > 0
                                    ? sprintf( 'Aguarda pagamento de %s MT à 1MZ.', number_format( $cost, 2, ',', '.' ) )
                                    : 'Orçamento ainda não definido.' ) );
                        ?>

                        <div class="rmbz-pjv2-payment-state <?php echo $auto_state_class; ?>">
                            <div class="ps-header">
                                <span class="ps-badge"><?php echo esc_html( $auto_state_label ); ?></span>
                                <span class="ps-pct"><?php echo $pct_pago; ?>%</span>
                            </div>
                            <div class="ps-bar"><div class="ps-bar-fill" style="width: <?php echo $pct_pago; ?>%;"></div></div>
                            <div class="ps-desc"><?php echo esc_html( $auto_state_desc ); ?></div>
                            <?php if ( $tem_assumidos ): ?>
                                <div class="ps-desc" style="font-size:11px; opacity:0.75; margin-top:4px;">
                                    💡 O artista assumiu <?php echo number_format( $cost_bruto - $cost, 2, ',', '.' ); ?> MT em items negociáveis (orçamento bruto: <?php echo number_format( $cost_bruto, 2, ',', '.' ); ?> MT).
                                </div>
                            <?php endif; ?>
                            <?php if ( $cost > 0 ): ?>
                                <div class="ps-numbers">
                                    <div class="ps-num">
                                        <span class="label">💵 Pago</span>
                                        <span class="value paid"><?php echo number_format( $paid, 2, ',', '.' ); ?> MT</span>
                                    </div>
                                    <div class="ps-num">
                                        <span class="label">📊 Total</span>
                                        <span class="value"><?php echo number_format( $cost, 2, ',', '.' ); ?> MT</span>
                                    </div>
                                    <?php if ( $is_part ): ?>
                                        <div class="ps-num">
                                            <span class="label">⏳ Falta</span>
                                            <span class="value falta"><?php echo number_format( $falta, 2, ',', '.' ); ?> MT</span>
                                        </div>
                                    <?php endif; ?>
                                </div>
                            <?php endif; ?>
                        </div>

                        <!-- Override manual (admin pode forçar estado se quiser, ex: pagamento offline) -->
                        <div class="rmbz-pjv2-field" style="margin-top: 12px;">
                            <label style="display:flex; align-items:center; gap:6px; cursor:pointer; font-size:12px;">
                                <input type="checkbox" id="rmbz-pjv2-pay-override" <?php checked( (int) $p->is_paid === 1 && ! $is_full ); ?>>
                                <span>Forçar como "Pago" (override manual — para pagamentos offline ou outros casos)</span>
                            </label>
                            <input type="hidden" name="is_paid" id="rmbz-pjv2-is-paid-final" value="<?php echo $is_full || ( (int) $p->is_paid === 1 ) ? '1' : '0'; ?>">
                        </div>
                    </div>

                    <script>
                    (function(){
                        var cb = document.getElementById('rmbz-pjv2-pay-override');
                        var hf = document.getElementById('rmbz-pjv2-is-paid-final');
                        var autoFull = <?php echo $is_full ? 'true' : 'false'; ?>;
                        if ( ! cb || ! hf ) return;
                        // Estado inicial: se já está totalmente pago automaticamente, hidden = 1
                        function syncHidden(){
                            hf.value = ( autoFull || cb.checked ) ? '1' : '0';
                        }
                        cb.addEventListener('change', syncHidden);
                        syncHidden();
                    })();
                    </script>

                    <?php
                    // [1.6.118.27] Bloco "Prazo do contrato" só faz sentido enquanto
                    // o contrato AINDA NÃO foi aceite pelo artista. Depois do aceite
                    // o prazo não tem utilidade — esconder para reduzir ruído visual.
                    // Estados onde NÃO mostra: já aceite, ou já avançou para fases pós-contrato.
                    $contract_already_accepted = ! empty( $extra['contract_accepted'] );
                    $post_contract_states = [ 'filming', 'editing', 'done', 'rejected' ];
                    $show_deadline_block = ! $contract_already_accepted
                                           && ! in_array( $cur, $post_contract_states, true );
                    ?>
                    <?php if ( $show_deadline_block ): ?>
                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">⏰</span> Prazo do contrato</h3>
                        <div class="rmbz-pjv2-field">
                            <label>Dia/hora limite para o artista aceitar</label>
                            <input type="datetime-local" name="contract_deadline"
                                value="<?php echo ! empty( $extra['contract_deadline'] ) ? esc_attr( date( 'Y-m-d\TH:i', is_numeric( $extra['contract_deadline'] ) ? (int) $extra['contract_deadline'] : strtotime( $extra['contract_deadline'] ) ) ) : ''; ?>">
                            <p style="font-size:11px;color:#5f6368;margin:4px 0 0 0;">Em branco = sistema cancela em 3 dias automaticamente.</p>
                        </div>
                    </div>
                    <?php endif; ?>

                    <!-- ORÇAMENTOS POR LOCALIZAÇÃO (lista de itens — feature crítica) -->
                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">📊</span> Orçamento por localização</h3>
                        <?php
                        $proposed_budgets = $extra['proposed_budgets'] ?? [];
                        $budget_accepted_loc = $extra['budget_accepted_location'] ?? '';
                        // [1.6.118.36] Fase 3 — limpado: $payment_choice e $show_checklist_column
                        // já não são usados (modo misto per-item substituiu-os).
                        $detalhes = ! empty( $p->scenario_details ) ? json_decode( $p->scenario_details, true ) : [];
                        if ( ! is_array( $detalhes ) ) $detalhes = [];
                        ?>

                        <?php if ( ! empty( $budget_accepted_loc ) ): ?>
                            <!-- Localização escolhida: tabela única editável (modo "checklist" se self-fund) -->
                            <div style="background:#d1fae5;border:1px solid #a7f3d0;color:#065f46;padding:8px 12px;border-radius:8px;font-size:12px;margin-bottom:10px;">
                                ✓ Artista escolheu: <strong><?php echo esc_html( $budget_accepted_loc ); ?></strong>
                                <br><span style="font-size:11px;">
                                    💡 <strong>Pagamento:</strong> marque items como <strong>Obrigatório</strong> (artista paga sempre)
                                    ou <strong>Negociável</strong> (artista decide se assume).
                                    Status (⏳/✅) é para items que o artista assumiu.
                                </span>
                            </div>

                            <?php
                            // [1.6.118.34] Cálculo dos sub-totais por categoria de pagamento
                            $sum_obrigatorio = 0;
                            $sum_negociavel  = 0;
                            $sum_artista     = 0;
                            foreach ( $detalhes as $it ) {
                                $c = (float) ( $it['cost'] ?? 0 );
                                $mp = isset( $it['must_pay'] ) ? (int) $it['must_pay'] : 1;
                                $aa = ! empty( $it['artist_assumes'] );
                                if ( $mp === 1 ) {
                                    $sum_obrigatorio += $c;
                                } else {
                                    $sum_negociavel += $c;
                                    if ( $aa ) $sum_artista += $c;
                                }
                            }
                            $sum_1mz_final = $sum_obrigatorio + ( $sum_negociavel - $sum_artista );
                            ?>

                            <div class="rmbz-pjv2-budget-scroll">
                            <table class="rmbz-pjv2-budget-table" id="rmbz-pjv2-single-budget">
                                <thead>
                                    <tr>
                                        <th>Categ.</th>
                                        <th>Item</th>
                                        <th>MT</th>
                                        <th style="width:120px;">Pagamento</th>
                                        <th style="width:82px;">Decisão</th>
                                        <th style="width:65px;">Status</th>
                                        <th style="width:34px;"></th>
                                    </tr>
                                </thead>
                                <tbody id="rmbz-pjv2-single-rows">
                                    <?php
                                    $rows_to_render = ! empty( $detalhes ) ? $detalhes : [ [ 'cat' => '', 'desc' => '', 'cost' => 0, 'checked' => 0, 'must_pay' => 1, 'artist_assumes' => 0 ] ];
                                    foreach ( $rows_to_render as $item ):
                                        $cat            = $item['cat'] ?? '';
                                        $desc           = $item['desc'] ?? '';
                                        $cost           = $item['cost'] ?? 0;
                                        $checked        = ! empty( $item['checked'] ) ? '1' : '0';
                                        $must_pay       = isset( $item['must_pay'] ) ? (string) (int) $item['must_pay'] : '1';
                                        $artist_assumes = ! empty( $item['artist_assumes'] ) ? '1' : '0';
                                    ?>
                                    <tr data-must-pay="<?php echo esc_attr( $must_pay ); ?>">
                                        <td><input type="text" name="budget_cat[]" value="<?php echo esc_attr( $cat ); ?>" placeholder="—"></td>
                                        <td><input type="text" name="budget_desc[]" value="<?php echo esc_attr( $desc ); ?>" placeholder="Ex: Câmera"></td>
                                        <td><input type="number" name="budget_cost[]" value="<?php echo esc_attr( $cost ); ?>" step="0.01" class="rmbz-pjv2-cost-input" oninput="rmbzPjv2CalcSingleTotal()"></td>
                                        <td>
                                            <select name="budget_must_pay[]" class="rmbz-pjv2-mustpay-select" onchange="rmbzPjv2OnMustPayChange(this)">
                                                <option value="1" <?php selected( $must_pay, '1' ); ?>>💰 Obrigatório</option>
                                                <option value="0" <?php selected( $must_pay, '0' ); ?>>🤝 Negociável</option>
                                            </select>
                                        </td>
                                        <td>
                                            <?php // Decisão do artista — só relevante se must_pay=0. Read-only para admin. ?>
                                            <span class="rmbz-pjv2-assumes-label" data-assumed="<?php echo esc_attr( $artist_assumes ); ?>" style="font-size:11px;<?php echo $must_pay === '1' ? 'opacity:0.3;' : ''; ?>">
                                                <?php
                                                if ( $must_pay === '1' ) {
                                                    echo '—';
                                                } elseif ( $artist_assumes === '1' ) {
                                                    echo '✋ Assume';
                                                } else {
                                                    echo '💰 1MZ paga';
                                                }
                                                ?>
                                            </span>
                                            <input type="hidden" name="budget_assumes[]" value="<?php echo esc_attr( $artist_assumes ); ?>">
                                        </td>
                                        <td>
                                            <?php
                                            // [1.6.118.39] Status — quando o item é Obrigatório OU o artista não
                                            // assumiu, NÃO faz sentido editar o checklist. Em vez de <select disabled>
                                            // (que renderiza mal em colunas estreitas mostrando ambas as options),
                                            // mostramos apenas um span estático com o emoji actual + hidden field
                                            // para preservar valor no submit.
                                            $status_editable = ( $must_pay !== '1' && $artist_assumes === '1' );
                                            if ( $status_editable ):
                                            ?>
                                                <select name="budget_checked[]" class="rmbz-pjv2-checked-select">
                                                    <option value="0" <?php selected( $checked, '0' ); ?>>⏳</option>
                                                    <option value="1" <?php selected( $checked, '1' ); ?>>✅</option>
                                                </select>
                                            <?php else: ?>
                                                <div class="rmbz-pjv2-status-static" title="<?php echo esc_attr( $must_pay === '1' ? 'Item obrigatório — sem checklist' : 'Artista escolheu deixar à 1MZ' ); ?>">—</div>
                                                <input type="hidden" name="budget_checked[]" value="<?php echo esc_attr( $checked ); ?>">
                                            <?php endif; ?>
                                        </td>
                                        <td><button type="button" class="rmbz-pjv2-row-del" onclick="this.closest('tr').remove(); rmbzPjv2CalcSingleTotal();">×</button></td>
                                    </tr>
                                    <?php endforeach; ?>
                                </tbody>
                            </table>
                            </div><?php /* /rmbz-pjv2-budget-scroll */ ?>
                            <div class="rmbz-pjv2-budget-foot">
                                <button type="button" class="rmbz-pjv2-row-add" onclick="rmbzPjv2AddSingleRow()">+ Adicionar item</button>
                                <div class="rmbz-pjv2-total">Total: <strong id="rmbz-pjv2-single-total"><?php echo number_format( (float) $p->scenario_cost, 2, ',', '.' ); ?></strong> MT</div>
                            </div>

                            <?php // [1.6.118.34] Breakdown dos sub-totais — ajuda admin a perceber valores finais ?>
                            <div style="margin-top:14px; padding:12px 14px; background:#f7f7fb; border-radius:8px; font-size:12px; line-height:1.7;">
                                <div style="display:flex; justify-content:space-between;">
                                    <span>💰 Obrigatório (artista paga sempre):</span>
                                    <strong><?php echo number_format( $sum_obrigatorio, 2, ',', '.' ); ?> MT</strong>
                                </div>
                                <div style="display:flex; justify-content:space-between;">
                                    <span>🤝 Negociável (decisão do artista):</span>
                                    <strong><?php echo number_format( $sum_negociavel, 2, ',', '.' ); ?> MT</strong>
                                </div>
                                <?php if ( $sum_artista > 0 ): ?>
                                <div style="display:flex; justify-content:space-between; color:#047857;">
                                    <span>↳ Artista assumiu:</span>
                                    <strong>− <?php echo number_format( $sum_artista, 2, ',', '.' ); ?> MT</strong>
                                </div>
                                <?php endif; ?>
                                <div style="display:flex; justify-content:space-between; margin-top:8px; padding-top:8px; border-top:1px solid #ddd; font-size:13px;">
                                    <span>💵 <strong>Total final a pagar à 1MZ:</strong></span>
                                    <strong style="color:#1e40af;"><?php echo number_format( $sum_1mz_final, 2, ',', '.' ); ?> MT</strong>
                                </div>
                            </div>

                        <?php else: ?>
                            <!-- Multi-localização: várias opções, artista escolhe -->
                            <p style="font-size:11px;color:#5f6368;margin:0 0 10px 0;">Crie várias opções (ex: Maputo, Nampula). O artista escolhe uma na conta dele.</p>
                            <div id="rmbz-pjv2-multi-container"></div>
                            <button type="button" class="rmbz-pjv2-row-add" style="width:100%;margin-top:8px;" onclick="rmbzPjv2AddLocation()">+ Adicionar localização</button>
                        <?php endif; ?>
                    </div>

                    <?php /* [1.6.118.30] Pitch da Produção — visão criativa da equipa 1MZ.
                          Diferente do "Guião" (operacional). Esta é a INSPIRAÇÃO/visão
                          partilhada com o artista para criar entusiasmo e alinhamento. */ ?>
                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">💡</span> Pitch da Produção
                            <span style="font-weight:400; font-size:11px; color:#5f6368; margin-left:6px;">(visão da equipa para o artista)</span>
                        </h3>
                        <?php /* [1.5.397] Gerar o pitch com IA a partir do pitch do artista + ideias da equipa. */ ?>
                        <?php if ( function_exists( 'rmbz_ai_available' ) && rmbz_ai_available() ) : ?>
                        <div style="background:linear-gradient(135deg,#f3f0ff,#faf9ff); border:1px solid #d9d2f5; border-radius:12px; padding:12px 14px; margin-bottom:12px;">
                            <label style="font-size:12px; font-weight:600; color:#4c3fd6; display:block; margin-bottom:6px;">
                                ✨ Gerar com IA — ideias da equipa (opcional)
                            </label>
                            <textarea id="rmbz-ai-pitch-ideas" rows="2" style="width:100%;"
                                placeholder="Ex: plano aéreo da baixa ao pôr-do-sol, cena de dança no mercado, tom nostálgico, referências a Mafalala…"></textarea>
                            <div style="display:flex; align-items:center; gap:10px; margin-top:8px;">
                                <button type="button" class="button button-primary" id="rmbz-ai-pitch-btn"
                                    data-project="<?php echo (int) $p->id; ?>"
                                    data-nonce="<?php echo esc_attr( wp_create_nonce( 'rmbz_ai_pitch_' . (int) $p->id ) ); ?>">
                                    ✨ Gerar Pitch com IA
                                </button>
                                <span id="rmbz-ai-pitch-status" style="font-size:12px; color:#5f6368;"></span>
                            </div>
                            <p style="font-size:11px;color:#7a739c;margin:6px 0 0 0;">
                                A IA usa o pitch do artista + as tuas ideias para escrever a visão/roteiro. Podes editar antes de guardar.
                            </p>
                        </div>
                        <script>
                        (function(){
                            var btn = document.getElementById('rmbz-ai-pitch-btn');
                            if (!btn) return;
                            btn.addEventListener('click', function(){
                                var ta = document.querySelector('textarea[name="production_pitch"]');
                                if (ta && ta.value.trim() !== '' && !confirm('Substituir o pitch atual pelo gerado pela IA?')) return;
                                var status = document.getElementById('rmbz-ai-pitch-status');
                                var ideas = (document.getElementById('rmbz-ai-pitch-ideas')||{value:''}).value;
                                btn.disabled = true;
                                status.textContent = 'A escrever o pitch… (pode demorar ~10s)';
                                var fd = new FormData();
                                fd.append('action', 'rmbz_ai_generate_pitch');
                                fd.append('project_id', btn.dataset.project);
                                fd.append('_wpnonce', btn.dataset.nonce);
                                fd.append('ideas', ideas);
                                fetch(ajaxurl, { method:'POST', credentials:'same-origin', body: fd })
                                    .then(function(r){ return r.json(); })
                                    .then(function(j){
                                        if (j && j.success && j.data && j.data.pitch) {
                                            if (ta) { ta.value = j.data.pitch; ta.style.height = 'auto'; ta.style.height = (ta.scrollHeight + 4) + 'px'; }
                                            status.textContent = '✓ Pitch gerado — revê e guarda.';
                                            status.style.color = '#1c9d6e';
                                        } else {
                                            status.textContent = '✗ ' + ((j && j.data && j.data.message) || 'Falha ao gerar.');
                                            status.style.color = '#d6453b';
                                        }
                                    })
                                    .catch(function(){ status.textContent = '✗ Erro de ligação.'; status.style.color = '#d6453b'; })
                                    .finally(function(){ btn.disabled = false; });
                            });
                        })();
                        </script>
                        <?php endif; ?>
                        <div class="rmbz-pjv2-field">
                            <label>Mensagem inspiradora ao artista sobre como vão produzir o videoclipe</label>
                            <textarea name="production_pitch" rows="5"
                                placeholder="Ex: Olá! Vamos criar algo épico. A nossa visão é começar com um plano aéreo da cidade ao nascer do sol, depois cortar para…"><?php echo esc_textarea( $extra['production_pitch'] ?? '' ); ?></textarea>
                            <p style="font-size:11px;color:#5f6368;margin:4px 0 0 0;">
                                Aparece no app e site do artista como card "💡 Pitch disponível" assim que o projeto for aprovado.
                                Em branco = não aparece para o artista.
                            </p>
                        </div>
                    </div>

                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">📅</span> Datas de Gravação
                            <span style="font-weight:400; font-size:11px; color:#5f6368; margin-left:6px;">(o artista vê e pode confirmar/propor)</span>
                        </h3>
                        <?php
                        $f_start = ! empty( $extra['filming_start'] ) ? (string) $extra['filming_start'] : '';
                        $f_end   = ! empty( $extra['filming_end'] )   ? (string) $extra['filming_end']   : '';
                        $f_confirmed = ! empty( $extra['filming_confirmed_by_artist'] );
                        $f_proposed  = ! empty( $extra['filming_proposed_by_artist'] ) && is_array( $extra['filming_proposed_by_artist'] )
                            ? $extra['filming_proposed_by_artist'] : null;
                        ?>
                        <div style="display:flex; gap:10px; flex-wrap:wrap;">
                            <div class="rmbz-pjv2-field" style="flex:1; min-width:140px;">
                                <label>Início das filmagens</label>
                                <input type="date" name="filming_start" value="<?php echo esc_attr( $f_start ); ?>">
                            </div>
                            <div class="rmbz-pjv2-field" style="flex:1; min-width:140px;">
                                <label>Fim das filmagens</label>
                                <input type="date" name="filming_end" value="<?php echo esc_attr( $f_end ); ?>">
                            </div>
                        </div>

                        <?php if ( $f_start !== '' || $f_end !== '' ): ?>
                            <?php if ( $f_confirmed ): ?>
                                <div style="background:#e6f4ea; border-left:3px solid #34a853; border-radius:6px; padding:8px 12px; margin-top:8px; font-size:12px; color:#1e7e34;">
                                    ✅ O artista <strong>confirmou</strong> estas datas.
                                </div>
                            <?php elseif ( $f_proposed ): ?>
                                <div style="background:#fff3e0; border-left:3px solid #f0b90b; border-radius:6px; padding:10px 12px; margin-top:8px; font-size:12px; color:#92400e;">
                                    📅 O artista <strong>propôs outras datas</strong>:
                                    <strong><?php echo esc_html( date_i18n( 'd/m/Y', strtotime( $f_proposed['start'] ?? '' ) ) ); ?></strong>
                                    a
                                    <strong><?php echo esc_html( date_i18n( 'd/m/Y', strtotime( $f_proposed['end'] ?? '' ) ) ); ?></strong>.
                                    <br>
                                    <span style="font-size:11px; color:#78350f;">Para aceitar, copia estas datas para os campos acima e guarda. Para manter as tuas, ignora e guarda na mesma (a proposta será limpa).</span>
                                </div>
                            <?php else: ?>
                                <div style="background:#e8eaed; border-left:3px solid #5f6368; border-radius:6px; padding:8px 12px; margin-top:8px; font-size:12px; color:#5f6368;">
                                    ⏳ Aguarda confirmação do artista.
                                </div>
                            <?php endif; ?>
                        <?php endif; ?>
                    </div>

                    <?php
                    // [1.6.118.87] Equipa do projecto — atribuir membros do banco
                    // de pessoas. Aparece logo após as datas de gravação.
                    $assigned_ids = ( isset( $extra['team_member_ids'] ) && is_array( $extra['team_member_ids'] ) )
                        ? array_map( 'intval', $extra['team_member_ids'] ) : [];
                    $requested_by = ( isset( $extra['team_requested_by'] ) && is_array( $extra['team_requested_by'] ) )
                        ? $extra['team_requested_by'] : [];
                    $all_members  = function_exists( 'rmbz_team_get_all' ) ? rmbz_team_get_all( true ) : [];
                    $team_link    = admin_url( 'admin.php?page=rmbz-projetos&action=team' );
                    // [1.6.118.98] Diagnóstico de requisitos da equipa
                    $diag = function_exists( 'rmbz_team_validate_project' ) ? rmbz_team_validate_project( $extra ) : null;
                    ?>
                    <style>
                    /* [1.5.407] Equipa do Videoclipe — M3 Expressive */
                    .rmbz-tm-banner{ border-radius:16px; padding:12px 14px; margin-bottom:12px; font-size:12px; line-height:1.55; }
                    .rmbz-tm-banner b{ font-size:13px; display:block; margin-bottom:2px; }
                    .rmbz-tm-banner--err{ background:#fdf1f0; border:1px solid #f6cbc8; color:#57536a; } .rmbz-tm-banner--err b{ color:#8c1d18; }
                    .rmbz-tm-banner--ok{ background:#e6f4ea; border:1px solid #bfe5cf; } .rmbz-tm-banner--ok b{ color:#0d5c34; margin:0; }
                    .rmbz-tm-banner--warn{ background:#fdf6e3; border:1px solid #efd9a0; } .rmbz-tm-banner--warn b{ color:#92400e; }
                    .rmbz-tm-chip{ display:inline-block; background:#fff; border:1px solid #f6cbc8; color:#8c1d18; border-radius:99px; padding:3px 12px; font-size:12px; font-weight:700; }
                    .rmbz-tm-member{ border:1.5px solid #e8e6ef; background:#fff; border-radius:16px; padding:10px 13px; transition:border-color .15s, background .15s; }
                    .rmbz-tm-member.is-on{ border-color:#34a853; background:#f2faf5; }
                    .rmbz-tm-member label.main{ display:flex; align-items:center; gap:10px; cursor:pointer; font-size:13px; }
                    .rmbz-tm-member img, .rmbz-tm-member .avatar{ width:36px; height:36px; border-radius:50%; object-fit:cover; flex:0 0 auto; }
                    .rmbz-tm-member .avatar{ background:#ece5fb; color:#3d2a66; display:inline-flex; align-items:center; justify-content:center; font-size:14px; font-weight:800; }
                    .rmbz-tm-member b{ display:block; line-height:1.25; color:#1a1a20; }
                    .rmbz-tm-member .role{ font-size:11px; color:#7a7688; }
                    .rmbz-tm-tag{ background:#fdf6e3; color:#92400e; font-size:9px; font-weight:800; padding:2px 8px; border-radius:99px; margin-left:6px; letter-spacing:.4px; vertical-align:1px; }
                    .rmbz-tm-seg{ display:inline-flex; background:#f3f1f9; border-radius:99px; padding:3px; gap:2px; }
                    .rmbz-tm-seg label{ font-size:11px; font-weight:700; color:#57536a; border-radius:99px; padding:4px 12px; cursor:pointer; display:inline-flex; gap:5px; align-items:center; }
                    .rmbz-tm-seg input{ display:none; }
                    .rmbz-tm-seg label:has(input:checked){ background:#fff; color:#3d2a66; box-shadow:0 1px 3px rgba(26,18,54,.15); }
                    </style>
                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">🎥</span> Equipa do Videoclipe
                            <span style="font-weight:400; font-size:11px; color:#5f6368; margin-left:6px;">(o artista vê quem vai trabalhar)</span>
                        </h3>
                        <input type="hidden" name="team_section_present" value="1">

                        <?php if ( $diag ): ?>
                            <!-- [1.6.118.98] Painel de diagnóstico inteligente -->
                            <?php if ( ! $diag['ok'] ): ?>
                                <div class="rmbz-tm-banner rmbz-tm-banner--err">
                                    <b>⛔ O projecto não pode avançar para filmagens.</b>
                                    Faltam cargos essenciais na equipa:
                                    <div style="display:flex; flex-wrap:wrap; gap:6px; margin-top:8px;">
                                        <?php foreach ( $diag['missing'] as $miss ): ?>
                                            <span class="rmbz-tm-chip"><?php echo esc_html( $miss['icon'] . ' ' . $miss['label'] ); ?></span>
                                        <?php endforeach; ?>
                                    </div>
                                </div>
                            <?php else: ?>
                                <div class="rmbz-tm-banner rmbz-tm-banner--ok">
                                    <b>✅ Equipa essencial completa — o projecto pode avançar.</b>
                                </div>
                            <?php endif; ?>

                            <?php if ( ! empty( $diag['external_by_mz'] ) ): ?>
                                <div class="rmbz-tm-banner rmbz-tm-banner--warn">
                                    <b>🌐 Atenção: definiste pessoa(s) externa(s) à 1MZ.</b>
                                    <?php echo esc_html( implode( ', ', array_map( fn($m)=>$m->name, $diag['external_by_mz'] ) ) ); ?> — confirma que querias mesmo alguém de fora da 1MZ.
                                </div>
                            <?php endif; ?>

                            <?php if ( ! empty( $diag['external_by_artist'] ) ): ?>
                                <?php
                                $fee_applied = ( isset( $extra['team_fee_applied'] ) && is_array( $extra['team_fee_applied'] ) )
                                    ? $extra['team_fee_applied'] : [];
                                // [1.5.409] Valores REALMENTE aplicados ao orçamento (por pessoa
                                // e por departamento) — o painel mostrava a taxa por defeito
                                // mesmo quando o admin tinha ajustado (ex.: 0 MT) ao aplicar.
                                $fee_real = []; // [mid][dept] => valor ; [mid]['__total'] => soma
                                $fee_items_src = ! empty( $p->scenario_details ) ? json_decode( $p->scenario_details, true ) : [];
                                if ( is_array( $fee_items_src ) ) {
                                    foreach ( $fee_items_src as $fi ) {
                                        if ( ! is_array( $fi ) || empty( $fi['team_fee_for'] ) ) continue;
                                        $fi_mid  = (int) $fi['team_fee_for'];
                                        $fi_dk   = (string) ( $fi['team_fee_dept'] ?? '__unico' );
                                        $fi_cost = (float) ( $fi['cost'] ?? 0 );
                                        $fee_real[ $fi_mid ][ $fi_dk ] = $fi_cost;
                                        $fee_real[ $fi_mid ]['__total'] = ( $fee_real[ $fi_mid ]['__total'] ?? 0 ) + $fi_cost;
                                    }
                                }
                                // Quantos externos do artista ainda NÃO têm taxa aplicada
                                $pending_fee = array_filter( $diag['external_by_artist'], fn( $m ) => empty( $fee_applied[ (int) $m->id ] ) );
                                // [1.5.408] Total real = soma das taxas de TODOS os departamentos
                                // dos cargos que cada pendente vai exercer neste projeto.
                                $pending_total = 0.0;
                                foreach ( $pending_fee as $pm ) {
                                    foreach ( rmbz_team_member_fee_lines( $pm, $extra ) as $pl ) {
                                        $pending_total += (float) $pl['fee'];
                                    }
                                }
                                $apply_url = wp_nonce_url(
                                    admin_url( 'admin-post.php?action=rmbz_team_apply_fee&project_id=' . (int) $p->id ),
                                    'rmbz_team_apply_fee_' . (int) $p->id
                                );
                                ?>
                                <?php $fee_form_id = 'rmbz-fee-form-' . (int) $p->id; ?>
                                <?php /* [1.5.407] Era um <form> ANINHADO dentro do form principal —
                                         HTML inválido que fechava o form principal e deixava as
                                         checkboxes da equipa (e tudo abaixo) SEM submissão. Agora é
                                         um <div>; o submit constrói o form via JS. */ ?>
                                <div class="rmbz-tm-banner rmbz-tm-banner--warn" id="<?php echo esc_attr( $fee_form_id ); ?>"
                                     data-nonce="<?php echo esc_attr( wp_create_nonce( 'rmbz_team_apply_fee_' . (int) $p->id ) ); ?>"
                                     data-project="<?php echo (int) $p->id; ?>">
                                    <b>💰 Pessoa(s) pedida(s) pelo artista — taxa de vistoria.</b>
                                    A 1MZ não conhece esta(s) pessoa(s). Vistoria por pessoa (garantia de qualidade 1MusicMoz). Podes <strong>ajustar o valor de cada pessoa</strong> antes de aplicar:
                                    <div style="display:flex; flex-direction:column; gap:8px; margin:10px 0;">
                                        <?php foreach ( $diag['external_by_artist'] as $m ):
                                            $m_done  = ! empty( $fee_applied[ (int) $m->id ] );
                                            // [1.5.408] Uma vistoria POR DEPARTAMENTO dos cargos
                                            // que a pessoa vai exercer NESTE projeto.
                                            $m_lines = rmbz_team_member_fee_lines( $m, $extra );
                                            // [1.5.409] Aplicada → mostra os valores REAIS do orçamento
                                            // (o admin pode ter ajustado, ex.: 0 MT); pendente → sugeridos.
                                            $m_real = $fee_real[ (int) $m->id ] ?? [];
                                            $m_sum  = $m_done && isset( $m_real['__total'] )
                                                ? (float) $m_real['__total']
                                                : array_sum( array_map( fn( $l ) => (float) $l['fee'], $m_lines ) );
                                        ?>
                                            <div style="background:#fff; border:1px solid #efd9a0; border-radius:14px; padding:10px 12px;">
                                                <div style="display:flex; align-items:center; justify-content:space-between; gap:10px;">
                                                    <span style="font-size:12px; font-weight:800; color:#1a1a20;">
                                                        👤 <?php echo esc_html( $m->name ); ?>
                                                        <span style="color:#9aa0a6; font-weight:600;">— <?php echo count( $m_lines ); ?> vistoria(s)</span>
                                                    </span>
                                                    <?php if ( $m_done ): ?>
                                                        <span style="font-size:12px; white-space:nowrap;"><strong><?php echo number_format( $m_sum, 0 ); ?> MT</strong> ✅</span>
                                                    <?php endif; ?>
                                                </div>
                                                <div style="display:flex; flex-direction:column; gap:4px; margin-top:6px;">
                                                    <?php foreach ( $m_lines as $m_dk => $m_line ): ?>
                                                        <div style="font-size:12px; color:#57536a; display:flex; align-items:center; justify-content:space-between; gap:10px;">
                                                            <span>
                                                                <?php echo esc_html( $m_line['icon'] . ' ' . $m_line['label'] ); ?>
                                                                <?php if ( ! empty( $m_line['roles'] ) ): ?>
                                                                    <span style="color:#9aa0a6;">· <?php echo esc_html( implode( ', ', $m_line['roles'] ) ); ?></span>
                                                                <?php endif; ?>
                                                            </span>
                                                            <?php if ( $m_done ):
                                                                // Valor real aplicado neste departamento (fallback: única linha antiga ou sugerido).
                                                                $m_line_real = $m_real[ $m_dk ] ?? $m_real['__unico'] ?? (float) $m_line['fee'];
                                                            ?>
                                                                <span style="white-space:nowrap; color:#137333; font-weight:700;"><?php echo number_format( (float) $m_line_real, 0 ); ?> MT ✅</span>
                                                            <?php else: ?>
                                                                <span style="white-space:nowrap; display:inline-flex; align-items:center; gap:4px;">
                                                                    <?php /* sem name= — não submete com o form principal; o JS envia fee_manual[mid][dept] */ ?>
                                                                    <input type="number" min="0" step="50"
                                                                           value="<?php echo esc_attr( (int) $m_line['fee'] ); ?>"
                                                                           class="rmbz-fee-input rmbz-fs-input"
                                                                           data-member="<?php echo (int) $m->id; ?>"
                                                                           data-dept="<?php echo esc_attr( $m_dk ); ?>"
                                                                           data-form="<?php echo esc_attr( $fee_form_id ); ?>"
                                                                           style="width:95px; text-align:right; min-height:32px; padding:5px 10px !important;">
                                                                    <span style="color:#9aa0a6;">MT</span>
                                                                </span>
                                                            <?php endif; ?>
                                                        </div>
                                                    <?php endforeach; ?>
                                                </div>
                                            </div>
                                        <?php endforeach; ?>
                                    </div>
                                    <?php if ( ! empty( $pending_fee ) ): ?>
                                        <div style="display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap;">
                                            <button type="button" class="rmbz-fs-btn rmbz-fs-btn--tonal rmbz-fee-apply" data-form="<?php echo esc_attr( $fee_form_id ); ?>"
                                                    style="background:#f0b90b; color:#1a1400;">
                                                ➕ Aplicar ao orçamento (<?php echo count( $pending_fee ); ?> em falta · <span class="rmbz-fee-total" data-form="<?php echo esc_attr( $fee_form_id ); ?>"><?php echo number_format( $pending_total, 0 ); ?></span> MT)
                                            </button>
                                            <a href="<?php echo esc_url( $apply_url ); ?>"
                                               onclick="return confirm('Aplicar os valores sugeridos (total <?php echo number_format( $pending_total, 0 ); ?> MT) sem alterações?');"
                                               style="font-size:11px; color:#92400e; text-decoration:underline;">usar valores sugeridos</a>
                                        </div>
                                    <?php else: ?>
                                        <p style="margin:8px 0 0; font-size:12px; color:#137333; font-weight:700;">✅ Taxa de vistoria já aplicada ao orçamento.</p>
                                    <?php endif; ?>
                                </div>
                                <script>
                                (function(){
                                    var fid = <?php echo wp_json_encode( $fee_form_id ); ?>;
                                    var box = document.getElementById(fid);
                                    if (!box || box.dataset.feeBound) return;
                                    box.dataset.feeBound = '1';
                                    function fmt(n){ return Math.round(n).toLocaleString('pt-PT'); }
                                    function recalc(){
                                        var sum = 0;
                                        box.querySelectorAll('.rmbz-fee-input').forEach(function(i){
                                            var v = parseFloat(i.value); if (!isNaN(v) && v > 0) sum += v;
                                        });
                                        var t = document.querySelector('.rmbz-fee-total[data-form="'+fid+'"]');
                                        if (t) t.textContent = fmt(sum);
                                    }
                                    box.querySelectorAll('.rmbz-fee-input').forEach(function(i){
                                        i.addEventListener('input', recalc);
                                    });
                                    var applyBtn = box.querySelector('.rmbz-fee-apply');
                                    if (applyBtn) applyBtn.addEventListener('click', function(){
                                        if (!confirm('Adicionar as vistorias ao orçamento deste projecto com os valores indicados?')) return;
                                        // Form construído na hora (fora do form principal) — HTML válido.
                                        var f = document.createElement('form');
                                        f.method = 'post';
                                        f.action = <?php echo wp_json_encode( admin_url( 'admin-post.php' ) ); ?>;
                                        function hid(n, v){ var i = document.createElement('input'); i.type = 'hidden'; i.name = n; i.value = v; f.appendChild(i); }
                                        hid('action', 'rmbz_team_apply_fee');
                                        hid('project_id', box.dataset.project);
                                        hid('_wpnonce', box.dataset.nonce);
                                        box.querySelectorAll('.rmbz-fee-input').forEach(function(i){
                                            // [1.5.408] Valor por pessoa E por departamento (cargo).
                                            // [1.5.409] Campo limpo = 0 MT (o admin apagou de propósito;
                                            // antes caía na taxa por defeito e "voltava sozinha").
                                            hid('fee_manual[' + i.dataset.member + '][' + (i.dataset.dept || 'outro') + ']', i.value === '' ? '0' : i.value);
                                        });
                                        document.body.appendChild(f);
                                        f.submit();
                                    });
                                })();
                                </script>
                            <?php endif; ?>

                            <?php
                            // [1.5.411] ENTREGA AO EDITOR EXTERNO — só com editor externo,
                            // taxa PAGA e filmagem terminada (ou quando já há registo).
                            // Passo 1: registar ficheiros (nº, GB, qualidade) → notifica o
                            // artista com os dados; Passo 2: "Entregue ao editor" → artista
                            // sabe que a 1MZ só aguarda a edição para aprovar o vídeo final.
                            $ed       = function_exists( 'rmbz_editor_delivery_get' ) ? rmbz_editor_delivery_get( $extra ) : null;
                            $ed_avail = function_exists( 'rmbz_editor_delivery_available' ) && rmbz_editor_delivery_available( $p );
                            if ( $ed && ( $ed_avail || $ed['files'] > 0 ) ):
                                $ed_nonce = wp_create_nonce( 'rmbz_editor_delivery_' . (int) $p->id );
                            ?>
                                <div id="rmbz-ed-panel"
                                     data-nonce="<?php echo esc_attr( $ed_nonce ); ?>"
                                     data-project="<?php echo (int) $p->id; ?>"
                                     style="margin-top:12px; background:#faf9fd; border:1.5px solid #e2ddf0; border-radius:18px; padding:14px 16px;">
                                    <div style="font-size:12px; font-weight:800; color:#3d2a66; letter-spacing:.4px; text-transform:uppercase; margin-bottom:8px;">
                                        📦 Entrega ao EDITOR EXTERNO
                                    </div>

                                    <?php if ( isset( $_GET['ed_error'] ) ): ?>
                                        <div class="rmbz-tm-banner rmbz-tm-banner--err" style="margin-bottom:10px;">
                                            <b>❌ <?php echo esc_html( sanitize_text_field( wp_unslash( $_GET['ed_error'] ) ) ); ?></b>
                                        </div>
                                    <?php elseif ( isset( $_GET['ed_info_saved'] ) ): ?>
                                        <div class="rmbz-tm-banner rmbz-tm-banner--ok" style="margin-bottom:10px;">
                                            <b>✅ Ficheiros registados — o artista foi notificado com os dados.</b>
                                        </div>
                                    <?php elseif ( isset( $_GET['ed_delivered'] ) ): ?>
                                        <div class="rmbz-tm-banner rmbz-tm-banner--ok" style="margin-bottom:10px;">
                                            <b>✅ Entrega marcada — o artista sabe que a 1MZ só aguarda a edição.</b>
                                        </div>
                                    <?php endif; ?>

                                    <?php if ( $ed['delivered'] ): ?>
                                        <div class="rmbz-tm-banner rmbz-tm-banner--ok" style="margin:0;">
                                            <b>🚚 Ficheiros ENTREGUES ao editor externo.</b><br>
                                            🎞️ <?php echo (int) $ed['files']; ?> ficheiro(s) ·
                                            💾 <?php echo $ed['size_gb'] > 0 ? esc_html( number_format( $ed['size_gb'], 2, ',', '.' ) ) . ' GB' : '—'; ?> ·
                                            ✨ <?php echo esc_html( $ed['quality'] ); ?><br>
                                            <span style="font-size:11px; color:#5f6368;">
                                                Entregue em <?php echo esc_html( $ed['delivered_at'] ); ?> por <?php echo esc_html( $ed['delivered_by'] ); ?> —
                                                a 1MZ aguarda a edição para aprovar o vídeo final.
                                            </span>
                                        </div>
                                    <?php elseif ( $ed['files'] > 0 ): ?>
                                        <div style="background:#fff; border:1px solid #e2ddf0; border-radius:14px; padding:10px 12px; margin-bottom:10px;">
                                            <div style="font-size:13px; font-weight:700; color:#1a1a20;">
                                                🎞️ <?php echo (int) $ed['files']; ?> ficheiro(s) ·
                                                💾 <?php echo $ed['size_gb'] > 0 ? esc_html( number_format( $ed['size_gb'], 2, ',', '.' ) ) . ' GB' : '—'; ?> ·
                                                ✨ <?php echo esc_html( $ed['quality'] ); ?>
                                            </div>
                                            <div style="font-size:11px; color:#9aa0a6; margin-top:4px;">
                                                Registado em <?php echo esc_html( $ed['info_at'] ); ?> por <?php echo esc_html( $ed['info_by'] ); ?> · o artista foi notificado.
                                            </div>
                                        </div>
                                        <div style="display:flex; align-items:center; gap:10px; flex-wrap:wrap;">
                                            <button type="button" class="rmbz-fs-btn rmbz-fs-btn--tonal" id="rmbz-ed-done-btn"
                                                    style="background:#e6f4ea; color:#137333;">
                                                🚚 Entregue ao editor — marcar
                                            </button>
                                            <button type="button" class="rmbz-fs-btn" id="rmbz-ed-edit-btn"
                                                    style="background:transparent; border:1.5px solid #e2ddf0; color:#57536a;">
                                                ✏️ Corrigir dados
                                            </button>
                                        </div>
                                    <?php endif; ?>

                                    <?php if ( ! $ed['delivered'] ): ?>
                                        <div id="rmbz-ed-form" style="<?php echo $ed['files'] > 0 ? 'display:none;' : ''; ?> margin-top:6px;">
                                            <p style="margin:0 0 8px; font-size:12px; color:#57536a;">
                                                A taxa do editor está paga ✅ — regista os ficheiros preparados; o artista é <b>notificado com os dados</b> e desbloqueia o passo "Entregue ao editor".
                                            </p>
                                            <div style="display:flex; gap:8px; flex-wrap:wrap; align-items:flex-end;">
                                                <label style="font-size:11px; font-weight:700; color:#5b3e70; display:flex; flex-direction:column; gap:4px;">
                                                    Nº de ficheiros
                                                    <input type="number" min="1" step="1" id="rmbz-ed-files" class="rmbz-fs-input"
                                                           value="<?php echo $ed['files'] > 0 ? (int) $ed['files'] : ''; ?>" style="width:110px;">
                                                </label>
                                                <label style="font-size:11px; font-weight:700; color:#5b3e70; display:flex; flex-direction:column; gap:4px;">
                                                    Tamanho total (GB)
                                                    <input type="number" min="0" step="0.01" id="rmbz-ed-gb" class="rmbz-fs-input"
                                                           value="<?php echo $ed['size_gb'] > 0 ? esc_attr( $ed['size_gb'] ) : ''; ?>" style="width:130px;">
                                                </label>
                                                <label style="font-size:11px; font-weight:700; color:#5b3e70; display:flex; flex-direction:column; gap:4px;">
                                                    Qualidade
                                                    <input type="text" id="rmbz-ed-quality" class="rmbz-fs-input" list="rmbz-ed-quality-list"
                                                           value="<?php echo esc_attr( $ed['quality'] ); ?>" placeholder="ex.: 4K UHD" style="width:150px;">
                                                    <datalist id="rmbz-ed-quality-list">
                                                        <option value="4K UHD (2160p)"></option>
                                                        <option value="2.7K"></option>
                                                        <option value="Full HD (1080p)"></option>
                                                        <option value="HD (720p)"></option>
                                                        <option value="RAW / ProRes"></option>
                                                    </datalist>
                                                </label>
                                                <button type="button" class="rmbz-fs-btn rmbz-fs-btn--tonal" id="rmbz-ed-save-btn"
                                                        style="background:#ece5fb; color:#3d2a66;">
                                                    💾 Registar e notificar o artista
                                                </button>
                                            </div>
                                        </div>
                                    <?php endif; ?>
                                </div>
                                <script>
                                (function(){
                                    var panel = document.getElementById('rmbz-ed-panel');
                                    if (!panel || panel.dataset.edBound) return;
                                    panel.dataset.edBound = '1';
                                    function post(action, fields){
                                        // Form construído na hora (fora do form principal) — HTML válido.
                                        var f = document.createElement('form');
                                        f.method = 'post';
                                        f.action = <?php echo wp_json_encode( admin_url( 'admin-post.php' ) ); ?>;
                                        function hid(n, v){ var i = document.createElement('input'); i.type = 'hidden'; i.name = n; i.value = v; f.appendChild(i); }
                                        hid('action', action);
                                        hid('project_id', panel.dataset.project);
                                        hid('_wpnonce', panel.dataset.nonce);
                                        Object.keys(fields || {}).forEach(function(k){ hid(k, fields[k]); });
                                        document.body.appendChild(f);
                                        f.submit();
                                    }
                                    var save = document.getElementById('rmbz-ed-save-btn');
                                    if (save) save.addEventListener('click', function(){
                                        var files = (document.getElementById('rmbz-ed-files') || {}).value || '';
                                        var gb = (document.getElementById('rmbz-ed-gb') || {}).value || '';
                                        var q = (document.getElementById('rmbz-ed-quality') || {}).value || '';
                                        if (!files || parseInt(files, 10) <= 0) { alert('Indica quantos ficheiros são.'); return; }
                                        if (!q.trim()) { alert('Indica a qualidade dos ficheiros.'); return; }
                                        if (!confirm('Registar ' + files + ' ficheiro(s)' + (gb ? ' · ' + gb + ' GB' : '') + ' · ' + q + ' e NOTIFICAR o artista?')) return;
                                        post('rmbz_editor_delivery_info', { ed_files: files, ed_size_gb: gb, ed_quality: q });
                                    });
                                    var done = document.getElementById('rmbz-ed-done-btn');
                                    if (done) done.addEventListener('click', function(){
                                        if (!confirm('Confirmas que o EDITOR EXTERNO já levou TODOS os ficheiros? O artista será notificado de que a 1MZ só aguarda a edição para aprovar o vídeo final.')) return;
                                        post('rmbz_editor_delivery_done', {});
                                    });
                                    var edit = document.getElementById('rmbz-ed-edit-btn');
                                    if (edit) edit.addEventListener('click', function(){
                                        var f = document.getElementById('rmbz-ed-form');
                                        if (f) f.style.display = f.style.display === 'none' ? 'block' : 'none';
                                    });
                                })();
                                </script>
                            <?php endif; ?>
                        <?php endif; ?>

                        <?php if ( empty( $all_members ) ): ?>
                            <p style="font-size:13px; color:#5f6368; margin:6px 0;">
                                Ainda não há pessoas no banco de equipa.
                                <a href="<?php echo esc_url( $team_link ); ?>">Adicionar pessoas →</a>
                            </p>
                        <?php else: ?>
                            <p style="font-size:12px; color:#5f6368; margin:4px 0 10px;">
                                Marca quem trabalha neste projecto.
                                <a href="<?php echo esc_url( $team_link ); ?>">Gerir banco de pessoas →</a>
                            </p>
                            <?php
                            // [1.5.408] Cargos escolhidos POR PROJETO (member_id => [cargos]).
                            $proj_roles_sel = ( isset( $extra['team_project_roles'] ) && is_array( $extra['team_project_roles'] ) )
                                ? $extra['team_project_roles'] : [];
                            ?>
                            <style>
                            .rmbz-tm-member .proj-roles{ display:none; margin-top:8px; padding:10px 12px 10px 46px; background:#faf9fd; border-radius:12px; }
                            .rmbz-tm-member.is-on .proj-roles{ display:block; }
                            .rmbz-tm-member .proj-roles .lbl{ font-size:11px; font-weight:800; color:#5b3e70; letter-spacing:.5px; text-transform:uppercase; display:block; margin-bottom:6px; }
                            .rmbz-tm-rolechip{ display:inline-flex; align-items:center; border:1.5px solid #e2ddf0; background:#fff; border-radius:99px; padding:4px 12px; font-size:11px; font-weight:700; color:#57536a; cursor:pointer; margin:0 5px 5px 0; user-select:none; transition:all .12s; }
                            .rmbz-tm-rolechip input{ display:none; }
                            .rmbz-tm-rolechip:has(input:checked){ background:#ece5fb; border-color:#7b5bd6; color:#3d2a66; }
                            .rmbz-tm-rolechip:has(input:checked)::before{ content:"✓ "; font-weight:900; }
                            .rmbz-tm-member.role-required{ outline:2px solid #b3261e; outline-offset:2px; border-radius:14px; }
                            </style>
                            <div style="display:flex; flex-direction:column; gap:8px;">
                                <?php foreach ( $all_members as $m ):
                                    $checked = in_array( (int) $m->id, $assigned_ids, true );
                                    $is_ext  = isset( $m->origin ) && $m->origin === 'externo';
                                    $who     = $requested_by[ (int) $m->id ] ?? 'mz';
                                    // Cargos disponiveis da pessoa + os escolhidos para ESTE projeto.
                                    $m_roles = array_values( array_filter( array_map( 'trim', explode( '·', (string) ( $m->role ?? '' ) ) ) ) );
                                    $m_sel   = isset( $proj_roles_sel[ (int) $m->id ] ) && is_array( $proj_roles_sel[ (int) $m->id ] )
                                        ? $proj_roles_sel[ (int) $m->id ] : [];
                                ?>
                                    <div class="rmbz-tm-member <?php echo $checked ? 'is-on' : ''; ?>">
                                        <label class="main">
                                            <input type="checkbox" name="team_member_ids[]" value="<?php echo (int) $m->id; ?>" <?php checked( $checked ); ?> style="margin:0;"
                                                   onchange="this.closest('.rmbz-tm-member').classList.toggle('is-on', this.checked);">
                                            <?php if ( ! empty( $m->photo_url ) ): ?>
                                                <img src="<?php echo esc_url( $m->photo_url ); ?>" alt="">
                                            <?php else: ?>
                                                <span class="avatar"><?php echo esc_html( mb_strtoupper( mb_substr( $m->name, 0, 1 ) ) ); ?></span>
                                            <?php endif; ?>
                                            <span style="flex:1;">
                                                <b><?php echo esc_html( $m->name ); ?><?php if ( $is_ext ): ?><span class="rmbz-tm-tag">🌐 EXTERNO</span><?php endif; ?></b>
                                                <?php if ( ! empty( $m->role ) ): ?>
                                                    <span class="role"><?php echo esc_html( $m->role ); ?></span>
                                                <?php endif; ?>
                                            </span>
                                        </label>

                                        <?php if ( count( $m_roles ) > 0 ): ?>
                                            <!-- [1.5.408] O que ELE vai fazer NESTE projeto (o artista vê só estes). -->
                                            <div class="proj-roles">
                                                <span class="lbl">🎬 O que vai fazer neste projeto</span>
                                                <?php foreach ( $m_roles as $mr ):
                                                    $mr_on = in_array( $mr, $m_sel, true );
                                                ?>
                                                    <label class="rmbz-tm-rolechip">
                                                        <input type="checkbox" name="team_project_roles[<?php echo (int) $m->id; ?>][]"
                                                               value="<?php echo esc_attr( $mr ); ?>" <?php checked( $mr_on ); ?>>
                                                        <?php echo esc_html( $mr ); ?>
                                                    </label>
                                                <?php endforeach; ?>
                                            </div>
                                        <?php endif; ?>

                                        <?php if ( $is_ext ): ?>
                                            <!-- Seletor "quem pediu" só para externos — segmented M3 -->
                                            <div style="margin-top:8px; padding-left:46px; display:flex; gap:8px; align-items:center;">
                                                <span style="font-size:11px; color:#7a7688;">Quem pediu:</span>
                                                <span class="rmbz-tm-seg">
                                                    <label><input type="radio" name="team_requested_by[<?php echo (int) $m->id; ?>]" value="mz" <?php checked( $who !== 'artist' ); ?>>1MZ</label>
                                                    <label><input type="radio" name="team_requested_by[<?php echo (int) $m->id; ?>]" value="artist" <?php checked( $who === 'artist' ); ?>>Artista (taxa)</label>
                                                </span>
                                            </div>
                                        <?php endif; ?>
                                    </div>
                                <?php endforeach; ?>
                            </div>
                            <script>
                            (function(){
                                var form = document.getElementById('rmbz-pjv2-form');
                                if (!form || form.dataset.teamRoleValidation === '1') return;
                                form.dataset.teamRoleValidation = '1';
                                form.addEventListener('change', function(event){
                                    var member = event.target.closest && event.target.closest('.rmbz-tm-member');
                                    if (member) member.classList.remove('role-required');
                                });
                                form.addEventListener('submit', function(event){
                                    var invalid = null;
                                    form.querySelectorAll('.rmbz-tm-member').forEach(function(member){
                                        if (invalid) return;
                                        var assigned = member.querySelector('input[name="team_member_ids[]"]');
                                        var roles = member.querySelectorAll('.proj-roles input[type="checkbox"]');
                                        if (!assigned || !assigned.checked || !roles.length) return;
                                        var selected = Array.prototype.some.call(roles, function(role){ return role.checked; });
                                        if (!selected) invalid = member;
                                    });
                                    if (!invalid) return;
                                    event.preventDefault();
                                    invalid.classList.add('role-required');
                                    invalid.scrollIntoView({ behavior:'smooth', block:'center' });
                                    window.alert('Escolhe pelo menos um cargo para cada pessoa atribuida ao projeto.');
                                });
                            })();
                            </script>
                        <?php endif; ?>
                    </div>

                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">🎬</span> Guião &amp; Plano
                            <span style="font-weight:400; font-size:11px; color:#5f6368; margin-left:6px;">(operacional)</span>
                        </h3>
                        <div class="rmbz-pjv2-field">
                            <label>Link do guião (PDF/Drive)</label>
                            <input type="url" name="script_url" value="<?php echo esc_url( $extra['script_url'] ?? '' ); ?>" placeholder="https://…">
                        </div>
                        <?php /* [1.6.118.36] Fase 3 — removida checkbox "Artista assume os custos".
                              Substituída pelo modo misto per-item na tabela do orçamento, onde admin
                              marca cada item como Obrigatório ou Negociável. */ ?>
                        <div class="rmbz-pjv2-field">
                            <label>Anotações (visíveis ao artista)</label>
                            <textarea name="script_content" rows="3" placeholder="Plano de ação…"><?php echo esc_textarea( $p->script_content ?? '' ); ?></textarea>
                        </div>
                    </div>

                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">🚀</span> Entrega final</h3>
                        <div class="rmbz-pjv2-field">
                            <label>Link HD (Drive)</label>
                            <input type="url" name="final_video_url" value="<?php echo esc_url( $p->final_video_url ?? '' ); ?>" placeholder="https://drive.google.com/…">
                        </div>
                        <div class="rmbz-pjv2-field">
                            <label>Link YouTube</label>
                            <input type="url" name="youtube_url" value="<?php echo esc_url( $p->youtube_url ?? '' ); ?>" placeholder="https://youtu.be/…">
                        </div>
                    </div>

                    <?php // [1.6.392] Desativar notificações deste projeto. ?>
                    <div class="rmbz-pjv2-manage-block">
                        <h3><span class="ico">🔕</span> Notificações</h3>
                        <label class="check" style="display:flex;gap:10px;align-items:flex-start;cursor:pointer;">
                            <input type="checkbox" name="notify_muted" value="1" <?php checked( ! empty( $extra['notifications_muted'] ) ); ?> style="margin-top:3px;width:16px;height:16px;">
                            <span style="font-size:13px;line-height:1.5;color:#1a1a1f;">
                                <strong>Desativar notificação deste projeto</strong>
                                <span style="display:block;color:#5f6368;font-size:12px;margin-top:2px;">Quando ligado, o artista NÃO é notificado (push, email nem sino) por nenhuma mudança deste projeto — incluindo lembretes de multa e avisos de subscrição. O conteúdo continua a aparecer no projeto/chat, só não dispara notificação.</span>
                            </span>
                        </label>
                    </div>

                    <button type="submit" class="rmbz-pjv2-save">
                        <span class="ico">💾</span> Guardar alterações
                    </button>
                </form>

                <?php
                // ============================================================
                // [1.5.404] 🎬 GRAVAÇÃO AO VIVO — Iniciar / presenças / finalizar.
                // Fora do form principal (tem forms próprios, incl. upload).
                // ============================================================
                $fs_sessions = ( ! empty( $extra['filming_sessions'] ) && is_array( $extra['filming_sessions'] ) ) ? $extra['filming_sessions'] : [];
                $fs_active = null; $fs_history = [];
                foreach ( $fs_sessions as $fs_s ) {
                    if ( ! is_array( $fs_s ) ) continue;
                    if ( empty( $fs_s['ended_at'] ) ) { $fs_active = $fs_s; } else { $fs_history[] = $fs_s; }
                }
                $fs_start_date = (string) ( $extra['filming_start'] ?? '' );
                $fs_end_date   = (string) ( $extra['filming_end'] ?? '' );
                $fs_has_dates = $fs_start_date !== '' || $fs_end_date !== '';
                // [1.5.407] "Iniciar Gravação" só DENTRO da janela de datas
                // (início..fim) ou já na fase FILMAGEM (dias de continuação).
                $fs_today = current_time( 'Y-m-d' );
                $fs_in_window = $fs_start_date !== '' && $fs_today >= $fs_start_date
                    && ( $fs_end_date === '' || $fs_today <= $fs_end_date );
                $fs_date_reached = $fs_in_window || (string) $p->production_status === 'filming';
                // [1.5.408] Sem a equipa essencial completa NÃO se pode iniciar
                // — mesma regra do diagnóstico da Equipa do Videoclipe.
                $fs_team_diag = function_exists( 'rmbz_team_validate_project' ) ? rmbz_team_validate_project( $extra ) : null;
                $fs_team_ok = $fs_team_diag === null || ! empty( $fs_team_diag['ok'] );
                $fs_can_start = in_array( (string) $p->production_status, [ 'pre-production', 'filming' ], true )
                    && $fs_has_dates && $fs_active === null && $fs_date_reached && $fs_team_ok;
                // Dia chegou mas equipa incompleta → mostra o aviso no lugar do botão.
                $fs_blocked_by_team = in_array( (string) $p->production_status, [ 'pre-production', 'filming' ], true )
                    && $fs_has_dates && $fs_active === null && $fs_date_reached && ! $fs_team_ok;
                $fs_pleft = isset( $extra['filming_progress']['percent_left'] ) ? (int) $extra['filming_progress']['percent_left'] : -1;

                // Só aparece com sessão a decorrer, histórico, janela aberta ou bloqueio por equipa.
                if ( $fs_active || ! empty( $fs_history ) || $fs_can_start || $fs_blocked_by_team ) : ?>
                <style>
                /* [1.5.407] Gravação ao Vivo — M3 Expressive */
                .rmbz-fs-card{ background:#fff; border:1px solid #e8e6ef; border-radius:22px; padding:18px; margin:22px 0; box-shadow:0 1px 3px rgba(26,18,54,.06); }
                .rmbz-fs-card.is-live{ border:2px solid #e5484d; box-shadow:0 8px 28px -10px rgba(229,72,77,.35); }
                .rmbz-fs-head{ display:flex; align-items:center; gap:12px; margin-bottom:14px; }
                .rmbz-fs-ico{ width:42px; height:42px; border-radius:14px; background:#fdecea; display:flex; align-items:center; justify-content:center; font-size:20px; flex:0 0 auto; }
                .rmbz-fs-title{ font-size:15px; font-weight:800; color:#1a1a20; letter-spacing:-.01em; flex:1; }
                .rmbz-fs-title small{ display:block; font-size:11px; font-weight:600; color:#8a8794; letter-spacing:.4px; text-transform:uppercase; margin-top:1px; }
                .rmbz-fs-pill{ font-size:11px; font-weight:800; border-radius:99px; padding:5px 12px; white-space:nowrap; }
                .rmbz-fs-pill--rec{ background:#e5484d; color:#fff; }
                .rmbz-fs-pill--warn{ background:#fff3e0; color:#92400e; }
                .rmbz-fs-pill--ok{ background:#e6f4ea; color:#1e7e34; }
                .rmbz-fs-hero{ background:linear-gradient(150deg,#211b2e,#141019 60%); border-radius:18px; padding:20px 16px 16px; text-align:center; margin-bottom:12px; }
                .rmbz-fs-hero .clock{ font-size:44px; font-weight:900; letter-spacing:3px; color:#fff; font-variant-numeric:tabular-nums; line-height:1.05; }
                .rmbz-fs-hero .sub{ font-size:12px; color:#b9b3c6; margin-top:6px; }
                .rmbz-fs-label{ font-size:11px; font-weight:800; color:#5b3e70; letter-spacing:.8px; text-transform:uppercase; margin:0 0 8px; }
                .rmbz-fs-chiprow{ display:flex; flex-wrap:wrap; gap:8px; margin-bottom:12px; }
                .rmbz-fs-person{ display:inline-flex; align-items:center; gap:9px; background:#f6f4fb; border:1px solid #e6e1f2; border-radius:99px; padding:5px 14px 5px 5px; }
                .rmbz-fs-person img{ width:34px; height:34px; border-radius:50%; object-fit:cover; cursor:zoom-in; display:block; }
                .rmbz-fs-person .noimg{ width:34px; height:34px; border-radius:50%; background:#e6e1f2; display:flex; align-items:center; justify-content:center; font-size:15px; }
                .rmbz-fs-person b{ display:block; font-size:12px; color:#1a1a20; line-height:1.2; }
                .rmbz-fs-person span{ font-size:11px; color:#7a7688; }
                .rmbz-fs-panel{ border-radius:16px; padding:14px; margin-bottom:12px; }
                .rmbz-fs-panel--soft{ background:#f6f4fb; border:1px solid #e6e1f2; }
                .rmbz-fs-panel--danger{ background:#fdf1f0; border:1px solid #f6cbc8; }
                .rmbz-fs-input{ border:1px solid #d9d2e8 !important; border-radius:12px !important; padding:9px 14px !important; font-size:13px !important; background:#fff !important; box-shadow:none !important; min-height:38px; }
                .rmbz-fs-input:focus{ border-color:#7b5bd6 !important; box-shadow:0 0 0 3px rgba(123,91,214,.15) !important; outline:none; }
                .rmbz-fs-btn{ border:0; border-radius:99px; padding:12px 22px; font-size:13px; font-weight:800; cursor:pointer; transition:filter .15s, transform .1s; }
                .rmbz-fs-btn:hover{ filter:brightness(1.06); }
                .rmbz-fs-btn:active{ transform:scale(.98); }
                .rmbz-fs-btn--rec{ background:#e5484d; color:#fff; width:100%; box-shadow:0 6px 18px -6px rgba(229,72,77,.55); }
                .rmbz-fs-btn--tonal{ background:#eaddff; color:#3d2a66; }
                .rmbz-fs-btn--ghost{ background:#eeebf7; color:#1a1a20; }
                .rmbz-fs-radio{ display:flex; gap:10px; align-items:flex-start; background:#fff; border:1.5px solid #eadfe0; border-radius:14px; padding:11px 13px; cursor:pointer; margin-bottom:8px; transition:border-color .15s; }
                .rmbz-fs-radio:hover{ border-color:#e5484d; }
                .rmbz-fs-radio input{ margin-top:2px; }
                .rmbz-fs-radio b{ font-size:13px; color:#1a1a20; display:block; }
                .rmbz-fs-radio small{ font-size:11px; color:#7a7688; line-height:1.45; }
                .rmbz-fs-file{ display:inline-flex; align-items:center; gap:8px; background:#fff; border:1.5px dashed #c9bfe0; border-radius:12px; padding:8px 14px; font-size:12px; font-weight:700; color:#5b3e70; cursor:pointer; }
                .rmbz-fs-file input{ display:none; }
                .rmbz-fs-day{ display:flex; gap:12px; padding:10px 0; border-bottom:1px solid #f0edf6; }
                .rmbz-fs-day:last-child{ border-bottom:0; }
                .rmbz-fs-daynum{ flex:0 0 auto; width:38px; height:38px; border-radius:13px; background:#f3effc; color:#5b3e70; font-weight:900; font-size:13px; display:flex; align-items:center; justify-content:center; }
                .rmbz-fs-day .meta{ font-size:12px; color:#57536a; line-height:1.5; }
                .rmbz-fs-day .meta b{ color:#1a1a20; }
                </style>

                <div class="rmbz-fs-card <?php echo $fs_active ? 'is-live' : ''; ?>">
                    <div class="rmbz-fs-head">
                        <div class="rmbz-fs-ico">🎬</div>
                        <div class="rmbz-fs-title">Gravação ao Vivo<small>Sessões de filmagem do videoclipe</small></div>
                        <?php if ( $fs_active ) : ?>
                            <span id="rmbz-fs-rec" class="rmbz-fs-pill rmbz-fs-pill--rec">● REC</span>
                        <?php elseif ( $fs_pleft > 0 ) : ?>
                            <span class="rmbz-fs-pill rmbz-fs-pill--warn">Falta <?php echo (int) $fs_pleft; ?>%</span>
                        <?php elseif ( $fs_pleft === 0 && ! empty( $fs_history ) ) : ?>
                            <span class="rmbz-fs-pill rmbz-fs-pill--ok">✓ Concluída</span>
                        <?php endif; ?>
                    </div>

                    <?php if ( $fs_active ) : ?>
                        <?php $fs_day = (int) ( $fs_active['day'] ?? 1 ); ?>
                        <div class="rmbz-fs-hero">
                            <div id="rmbz-fs-timer" class="clock" data-started="<?php echo (int) ( $fs_active['started_ts'] ?? 0 ); ?>" data-servernow="<?php echo (int) current_time( 'timestamp', true ); ?>">--:--:--</div>
                            <div class="sub">Dia <?php echo $fs_day; ?> de filmagem · a decorrer desde <?php echo esc_html( (string) ( $fs_active['started_at'] ?? '' ) ); ?></div>
                        </div>
                        <script>
                        (function(){
                            var el = document.getElementById('rmbz-fs-timer'); if (!el) return;
                            var started = parseInt(el.getAttribute('data-started'), 10) || 0;
                            var serverNow = parseInt(el.getAttribute('data-servernow'), 10) || 0;
                            var offset = serverNow > 0 ? Math.floor(Date.now()/1000) - serverNow : 0;
                            var rec = document.getElementById('rmbz-fs-rec');
                            function tick(){
                                var s = Math.max(0, Math.floor(Date.now()/1000) - offset - started);
                                var h = Math.floor(s/3600), m = Math.floor((s%3600)/60), x = s%60;
                                var pad = function(n){ return (n<10?'0':'')+n; };
                                el.textContent = pad(h)+':'+pad(m)+':'+pad(x);
                                if (rec) rec.style.opacity = (s % 2 === 0) ? '1' : '0.35';
                            }
                            tick(); setInterval(tick, 1000);
                        })();
                        </script>

                        <?php $fs_people = (array) ( $fs_active['participants'] ?? [] ); ?>
                        <?php if ( ! empty( $fs_people ) ) : ?>
                            <div class="rmbz-fs-label">👥 Na filmagem (<?php echo count( $fs_people ); ?>)</div>
                            <div class="rmbz-fs-chiprow">
                                <?php foreach ( $fs_people as $fs_pp ) : ?>
                                    <span class="rmbz-fs-person">
                                        <?php if ( ! empty( $fs_pp['photo'] ) ) : ?>
                                            <img src="<?php echo esc_url( (string) $fs_pp['photo'] ); ?>" alt=""
                                                 onclick="var lb=document.getElementById('rmbz-pjv2-lightbox'); if(lb){ document.getElementById('rmbz-pjv2-lightbox-img').src=this.src; lb.classList.add('is-show'); }">
                                        <?php else : ?>
                                            <span class="noimg">👤</span>
                                        <?php endif; ?>
                                        <span><b><?php echo esc_html( (string) ( $fs_pp['name'] ?? '' ) ); ?></b><span><?php echo esc_html( (string) ( $fs_pp['role'] ?? '' ) ); ?></span></span>
                                    </span>
                                <?php endforeach; ?>
                            </div>
                        <?php endif; ?>

                        <?php /* Registar quem está na filmagem (foto + nome + papel). */ ?>
                        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" enctype="multipart/form-data" class="rmbz-fs-panel rmbz-fs-panel--soft">
                            <input type="hidden" name="action" value="rmbz_filming_add_person">
                            <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                            <?php wp_nonce_field( 'rmbz_filming_add_person_' . (int) $proj_id ); ?>
                            <div class="rmbz-fs-label">📸 Registar quem está na filmagem</div>
                            <div style="display:flex; gap:8px; flex-wrap:wrap; margin-bottom:8px;">
                                <input type="text" name="person_name" class="rmbz-fs-input" placeholder="Nome da pessoa" required style="flex:1.2; min-width:130px;">
                                <select name="person_category" class="rmbz-fs-input" required style="flex:1; min-width:150px;">
                                    <option value="">— Categoria —</option>
                                    <?php foreach ( ( function_exists('rmbz_fs_categories') ? rmbz_fs_categories() : [] ) as $fs_ck => $fs_cm ) : ?>
                                        <option value="<?php echo esc_attr( $fs_ck ); ?>"><?php echo esc_html( $fs_cm['icon'] . ' ' . $fs_cm['label'] ); ?></option>
                                    <?php endforeach; ?>
                                </select>
                                <input type="text" name="person_role" class="rmbz-fs-input" placeholder="Detalhe (opcional)" style="flex:1; min-width:120px;">
                            </div>
                            <div style="display:flex; gap:10px; align-items:center; flex-wrap:wrap;">
                                <label class="rmbz-fs-file">
                                    <input type="file" name="person_photo" accept="image/*" capture="environment"
                                           onchange="this.parentNode.querySelector('span').textContent = this.files.length ? '📷 ' + this.files[0].name : '📷 Tirar/escolher foto';">
                                    <span>📷 Tirar/escolher foto</span>
                                </label>
                                <button type="submit" class="rmbz-fs-btn rmbz-fs-btn--tonal">Registar presença</button>
                            </div>
                        </form>

                        <?php /* Finalizar o dia: tudo filmado? / continua (falta % + próximo dia). */ ?>
                        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="rmbz-fs-panel rmbz-fs-panel--danger" style="margin-bottom:0;"
                              onsubmit="var ad=this.querySelector('input[name=finish_result]:checked'); if(!ad){alert('Escolhe se o vídeo já foi todo filmado.');return false;} if(ad.value!=='all_done'){ var pl=parseInt(this.percent_left.value,10)||0; if(pl<1||pl>99){alert('Indica quantos % faltam (1–99).');return false;} if(!this.next_date.value){alert('Indica o próximo dia de filmagem.');return false;} } return confirm(ad.value==='all_done' ? '🎉 Confirmar: TUDO filmado? O projeto passa para EDIÇÃO e o artista (e feat) são notificados.' : 'Finalizar o dia e avisar o artista (e feat) de que a filmagem continua?');">
                            <input type="hidden" name="action" value="rmbz_filming_finish">
                            <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                            <?php wp_nonce_field( 'rmbz_filming_finish_' . (int) $proj_id ); ?>
                            <div class="rmbz-fs-label" style="color:#8c1d18;">🏁 Filmagem do dia finalizada</div>
                            <label class="rmbz-fs-radio">
                                <input type="radio" name="finish_result" value="all_done" onchange="document.getElementById('rmbz-fs-cont-<?php echo (int) $proj_id; ?>').style.display='none';">
                                <span><b>🎉 Sim — tudo filmado</b><small>O projeto passa para edição; artista (e feat) são notificados.</small></span>
                            </label>
                            <label class="rmbz-fs-radio">
                                <input type="radio" name="finish_result" value="continue" onchange="document.getElementById('rmbz-fs-cont-<?php echo (int) $proj_id; ?>').style.display='flex';">
                                <span><b>📅 Não — continua noutro dia</b><small>Indica quanto falta e o próximo dia; artista (e feat) são avisados.</small></span>
                            </label>
                            <div id="rmbz-fs-cont-<?php echo (int) $proj_id; ?>" style="display:none; gap:8px; flex-wrap:wrap; margin:2px 0 10px;">
                                <input type="number" name="percent_left" class="rmbz-fs-input" min="1" max="99" placeholder="% em falta" style="width:120px;">
                                <input type="date" name="next_date" class="rmbz-fs-input" style="flex:1; min-width:150px;">
                            </div>
                            <button type="submit" class="rmbz-fs-btn rmbz-fs-btn--rec" style="margin-top:4px;">🏁 Finalizar o dia</button>
                        </form>

                    <?php else : ?>
                        <?php if ( $fs_blocked_by_team ) : ?>
                            <?php /* [1.5.408] Dia de filmagem MAS equipa incompleta → sem botão. */ ?>
                            <div class="rmbz-tm-banner rmbz-tm-banner--err" style="margin-bottom:0;">
                                <b>⛔ Não podes iniciar a gravação — faltam cargos essenciais na equipa.</b>
                                Completa a "Equipa do Videoclipe" (acima) e guarda; o botão INICIAR GRAVAÇÃO aparece aqui.
                                <div style="display:flex; flex-wrap:wrap; gap:6px; margin-top:8px;">
                                    <?php foreach ( (array) ( $fs_team_diag['missing'] ?? [] ) as $fs_miss ) : ?>
                                        <span class="rmbz-tm-chip"><?php echo esc_html( ( $fs_miss['icon'] ?? '' ) . ' ' . ( $fs_miss['label'] ?? '' ) ); ?></span>
                                    <?php endforeach; ?>
                                </div>
                            </div>
                        <?php endif; ?>
                        <?php if ( $fs_can_start ) : ?>
                            <p style="font-size:13px; color:#57536a; line-height:1.6; margin:0 0 12px;">É dia de filmagem! Ao iniciar, o artista (e o participante feat) são notificados e o cronómetro começa a contar.</p>
                            <button type="button" class="rmbz-fs-btn rmbz-fs-btn--rec"
                                    onclick="document.getElementById('rmbz-fs-start-<?php echo (int) $proj_id; ?>').style.display='flex';">🎬 INICIAR GRAVAÇÃO</button>

                            <?php /* [1.5.407] Diálogo: confirmar que a equipa está NO LOCAL antes de iniciar. */ ?>
                            <div id="rmbz-fs-start-<?php echo (int) $proj_id; ?>" style="display:none; position:fixed; inset:0; z-index:99999; background:rgba(20,16,40,0.55); align-items:center; justify-content:center; padding:16px;">
                                <div style="background:#fff; border-radius:24px; max-width:440px; width:100%; padding:26px 22px; box-shadow:0 30px 60px -20px rgba(0,0,0,0.5); text-align:center;">
                                    <div style="width:64px; height:64px; border-radius:20px; background:#fdecea; display:flex; align-items:center; justify-content:center; font-size:30px; margin:0 auto;">📍</div>
                                    <div style="font-size:18px; font-weight:800; color:#1a1a20; margin-top:12px;">Estás no local da filmagem?</div>
                                    <p style="font-size:13px; color:#56535f; line-height:1.6; margin:10px 0 18px;">
                                        Confirma que a equipa já está no local e pronta para gravar.
                                        Ao confirmar, o artista (e o participante feat) são notificados de que a
                                        filmagem <strong>começou</strong> e o cronómetro começa a contar.
                                    </p>
                                    <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="display:flex; gap:10px;">
                                        <input type="hidden" name="action" value="rmbz_filming_start">
                                        <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                                        <?php wp_nonce_field( 'rmbz_filming_start_' . (int) $proj_id ); ?>
                                        <button type="button" class="rmbz-fs-btn rmbz-fs-btn--ghost" style="flex:1;"
                                                onclick="document.getElementById('rmbz-fs-start-<?php echo (int) $proj_id; ?>').style.display='none';">Ainda não</button>
                                        <button type="submit" class="rmbz-fs-btn rmbz-fs-btn--rec" style="flex:1.4; width:auto;">✅ Sim, estou no local</button>
                                    </form>
                                </div>
                            </div>
                        <?php endif; ?>

                        <?php if ( ! empty( $fs_history ) ) : ?>
                            <style>
                            /* [1.5.410] Árvore de participantes por categoria */
                            .rmbz-fs-tree{ margin:10px 0 4px; padding-left:6px; }
                            .rmbz-fs-tree .cat{ position:relative; padding-left:18px; margin-bottom:8px; }
                            .rmbz-fs-tree .cat::before{ content:""; position:absolute; left:4px; top:12px; bottom:8px; width:2px; background:#e2ddf0; border-radius:2px; }
                            .rmbz-fs-tree .cat > b{ font-size:12px; color:#3d2a66; display:inline-block; background:#f3effc; border-radius:99px; padding:3px 12px; }
                            .rmbz-fs-tree .leaf{ position:relative; padding-left:22px; margin-top:6px; }
                            .rmbz-fs-tree .leaf::before{ content:""; position:absolute; left:4px; top:14px; width:14px; height:2px; background:#e2ddf0; }
                            .rmbz-fs-editbtn{ background:#ece5fb; color:#3d2a66; border:0; border-radius:99px; padding:5px 14px; font-size:11px; font-weight:800; cursor:pointer; }
                            .rmbz-fs-audit{ font-size:11px; color:#8a8794; margin-top:6px; }
                            </style>
                            <div class="rmbz-fs-label" style="margin-top:<?php echo $fs_can_start ? '14px' : '0'; ?>;">📋 Dias de filmagem</div>
                            <?php $fs_cats_all = function_exists('rmbz_fs_categories') ? rmbz_fs_categories() : [];
                            foreach ( $fs_history as $fs_h ) :
                                $fs_day_n = (int) ( $fs_h['day'] ?? 0 );
                                $fs_dm = (int) ( $fs_h['duration_min'] ?? 0 );
                                $fs_dur = $fs_dm >= 60 ? floor( $fs_dm / 60 ) . 'h' . str_pad( (string) ( $fs_dm % 60 ), 2, '0', STR_PAD_LEFT ) : $fs_dm . ' min';
                                $fs_hp = (array) ( $fs_h['participants'] ?? [] );
                                // Agrupar por categoria (ordem do catálogo; sem categoria → outro)
                                $fs_by_cat = [];
                                foreach ( $fs_hp as $fs_pp ) {
                                    $fs_pc = (string) ( $fs_pp['category'] ?? 'outro' );
                                    if ( ! isset( $fs_cats_all[ $fs_pc ] ) ) $fs_pc = 'outro';
                                    $fs_by_cat[ $fs_pc ][] = $fs_pp;
                                }
                                $fs_edits = (int) ( $fs_h['participants_edits'] ?? 0 );
                            ?>
                                <div class="rmbz-fs-day">
                                    <div class="rmbz-fs-daynum">D<?php echo $fs_day_n; ?></div>
                                    <div style="flex:1;">
                                        <div class="meta" style="display:flex; align-items:flex-start; gap:8px;">
                                            <span style="flex:1;">
                                                <b><?php echo esc_html( date_i18n( 'd/m/Y', strtotime( (string) ( $fs_h['date'] ?? '' ) . ' 12:00:00' ) ) ); ?></b>
                                                · ⏱ <?php echo esc_html( $fs_dur ); ?><br>
                                                👥 <strong>No dia <?php echo $fs_day_n; ?> participaram <?php echo count( $fs_hp ); ?> pessoa(s)</strong><br>
                                                <?php if ( ( $fs_h['result'] ?? '' ) === 'wrapped' ) : ?>
                                                    <span class="rmbz-fs-pill rmbz-fs-pill--ok" style="display:inline-block; margin-top:4px;">🎉 Tudo filmado</span>
                                                <?php else : ?>
                                                    <span class="rmbz-fs-pill rmbz-fs-pill--warn" style="display:inline-block; margin-top:4px;">Faltava <?php echo (int) ( $fs_h['percent_left'] ?? 0 ); ?>% · continua a <?php echo esc_html( date_i18n( 'd/m/Y', strtotime( (string) ( $fs_h['next_date'] ?? '' ) . ' 12:00:00' ) ) ); ?></span>
                                                <?php endif; ?>
                                            </span>
                                            <button type="button" class="rmbz-fs-editbtn"
                                                    onclick="var e=document.getElementById('rmbz-fs-editor-<?php echo (int) $proj_id . '-' . $fs_day_n; ?>'); e.style.display = e.style.display==='none' ? 'block' : 'none';">✏️ Editar participantes</button>
                                        </div>

                                        <?php /* [1.5.410] ÁRVORE: dia → categorias → pessoas */ ?>
                                        <?php if ( ! empty( $fs_by_cat ) ) : ?>
                                            <div class="rmbz-fs-tree">
                                                <?php foreach ( $fs_cats_all as $fs_ck => $fs_cm ) : if ( empty( $fs_by_cat[ $fs_ck ] ) ) continue; ?>
                                                    <div class="cat">
                                                        <b><?php echo esc_html( $fs_cm['icon'] . ' ' . $fs_cm['label'] ); ?> (<?php echo count( $fs_by_cat[ $fs_ck ] ); ?>)</b>
                                                        <?php foreach ( $fs_by_cat[ $fs_ck ] as $fs_pp ) : ?>
                                                            <div class="leaf">
                                                                <span class="rmbz-fs-person">
                                                                    <?php if ( ! empty( $fs_pp['photo'] ) ) : ?>
                                                                        <img src="<?php echo esc_url( (string) $fs_pp['photo'] ); ?>" alt=""
                                                                             onclick="var lb=document.getElementById('rmbz-pjv2-lightbox'); if(lb){ document.getElementById('rmbz-pjv2-lightbox-img').src=this.src; lb.classList.add('is-show'); }">
                                                                    <?php else : ?>
                                                                        <span class="noimg">👤</span>
                                                                    <?php endif; ?>
                                                                    <span><b><?php echo esc_html( (string) ( $fs_pp['name'] ?? '' ) ); ?></b><?php if ( ! empty( $fs_pp['role'] ) ) : ?><span><?php echo esc_html( (string) $fs_pp['role'] ); ?></span><?php endif; ?></span>
                                                                </span>
                                                            </div>
                                                        <?php endforeach; ?>
                                                    </div>
                                                <?php endforeach; ?>
                                            </div>
                                        <?php endif; ?>

                                        <?php if ( $fs_edits > 0 ) : ?>
                                            <div class="rmbz-fs-audit">✏️ Modificado <?php echo $fs_edits; ?>× · última vez: <?php echo esc_html( (string) ( $fs_h['participants_edited_at'] ?? '' ) ); ?> por <?php echo esc_html( (string) ( $fs_h['participants_edited_by'] ?? 'admin' ) ); ?></div>
                                        <?php endif; ?>

                                        <?php /* [1.5.410] Editor total (mesmo depois de finalizado) — auditado */ ?>
                                        <div id="rmbz-fs-editor-<?php echo (int) $proj_id . '-' . $fs_day_n; ?>" style="display:none; margin-top:10px;">
                                            <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" enctype="multipart/form-data" class="rmbz-fs-panel rmbz-fs-panel--soft" style="margin-bottom:0;">
                                                <input type="hidden" name="action" value="rmbz_filming_edit_people">
                                                <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                                                <input type="hidden" name="day" value="<?php echo $fs_day_n; ?>">
                                                <?php wp_nonce_field( 'rmbz_filming_edit_people_' . (int) $proj_id . '_' . $fs_day_n ); ?>
                                                <div class="rmbz-fs-label">✏️ Editar participantes do dia <?php echo $fs_day_n; ?></div>
                                                <div id="rmbz-fs-editor-rows-<?php echo (int) $proj_id . '-' . $fs_day_n; ?>">
                                                    <?php foreach ( $fs_hp as $fs_pp ) : $fs_pp_photo = (string) ( $fs_pp['photo'] ?? '' ); ?>
                                                        <div style="display:flex; gap:6px; flex-wrap:wrap; margin-bottom:6px; align-items:center;">
                                                            <?php /* [1.5.410] Foto: miniatura atual + escolher/tirar nova */ ?>
                                                            <label class="rmbz-fs-file" style="padding:4px 8px; flex:0 0 auto;" title="Mudar a foto desta pessoa">
                                                                <?php if ( $fs_pp_photo !== '' ) : ?>
                                                                    <img src="<?php echo esc_url( $fs_pp_photo ); ?>" alt="" style="width:28px; height:28px; border-radius:50%; object-fit:cover; display:block;">
                                                                <?php else : ?>
                                                                    <span style="font-size:16px;">📷</span>
                                                                <?php endif; ?>
                                                                <input type="file" name="pp_photo_file[]" accept="image/*" capture="environment"
                                                                       onchange="this.parentNode.style.outline = this.files.length ? '2px solid #7b5bd6' : 'none';">
                                                            </label>
                                                            <input type="text" name="pp_name[]" class="rmbz-fs-input" value="<?php echo esc_attr( (string) ( $fs_pp['name'] ?? '' ) ); ?>" placeholder="Nome" required style="flex:1.2; min-width:110px;">
                                                            <select name="pp_cat[]" class="rmbz-fs-input" style="flex:1; min-width:140px;">
                                                                <?php $fs_sel = (string) ( $fs_pp['category'] ?? 'outro' ); foreach ( $fs_cats_all as $fs_ck => $fs_cm ) : ?>
                                                                    <option value="<?php echo esc_attr( $fs_ck ); ?>" <?php selected( $fs_sel, $fs_ck ); ?>><?php echo esc_html( $fs_cm['icon'] . ' ' . $fs_cm['label'] ); ?></option>
                                                                <?php endforeach; ?>
                                                            </select>
                                                            <input type="text" name="pp_role[]" class="rmbz-fs-input" value="<?php echo esc_attr( (string) ( $fs_pp['role'] ?? '' ) ); ?>" placeholder="Detalhe" style="flex:1; min-width:100px;">
                                                            <input type="hidden" name="pp_photo[]" value="<?php echo esc_attr( $fs_pp_photo ); ?>">
                                                            <button type="button" class="rmbz-pjv2-row-del" onclick="this.parentNode.remove();">×</button>
                                                        </div>
                                                    <?php endforeach; ?>
                                                </div>
                                                <div style="display:flex; gap:8px; align-items:center; margin-top:8px;">
                                                    <button type="button" class="rmbz-fs-btn rmbz-fs-btn--ghost" style="padding:8px 16px; font-size:12px;"
                                                            onclick="var r=document.getElementById('rmbz-fs-editor-rows-<?php echo (int) $proj_id . '-' . $fs_day_n; ?>'); var d=document.createElement('div'); d.style.cssText='display:flex;gap:6px;flex-wrap:wrap;margin-bottom:6px;align-items:center;'; d.innerHTML=<?php echo esc_attr( wp_json_encode(
                                                                '<label class="rmbz-fs-file" style="padding:4px 8px;flex:0 0 auto;" title="Foto desta pessoa"><span style="font-size:16px;">📷</span><input type="file" name="pp_photo_file[]" accept="image/*" capture="environment" onchange="this.parentNode.style.outline = this.files.length ? \'2px solid #7b5bd6\' : \'none\';"></label>'
                                                                . '<input type="text" name="pp_name[]" class="rmbz-fs-input" placeholder="Nome" required style="flex:1.2;min-width:110px;">'
                                                                . '<select name="pp_cat[]" class="rmbz-fs-input" style="flex:1;min-width:140px;">' . implode( '', array_map( fn( $k ) => '<option value="' . esc_attr( $k ) . '">' . esc_html( $fs_cats_all[ $k ]['icon'] . ' ' . $fs_cats_all[ $k ]['label'] ) . '</option>', array_keys( $fs_cats_all ) ) ) . '</select>'
                                                                . '<input type="text" name="pp_role[]" class="rmbz-fs-input" placeholder="Detalhe" style="flex:1;min-width:100px;">'
                                                                . '<input type="hidden" name="pp_photo[]" value="">'
                                                                . '<button type="button" class="rmbz-pjv2-row-del" onclick="this.parentNode.remove();">×</button>'
                                                            ) ); ?>; r.appendChild(d);">＋ Pessoa</button>
                                                    <button type="submit" class="rmbz-fs-btn rmbz-fs-btn--tonal" style="padding:8px 18px; font-size:12px;"
                                                            onclick="return confirm('Guardar as alterações aos participantes do dia <?php echo $fs_day_n; ?>? A edição fica registada.');">💾 Guardar participantes</button>
                                                </div>
                                            </form>
                                        </div>
                                    </div>
                                </div>
                            <?php endforeach; ?>
                        <?php endif; ?>
                    <?php endif; ?>
                </div>
                <?php endif; ?>

                <?php rmbz_pjv2_render_contract_block( $proj_id, $extra ); ?>

                <!-- Bloco: HISTÓRICO DE ALTERAÇÕES (preenchido por AJAX) -->
                <div class="rmbz-pjv2-manage-block" id="rmbz-pjv2-changelog-block" style="display:none;margin-top:22px;position:relative;">
                    <h3 style="line-height:1.6;padding-right:78px;">
                        <span class="ico">📜</span>
                        <span>Histórico de alterações</span>
                    </h3>
                    <button type="button" id="rmbz-pjv2-history-open" class="button button-small" style="position:absolute;top:0;right:0;margin:0;">Ver tudo</button>
                    <div id="rmbz-pjv2-changelog-list"></div>
                </div>
            </aside>
        </div>
    </div>

    <!-- Lightbox para imagens -->
    <div class="rmbz-pjv2-lightbox" id="rmbz-pjv2-lightbox" onclick="this.classList.remove('is-show')">
        <img id="rmbz-pjv2-lightbox-img" src="" alt="">
    </div>

    <!-- [1.5.373] Modal: HISTÓRICO COMPLETO DO PROJETO -->
    <div class="rmbz-pjv2-histmodal" id="rmbz-pjv2-histmodal" aria-hidden="true">
        <div class="rmbz-pjv2-histmodal__backdrop" data-hist-close></div>
        <div class="rmbz-pjv2-histmodal__panel" role="dialog" aria-modal="true" aria-label="Histórico completo do projeto">
            <div class="rmbz-pjv2-histmodal__head">
                <h3>📜 Histórico completo do projeto</h3>
                <button type="button" class="rmbz-pjv2-histmodal__x" data-hist-close aria-label="Fechar">×</button>
            </div>
            <div class="rmbz-pjv2-histmodal__body" id="rmbz-pjv2-histmodal-body">
                <div class="rmbz-pjv2-log-empty">A carregar…</div>
            </div>
        </div>
    </div>

    <script>
    // === BUDGET TABLE JS (orçamento por localização) ===
    function rmbzPjv2CalcSingleTotal() {
        var t = 0;
        document.querySelectorAll('#rmbz-pjv2-single-rows .rmbz-pjv2-cost-input').forEach(function(i){
            t += parseFloat(i.value) || 0;
        });
        var s = document.getElementById('rmbz-pjv2-single-total');
        if (s) s.textContent = t.toLocaleString('pt-MZ', { minimumFractionDigits: 2 });
    }
    function rmbzPjv2AddSingleRow() {
        // [1.6.118.34] Nova linha sempre com colunas Pagamento + Decisão Artista + Status.
        // Default: must_pay=1 (obrigatório), assumes=0, status=⏳ disabled.
        var tbody = document.getElementById('rmbz-pjv2-single-rows');
        if (!tbody) return;
        var html = '<tr data-must-pay="1">'
            + '<td><input type="text" name="budget_cat[]" placeholder="—"></td>'
            + '<td><input type="text" name="budget_desc[]" placeholder="Ex: Câmera"></td>'
            + '<td><input type="number" name="budget_cost[]" value="0" step="0.01" class="rmbz-pjv2-cost-input" oninput="rmbzPjv2CalcSingleTotal()"></td>'
            + '<td><select name="budget_must_pay[]" class="rmbz-pjv2-mustpay-select" onchange="rmbzPjv2OnMustPayChange(this)">'
            +   '<option value="1" selected>💰 Obrigatório</option>'
            +   '<option value="0">🤝 Negociável</option>'
            + '</select></td>'
            + '<td><span class="rmbz-pjv2-assumes-label" data-assumed="0" style="font-size:11px;opacity:0.3;">—</span>'
            +   '<input type="hidden" name="budget_assumes[]" value="0">'
            + '</td>'
            + '<td>'
            +   '<div class="rmbz-pjv2-status-static" title="Item obrigatório — sem checklist">—</div>'
            +   '<input type="hidden" name="budget_checked[]" value="0">'
            + '</td>'
            + '<td><button type="button" class="rmbz-pjv2-row-del" onclick="this.closest(\'tr\').remove(); rmbzPjv2CalcSingleTotal();">×</button></td>'
            + '</tr>';
        tbody.insertAdjacentHTML('beforeend', html);
    }

    /**
     * [1.6.118.34] Handler de mudança do select "Pagamento" (Obrigatório vs Negociável).
     * - Obrigatório: força artist_assumes=0, desabilita coluna Status (não relevante)
     * - Negociável: deixa artist_assumes editável (vem do artista, admin só vê)
     * Nota: a decisão do artista é gravada no contrato. Admin não a edita aqui —
     * apenas vê o estado actual. Quando admin muda Obrigatório → Negociável,
     * a decisão fica "1MZ paga" (default, artista vai decidir depois).
     */
    function rmbzPjv2OnMustPayChange(sel) {
        var tr = sel.closest('tr');
        if (!tr) return;
        var newVal = sel.value;
        tr.setAttribute('data-must-pay', newVal);

        // [1.6.118.43] Coluna "Decisão Artista" — preservar valor original do artista
        // quando admin alterna Pagamento. Antes APAGAVA quando ia para Obrigatório,
        // perdendo a decisão se admin voltasse a Negociável.
        var label = tr.querySelector('.rmbz-pjv2-assumes-label');
        var hidden = tr.querySelector('input[name="budget_assumes[]"]');
        if (label && hidden) {
            // Guardar o valor original na primeira vez que tocamos (snapshot)
            if (!tr.hasAttribute('data-orig-assumes')) {
                tr.setAttribute('data-orig-assumes', hidden.value);
            }
            var origAssumes = tr.getAttribute('data-orig-assumes') === '1';

            if (newVal === '1') {
                // Obrigatório → label cinzento mas NÃO apagar valor original
                // (manter no hidden caso admin volte a Negociável)
                label.textContent = '—';
                label.style.opacity = '0.3';
                // hidden.value FICA com o valor original (snapshot preservado)
            } else {
                // Negociável → restaurar label do valor original
                label.textContent = origAssumes ? '✋ Assume' : '💰 1MZ paga';
                label.style.opacity = '';
                hidden.value = origAssumes ? '1' : '0';
            }
        }

        // [1.6.118.39] Coluna Status — TROCAR entre <select> e <div estático>
        // canCheck = item é negociável E artista assumiu (valor preservado).
        var canCheck = (newVal === '0' && hidden && hidden.value === '1');
        var statusCell = tr.children[5]; // 6ª <td> (0-indexed)
        if (statusCell) {
            // Preservar valor actual (lê do select ou hidden anterior)
            var currentVal = '0';
            var prevSelect = statusCell.querySelector('select.rmbz-pjv2-checked-select');
            var prevHidden = statusCell.querySelector('input[name="budget_checked[]"]');
            if (prevSelect) currentVal = prevSelect.value;
            else if (prevHidden) currentVal = prevHidden.value;

            if (canCheck) {
                // Render select editável
                statusCell.innerHTML =
                    '<select name="budget_checked[]" class="rmbz-pjv2-checked-select">'
                  +   '<option value="0"' + (currentVal === '0' ? ' selected' : '') + '>⏳</option>'
                  +   '<option value="1"' + (currentVal === '1' ? ' selected' : '') + '>✅</option>'
                  + '</select>';
            } else {
                // Render span estático + hidden (preserva valor mesmo se obrigatório)
                var title = (newVal === '1') ? 'Item obrigatório — sem checklist' : 'Artista escolheu deixar à 1MZ';
                statusCell.innerHTML =
                    '<div class="rmbz-pjv2-status-static" title="' + title + '">—</div>'
                  + '<input type="hidden" name="budget_checked[]" value="' + currentVal + '">';
            }
        }
    }

    // === MULTI-LOCATION BUDGETS ===
    var rmbzPjv2LocIdx = 0;
    // [1.6.118.42] Item agora tem 4 campos: cat, desc, cost, must_pay.
    // Admin pode marcar obrigatório/negociável antes do artista escolher localização.
    function rmbzPjv2RowHtml(idx, cat, desc, cost, mustPay) {
        var mp = (mustPay === undefined || mustPay === null) ? 1 : parseInt(mustPay, 10);
        if (isNaN(mp)) mp = 1;
        return '<tr>'
            + '<td><input type="text" name="budget_cat_' + idx + '[]" value="' + (cat || '') + '" placeholder="—"></td>'
            + '<td><input type="text" name="budget_desc_' + idx + '[]" value="' + (desc || '') + '" placeholder="Ex: Câmera"></td>'
            + '<td><input type="number" name="budget_cost_' + idx + '[]" value="' + (cost || 0) + '" step="0.01" class="rmbz-pjv2-cost-input-' + idx + '" oninput="rmbzPjv2CalcLocTotal(' + idx + ')"></td>'
            + '<td><select name="budget_must_pay_' + idx + '[]" class="rmbz-pjv2-mustpay-select">'
            +   '<option value="1"' + (mp === 1 ? ' selected' : '') + '>💰 Obrigatório</option>'
            +   '<option value="0"' + (mp === 0 ? ' selected' : '') + '>🤝 Negociável</option>'
            + '</select></td>'
            + '<td><button type="button" class="rmbz-pjv2-row-del" onclick="this.closest(\'tr\').remove(); rmbzPjv2CalcLocTotal(' + idx + ');">×</button></td>'
            + '</tr>';
    }
    function rmbzPjv2CalcLocTotal(idx) {
        var t = 0;
        document.querySelectorAll('.rmbz-pjv2-cost-input-' + idx).forEach(function(i){
            t += parseFloat(i.value) || 0;
        });
        var s = document.querySelector('.rmbz-pjv2-loc-total-' + idx);
        if (s) s.textContent = t.toLocaleString('pt-MZ', { minimumFractionDigits: 2 });
    }
    function rmbzPjv2AddLocation(name, items) {
        name = name || ''; items = items || [];
        var idx = rmbzPjv2LocIdx++;
        var rows = items.length > 0
            ? items.map(function(it){ return rmbzPjv2RowHtml(idx, it.cat || '', it.desc || '', it.cost || 0, it.must_pay); }).join('')
            : rmbzPjv2RowHtml(idx, '', '', 0, 1);
        var html = '<div class="rmbz-pjv2-budget-loc">'
            + '<div class="rmbz-pjv2-budget-loc-head">'
            + '  <input type="text" name="budget_loc_name[' + idx + ']" value="' + name + '" placeholder="Nome do local (ex: Nampula)" required>'
            + '  <button type="button" class="rmbz-pjv2-row-del rmbz-pjv2-loc-del" onclick="this.closest(\'.rmbz-pjv2-budget-loc\').remove();">✕ Remover local</button>'
            + '</div>'
            + '<div class="rmbz-pjv2-budget-scroll">'
            + '<table class="rmbz-pjv2-budget-table">'
            + '  <thead><tr>'
            +     '<th>Categ.</th>'
            +     '<th>Item</th>'
            +     '<th>MT</th>'
            +     '<th style="width:120px;">Pagamento</th>'
            +     '<th style="width:34px;"></th>'
            +   '</tr></thead>'
            + '  <tbody id="rmbz-pjv2-loc-rows-' + idx + '">' + rows + '</tbody>'
            + '</table>'
            + '</div>'
            + '<div class="rmbz-pjv2-budget-foot">'
            + '  <button type="button" class="rmbz-pjv2-row-add" onclick="document.getElementById(\'rmbz-pjv2-loc-rows-' + idx + '\').insertAdjacentHTML(\'beforeend\', rmbzPjv2RowHtml(' + idx + ', \'\', \'\', 0, 1)); rmbzPjv2CalcLocTotal(' + idx + ');">+ Item</button>'
            + '  <div class="rmbz-pjv2-total">Total: <strong class="rmbz-pjv2-loc-total-' + idx + '">0,00</strong> MT</div>'
            + '</div>'
            + '</div>';
        var container = document.getElementById('rmbz-pjv2-multi-container');
        if (container) {
            container.insertAdjacentHTML('beforeend', html);
            rmbzPjv2CalcLocTotal(idx);
        }
    }

    // Pre-carregar localizações existentes (se houver) — só dispara se o container existir
    (function(){
        var container = document.getElementById('rmbz-pjv2-multi-container');
        if (!container) return; // já está em modo single (artista escolheu)
        var existing = <?php echo ! empty( $extra['proposed_budgets'] ) ? wp_json_encode( $extra['proposed_budgets'] ) : 'null'; ?>;
        if (existing && Object.keys(existing).length > 0) {
            Object.keys(existing).forEach(function(loc){
                rmbzPjv2AddLocation(loc, existing[loc].items || []);
            });
        } else {
            rmbzPjv2AddLocation('Opção 1', []);
        }
    })();
    </script>

    <?php rmbz_pjv2_chat_script( $proj_id ); ?>
    <?php
}

/* ============================================================================
 * CONTRACT BLOCK — gestão de contrato + KYC (todos os hooks legado)
 * ============================================================================
 *
 * Renderiza um bloco completo da coluna direita que cobre:
 *   - Upload de contrato (PDF/imagem)
 *   - Bloco "aguardando KYC" — admin aprova/rejeita identidade
 *   - Bloco "contrato aceite e KYC aprovado" — vê nome real + data + foto
 *   - Bloco "contrato rejeitado pelo artista" — re-upload ou bloquear
 *   - Botão "revogar contrato"
 *
 * Cada acção é um form separado (com seu próprio handler legado já existente
 * no plugin: rmbz_admin_upload_contract, onemz_admin_approve_kyc, etc).
 */
function rmbz_pjv2_render_contract_block( $proj_id, $extra ) {
    $contract_url      = $extra['contract_url'] ?? '';
    $contract_accepted = ! empty( $extra['contract_accepted'] );
    $contract_rejected = ! empty( $extra['contract_rejected'] );
    $kyc_status        = $extra['kyc_status'] ?? '';
    ?>
    <div class="rmbz-pjv2-manage-block">
        <h3><span class="ico">📄</span> Contrato &amp; identidade</h3>

        <?php /* [1.5.399] Gerador de contrato em PDF — abre um MODAL com todos os
              campos pré-preenchidos e EDITÁVEIS (incluindo N.º do B.I. e quem
              assina pela 1MZ). Os valores saem no PDF com aspeto manuscrito.
              Escondido quando o contrato já está assinado. */ ?>
        <?php if ( ! $contract_accepted && function_exists( 'rmbz_contract_generate_for_project' ) ):
            global $wpdb;
            $rmbz_cg_p = $wpdb->get_row( $wpdb->prepare(
                "SELECT p.project_title, p.scenario_type, p.scenario_cost, p.artist_telemovel, w.user_nome
                 FROM {$wpdb->prefix}rmbz_artist_projects p
                 LEFT JOIN {$wpdb->prefix}rmbz_wallets w ON w.user_telemovel = p.artist_telemovel
                 WHERE p.id=%d", (int) $proj_id
            ) );
            $rmbz_cg_levels = [ 'basic' => 'BÁSICO', 'professional' => 'PROFISSIONAL', 'cinema' => 'CINEMA' ];
            $rmbz_cg_name  = $rmbz_cg_p ? ( $rmbz_cg_p->user_nome ?: ( $extra['artist_name'] ?? '' ) ) : '';
            $rmbz_cg_level = $rmbz_cg_p ? ( $rmbz_cg_levels[ (string) $rmbz_cg_p->scenario_type ] ?? strtoupper( (string) $rmbz_cg_p->scenario_type ) ) : '';
            $rmbz_cg_value = ( $rmbz_cg_p && (float) $rmbz_cg_p->scenario_cost > 0 ) ? number_format( (float) $rmbz_cg_p->scenario_cost, 2, ',', '.' ) : '';
            $rmbz_cg_admin = wp_get_current_user();
        ?>
            <?php $rmbz_cg_draft = ! empty( $extra['contract_draft']['url'] ) ? (string) $extra['contract_draft']['url'] : ''; ?>

            <?php if ( $rmbz_cg_draft !== '' ) : ?>
                <?php /* RASCUNHO pendente — pré-visualizar e decidir antes de enviar. */ ?>
                <div style="background:#fff8e6; border:1.5px solid #e8c56a; border-radius:12px; padding:12px 13px; margin-bottom:12px;">
                    <div style="font-size:12px; font-weight:800; color:#5b3e00;">👀 Rascunho do contrato — à espera da tua decisão</div>
                    <div style="font-size:11px; color:#8a6d3b; margin:3px 0 8px;">
                        Gerado em <?php echo esc_html( $extra['contract_draft']['created_at'] ?? '' ); ?>.
                        O artista <strong>ainda não recebeu nada</strong> — revê e decide.
                    </div>
                    <div class="rmbz-pjv2-contract-preview" style="margin-bottom:10px;">
                        <iframe src="<?php echo esc_url( $rmbz_cg_draft ); ?>#toolbar=0&navpanes=0" loading="lazy" style="width:100%; height:340px; border:1px solid #e8e4f1; border-radius:10px; background:#fff;"></iframe>
                    </div>
                    <div style="display:flex; gap:8px; flex-wrap:wrap;">
                        <a class="button button-primary" style="background:#1a8a4a; border-color:#1a8a4a;"
                           href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=rmbz_contract_draft_send&project_id=' . (int) $proj_id ), 'rmbz_contract_draft_send_' . (int) $proj_id ) ); ?>"
                           onclick="return confirm('Concordas com o contrato? Vai ser enviado ao artista para assinar (email + push + sino).');">
                            ✅ Concordo — enviar ao artista
                        </a>
                        <a class="button"
                           href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin-post.php?action=rmbz_contract_draft_discard&project_id=' . (int) $proj_id ), 'rmbz_contract_draft_discard_' . (int) $proj_id ) ); ?>"
                           onclick="return confirm('Rejeitar e apagar este rascunho? Nada será enviado.');"
                           style="color:#b3261e; border-color:#e8c5c0;">✗ Rejeitar rascunho</a>
                        <button type="button" class="button"
                                onclick="document.getElementById('rmbz-cg-modal').style.display='flex';">✏️ Gerar de novo…</button>
                        <a class="button" href="<?php echo esc_url( $rmbz_cg_draft ); ?>" target="_blank" rel="noopener">↗ Abrir PDF</a>
                    </div>
                </div>
            <?php endif; ?>

            <div style="background:linear-gradient(135deg,#f3f0ff,#faf9ff); border:1px solid #d9d2f5; border-radius:12px; padding:11px 13px; margin-bottom:12px; display:flex; align-items:center; gap:10px; flex-wrap:wrap;">
                <div style="flex:1; min-width:180px;">
                    <div style="font-size:12px; font-weight:700; color:#4c3fd6;">⚡ Gerar contrato automático (PDF)</div>
                    <div style="font-size:11px; color:#7a739c;">Gera um <strong>rascunho</strong> para pré-visualizar — só envias ao artista se concordares.</div>
                </div>
                <button type="button" class="button <?php echo $rmbz_cg_draft === '' ? 'button-primary' : ''; ?>"
                        onclick="document.getElementById('rmbz-cg-modal').style.display='flex';">📄 <?php echo $rmbz_cg_draft !== '' ? 'Gerar novo rascunho…' : 'Gerar contrato…'; ?></button>
            </div>

            <?php /* MODAL: dados do contrato, todos editáveis. */ ?>
            <div id="rmbz-cg-modal" style="display:none; position:fixed; inset:0; z-index:100000; background:rgba(20,16,40,0.55); align-items:center; justify-content:center; padding:16px;">
                <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"
                      style="background:#fff; border-radius:18px; max-width:520px; width:100%; max-height:90vh; overflow-y:auto; padding:22px 20px; box-shadow:0 30px 60px -20px rgba(0,0,0,0.5);">
                    <input type="hidden" name="action" value="rmbz_generate_project_contract">
                    <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                    <?php wp_nonce_field( 'rmbz_generate_contract_' . (int) $proj_id ); ?>

                    <div style="font-size:17px; font-weight:800; color:#1a1a20; margin-bottom:4px;">📄 Contrato — rever antes de gerar</div>
                    <p style="font-size:12px; color:#56535f; margin:0 0 14px;">Estes dados saem no PDF com aspeto de escrita à mão. Podes corrigir qualquer campo.</p>

                    <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px;">
                        <label style="font-size:11px; font-weight:600; color:#3a3744;">Nome do artista
                            <input type="text" name="c_artist_name" value="<?php echo esc_attr( $rmbz_cg_name ); ?>" style="width:100%; margin-top:3px;">
                        </label>
                        <label style="font-size:11px; font-weight:600; color:#3a3744;">Conta (telemóvel)
                            <input type="text" name="c_artist_tel" value="<?php echo esc_attr( $rmbz_cg_p->artist_telemovel ?? '' ); ?>" style="width:100%; margin-top:3px;">
                        </label>
                    </div>
                    <label style="font-size:11px; font-weight:600; color:#3a3744; display:block; margin-top:10px;">Música
                        <input type="text" name="c_music" value="<?php echo esc_attr( $rmbz_cg_p->project_title ?? '' ); ?>" style="width:100%; margin-top:3px;">
                    </label>
                    <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;">
                        <label style="font-size:11px; font-weight:600; color:#3a3744;">Nível (cenário)
                            <input type="text" name="c_level" value="<?php echo esc_attr( $rmbz_cg_level ); ?>" style="width:100%; margin-top:3px;">
                        </label>
                        <label style="font-size:11px; font-weight:600; color:#3a3744;">Valor (MT)
                            <input type="text" name="c_value" value="<?php echo esc_attr( $rmbz_cg_value ); ?>" placeholder="deixa vazio p/ linha em branco" style="width:100%; margin-top:3px;">
                        </label>
                    </div>
                    <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;">
                        <label style="font-size:11px; font-weight:600; color:#3a3744;">N.º do B.I. do artista
                            <input type="text" name="c_bi_number" value="" placeholder="opcional (fica em branco)" style="width:100%; margin-top:3px;">
                        </label>
                        <label style="font-size:11px; font-weight:600; color:#3a3744;">Cidade
                            <input type="text" name="c_city" value="Maputo" style="width:100%; margin-top:3px;">
                        </label>
                    </div>
                    <label style="font-size:11px; font-weight:600; color:#3a3744; display:block; margin-top:10px;">✍️ Assina pela 1MZ (sai como assinatura manuscrita)
                        <input type="text" name="c_signer_name" value="<?php echo esc_attr( $rmbz_cg_admin ? $rmbz_cg_admin->display_name : '' ); ?>" style="width:100%; margin-top:3px;">
                    </label>

                    <p style="font-size:11px; color:#0d5c34; background:#eaf7f0; border-radius:8px; padding:8px 10px; margin:12px 0;">
                        Isto gera apenas um <strong>rascunho para pré-visualizares</strong> — o artista
                        <strong>não recebe nada</strong> até clicares "✅ Concordo — enviar ao artista".
                    </p>

                    <div style="display:flex; gap:10px;">
                        <button type="button" class="button" style="flex:1;"
                                onclick="document.getElementById('rmbz-cg-modal').style.display='none';">Cancelar</button>
                        <button type="submit" class="button button-primary" style="flex:1.4;">👀 Gerar pré-visualização</button>
                    </div>
                </form>
            </div>
        <?php endif; ?>

        <?php if ( $contract_accepted && $kyc_status === 'pending_admin_review' ): ?>
            <!-- KYC pendente: admin aprova/rejeita identidade -->
            <div class="rmbz-pjv2-kyc-box rmbz-pjv2-kyc-box--pending">
                <p class="title">⏳ Aguardando validação de identidade</p>
                <p class="row"><span class="k">Nome no BI:</span> <strong><?php echo esc_html( $extra['contract_real_name'] ?? '—' ); ?></strong></p>
                <?php if ( ! empty( $extra['contract_kyc_photo'] ) ): ?>
                    <button type="button"
                            class="rmbz-pjv2-kyc-photo-btn rmbz-pjv2-bi-lightbox-trigger"
                            data-bi-url="<?php echo esc_url( $extra['contract_kyc_photo'] ); ?>"
                            data-bi-name="<?php echo esc_attr( $extra['contract_real_name'] ?? '' ); ?>">📸 Abrir foto do BI</button>
                <?php endif; ?>

                <div class="rmbz-pjv2-kyc-actions">
                    <a href="<?php echo wp_nonce_url( admin_url( 'admin-post.php?action=onemz_admin_approve_kyc&project_id=' . $proj_id ), 'onemz_approve_kyc_' . $proj_id ); ?>"
                       class="rmbz-pjv2-btn-success"
                       onclick="return confirm('Confirmar que a foto e o nome são válidos?');">
                        ✓ Aprovar identidade
                    </a>
                    <button type="button" class="rmbz-pjv2-btn-danger" onclick="document.getElementById('rmbz-pjv2-kyc-reject-<?php echo $proj_id; ?>').style.display='block'; this.style.display='none';">
                        ✕ Rejeitar foto
                    </button>
                </div>

                <form id="rmbz-pjv2-kyc-reject-<?php echo $proj_id; ?>" method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" style="display:none;margin-top:12px;">
                    <input type="hidden" name="action" value="onemz_admin_reject_kyc">
                    <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                    <?php wp_nonce_field( 'onemz_reject_kyc_' . $proj_id ); ?>
                    <label style="font-size:11px;color:#991b1b;font-weight:600;display:block;margin-bottom:5px;">Motivo da rejeição:</label>
                    <textarea name="kyc_rejection_reason" required rows="2" class="rmbz-pjv2-kyc-textarea" placeholder="Explique porque é que a foto/nome não estão válidos…"></textarea>
                    <button type="submit" class="rmbz-pjv2-btn-danger" style="width:100%;margin-top:6px;">Enviar rejeição ao artista</button>
                </form>
            </div>

        <?php elseif ( $contract_accepted && $kyc_status === 'approved' ): ?>
            <!-- KYC aprovado: contrato totalmente assinado -->
            <div class="rmbz-pjv2-kyc-box rmbz-pjv2-kyc-box--ok">
                <p class="title">✓ Identidade validada e contrato assinado</p>
                <p class="row"><span class="k">Nome real (BI):</span> <strong><?php echo esc_html( $extra['contract_real_name'] ?? '—' ); ?></strong></p>
                <p class="row"><span class="k">Data:</span>
                    <strong><?php echo ! empty( $extra['contract_accepted_date'] ) ? esc_html( date( 'd/m/Y H:i', strtotime( $extra['contract_accepted_date'] ) ) ) : '—'; ?></strong>
                </p>
                <div class="rmbz-pjv2-kyc-actions">
                    <?php if ( ! empty( $extra['contract_kyc_photo'] ) ): ?>
                        <button type="button"
                                class="rmbz-pjv2-btn-outline rmbz-pjv2-bi-lightbox-trigger"
                                data-bi-url="<?php echo esc_url( $extra['contract_kyc_photo'] ); ?>"
                                data-bi-name="<?php echo esc_attr( $extra['contract_real_name'] ?? '' ); ?>">📸 Rever foto BI</button>
                    <?php endif; ?>
                    <?php if ( $contract_url ): ?>
                        <?php
                        $co_ext = strtolower( pathinfo( parse_url( $contract_url, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
                        $co_type = ( $co_ext === 'pdf' ) ? 'pdf' : 'image';
                        ?>
                        <button type="button"
                                class="rmbz-pjv2-btn-outline rmbz-pjv2-doc-lightbox-trigger"
                                data-doc-url="<?php echo esc_url( $contract_url ); ?>"
                                data-doc-type="<?php echo esc_attr( $co_type ); ?>"
                                data-doc-title="📄 Contrato original"
                                data-doc-subtitle="<?php echo esc_attr( $extra['contract_real_name'] ?? '' ); ?>">📄 Contrato original</button>
                    <?php endif; ?>
                </div>
            </div>

        <?php elseif ( $contract_rejected ): ?>
            <!-- Artista rejeitou o contrato -->
            <div class="rmbz-pjv2-kyc-box rmbz-pjv2-kyc-box--reject">
                <p class="title">✕ Artista RECUSOU o contrato</p>
                <p class="row"><span class="k">Motivo:</span> <strong><?php echo esc_html( $extra['contract_rejected_reason'] ?? '—' ); ?></strong></p>

                <div style="margin-top:12px;">
                    <p style="font-size:11px;font-weight:600;color:#1a1a1f;margin:0 0 6px 0;">Opção A: enviar novo contrato corrigido</p>
                    <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" enctype="multipart/form-data">
                        <input type="hidden" name="action" value="rmbz_admin_upload_contract">
                        <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                        <?php wp_nonce_field( 'rmbz_admin_upload_contract_nonce' ); ?>
                        <input type="file" name="contract_file" required accept=".pdf,image/*" class="rmbz-pjv2-file-input">
                        <button type="submit" class="rmbz-pjv2-btn-outline" style="width:100%;margin-top:6px;">Upload novo contrato</button>
                    </form>
                </div>

                <div style="margin-top:12px;padding-top:12px;border-top:1px dashed #fca5a5;">
                    <p style="font-size:11px;font-weight:600;color:#991b1b;margin:0 0 6px 0;">Opção B: bloquear projeto definitivamente</p>
                    <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>"
                          onsubmit="return confirm('⚠ Vai bloquear o projeto e apagar em 30 dias. Continuar?');">
                        <input type="hidden" name="action" value="rmbz_admin_force_reject_project">
                        <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                        <?php wp_nonce_field( 'rmbz_admin_force_reject_nonce' ); ?>
                        <input type="text" name="admin_rejection_reason" required placeholder="Motivo do bloqueio (vai para o artista)"
                               class="rmbz-pjv2-kyc-textarea" style="margin-bottom:6px;">
                        <button type="submit" class="rmbz-pjv2-btn-danger" style="width:100%;">Rejeitar motivo &amp; cancelar</button>
                    </form>
                </div>
            </div>

        <?php elseif ( $contract_url ): ?>
            <!-- Contrato enviado, aguardando aceite -->
            <div class="rmbz-pjv2-kyc-box rmbz-pjv2-kyc-box--wait">
                <p class="title">⏳ Aguardando assinatura do artista</p>
                <p class="row"><span class="k">Contrato actual:</span>
                    <?php
                    $ca_ext  = strtolower( pathinfo( parse_url( $contract_url, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
                    $ca_type = ( $ca_ext === 'pdf' ) ? 'pdf' : 'image';
                    ?>
                    <button type="button"
                            class="rmbz-pjv2-doc-lightbox-trigger"
                            data-doc-url="<?php echo esc_url( $contract_url ); ?>"
                            data-doc-type="<?php echo esc_attr( $ca_type ); ?>"
                            data-doc-title="📄 Contrato"
                            style="background:none;border:none;padding:0;color:#0b57d0;cursor:pointer;font:inherit;text-decoration:underline;">abrir ↗</button>
                </p>

                <?php /* [1.6.118.24] Preview embed do contrato — PDF em iframe, imagem inline */
                $contract_ext = strtolower( pathinfo( parse_url( $contract_url, PHP_URL_PATH ), PATHINFO_EXTENSION ) );
                $is_pdf       = ( $contract_ext === 'pdf' );
                $is_image     = in_array( $contract_ext, [ 'jpg', 'jpeg', 'png', 'gif', 'webp' ], true );
                ?>
                <?php if ( $is_pdf ): ?>
                    <div class="rmbz-pjv2-contract-preview">
                        <iframe src="<?php echo esc_url( $contract_url ); ?>#toolbar=0&navpanes=0" loading="lazy"></iframe>
                        <button type="button"
                                class="rmbz-pjv2-contract-preview-zoom rmbz-pjv2-doc-lightbox-trigger"
                                data-doc-url="<?php echo esc_url( $contract_url ); ?>"
                                data-doc-type="pdf"
                                data-doc-title="📄 Contrato"
                                title="Ver em tamanho completo">⛶</button>
                    </div>
                <?php elseif ( $is_image ): ?>
                    <div class="rmbz-pjv2-contract-preview rmbz-pjv2-contract-preview--img">
                        <button type="button"
                                class="rmbz-pjv2-doc-lightbox-trigger"
                                data-doc-url="<?php echo esc_url( $contract_url ); ?>"
                                data-doc-type="image"
                                data-doc-title="📄 Contrato"
                                style="background:none;border:none;padding:0;cursor:zoom-in;width:100%;">
                            <img src="<?php echo esc_url( $contract_url ); ?>" alt="Contrato" loading="lazy">
                        </button>
                    </div>
                <?php endif; ?>

                <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" enctype="multipart/form-data" style="margin-top:10px;">
                    <input type="hidden" name="action" value="rmbz_admin_upload_contract">
                    <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                    <?php wp_nonce_field( 'rmbz_admin_upload_contract_nonce' ); ?>
                    <label style="font-size:11px;color:#5f6368;display:block;margin-bottom:4px;">Substituir contrato:</label>
                    <input type="file" name="contract_file" required accept=".pdf,image/*" class="rmbz-pjv2-file-input">
                    <button type="submit" class="rmbz-pjv2-btn-outline" style="width:100%;margin-top:6px;">Substituir</button>
                </form>
            </div>

            <!-- Botão revogar -->
            <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" style="margin-top:12px;"
                  onsubmit="return confirm('🚨 Vai APAGAR o contrato actual e o artista perde acesso a este orçamento. Continuar?');">
                <input type="hidden" name="action" value="onemz_admin_revoke_contract">
                <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                <?php wp_nonce_field( 'onemz_revoke_contract_nonce' ); ?>
                <button type="submit" class="rmbz-pjv2-btn-danger" style="width:100%;">🗑 Revogar contrato e cancelar projeto</button>
            </form>

        <?php else: ?>
            <!-- Nenhum contrato ainda: upload inicial -->
            <p style="font-size:12px;color:#5f6368;margin:0 0 10px 0;">Pagamento desbloqueia quando o artista aceitar o contrato.</p>
            <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" enctype="multipart/form-data">
                <input type="hidden" name="action" value="rmbz_admin_upload_contract">
                <input type="hidden" name="project_id" value="<?php echo (int) $proj_id; ?>">
                <?php wp_nonce_field( 'rmbz_admin_upload_contract_nonce' ); ?>
                <input type="file" name="contract_file" required accept=".pdf,image/*" class="rmbz-pjv2-file-input">
                <button type="submit" class="rmbz-pjv2-btn-primary-full">📤 Fazer upload do contrato</button>
            </form>
        <?php endif; ?>
    </div>

    <?php
    /* ------------------------------------------------------------------------
     * [1.6.118.55] Lightbox para foto do BI (KYC)
     *
     * Renderizado UMA VEZ por bloco de contrato. Os botões "Abrir foto do BI"
     * e "Rever foto BI" disparam este lightbox via classe
     * `.rmbz-pjv2-bi-lightbox-trigger` + atributo data-bi-url.
     *
     * Comportamento:
     *   - Fundo escuro (overlay 85% opacidade)
     *   - Clique na imagem alterna zoom 1x ↔ 2x (cursor zoom-in/zoom-out)
     *   - Fechar: ESC, clique no overlay, ou clique no X
     *   - body fica overflow:hidden enquanto modal aberto
     *
     * Guard `__rmbzBiLightboxInit` impede duplo bind se a função correr 2x
     * por página (defensivo).
     * ----------------------------------------------------------------------- */
    static $lightbox_emitted = false;
    if ( ! $lightbox_emitted ) :
        $lightbox_emitted = true;
        ?>
        <div id="rmbz-pjv2-bi-lightbox" class="rmbz-pjv2-bi-lightbox" role="dialog" aria-modal="true" aria-hidden="true">
            <div class="rmbz-pjv2-bi-lightbox__overlay" data-bi-close></div>
            <div class="rmbz-pjv2-bi-lightbox__content">
                <button type="button" class="rmbz-pjv2-bi-lightbox__close" data-bi-close aria-label="Fechar">×</button>
                <div class="rmbz-pjv2-bi-lightbox__caption">
                    <span class="rmbz-pjv2-bi-lightbox__title">📸 Foto do BI</span>
                    <span class="rmbz-pjv2-bi-lightbox__name"></span>
                </div>
                <div class="rmbz-pjv2-bi-lightbox__img-wrap">
                    <img alt="" class="rmbz-pjv2-bi-lightbox__img" />
                    <iframe class="rmbz-pjv2-bi-lightbox__pdf" title="Documento PDF" style="display:none;"></iframe>
                </div>
                <p class="rmbz-pjv2-bi-lightbox__hint">Clica na imagem para ampliar · ESC ou clica fora para fechar</p>
            </div>
        </div>

        <style>
        .rmbz-pjv2-bi-lightbox {
            position: fixed;
            inset: 0;
            z-index: 99999;
            display: none;
            align-items: center;
            justify-content: center;
        }
        .rmbz-pjv2-bi-lightbox.is-open { display: flex; }
        .rmbz-pjv2-bi-lightbox__overlay {
            position: absolute;
            inset: 0;
            background: rgba(0, 0, 0, 0.85);
            backdrop-filter: blur(2px);
            cursor: pointer;
        }
        .rmbz-pjv2-bi-lightbox__content {
            position: relative;
            z-index: 1;
            max-width: min(92vw, 1100px);
            max-height: 92vh;
            display: flex;
            flex-direction: column;
            gap: 10px;
            padding: 16px;
            box-sizing: border-box;
        }
        .rmbz-pjv2-bi-lightbox__close {
            position: absolute;
            top: -6px;
            right: -6px;
            width: 38px;
            height: 38px;
            border-radius: 50%;
            background: #fff;
            color: #111;
            border: none;
            font-size: 22px;
            line-height: 1;
            cursor: pointer;
            box-shadow: 0 4px 12px rgba(0,0,0,0.4);
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 600;
        }
        .rmbz-pjv2-bi-lightbox__close:hover { background: #f3f4f6; }
        .rmbz-pjv2-bi-lightbox__caption {
            display: flex;
            align-items: baseline;
            gap: 10px;
            color: #fff;
            font-size: 13px;
            flex-wrap: wrap;
        }
        .rmbz-pjv2-bi-lightbox__title { font-weight: 600; }
        .rmbz-pjv2-bi-lightbox__name {
            color: #fbbf24;
            font-weight: 500;
        }
        .rmbz-pjv2-bi-lightbox__name:not(:empty)::before { content: "· "; color: #9ca3af; }
        .rmbz-pjv2-bi-lightbox__img-wrap {
            overflow: auto;
            border-radius: 8px;
            background: #1f2937;
            display: flex;
            align-items: center;
            justify-content: center;
            min-height: 0;
            flex: 1;
        }
        .rmbz-pjv2-bi-lightbox__img {
            max-width: 100%;
            max-height: 80vh;
            display: block;
            cursor: zoom-in;
            transition: transform 0.18s ease;
            transform-origin: center center;
            user-select: none;
        }
        .rmbz-pjv2-bi-lightbox__img.is-zoomed {
            cursor: zoom-out;
            transform: scale(2);
            max-width: none;
            max-height: none;
        }
        /* [1.6.118.57] Iframe para PDF — ocupa todo o espaço disponível */
        .rmbz-pjv2-bi-lightbox__pdf {
            width: 88vw;
            max-width: 1100px;
            height: 80vh;
            border: none;
            border-radius: 8px;
            background: #fff;
        }
        .rmbz-pjv2-bi-lightbox__hint {
            color: #9ca3af;
            font-size: 11px;
            text-align: center;
            margin: 0;
        }
        /* Bloquear scroll do body enquanto lightbox aberto */
        body.rmbz-pjv2-bi-lightbox-open { overflow: hidden; }
        </style>

        <script>
        (function() {
            // Guard contra duplo bind (defensivo — função pode correr 2x)
            if (window.__rmbzBiLightboxInit) return;
            window.__rmbzBiLightboxInit = true;

            var modal   = document.getElementById('rmbz-pjv2-bi-lightbox');
            if (!modal) return;
            var imgEl     = modal.querySelector('.rmbz-pjv2-bi-lightbox__img');
            var pdfEl     = modal.querySelector('.rmbz-pjv2-bi-lightbox__pdf');
            var titleEl   = modal.querySelector('.rmbz-pjv2-bi-lightbox__title');
            var nameEl    = modal.querySelector('.rmbz-pjv2-bi-lightbox__name');
            var hintEl    = modal.querySelector('.rmbz-pjv2-bi-lightbox__hint');

            /**
             * [1.6.118.57] Lightbox generalizado para imagem OU PDF.
             *
             * Detecta o tipo:
             *  - opts.type === 'pdf' OU URL termina em .pdf → iframe
             *  - caso contrário → <img>
             *
             * opts: { url, title, subtitle, type }
             */
            function openLightbox(opts) {
                opts = opts || {};
                var url = opts.url || '';
                if (!url) return;

                var isPdf = (opts.type === 'pdf') ||
                            /\.pdf(\?|#|$)/i.test(url);

                titleEl.textContent = opts.title || '📸 Foto do BI';
                nameEl.textContent  = opts.subtitle || '';

                if (isPdf) {
                    imgEl.style.display = 'none';
                    imgEl.classList.remove('is-zoomed');
                    pdfEl.style.display = 'block';
                    pdfEl.src = url + (url.indexOf('#') === -1 ? '#toolbar=1&navpanes=0' : '');
                    hintEl.textContent = 'Usa os controlos do PDF · ESC ou clica fora para fechar';
                } else {
                    pdfEl.style.display = 'none';
                    pdfEl.src = 'about:blank';
                    imgEl.style.display = 'block';
                    imgEl.classList.remove('is-zoomed');
                    imgEl.src = url;
                    hintEl.textContent = 'Clica na imagem para ampliar · ESC ou clica fora para fechar';
                }

                modal.classList.add('is-open');
                modal.setAttribute('aria-hidden', 'false');
                document.body.classList.add('rmbz-pjv2-bi-lightbox-open');
            }
            function closeLightbox() {
                modal.classList.remove('is-open');
                modal.setAttribute('aria-hidden', 'true');
                document.body.classList.remove('rmbz-pjv2-bi-lightbox-open');
                imgEl.classList.remove('is-zoomed');
                // Limpa src para libertar memória / parar carregamento PDF
                setTimeout(function() {
                    if (!modal.classList.contains('is-open')) {
                        imgEl.src = '';
                        pdfEl.src = 'about:blank';
                    }
                }, 200);
            }

            // Triggers — delegação no document para apanhar elementos
            // injectados dinamicamente também
            document.addEventListener('click', function(e) {
                // Novo trigger genérico (contrato + futuros docs)
                var docTrigger = e.target.closest('.rmbz-pjv2-doc-lightbox-trigger');
                if (docTrigger) {
                    e.preventDefault();
                    openLightbox({
                        url:      docTrigger.getAttribute('data-doc-url'),
                        type:     docTrigger.getAttribute('data-doc-type'),
                        title:    docTrigger.getAttribute('data-doc-title'),
                        subtitle: docTrigger.getAttribute('data-doc-subtitle'),
                    });
                    return;
                }
                // Trigger legado da foto BI — mantido para retro-compat
                var biTrigger = e.target.closest('.rmbz-pjv2-bi-lightbox-trigger');
                if (biTrigger) {
                    e.preventDefault();
                    openLightbox({
                        url:      biTrigger.getAttribute('data-bi-url'),
                        type:     'image',
                        title:    '📸 Foto do BI',
                        subtitle: biTrigger.getAttribute('data-bi-name'),
                    });
                    return;
                }
                if (e.target.matches('[data-bi-close]')) {
                    closeLightbox();
                }
            });

            // Zoom toggle na imagem (não aplica a PDF)
            imgEl.addEventListener('click', function() {
                imgEl.classList.toggle('is-zoomed');
            });

            // ESC para fechar
            document.addEventListener('keydown', function(e) {
                if (e.key === 'Escape' && modal.classList.contains('is-open')) {
                    closeLightbox();
                }
            });
        })();
        </script>
        <?php
    endif; // $lightbox_emitted
}

/* ============================================================================
 * CHAT JS — polling 3s, send, upload, edit, delete, toggle
 * ============================================================================ */
function rmbz_pjv2_chat_script( $proj_id ) {
    ?>
    <script>
    (function(){
        var cfg = window.rmbzChatConfig || {};
        var pid = <?php echo (int) $proj_id; ?>;
        var stream = document.getElementById('rmbz-pjv2-stream');
        var empty  = document.getElementById('rmbz-pjv2-empty');

        // GUARD — se a config não foi emitida (bug no hook do plugin), mostrar
        // erro útil em vez de "URL desconhecido: get" críptico.
        if (!cfg.urls || !cfg.urls.get) {
            if (empty) {
                empty.innerHTML = '<div class="icon">⚠</div>'
                    + '<p style="margin:0;font-weight:600;color:#991b1b;">Chat não inicializou.</p>'
                    + '<p style="margin:6px 0 0 0;font-size:12px;">window.rmbzChatConfig.urls está vazio. '
                    + 'Causas comuns: cache do browser, plugin de cache no servidor, '
                    + 'ou erro PHP no carregamento. Tenta Ctrl+Shift+R.</p>';
            }
            console.error('[1MZ Chat] window.rmbzChatConfig.urls em falta. Config recebida:', cfg);
            return; // Não arranca polling, evita loop de toasts vermelhos
        }

        var input  = document.getElementById('rmbz-pjv2-input');
        var sendBtn= document.getElementById('rmbz-pjv2-send');
        var fileIn = document.getElementById('rmbz-pjv2-file');
        var attachBtn = document.getElementById('rmbz-pjv2-attach-btn');
        var preview   = document.getElementById('rmbz-pjv2-preview');
        var pvName    = document.getElementById('rmbz-pjv2-preview-name');
        var pvSize    = document.getElementById('rmbz-pjv2-preview-size');
        var pvIco     = document.getElementById('rmbz-pjv2-preview-ico');
        var pvRemove  = document.getElementById('rmbz-pjv2-preview-remove');
        var pvProg    = document.getElementById('rmbz-pjv2-preview-progress');
        var pvProgWrap= document.getElementById('rmbz-pjv2-preview-progress-wrap');
        var toggleBtn = document.getElementById('rmbz-pjv2-toggle-attach');
        var statePills= document.querySelectorAll('#rmbz-pjv2-state-pills .rmbz-pjv2-state-pill');
        var prodHid   = document.getElementById('rmbz-pjv2-prod-status');
        var rejbox    = document.getElementById('rmbz-pjv2-rejbox');
        var rejlabel  = document.getElementById('rmbz-pjv2-rejlabel');
        var lightbox  = document.getElementById('rmbz-pjv2-lightbox');
        var lightImg  = document.getElementById('rmbz-pjv2-lightbox-img');

        var lastId = 0;       // id mais alto que já recebemos
        var pollTimer = null;
        var pendingAtt = null; // anexo carregado mas ainda não enviado
        var renderedIds = new Set();

        // ── Som de mensagem nova (pop curto, igual aos apps) ─────
        // bootDone evita o pop em todo o histórico do primeiro load.
        var bootDone = false;
        var chatPop = null;
        try {
            chatPop = new Audio('<?php echo esc_js( RMBZ_PLUGIN_URL . 'assets/audio/chat-pop.wav' ); ?>');
            chatPop.volume = 0.6;
        } catch (e) {}
        function chatMuted() {
            try { return localStorage.getItem('rmbz_chat_muted') === '1'; } catch (e) { return false; }
        }
        function playChatPop() {
            if (!chatPop || chatMuted()) return;
            try {
                chatPop.currentTime = 0;
                var p = chatPop.play();
                if (p && p.catch) p.catch(function(){}); // autoplay bloqueado antes da 1ª interação
            } catch (e) {}
        }
        var soundToggle = document.getElementById('rmbz-pjv2-sound-toggle');
        function refreshSoundToggle() {
            if (soundToggle) soundToggle.textContent = chatMuted() ? '🔕' : '🔔';
        }
        if (soundToggle) {
            refreshSoundToggle();
            soundToggle.addEventListener('click', function(){
                try { localStorage.setItem('rmbz_chat_muted', chatMuted() ? '0' : '1'); } catch (e) {}
                refreshSoundToggle();
            });
        }

        function toast(msg, isErr) {
            var t = document.createElement('div');
            t.className = 'rmbz-pjv2-toast' + (isErr ? ' is-error' : '');
            t.innerHTML = '<span class="ico">' + (isErr ? '!' : '✓') + '</span>' + msg;
            document.body.appendChild(t);
            requestAnimationFrame(function(){ t.classList.add('is-show'); });
            setTimeout(function(){
                t.classList.remove('is-show');
                setTimeout(function(){ t.remove(); }, 250);
            }, 1800);
        }

        function fmtSize(n) {
            if (!n) return '';
            if (n < 1024) return n + ' B';
            if (n < 1048576) return Math.round(n / 1024) + ' KB';
            return (n / 1048576).toFixed(1) + ' MB';
        }

        function escHtml(s) {
            return String(s == null ? '' : s)
                .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;').replace(/'/g, '&#039;');
        }

        function autoLink(text) {
            return escHtml(text).replace(/(https?:\/\/[^\s<]+)/g, function(u) {
                return '<a href="' + u + '" target="_blank" rel="noopener">' + u + '</a>';
            });
        }

        function rebuildEmptyState() {
            var hasMsg = stream.querySelector('.rmbz-pjv2-msg');
            if (hasMsg) {
                if (empty && empty.parentNode) empty.parentNode.removeChild(empty);
            }
        }

        function attachIcon(type) {
            switch (type) {
                case 'image': return '🖼';
                case 'audio': return '🎵';
                case 'video': return '🎬';
                case 'pdf':   return '📄';
                default:      return '📎';
            }
        }

        function renderAttachment(att, who) {
            if (!att || !att.url) return '';
            var t = att.type || 'file';
            if (t === 'image') {
                return '<a class="rmbz-pjv2-att" href="javascript:void(0)" data-img="' + escHtml(att.url) + '">'
                     + '<img src="' + escHtml(att.url) + '" alt=""></a>';
            }
            if (t === 'audio') {
                return '<div class="rmbz-pjv2-att"><audio controls preload="none"><source src="' + escHtml(att.url) + '"></audio></div>';
            }
            if (t === 'video') {
                return '<div class="rmbz-pjv2-att"><video controls preload="none"><source src="' + escHtml(att.url) + '"></video></div>';
            }
            // pdf / file
            return '<a class="rmbz-pjv2-att rmbz-pjv2-att-file" href="' + escHtml(att.url) + '" target="_blank" rel="noopener" download>'
                 + '<span class="ico">' + attachIcon(t) + '</span>'
                 + '<span class="name">' + escHtml(att.name || 'Ficheiro') + '</span>'
                 + '<span class="size">' + fmtSize(att.size) + '</span>'
                 + '</a>';
        }

        function renderMessage(m) {
            if (renderedIds.has(m.id)) return; // dedup
            renderedIds.add(m.id);
            if (m.id > lastId && !m.is_legacy) lastId = m.id;

            var who = m.author_type || 'admin';
            var cls = 'rmbz-pjv2-msg rmbz-pjv2-msg--' + who;
            var avatarLetter = who === 'admin' ? '1' : (who === 'system' ? 'i' : (m.author_label ? m.author_label.charAt(0).toUpperCase() : 'A'));

            var bodyHtml = '';
            if (m.is_deleted) {
                bodyHtml = '<em style="opacity:0.6;">Mensagem apagada</em>';
            } else {
                if (m.body) bodyHtml += '<div>' + autoLink(m.body) + '</div>';
                if (m.attachment) bodyHtml += renderAttachment(m.attachment, who);
            }

            var metaHtml = '<div class="meta">'
                + '<span>' + escHtml(m.created_at_label || '') + '</span>'
                + (m.is_edited ? '<span class="edited">(editado)</span>' : '');
            if ((who === 'admin' || who === 'artist') && !m.is_legacy && !m.is_deleted) {
                metaHtml += '<span class="actions">'
                  + (who === 'admin' ? '<a data-action="edit" data-id="' + m.id + '">editar</a>' : '')
                  + '<a data-action="delete" data-id="' + m.id + '">apagar</a>'
                  + '</span>';
            }
            metaHtml += '</div>';

            var html = '<div class="avatar">' + escHtml(avatarLetter) + '</div>'
                     + '<div class="bubble">' + bodyHtml + metaHtml + '</div>';

            var el = document.createElement('div');
            el.className = cls;
            el.dataset.msgId = m.id;
            el.innerHTML = html;
            stream.appendChild(el);
        }

        function applyMessages(list) {
            if (!list || !list.length) return;
            var freshArtistMsg = bootDone && list.some(function(m){
                return m.author_type === 'artist' && !m.is_deleted && !renderedIds.has(m.id);
            });
            list.forEach(renderMessage);
            rebuildEmptyState();
            stream.scrollTop = stream.scrollHeight;
            if (freshArtistMsg) playChatPop();
        }

        function reconcileDeletedMessages(ids) {
            (Array.isArray(ids) ? ids : []).forEach(function(id){
                var numericId = parseInt(id, 10) || 0;
                var message = numericId > 0 ? stream.querySelector('[data-msg-id="' + numericId + '"]') : null;
                if (!message || message.classList.contains('is-deleted')) return;
                var bubble = message.querySelector('.bubble');
                if (!bubble) return;
                var meta = bubble.querySelector('.meta');
                if (meta) {
                    var actions = meta.querySelector('.actions');
                    if (actions) actions.remove();
                }
                bubble.innerHTML = '<em style="opacity:0.6;">Mensagem apagada</em>' + (meta ? meta.outerHTML : '');
                message.classList.add('is-deleted');
            });
            rebuildEmptyState();
        }

        function apiUrl(name, params) {
            var base = cfg.urls && cfg.urls[name] ? cfg.urls[name] : '';
            if (!base) return '';
            if (name === 'get') {
                // template ?since=__SINCE__ — substituir
                var since = (params && params.since) ? params.since : 0;
                return base.replace('__SINCE__', since);
            }
            // [1.5.373] Anexar params genéricos (ex.: ?full=1) a outros endpoints.
            if (params) {
                var qs = Object.keys(params).map(function(k){
                    return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]);
                }).join('&');
                if (qs) base += (base.indexOf('?') >= 0 ? '&' : '?') + qs;
            }
            return base;
        }

        // Defesa: o WP REST devolve HTML quando há login expirado ou plugin
        // de cache mete output antes do JSON. Vamos sempre ler como texto
        // primeiro e tentar JSON.parse, expondo o erro real se vier HTML.
        function safeJson(r) {
            return r.text().then(function(txt){
                if (!txt) return null;
                try {
                    return JSON.parse(txt);
                } catch (e) {
                    // Detectar HTML típico de erro WP
                    var preview = txt.substring(0, 120).replace(/\s+/g, ' ');
                    throw new Error('Resposta não é JSON (HTTP ' + r.status + '): ' + preview);
                }
            });
        }

        function api(method, name, body, isForm, params) {
            var url = apiUrl(name, params);
            if (!url) return Promise.reject(new Error('URL desconhecido: ' + name));
            var opts = { method: method, headers: { 'X-WP-Nonce': cfg.nonce, 'Accept': 'application/json' }, credentials: 'same-origin' };
            if (body) {
                if (isForm) {
                    opts.body = body;
                } else {
                    opts.headers['Content-Type'] = 'application/json';
                    opts.body = JSON.stringify(body);
                }
            }
            return fetch(url, opts).then(function(r){
                return safeJson(r).then(function(j){
                    if (!r.ok || (j && j.success === false)) {
                        var msg = (j && j.error && j.error.message) || ('HTTP ' + r.status);
                        throw new Error(msg);
                    }
                    return (j && j.data !== undefined) ? j.data : j;
                });
            });
        }

        function loadInitial() {
            api('GET', 'get', null, false, { since: 0 }).then(function(data){
                applyMessages(data.messages || []);
                reconcileDeletedMessages(data.deleted_message_ids || []);
                bootDone = true; // a partir daqui, mensagens novas tocam o pop
                if (toggleBtn) {
                    var on = !!data.artist_can_attach;
                    toggleBtn.classList.toggle('is-on', on);
                    toggleBtn.setAttribute('aria-pressed', on ? 'true' : 'false');
                    var hint = toggleBtn.querySelector('.hint');
                    if (hint) hint.textContent = on ? 'Permitido' : 'Bloqueado';
                }
                if ((data.messages || []).length === 0) {
                    empty.innerHTML = '<div class="icon">💬</div><p style="margin:0;">Comece a conversa — envie a primeira mensagem.</p>';
                }
            }).catch(function(e){ toast('Erro a carregar: ' + e.message, true); });
        }

        // Buscar info do artista + change log + recomendações
        function loadInfo() {
            api('GET', 'info').then(function(data){
                if (data.artist) renderArtist(data.artist);
                if (data.recommendations) renderRecs(data.recommendations);
                if (data.change_log) renderChangeLog(data.change_log);
            }).catch(function(e){
                // não bloquear o chat se isto falhar
                console.warn('loadInfo:', e.message);
            });
        }

        function renderArtist(a) {
            var block = document.getElementById('rmbz-pjv2-artist-block');
            var box   = document.getElementById('rmbz-pjv2-artist-card');
            if (!block || !box) return;
            var initials = (a.name || '?').split(/\s+/).slice(0,2).map(function(w){return w.charAt(0).toUpperCase();}).join('') || '?';
            var prov = a.provincia ? ' · ' + escHtml(a.provincia) : '';
            var balance = (a.balance || 0).toLocaleString('pt-MZ', { minimumFractionDigits: 2 });

            var badges = '';
            if (a.is_banned)  badges += '<span class="rmbz-pjv2-artist-badge rmbz-pjv2-artist-badge--banned">🚫 banido</span>';
            if (a.is_creator) badges += '<span class="rmbz-pjv2-artist-badge rmbz-pjv2-artist-badge--creator">✓ criador</span>';

            var p = a.projects || {}, s = a.submissions || {};
            var stats = '';
            if (p.total > 0) {
                stats += '<div class="rmbz-pjv2-artist-stat"><div class="n">' + (p.total||0) + '</div><div class="l">Projetos</div></div>';
                if (p.done > 0)    stats += '<div class="rmbz-pjv2-artist-stat is-good"><div class="n">' + p.done + '</div><div class="l">Lançados</div></div>';
                if (p.in_progress > 0) stats += '<div class="rmbz-pjv2-artist-stat"><div class="n">' + p.in_progress + '</div><div class="l">Em curso</div></div>';
                if (p.rejected > 0)   stats += '<div class="rmbz-pjv2-artist-stat is-bad"><div class="n">' + p.rejected + '</div><div class="l">Rejeitados</div></div>';
            }
            if (s.music_published > 0) stats += '<div class="rmbz-pjv2-artist-stat is-good"><div class="n">' + s.music_published + '</div><div class="l">Músicas pub.</div></div>';
            if (s.video_published > 0) stats += '<div class="rmbz-pjv2-artist-stat is-good"><div class="n">' + s.video_published + '</div><div class="l">Vídeos pub.</div></div>';

            var html = '<div class="rmbz-pjv2-artist-head">'
                     + '<div class="rmbz-pjv2-artist-avatar">' + escHtml(initials) + '</div>'
                     + '<div style="flex:1;min-width:0;">'
                     +   '<div class="name">' + escHtml(a.name || '—') + '</div>'
                     +   '<div class="sub">' + escHtml(a.telemovel || '') + escHtml(prov.replace(' · ','')) + (prov ? ' · ' + escHtml(a.provincia) : '') + '</div>'
                     + '</div>'
                     + '</div>';
            // Reparar duplicado acima — fica só uma vez a provincia (limpar)
            html = '<div class="rmbz-pjv2-artist-head">'
                 + '<div class="rmbz-pjv2-artist-avatar">' + escHtml(initials) + '</div>'
                 + '<div style="flex:1;min-width:0;">'
                 +   '<div class="name">' + escHtml(a.name || '—') + '</div>'
                 +   '<div class="sub">' + escHtml(a.telemovel || '') + (a.provincia ? ' · ' + escHtml(a.provincia) : '') + '</div>'
                 + '</div>'
                 + '</div>';

            if (badges) html += '<div class="rmbz-pjv2-artist-badges">' + badges + '</div>';

            html += '<div class="rmbz-pjv2-artist-balance">'
                  + '<span class="lab">Saldo</span>'
                  + '<span>' + balance + ' MT</span>'
                  + '</div>';

            if (stats) html += '<div class="rmbz-pjv2-artist-stats">' + stats + '</div>';

            box.innerHTML = html;
            block.style.display = '';
        }

        function renderRecs(list) {
            var block = document.getElementById('rmbz-pjv2-recs-block');
            var lst   = document.getElementById('rmbz-pjv2-recs-list');
            if (!block || !lst) return;
            if (!list || !list.length) { block.style.display = 'none'; return; }
            var html = '';
            list.forEach(function(r){
                html += '<div class="rmbz-pjv2-rec rmbz-pjv2-rec--' + escHtml(r.severity || 'info') + '">'
                      + '<span class="ico">' + escHtml(r.icon || 'ℹ') + '</span>'
                      + '<span>' + escHtml(r.text || '') + '</span>'
                      + '</div>';
            });
            lst.innerHTML = html;
            block.style.display = '';
        }

        // [1.5.373] Construtor de HTML do log (reutilizado pela sidebar e modal).
        function buildChangeLogHtml(list) {
            if (!list || !list.length) {
                return '<div class="rmbz-pjv2-log-empty">Sem alterações registadas ainda.</div>';
            }
            var html = '<div class="rmbz-pjv2-log-list">';
            list.forEach(function(e){
                var who = (e.who || 'admin').toLowerCase();
                var cls = who === 'artista' || who === 'artist' ? 'artist'
                        : who === 'sistema' || who === 'system' ? 'system'
                        : 'admin';
                html += '<div class="rmbz-pjv2-log-entry rmbz-pjv2-log-entry--' + cls + '">'
                      + '<span class="ts">' + escHtml(e.ts_label || '') + '</span>'
                      + '<span class="who">' + escHtml(e.who || 'admin') + '</span>'
                      + '<span class="what">' + escHtml(e.what || '') + '</span>';
                if (e.from != null || e.to != null) {
                    html += '<div class="diff">'
                          + '<span class="from">' + escHtml(e.from || '(vazio)') + '</span>'
                          + '<span class="arrow">→</span>'
                          + '<span class="to">' + escHtml(e.to || '(vazio)') + '</span>'
                          + '</div>';
                }
                html += '</div>';
            });
            html += '</div>';
            return html;
        }

        function renderChangeLog(list) {
            var block = document.getElementById('rmbz-pjv2-changelog-block');
            var lst   = document.getElementById('rmbz-pjv2-changelog-list');
            if (!block || !lst) return;
            block.style.display = '';
            lst.innerHTML = buildChangeLogHtml(list);
        }

        // [1.5.373] Modal de histórico completo.
        function openFullHistory() {
            var modal = document.getElementById('rmbz-pjv2-histmodal');
            var body  = document.getElementById('rmbz-pjv2-histmodal-body');
            if (!modal || !body) return;
            body.innerHTML = '<div class="rmbz-pjv2-log-empty">A carregar…</div>';
            modal.classList.add('is-show');
            modal.setAttribute('aria-hidden', 'false');
            api('GET', 'info', null, false, { full: 1 }).then(function(data){
                body.innerHTML = buildChangeLogHtml(data.change_log || []);
            }).catch(function(e){
                body.innerHTML = '<div class="rmbz-pjv2-log-empty">Erro a carregar: ' + escHtml(e.message) + '</div>';
            });
        }
        function closeFullHistory() {
            var modal = document.getElementById('rmbz-pjv2-histmodal');
            if (!modal) return;
            modal.classList.remove('is-show');
            modal.setAttribute('aria-hidden', 'true');
        }
        (function(){
            var openBtn = document.getElementById('rmbz-pjv2-history-open');
            if (openBtn) openBtn.addEventListener('click', openFullHistory);
            var modal = document.getElementById('rmbz-pjv2-histmodal');
            if (modal) {
                modal.querySelectorAll('[data-hist-close]').forEach(function(el){
                    el.addEventListener('click', closeFullHistory);
                });
            }
            document.addEventListener('keydown', function(ev){
                if (ev.key === 'Escape') closeFullHistory();
            });
        })();

        function poll() {
            api('GET', 'get', null, false, { since: lastId }).then(function(data){
                applyMessages(data.messages || []);
                reconcileDeletedMessages(data.deleted_message_ids || []);
            }).catch(function(){ /* silent */ });
        }

        function startPolling() {
            if (pollTimer) return;
            pollTimer = setInterval(poll, cfg.pollIntervalMs || 3000);
        }

        // ── Composer ────────────────────────────────────────────
        // O composer não é renderizado quando o projeto está rejeitado ou
        // cancelado (chat bloqueado) — só o histórico fica visível.
        var composerActive = !!(input && sendBtn && attachBtn && fileIn && pvRemove);
        function updateSendEnabled() {
            if (!composerActive) return;
            var hasText = input.value.trim() !== '';
            var hasAtt  = !!pendingAtt;
            sendBtn.disabled = !(hasText || hasAtt);
        }
        if (composerActive) {
        input.addEventListener('input', function(){
            updateSendEnabled();
            input.style.height = 'auto';
            input.style.height = Math.min(input.scrollHeight, 120) + 'px';
        });
        input.addEventListener('keydown', function(e){
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendBtn.click();
            }
        });

        attachBtn.addEventListener('click', function(){ fileIn.click(); });
        fileIn.addEventListener('change', function(){
            if (!fileIn.files || !fileIn.files[0]) return;
            var f = fileIn.files[0];
            if (f.size > 15 * 1024 * 1024) {
                toast('Ficheiro acima de 15 MB.', true);
                fileIn.value = '';
                return;
            }
            // mostrar preview imediato
            pvName.textContent = f.name;
            pvSize.textContent = fmtSize(f.size);
            pvIco.textContent = f.type.startsWith('image/') ? '🖼'
                              : f.type.startsWith('audio/') ? '🎵'
                              : f.type.startsWith('video/') ? '🎬'
                              : f.type === 'application/pdf' ? '📄' : '📎';
            preview.classList.add('is-show', 'is-uploading');
            pvProgWrap.style.display = 'block';
            pvProg.style.width = '20%';

            // upload
            var fd = new FormData();
            fd.append('file', f);

            api('POST', 'upload', fd, true).then(function(att){
                pendingAtt = att;
                preview.classList.remove('is-uploading');
                pvProg.style.width = '100%';
                setTimeout(function(){ pvProgWrap.style.display = 'none'; }, 300);
                updateSendEnabled();
            }).catch(function(e){
                toast('Erro upload: ' + e.message, true);
                preview.classList.remove('is-show', 'is-uploading');
                fileIn.value = '';
            });
        });
        pvRemove.addEventListener('click', function(){
            pendingAtt = null;
            preview.classList.remove('is-show', 'is-uploading');
            pvProgWrap.style.display = 'none';
            pvProg.style.width = '0%';
            fileIn.value = '';
            updateSendEnabled();
        });

        sendBtn.addEventListener('click', function(){
            var text = input.value.trim();
            var att  = pendingAtt;
            if (!text && !att) return;
            sendBtn.disabled = true;

            api('POST', 'send', { body: text, attachment: att })
                .then(function(data){
                    input.value = ''; input.style.height = '42px';
                    pendingAtt = null;
                    preview.classList.remove('is-show', 'is-uploading');
                    pvProgWrap.style.display = 'none';
                    fileIn.value = '';
                    applyMessages(data.messages || []);
                })
                .catch(function(e){ toast('Erro a enviar: ' + e.message, true); })
                .finally(function(){ updateSendEnabled(); });
        });
        } // fim composerActive

        // ── Edit / Delete via delegation ────────────────────────
        stream.addEventListener('click', function(e){
            var t = e.target;
            if (t.dataset && t.dataset.action === 'edit') {
                var id = parseInt(t.dataset.id, 10);
                var bubble = t.closest('.rmbz-pjv2-msg').querySelector('.bubble > div');
                var current = bubble ? bubble.textContent : '';
                var n = prompt('Editar mensagem:', current);
                if (n != null && n.trim() && n !== current) {
                    api('POST', 'edit', { message_id: id, body: n }).then(function(){
                        // recarrega só essa entrada simples: poll vai trazer? não — edit não muda id.
                        // Vamos actualizar inline:
                        if (bubble) bubble.innerHTML = autoLink(n);
                        var meta = t.closest('.bubble').querySelector('.meta');
                        if (meta && !meta.querySelector('.edited')) {
                            var em = document.createElement('span');
                            em.className = 'edited'; em.textContent = '(editado)';
                            meta.insertBefore(em, meta.querySelector('.actions'));
                        }
                        toast('Editado.');
                    }).catch(function(e){ toast(e.message, true); });
                }
            }
            if (t.dataset && t.dataset.action === 'delete') {
                if (!confirm('Apagar esta mensagem?')) return;
                var id2 = parseInt(t.dataset.id, 10);
                api('POST', 'delete', { message_id: id2 }).then(function(){
                    reconcileDeletedMessages([ id2 ]);
                    toast('Apagada.');
                }).catch(function(e){ toast(e.message, true); });
            }
            // Lightbox imagens
            if (t.dataset && t.dataset.img) {
                lightImg.src = t.dataset.img;
                lightbox.classList.add('is-show');
            } else if (t.tagName === 'IMG' && t.closest('[data-img]')) {
                lightImg.src = t.closest('[data-img]').dataset.img;
                lightbox.classList.add('is-show');
            }
        });

        // ── Toggle anexos do artista ────────────────────────────
        if (toggleBtn) {
            toggleBtn.addEventListener('click', function(){
                var newState = !toggleBtn.classList.contains('is-on');
                api('POST', 'toggle_attach', { enabled: newState }).then(function(data){
                    var on = !!data.artist_can_attach;
                    toggleBtn.classList.toggle('is-on', on);
                    toggleBtn.setAttribute('aria-pressed', on ? 'true' : 'false');
                    var hint = toggleBtn.querySelector('.hint');
                    if (hint) hint.textContent = on ? 'Permitido' : 'Bloqueado';
                    toast(on ? 'Anexos permitidos.' : 'Anexos bloqueados.');
                    // poll para apanhar a mensagem de sistema
                    poll();
                }).catch(function(e){ toast(e.message, true); });
            });
        }

        // ── State pills no painel da direita ────────────────────
        statePills.forEach(function(b){
            b.addEventListener('click', function(){
                statePills.forEach(function(x){ x.classList.remove('is-active'); });
                b.classList.add('is-active');
                var k = b.dataset.status;
                prodHid.value = k;
                if (k === 'rejected' || k === 'correction') {
                    rejbox.style.display = 'block';
                    rejbox.classList.toggle('rmbz-pjv2-rejbox--correction', k === 'correction');
                    rejlabel.textContent = k === 'correction'
                        ? '✉ Instruções para correção (irá no email):'
                        : '✉ Motivo da rejeição (irá no email):';
                } else {
                    rejbox.style.display = 'none';
                }
            });
        });

        // [1.6.118.21] Quick actions: aprovar / pedir correção / rejeitar.
        // Disparam o click no pill correspondente (mantém toda a lógica em 1 sítio).
        var quickBtns = document.querySelectorAll('.rmbz-pjv2-quick-actions .qa-btn');
        quickBtns.forEach(function(qb){
            qb.addEventListener('click', function(){
                var target = qb.dataset.targetStatus;
                if (!target) return;

                // marca botão como selecionado
                quickBtns.forEach(function(x){ x.classList.remove('is-selected'); });
                qb.classList.add('is-selected');

                // procura o pill correspondente e simula click
                var targetPill = document.querySelector('#rmbz-pjv2-state-pills .rmbz-pjv2-state-pill[data-status="' + target + '"]');
                if (targetPill) {
                    targetPill.click();
                }

                // se for rejeição/correção, foca o textarea
                if (target === 'rejected' || target === 'correction') {
                    setTimeout(function(){
                        var ta = document.querySelector('#rmbz-pjv2-rejbox textarea[name="rejection_reason"]');
                        if (ta) { ta.focus(); ta.scrollIntoView({ behavior: 'smooth', block: 'center' }); }
                    }, 100);
                }
            });
        });

        // [1.6.118.24] Filtros do chat — filtrar mensagens visíveis por autor.
        // As mensagens já têm classe rmbz-pjv2-msg--artist / --admin / --system.
        // Aplicamos CSS de hide com data-attr no contentor.
        var chatFilterBtns = document.querySelectorAll('.rmbz-pjv2-cf-btn');
        var streamEl = document.getElementById('rmbz-pjv2-stream');
        chatFilterBtns.forEach(function(b){
            b.addEventListener('click', function(){
                chatFilterBtns.forEach(function(x){ x.classList.remove('is-active'); });
                b.classList.add('is-active');
                if ( streamEl ) {
                    var f = b.dataset.filter || 'all';
                    streamEl.setAttribute('data-chat-filter', f);
                }
            });
        });

        // ── Boot ───────────────────────────────────────────────
        loadInitial();
        loadInfo();
        startPolling();
        // refrescar info a cada 30s (change log + recomendações)
        setInterval(loadInfo, 30000);
        // re-foco no input
        input.focus();
    })();
    </script>
    <?php
}

/* ============================================================================
 * [1.6.118.87] BANCO DE PESSOAS — gestor de equipa (action=team)
 * ============================================================================ */
function rmbz_pjv2_render_team_manager() {
    if ( ! current_user_can( 'manage_options' ) ) { wp_die( 'Sem permissão.' ); }
    rmbz_projects_v2_styles();
    wp_enqueue_media(); // para o selector de foto

    $editing = ( isset( $_GET['member'] ) && absint( $_GET['member'] ) > 0 )
        ? rmbz_team_get( absint( $_GET['member'] ) ) : null;
    $members  = function_exists( 'rmbz_team_get_all' ) ? rmbz_team_get_all( false ) : [];
    $back_url = admin_url( 'admin.php?page=rmbz-projetos' );
    $self_url = admin_url( 'admin.php?page=rmbz-projetos&action=team' );

    // valores do form (edição ou vazios)
    $v = [
        'name' => $editing->name ?? '', 'department' => $editing->department ?? '', 'origin' => $editing->origin ?? '1mz', 'role' => $editing->role ?? '',
        'specialty' => $editing->specialty ?? '', 'bio' => $editing->bio ?? '',
        'photo_url' => $editing->photo_url ?? '',
        'contact_phone' => $editing->contact_phone ?? '', 'contact_email' => $editing->contact_email ?? '',
    ];
    $socials = [];
    if ( $editing && ! empty( $editing->socials ) ) {
        $dec = json_decode( $editing->socials, true );
        if ( is_array( $dec ) ) $socials = $dec;
    }
    ?>
    <style>
    /* [1.5.408] Equipas & Pessoas — M3 Expressive */
    .rmbz-tp-tabs{ display:inline-flex; background:#f3f1f9; border-radius:99px; padding:4px; gap:4px; margin:12px 0 16px; }
    .rmbz-tp-tabs a{ padding:9px 20px; font-weight:700; font-size:13px; text-decoration:none; color:#57536a; border-radius:99px; }
    .rmbz-tp-tabs a.is-on{ background:#fff; color:#3d2a66; box-shadow:0 1px 4px rgba(26,18,54,.18); }
    .rmbz-tp-card{ background:#fff; border:1px solid #e8e6ef; border-radius:22px; padding:20px; box-shadow:0 1px 3px rgba(26,18,54,.06); }
    .rmbz-tp-card h2{ margin:0 0 4px; font-size:16px; font-weight:800; color:#1a1a20; letter-spacing:-.01em; }
    .rmbz-tp-label{ display:block; font-size:11px; font-weight:800; color:#5b3e70; letter-spacing:.7px; text-transform:uppercase; margin:14px 0 6px; }
    .rmbz-tp-input, .rmbz-tp-card input[type=text], .rmbz-tp-card input[type=url], .rmbz-tp-card input[type=email], .rmbz-tp-card input[type=number], .rmbz-tp-card textarea{
        border:1px solid #d9d2e8 !important; border-radius:12px !important; padding:9px 14px !important;
        font-size:13px !important; background:#fff !important; box-shadow:none !important; width:100%;
    }
    .rmbz-tp-card input:focus, .rmbz-tp-card textarea:focus{ border-color:#7b5bd6 !important; box-shadow:0 0 0 3px rgba(123,91,214,.15) !important; outline:none; }
    .rmbz-tp-btn{ border:0; border-radius:99px; padding:11px 24px; font-size:13px; font-weight:800; cursor:pointer; transition:filter .15s; }
    .rmbz-tp-btn:hover{ filter:brightness(1.06); }
    .rmbz-tp-btn--primary{ background:#3d2a66; color:#fff; box-shadow:0 5px 14px -5px rgba(61,42,102,.5); }
    .rmbz-tp-btn--ghost{ background:#eeebf7; color:#1a1a20; text-decoration:none; display:inline-block; }
    .rmbz-tp-origin{ display:flex; gap:8px; }
    .rmbz-tp-origin label{ flex:1; display:flex; align-items:center; gap:8px; border:1.5px solid #e8e6ef; background:#fff; border-radius:14px; padding:10px 14px; cursor:pointer; font-size:13px; font-weight:600; transition:all .15s; }
    .rmbz-tp-origin label:has(input:checked){ border-color:#34a853; background:#f2faf5; }
    .rmbz-tp-origin label.ext:has(input:checked){ border-color:#f0b90b; background:#fdf6e3; }
    /* Chips de cargos (multi-seleção) agrupados por departamento */
    .rmbz-tp-dept{ margin-bottom:10px; }
    .rmbz-tp-dept > b{ display:flex; align-items:center; gap:6px; font-size:12px; color:#1a1a20; margin-bottom:6px; }
    .rmbz-tp-dept > b i{ width:8px; height:8px; border-radius:50%; display:inline-block; font-style:normal; }
    .rmbz-tp-chips{ display:flex; flex-wrap:wrap; gap:6px; }
    .rmbz-tp-chip{ display:inline-flex; align-items:center; gap:5px; border:1.5px solid #e2ddf0; background:#faf9fd; border-radius:99px; padding:5px 13px; font-size:12px; font-weight:600; color:#57536a; cursor:pointer; transition:all .12s; user-select:none; }
    .rmbz-tp-chip input{ display:none; }
    .rmbz-tp-chip:has(input:checked){ background:#ece5fb; border-color:#7b5bd6; color:#3d2a66; }
    .rmbz-tp-chip:has(input:checked)::before{ content:"✓ "; font-weight:900; }
    .rmbz-tp-count{ background:#ece5fb; color:#3d2a66; font-size:11px; font-weight:800; border-radius:99px; padding:3px 10px; }
    /* Cartão de pessoa */
    .rmbz-tp-person{ background:#fff; border:1px solid #e8e6ef; border-radius:20px; padding:18px 16px; text-align:center; box-shadow:0 1px 3px rgba(26,18,54,.05); }
    .rmbz-tp-person .rolepills{ display:flex; flex-wrap:wrap; gap:4px; justify-content:center; margin-top:6px; }
    .rmbz-tp-person .rolepills span{ background:#fdf3d7; color:#92400e; font-size:10px; font-weight:800; border-radius:99px; padding:3px 10px; }
    .rmbz-tp-note{ font-size:12px; color:#92400e; background:#fdf6e3; border:1px solid #efd9a0; padding:9px 13px; border-radius:12px; }
    </style>
    <div class="rmbz-admin-wrap" style="padding:20px;">
        <h1 style="margin-bottom:4px;">🎥 Projetos & Videoclipes</h1>
        <?php
        $tab_projetos = admin_url( 'admin.php?page=rmbz-projetos' );
        $tab_equipas  = admin_url( 'admin.php?page=rmbz-projetos&action=team' );
        ?>
        <div class="rmbz-tp-tabs">
            <a href="<?php echo esc_url( $tab_projetos ); ?>">📁 Projetos</a>
            <a href="<?php echo esc_url( $tab_equipas ); ?>" class="is-on">🎥 Equipas &amp; Pessoas</a>
        </div>
        <p style="color:#5f6368; margin-top:0;">Cria pessoas uma vez e atribui-as aos projectos. O artista vê tudo menos o contacto.</p>

        <?php // [1.5.412] Resultado do PIN do portal da equipa. ?>
        <?php if ( isset( $_GET['pin_error'] ) ): ?>
            <div class="rmbz-tp-note" style="margin-bottom:14px; background:#fdf1f0; border-color:#f6cbc8; color:#8c1d18;">
                ❌ PIN não guardado: <?php echo esc_html( sanitize_text_field( wp_unslash( $_GET['pin_error'] ) ) ); ?> (os restantes dados foram guardados)
            </div>
        <?php elseif ( isset( $_GET['pin_set'] ) ): ?>
            <div class="rmbz-tp-note" style="margin-bottom:14px; background:#e6f4ea; border-color:#b7e1c3; color:#137333;">
                🔑 PIN inicial definido — entrega-o à pessoa em privado; ela troca no primeiro login ao Portal da Equipa.
            </div>
        <?php endif; ?>

        <div style="display:flex; gap:24px; flex-wrap:wrap; align-items:flex-start;">
            <!-- Formulário -->
            <div style="flex:1; min-width:320px;" class="rmbz-tp-card">
                <h2><?php echo $editing ? '✏️ Editar pessoa' : '➕ Nova pessoa'; ?></h2>
                <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>">
                    <input type="hidden" name="action" value="rmbz_team_save_member">
                    <?php wp_nonce_field( 'rmbz_team_save_member_nonce' ); ?>
                    <?php if ( $editing ): ?><input type="hidden" name="member_id" value="<?php echo (int) $editing->id; ?>"><?php endif; ?>

                    <div class="rmbz-pjv2-field" style="margin-bottom:12px;">
                        <label>Foto</label>
                        <div style="display:flex; align-items:center; gap:12px;">
                            <img id="rmbz-team-photo-preview" src="<?php echo esc_url( $v['photo_url'] ); ?>"
                                 style="width:64px; height:64px; border-radius:50%; object-fit:cover; background:#e8eaed; <?php echo $v['photo_url'] ? '' : 'display:none;'; ?>">
                            <input type="hidden" id="rmbz-team-photo-url" name="photo_url" value="<?php echo esc_attr( $v['photo_url'] ); ?>">
                            <button type="button" class="button" id="rmbz-team-photo-btn">Escolher foto</button>
                            <button type="button" class="button" id="rmbz-team-photo-clear" style="<?php echo $v['photo_url'] ? '' : 'display:none;'; ?>">Remover</button>
                        </div>
                    </div>

                    <label class="rmbz-tp-label">Nome *</label>
                    <input type="text" name="name" required value="<?php echo esc_attr( $v['name'] ); ?>">

                    <label class="rmbz-tp-label">Origem da pessoa</label>
                    <div class="rmbz-tp-origin">
                        <label>
                            <input type="radio" name="origin" value="1mz" <?php checked( $v['origin'] !== 'externo' ); ?> style="margin:0;">
                            ✅ Da 1MZ (oficial)
                        </label>
                        <label class="ext">
                            <input type="radio" name="origin" value="externo" <?php checked( $v['origin'] === 'externo' ); ?> style="margin:0;">
                            🌐 Externo (fora da 1MZ)
                        </label>
                    </div>
                    <p style="font-size:11px; color:#7a7688; margin:6px 0 0;">Pessoas externas geram avisos no projecto e podem ter taxa de vistoria se pedidas pelo artista.</p>

                    <?php
                    // [1.5.408] MÚLTIPLOS CARGOS — a mesma pessoa pode ser Editor,
                    // Realizador, etc. Chips por departamento + campo livre.
                    $depts = rmbz_team_departments();
                    // Cargos atuais da pessoa (separados por " · " — formato novo)
                    // ou o cargo único antigo. Marcamos os chips que baterem com o
                    // catálogo; o resto vai para o campo livre.
                    $cur_roles = array_filter( array_map( 'trim', explode( '·', (string) $v['role'] ) ) );
                    $catalog_flat = [];
                    foreach ( $depts as $dkey => $d ) {
                        foreach ( $d['roles'] as $r ) $catalog_flat[ $r ] = $dkey;
                    }
                    $free_roles = array_values( array_filter( $cur_roles, fn( $r ) => ! isset( $catalog_flat[ $r ] ) ) );
                    ?>
                    <label class="rmbz-tp-label" style="display:flex; align-items:center; gap:8px;">
                        Cargos / Funções
                        <span class="rmbz-tp-count" id="rmbz-tp-role-count"><?php echo count( $cur_roles ); ?> selecionado(s)</span>
                        <span style="font-weight:400; text-transform:none; letter-spacing:0; color:#7a7688;">— a mesma pessoa pode exercer vários (ex.: Editor + Realizador)</span>
                    </label>
                    <div style="max-height:260px; overflow-y:auto; border:1px solid #ece8f5; border-radius:16px; padding:12px; background:#fcfbfe;">
                        <?php foreach ( $depts as $dkey => $d ): if ( empty( $d['roles'] ) ) continue; ?>
                            <div class="rmbz-tp-dept">
                                <b><i style="background:<?php echo esc_attr( $d['color'] ); ?>;"></i><?php echo esc_html( $d['icon'] . ' ' . $d['label'] ); ?></b>
                                <div class="rmbz-tp-chips">
                                    <?php foreach ( $d['roles'] as $r ): ?>
                                        <label class="rmbz-tp-chip">
                                            <input type="checkbox" name="roles[]" value="<?php echo esc_attr( $dkey . '|' . $r ); ?>"
                                                   <?php checked( in_array( $r, $cur_roles, true ) ); ?>
                                                   onchange="rmbzTpCount();">
                                            <?php echo esc_html( $r ); ?>
                                        </label>
                                    <?php endforeach; ?>
                                </div>
                            </div>
                        <?php endforeach; ?>
                    </div>
                    <label class="rmbz-tp-label">Outros cargos (separados por vírgula)</label>
                    <input type="text" name="roles_free" value="<?php echo esc_attr( implode( ', ', $free_roles ) ); ?>" placeholder="Ex.: Coreógrafo, Making-of" oninput="rmbzTpCount();">
                    <script>
                    function rmbzTpCount(){
                        var n = document.querySelectorAll('input[name="roles[]"]:checked').length;
                        var free = (document.querySelector('input[name="roles_free"]').value || '').split(',').filter(function(s){ return s.trim() !== ''; }).length;
                        var el = document.getElementById('rmbz-tp-role-count');
                        if (el) el.textContent = (n + free) + ' selecionado(s)';
                    }
                    </script>

                    <label class="rmbz-tp-label">Especialidade</label>
                    <input type="text" name="specialty" value="<?php echo esc_attr( $v['specialty'] ); ?>" placeholder="Videoclipes, cor…">
                    <label class="rmbz-tp-label">Bio curta</label>
                    <textarea name="bio" rows="2" placeholder="Uma ou duas frases…"><?php echo esc_textarea( $v['bio'] ); ?></textarea>
                    <div style="display:flex; gap:10px;">
                        <div style="flex:1;">
                            <label class="rmbz-tp-label">Instagram</label>
                            <input type="url" name="socials[instagram]" value="<?php echo esc_attr( $socials['instagram'] ?? '' ); ?>" placeholder="https://instagram.com/…">
                        </div>
                        <div style="flex:1;">
                            <label class="rmbz-tp-label">Outra rede (URL)</label>
                            <input type="url" name="socials[other]" value="<?php echo esc_attr( $socials['other'] ?? '' ); ?>" placeholder="https://…">
                        </div>
                    </div>
                    <div class="rmbz-tp-note" style="margin-top:16px;">🔒 Contacto — só visível ao admin, nunca enviado ao artista.</div>
                    <div style="display:flex; gap:10px;">
                        <div style="flex:1;">
                            <label class="rmbz-tp-label">Telefone</label>
                            <input type="text" name="contact_phone" value="<?php echo esc_attr( $v['contact_phone'] ); ?>">
                        </div>
                        <div style="flex:1;">
                            <label class="rmbz-tp-label">Email</label>
                            <input type="email" name="contact_email" value="<?php echo esc_attr( $v['contact_email'] ); ?>">
                        </div>
                    </div>

                    <?php
                    // [1.5.412] PORTAL DA EQUIPA — o membro entra no site
                    // (minha-conta) com o TELEFONE acima + este PIN inicial.
                    // No primeiro login é obrigado a definir um PIN novo.
                    $tp_has_pin  = $editing && ! empty( $editing->pin_hash );
                    $tp_must     = $editing && ! empty( $editing->pin_must_change );
                    $tp_last     = $editing->last_login_at ?? '';
                    ?>
                    <div class="rmbz-tp-note" style="margin-top:14px; background:#ece5fb; border-color:#d9d2e8; color:#3d2a66;">
                        🎬 Acesso ao <b>Portal da Equipa</b> (login no site com o telefone acima)
                        <?php if ( $tp_has_pin ): ?>
                            — <b><?php echo $tp_must ? '🔑 PIN inicial definido (vai trocar ao entrar)' : '✅ ativo (já definiu o PIN dele)'; ?></b>
                            <?php if ( $tp_last ): ?><span style="font-weight:400;">· último login: <?php echo esc_html( $tp_last ); ?></span><?php endif; ?>
                        <?php else: ?>
                            — <b>sem acesso</b> (define um PIN inicial para ativar)
                        <?php endif; ?>
                    </div>
                    <label class="rmbz-tp-label"><?php echo $tp_has_pin ? 'Repor PIN (deixa vazio para manter)' : 'PIN inicial (4–8 dígitos)'; ?></label>
                    <input type="text" name="access_pin" value="" inputmode="numeric" pattern="\d{4,8}" maxlength="8"
                           placeholder="<?php echo $tp_has_pin ? '••••  (só se quiseres repor)' : 'Ex.: 2468'; ?>" autocomplete="off">
                    <p style="font-size:11px; color:#7a7688; margin:6px 0 0;">
                        Entrega este PIN à pessoa em privado. Ao entrar pela primeira vez (ou depois de repores), ela é obrigada a definir um PIN novo só dela.
                    </p>

                    <div style="display:flex; gap:10px; margin-top:18px;">
                        <button type="submit" class="rmbz-tp-btn rmbz-tp-btn--primary"><?php echo $editing ? '💾 Guardar alterações' : '➕ Adicionar pessoa'; ?></button>
                        <?php if ( $editing ): ?>
                            <a href="<?php echo esc_url( $self_url ); ?>" class="rmbz-tp-btn rmbz-tp-btn--ghost">Cancelar</a>
                        <?php endif; ?>
                    </div>
                </form>
            </div>

            <!-- Dashboard de cartões -->
            <div style="flex:1.2; min-width:340px;">
                <?php
                // [1.6.118.98] Painel de configuração de requisitos
                $req_depts = function_exists( 'rmbz_team_required_departments' ) ? rmbz_team_required_departments() : [];
                $fee_val   = function_exists( 'rmbz_team_inspection_fee' ) ? rmbz_team_inspection_fee() : 1500;
                $all_depts = rmbz_team_departments();
                // [1.6.118.102] Taxas por departamento guardadas
                $fee_by_dept = get_option( 'rmbz_team_inspection_fee_by_dept', [] );
                if ( ! is_array( $fee_by_dept ) ) $fee_by_dept = [];
                ?>
                <details class="rmbz-tp-card" style="padding:16px 18px; margin-bottom:18px;">
                    <summary style="cursor:pointer; font-weight:800; font-size:14px; color:#1a1a20;">⚙️ Requisitos do projecto (cargos obrigatórios + taxas)</summary>
                    <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>" style="margin-top:14px;">
                        <input type="hidden" name="action" value="rmbz_team_save_config">
                        <?php wp_nonce_field( 'rmbz_team_save_config_nonce' ); ?>

                        <label class="rmbz-tp-label" style="margin-top:0;">Departamentos obrigatórios</label>
                        <p style="font-size:12px; color:#7a7688; margin:0 0 8px;">Marca os que TÊM de estar presentes para um projecto poder avançar para filmagens.</p>
                        <div class="rmbz-tp-chips" style="margin-bottom:16px;">
                            <?php foreach ( $all_depts as $dkey => $d ):
                                if ( $dkey === 'outro' ) continue;
                                $on = in_array( $dkey, $req_depts, true );
                            ?>
                                <label class="rmbz-tp-chip">
                                    <input type="checkbox" name="required_depts[]" value="<?php echo esc_attr( $dkey ); ?>" <?php checked( $on ); ?>>
                                    <?php echo esc_html( $d['icon'] . ' ' . $d['label'] ); ?>
                                </label>
                            <?php endforeach; ?>
                        </div>

                        <label class="rmbz-tp-label">💰 Taxa de vistoria base</label>
                        <div style="display:flex; align-items:center; gap:8px; margin-bottom:14px;">
                            <input type="number" name="inspection_fee" value="<?php echo esc_attr( $fee_val ); ?>" min="0" step="50" style="width:130px !important; text-align:right;">
                            <span style="font-size:13px; color:#7a7688; font-weight:700;">MT</span>
                        </div>

                        <label class="rmbz-tp-label">Taxa por departamento (opcional)</label>
                        <p style="font-size:12px; color:#7a7688; margin:0 0 8px;">Deixa vazio para usar a taxa base. Útil porque vistoriar um editor dá trabalho diferente de um modelo.</p>
                        <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(240px, 1fr)); gap:8px; margin-bottom:16px;">
                            <?php foreach ( $all_depts as $dkey => $d ):
                                if ( $dkey === 'outro' ) continue;
                                $dv = isset( $fee_by_dept[ $dkey ] ) ? $fee_by_dept[ $dkey ] : '';
                            ?>
                                <div style="display:flex; align-items:center; gap:8px; font-size:12px; background:#faf9fd; border:1px solid #ece8f5; border-radius:14px; padding:8px 12px;">
                                    <span style="flex:1; color:#57536a; font-weight:600;"><?php echo esc_html( $d['icon'] . ' ' . $d['label'] ); ?></span>
                                    <input type="number" name="fee_by_dept[<?php echo esc_attr( $dkey ); ?>]" value="<?php echo esc_attr( $dv ); ?>" min="0" step="50" placeholder="base"
                                           style="width:90px !important; text-align:right; min-height:32px; padding:5px 10px !important;">
                                    <span style="color:#9aa0a6; font-weight:700;">MT</span>
                                </div>
                            <?php endforeach; ?>
                        </div>
                        <button type="submit" class="rmbz-tp-btn rmbz-tp-btn--primary">💾 Guardar requisitos</button>
                    </form>
                </details>

                <h2 style="font-size:16px; font-weight:800; color:#1a1a20; display:flex; align-items:center; gap:10px;">
                    Pessoas <span class="rmbz-tp-count"><?php echo count( array_filter( $members, fn($m)=>$m->is_active==1 ) ); ?> activas</span>
                </h2>
                <?php if ( empty( $members ) ): ?>
                    <p style="color:#5f6368;">Ainda não há pessoas. Adiciona a primeira no formulário ao lado.</p>
                <?php else: ?>
                    <?php
                    // [1.6.118.90] Agrupar membros activos por departamento.
                    $depts_meta = rmbz_team_departments();
                    $grouped = [];
                    foreach ( $members as $m ) {
                        if ( $m->is_active != 1 ) continue;
                        $dk = $m->department && isset( $depts_meta[ $m->department ] ) ? $m->department : 'outro';
                        $grouped[ $dk ][] = $m;
                    }
                    // Mostrar departamentos pela ordem do catálogo
                    foreach ( $depts_meta as $dkey => $dmeta ):
                        if ( empty( $grouped[ $dkey ] ) ) continue;
                    ?>
                        <div style="margin-bottom:22px;">
                            <h3 style="font-size:14px; color:<?php echo esc_attr( $dmeta['color'] ); ?>; border-left:4px solid <?php echo esc_attr( $dmeta['color'] ); ?>; padding-left:10px; margin:0 0 12px;">
                                <?php echo esc_html( $dmeta['icon'] . '  ' . $dmeta['label'] ); ?>
                                <span style="color:#9aa0a6; font-weight:400;">(<?php echo count( $grouped[ $dkey ] ); ?>)</span>
                            </h3>
                            <div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(210px, 1fr)); gap:14px;">
                                <?php foreach ( $grouped[ $dkey ] as $m ):
                                    $stats    = function_exists( 'rmbz_team_with_stats' ) ? rmbz_team_with_stats( $m ) : [ 'projects' => 0, 'rating_avg' => 0, 'rating_count' => 0 ];
                                    $edit_url = add_query_arg( 'member', (int) $m->id, $self_url );
                                    $del_url  = wp_nonce_url( admin_url( 'admin-post.php?action=rmbz_team_delete_member&member_id=' . (int) $m->id ), 'rmbz_team_delete_' . (int) $m->id );
                                    $avg      = (float) $stats['rating_avg'];
                        ?>
                            <div class="rmbz-tp-person">
                                <?php if ( ! empty( $m->photo_url ) ): ?>
                                    <img src="<?php echo esc_url( $m->photo_url ); ?>" style="width:76px; height:76px; border-radius:50%; object-fit:cover; margin:0 auto 10px; display:block; box-shadow:0 0 0 4px <?php echo esc_attr( $dmeta['color'] ); ?>22;">
                                <?php else: ?>
                                    <span style="width:76px; height:76px; border-radius:50%; background:linear-gradient(135deg,#f0b90b,#d4960a); color:#fff; display:flex; align-items:center; justify-content:center; font-size:28px; font-weight:800; margin:0 auto 10px;"><?php echo esc_html( mb_strtoupper( mb_substr( $m->name, 0, 1 ) ) ); ?></span>
                                <?php endif; ?>

                                <div style="font-size:15px; font-weight:800; color:#1a1a20; letter-spacing:-.01em;"><?php echo esc_html( $m->name ); ?>
                                    <?php if ( isset( $m->origin ) && $m->origin === 'externo' ): ?>
                                        <span style="background:#fdf6e3; color:#92400e; font-size:9px; font-weight:800; padding:2px 8px; border-radius:99px; vertical-align:2px;">🌐</span>
                                    <?php endif; ?>
                                </div>
                                <?php if ( ! empty( $m->role ) ): ?>
                                    <?php $m_roles = array_filter( array_map( 'trim', explode( '·', (string) $m->role ) ) ); ?>
                                    <div class="rolepills">
                                        <?php foreach ( $m_roles as $mr ): ?><span><?php echo esc_html( $mr ); ?></span><?php endforeach; ?>
                                    </div>
                                <?php endif; ?>
                                <?php if ( ! empty( $m->specialty ) ): ?>
                                    <div style="font-size:11px; color:#7a7688; margin-top:5px;"><?php echo esc_html( $m->specialty ); ?></div>
                                <?php endif; ?>

                                <!-- Estrelas (média) -->
                                <div style="margin:10px 0 4px; font-size:14px; letter-spacing:1px;">
                                    <?php
                                    for ( $s = 1; $s <= 5; $s++ ) {
                                        $on = $avg >= ( $s - 0.25 );
                                        echo '<span style="color:' . ( $on ? '#f0b90b' : '#e2ddf0' ) . ';">★</span>';
                                    }
                                    ?>
                                </div>
                                <div style="font-size:11px; color:#7a7688;">
                                    <?php if ( $stats['rating_count'] > 0 ): ?>
                                        <?php echo esc_html( number_format( $avg, 1 ) ); ?> · <?php echo (int) $stats['rating_count']; ?> avaliação(ões)
                                    <?php else: ?>
                                        Sem avaliações ainda
                                    <?php endif; ?>
                                </div>

                                <!-- Nº de trabalhos -->
                                <div style="margin-top:12px; padding-top:12px; border-top:1px solid #f0edf6;">
                                    <span style="font-size:22px; font-weight:900; color:#1a1a20;"><?php echo (int) $stats['projects']; ?></span>
                                    <span style="font-size:11px; color:#7a7688; display:block;">trabalho<?php echo $stats['projects'] == 1 ? '' : 's'; ?> em que participou</span>
                                </div>

                                <div style="display:flex; gap:8px; justify-content:center; margin-top:14px;">
                                    <a href="<?php echo esc_url( $edit_url ); ?>" class="rmbz-tp-btn rmbz-tp-btn--ghost" style="padding:7px 18px; font-size:12px;">✏️ Editar</a>
                                    <a href="<?php echo esc_url( $del_url ); ?>" class="rmbz-tp-btn" style="padding:7px 18px; font-size:12px; background:#fdf1f0; color:#8c1d18; text-decoration:none;" onclick="return confirm('Remover <?php echo esc_js( $m->name ); ?> do banco? (projectos antigos mantêm o histórico)');">Remover</a>
                                </div>
                            </div>
                        <?php endforeach; ?>
                            </div>
                        </div>
                    <?php endforeach; /* departamentos */ ?>
                <?php endif; ?>
            </div>
        </div>
    </div>

    <script>
    (function(){
        var btn = document.getElementById('rmbz-team-photo-btn');
        var clearBtn = document.getElementById('rmbz-team-photo-clear');
        var urlInput = document.getElementById('rmbz-team-photo-url');
        var preview = document.getElementById('rmbz-team-photo-preview');
        var frame;
        if (btn) btn.addEventListener('click', function(e){
            e.preventDefault();
            if (frame) { frame.open(); return; }
            frame = wp.media({ title:'Escolher foto', button:{text:'Usar esta foto'}, multiple:false });
            frame.on('select', function(){
                var att = frame.state().get('selection').first().toJSON();
                urlInput.value = att.url;
                preview.src = att.url; preview.style.display = '';
                clearBtn.style.display = '';
            });
            frame.open();
        });
        if (clearBtn) clearBtn.addEventListener('click', function(e){
            e.preventDefault();
            urlInput.value = ''; preview.src=''; preview.style.display='none';
            clearBtn.style.display='none';
        });
    })();
    </script>
    <?php
}
