<?php
declare(strict_types=1);

if (!isset($tags) || !is_array($tags)) {
    try {
        $tags = db()->query('SELECT id, name FROM tags ORDER BY name')->fetchAll();
    } catch (Throwable $e) {
        $tags = [];
    }
}

try {
    $stmtContactTags = db()->prepare("
        SELECT t.id, t.name
        FROM contact_tags ct
        INNER JOIN tags t ON t.id = ct.tag_id
        WHERE ct.contact_id = :contact_id
        ORDER BY t.name
    ");
    $stmtContactTags->execute([
        'contact_id' => (int)($contact['id'] ?? 0),
    ]);
    $contactTags = $stmtContactTags->fetchAll();
} catch (Throwable $e) {
    $contactTags = [];
}

try {
    $pipelines = db()->query('SELECT id, name FROM pipelines ORDER BY name')->fetchAll();
} catch (Throwable $e) {
    $pipelines = [];
}

$pipelineStagesMap = [];
try {
    $pipelineStagesRows = db()->query('
        SELECT id, pipeline_id, name, stage_order
        FROM pipeline_stages
        ORDER BY pipeline_id ASC, stage_order ASC, id ASC
    ')->fetchAll();

    foreach ($pipelineStagesRows as $row) {
        $pid = (int)$row['pipeline_id'];
        if (!isset($pipelineStagesMap[$pid])) {
            $pipelineStagesMap[$pid] = [];
        }

        $pipelineStagesMap[$pid][] = [
            'id' => (int)$row['id'],
            'name' => (string)$row['name'],
            'stage_order' => (int)$row['stage_order'],
        ];
    }
} catch (Throwable $e) {
    $pipelineStagesMap = [];
}

$contactTagIds = array_map(static fn(array $row): int => (int)$row['id'], $contactTags);

$contactName = (string)($contact['full_name'] ?? ('Contato #' . (int)($contact['id'] ?? 0)));
$contactPhone = trim((string)($contact['phone'] ?? '-'));
$contactEmail = trim((string)($contact['email'] ?? ''));
$contactCompany = trim((string)($contact['company'] ?? ''));
$contactPosition = trim((string)($contact['job_title'] ?? ''));
$contactObs = trim((string)($contact['notes'] ?? ''));

$normalizeWaPhone = static function (string $phone): string {
    $digits = preg_replace('/\D+/', '', $phone);
    if ($digits === '') {
        return '';
    }

    if (!str_starts_with($digits, '55') && (strlen($digits) === 10 || strlen($digits) === 11)) {
        $digits = '55' . $digits;
    }

    return $digits;
};

$waPhone = $normalizeWaPhone($contactPhone);
$waExternalLink = $waPhone !== '' ? ('https://wa.me/' . $waPhone) : '';

$formatBytes = static function ($bytes): string {
    $bytes = (int)$bytes;
    if ($bytes <= 0) {
        return '';
    }

    $units = ['B', 'KB', 'MB', 'GB'];
    $power = (int)floor(log($bytes, 1024));
    $power = max(0, min($power, count($units) - 1));

    $value = $bytes / (1024 ** $power);
    return number_format($value, $power === 0 ? 0 : 1, ',', '.') . ' ' . $units[$power];
};

$mediaToneClass = static function (string $mediaType, string $extension): string {
    $mediaType = strtolower(trim($mediaType));
    $extension = strtolower(trim($extension));

    if ($mediaType === 'image') return 'is-image';
    if ($mediaType === 'video') return 'is-video';
    if ($mediaType === 'audio') return 'is-audio';

    return match ($extension) {
        'pdf' => 'is-pdf',
        'doc', 'docx' => 'is-doc',
        'xls', 'xlsx', 'csv' => 'is-sheet',
        'ppt', 'pptx' => 'is-slide',
        'zip', 'rar' => 'is-archive',
        default => 'is-file',
    };
};

$mediaKindLabel = static function (string $mediaType): string {
    return match (strtolower(trim($mediaType))) {
        'image' => 'Imagem',
        'video' => 'Vídeo',
        'audio' => 'Áudio',
        default => 'Documento',
    };
};

$replyPreviewLabel = static function (array $msg): string {
    $text = trim((string)($msg['reply_body'] ?? ''));
    if ($text !== '') {
        return $text;
    }

    $mediaType = trim((string)($msg['reply_media_type'] ?? ''));
    $mediaName = trim((string)($msg['reply_media_file_name'] ?? ''));

    if ($mediaName !== '') {
        return $mediaName;
    }

    return match (strtolower($mediaType)) {
        'image' => '[Imagem]',
        'video' => '[Vídeo]',
        'audio' => '[Áudio]',
        'document' => '[Documento]',
        default => '',
    };
};

$mediaIconSvg = static function (string $mediaType, string $extension = ''): string {
    $mediaType = strtolower(trim($mediaType));
    $extension = strtolower(trim($extension));

    if ($mediaType === 'image') {
        return <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <rect x="4" y="5" width="16" height="14" rx="3" stroke="currentColor" stroke-width="1.8"/>
  <circle cx="9" cy="10" r="1.5" fill="currentColor"/>
  <path d="m7 16 3.4-3.2a1 1 0 0 1 1.4 0l1.7 1.5 1.8-1.8a1 1 0 0 1 1.4 0L18 14v2H7Z" fill="currentColor"/>
</svg>
SVG;
    }

    if ($mediaType === 'video') {
        return <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <rect x="4" y="5.5" width="12.5" height="13" rx="2.8" stroke="currentColor" stroke-width="1.8"/>
  <path d="m18.5 9-3.5 2.2v1.6l3.5 2.2V9Z" fill="currentColor"/>
  <path d="M9.3 9.5 13 12l-3.7 2.5v-5Z" fill="currentColor"/>
</svg>
SVG;
    }

    if ($mediaType === 'audio') {
        return <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M14 5v10.2" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
  <path d="M14 5 9 6.7v8.1" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
  <circle cx="9" cy="17" r="2.2" stroke="currentColor" stroke-width="1.8"/>
  <circle cx="14" cy="15.2" r="2.2" stroke="currentColor" stroke-width="1.8"/>
</svg>
SVG;
    }

    if (in_array($extension, ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'csv', 'ppt', 'pptx', 'zip', 'rar'], true)) {
        return <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M7 4.8A1.8 1.8 0 0 1 8.8 3h5.8L19 7.4v10.8A1.8 1.8 0 0 1 17.2 20H8.8A1.8 1.8 0 0 1 7 18.2V4.8Z" stroke="currentColor" stroke-width="1.8"/>
  <path d="M14.5 3.4V8H19" stroke="currentColor" stroke-width="1.8"/>
  <path d="M9 13h6M9 16h4.2" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
</svg>
SVG;
    }

    return <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M7 4.8A1.8 1.8 0 0 1 8.8 3h5.8L19 7.4v10.8A1.8 1.8 0 0 1 17.2 20H8.8A1.8 1.8 0 0 1 7 18.2V4.8Z" stroke="currentColor" stroke-width="1.8"/>
  <path d="M14.5 3.4V8H19" stroke="currentColor" stroke-width="1.8"/>
  <path d="M9 13h6M9 16h4.2" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/>
</svg>
SVG;
};

$iconEyeSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M2.8 12s3.2-5.6 9.2-5.6 9.2 5.6 9.2 5.6-3.2 5.6-9.2 5.6S2.8 12 2.8 12Z" stroke="currentColor" stroke-width="1.8"/>
  <circle cx="12" cy="12" r="2.7" stroke="currentColor" stroke-width="1.8"/>
</svg>
SVG;

$iconDownloadSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M12 4.5v9.3" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
  <path d="m8.3 10.7 3.7 3.8 3.7-3.8" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="M5 18.5h14" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;

$iconExpandSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M8.5 5H5v3.5M15.5 5H19v3.5M8.5 19H5v-3.5M15.5 19H19v-3.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="m9.2 9.2 5.6 5.6M14.8 9.2l-5.6 5.6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;

$iconEditSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M4 15.8V20h4.2L18.7 9.5 14.5 5.3 4 15.8Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
  <path d="m13.8 6 4.2 4.2M12.5 19H20" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;

$iconExternalSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M14 5h5v5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="M10 14 19 5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
  <path d="M19 13v4a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h4" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;

$iconTagSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M10 4H5v5l8.6 8.6a2 2 0 0 0 2.8 0l3.2-3.2a2 2 0 0 0 0-2.8L11 4Z" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round"/>
  <circle cx="7.5" cy="7.5" r="1.2" fill="currentColor"/>
</svg>
SVG;

$iconReplySvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="M9 8 4.5 12 9 16" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
  <path d="M5 12h7.5c3.6 0 6.5 2.9 6.5 6.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;

$iconCopySvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <rect x="9" y="9" width="10" height="10" rx="2" stroke="currentColor" stroke-width="1.8"/>
  <path d="M7 15H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h7a2 2 0 0 1 2 2v1" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;

$iconCloseSvg = <<<SVG
<svg viewBox="0 0 24 24" aria-hidden="true" fill="none">
  <path d="m7 7 10 10M17 7 7 17" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
</svg>
SVG;
?>

<style>
  .wa-page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 12px;
  }

  .wa-page-title {
    margin: 0;
    font-size: 18px;
    font-weight: 900;
    letter-spacing: -.02em;
  }

  .wa-page-subtitle {
    margin: 4px 0 0;
    color: rgba(255,255,255,.72);
    font-size: 13px;
  }

  .wa-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 18px;
    align-items: start;
  }

  .wa-chat-shell,
  .wa-side-card {
    border-radius: 24px;
    border: 1px solid rgba(255,255,255,.06);
    background:
      linear-gradient(180deg, rgba(255,255,255,.02), rgba(255,255,255,.01)),
      rgba(8,12,26,.92);
    box-shadow: 0 22px 60px rgba(0,0,0,.28);
    overflow: hidden;
  }

  .wa-chat-shell {
    display: flex;
    flex-direction: column;
    height: calc(100vh - 88px);
    min-height: 760px;
  }

  .wa-side-card {
    padding: 16px;
    position: sticky;
    top: 14px;
    max-height: calc(100vh - 88px);
    overflow-y: auto;
  }

  .wa-chat-topbar {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border-bottom: 1px solid rgba(255,255,255,.06);
    background: rgba(255,255,255,.02);
    flex: 0 0 auto;
  }

  .wa-chat-avatar,
  .wa-side-avatar {
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: 900;
    color: #08101b;
    background: linear-gradient(180deg, #d8ef49, #bfdc24);
    box-shadow: 0 10px 20px rgba(198,223,32,.18);
  }

  .wa-chat-avatar {
    width: 46px;
    height: 46px;
    font-size: 17px;
    flex: 0 0 46px;
  }

  .wa-side-avatar {
    width: 54px;
    height: 54px;
    font-size: 18px;
    flex: 0 0 54px;
  }

  .wa-chat-contact {
    min-width: 0;
    flex: 1;
  }

  .wa-chat-contact-name {
    font-size: 15px;
    font-weight: 800;
    line-height: 1.2;
    word-break: break-word;
  }

  .wa-chat-contact-phone {
    font-size: 12px;
    color: rgba(255,255,255,.62);
    margin-top: 3px;
  }

  .wa-chat-body {
    padding: 16px 18px;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
    background:
      radial-gradient(circle at top left, rgba(198,223,32,.07), transparent 24%),
      linear-gradient(90deg, rgba(255,255,255,.016), rgba(255,255,255,0));
  }

  .wa-row {
    display: flex;
    margin-bottom: 14px;
  }

  .wa-row.in {
    justify-content: flex-start;
  }

  .wa-row.out {
    justify-content: flex-end;
  }

  .wa-bubble-wrap {
    display: flex;
    flex-direction: column;
    gap: 6px;
    max-width: 78%;
  }

  .wa-row.out .wa-bubble-wrap {
    align-items: flex-end;
  }

  .wa-row.in .wa-bubble-wrap {
    align-items: flex-start;
  }

  .wa-bubble {
    width: 100%;
    border-radius: 22px;
    padding: 12px 14px 11px;
    border: 1px solid rgba(255,255,255,.06);
    box-shadow: 0 10px 26px rgba(0,0,0,.14);
    position: relative;
  }

  .wa-row.in .wa-bubble {
    background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.03));
    border-top-left-radius: 10px;
  }

  .wa-row.out .wa-bubble {
    background: linear-gradient(180deg, rgba(198,223,32,.13), rgba(198,223,32,.06));
    border-color: rgba(198,223,32,.18);
    border-top-right-radius: 10px;
  }

  .wa-quoted {
    margin-bottom: 10px;
    padding: 9px 10px;
    border-radius: 14px;
    border-left: 3px solid rgba(198,223,32,.72);
    background: rgba(255,255,255,.05);
  }

  .wa-quoted__label {
    font-size: 11px;
    font-weight: 900;
    color: rgba(255,255,255,.7);
    margin-bottom: 3px;
  }

  .wa-quoted__text {
    font-size: 12px;
    line-height: 1.4;
    color: rgba(255,255,255,.88);
    white-space: pre-wrap;
    word-break: break-word;
  }

  .wa-text {
    font-size: 14px;
    line-height: 1.58;
    word-break: break-word;
    white-space: pre-wrap;
  }

  .wa-info {
    margin-top: 8px;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    font-size: 11px;
    color: rgba(255,255,255,.62);
  }

  .wa-dot {
    opacity: .5;
  }

  .wa-status {
    font-weight: 800;
  }

  .wa-bubble-actions {
    display: flex;
    gap: 8px;
    opacity: 0;
    transform: translateY(-2px);
    transition: .16s ease;
  }

  .wa-row:hover .wa-bubble-actions {
    opacity: 1;
    transform: translateY(0);
  }

  .wa-action-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 30px;
    padding: 0 10px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(255,255,255,.05);
    color: #fff;
    font-size: 12px;
    font-weight: 800;
    cursor: pointer;
  }

  .wa-action-btn:hover {
    background: rgba(255,255,255,.1);
  }

  .wa-action-btn svg {
    width: 14px;
    height: 14px;
    display: block;
  }

  .wa-media-card {
    margin-top: 4px;
    padding: 13px;
    border-radius: 18px;
    border: 1px solid rgba(255,255,255,.08);
    background: linear-gradient(180deg, rgba(255,255,255,.04), rgba(255,255,255,.02));
  }

  .wa-media-card.is-image { border-color: rgba(112,210,255,.18); background: linear-gradient(180deg, rgba(112,210,255,.10), rgba(112,210,255,.04)); }
  .wa-media-card.is-video { border-color: rgba(255,132,112,.18); background: linear-gradient(180deg, rgba(255,132,112,.10), rgba(255,132,112,.04)); }
  .wa-media-card.is-audio { border-color: rgba(179,146,255,.18); background: linear-gradient(180deg, rgba(179,146,255,.10), rgba(179,146,255,.04)); }
  .wa-media-card.is-pdf { border-color: rgba(255,96,96,.18); background: linear-gradient(180deg, rgba(255,96,96,.10), rgba(255,96,96,.04)); }
  .wa-media-card.is-doc { border-color: rgba(93,156,255,.18); background: linear-gradient(180deg, rgba(93,156,255,.10), rgba(93,156,255,.04)); }
  .wa-media-card.is-sheet { border-color: rgba(70,208,120,.18); background: linear-gradient(180deg, rgba(70,208,120,.10), rgba(70,208,120,.04)); }
  .wa-media-card.is-slide { border-color: rgba(255,178,72,.18); background: linear-gradient(180deg, rgba(255,178,72,.10), rgba(255,178,72,.04)); }

  .wa-media-head {
    display: flex;
    gap: 12px;
    align-items: center;
    min-width: 0;
  }

  .wa-media-icon {
    width: 44px;
    height: 44px;
    border-radius: 14px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 44px;
    color: #edf5ff;
    background: rgba(255,255,255,.08);
    border: 1px solid rgba(255,255,255,.10);
  }

  .wa-media-icon svg {
    width: 22px;
    height: 22px;
    display: block;
  }

  .wa-media-meta {
    min-width: 0;
    flex: 1;
  }

  .wa-media-title {
    font-size: 14px;
    font-weight: 800;
    line-height: 1.35;
    word-break: break-word;
  }

  .wa-media-sub {
    margin-top: 7px;
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    align-items: center;
  }

  .wa-badge {
    display: inline-flex;
    align-items: center;
    height: 24px;
    padding: 0 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .02em;
    background: rgba(255,255,255,.08);
    border: 1px solid rgba(255,255,255,.10);
  }

  .wa-badge.is-image { background: rgba(112,210,255,.12); border-color: rgba(112,210,255,.22); }
  .wa-badge.is-video { background: rgba(255,132,112,.12); border-color: rgba(255,132,112,.22); }
  .wa-badge.is-audio { background: rgba(179,146,255,.12); border-color: rgba(179,146,255,.22); }
  .wa-badge.is-pdf { background: rgba(255,96,96,.12); border-color: rgba(255,96,96,.22); }
  .wa-badge.is-doc { background: rgba(93,156,255,.12); border-color: rgba(93,156,255,.22); }
  .wa-badge.is-sheet { background: rgba(70,208,120,.12); border-color: rgba(70,208,120,.22); }
  .wa-badge.is-slide { background: rgba(255,178,72,.12); border-color: rgba(255,178,72,.22); }

  .wa-media-thumb-wrap,
  .wa-media-audio-wrap,
  .wa-media-video-wrap {
    margin-top: 12px;
  }

  .wa-media-thumb-link {
    display: inline-block;
    position: relative;
    overflow: hidden;
    border-radius: 18px;
    max-width: 320px;
    background: rgba(0,0,0,.18);
    border: 1px solid rgba(255,255,255,.08);
    text-decoration: none;
  }

  .wa-media-thumb {
    display: block;
    width: 100%;
    max-width: 320px;
    max-height: 280px;
    object-fit: cover;
    transition: transform .18s ease, opacity .18s ease;
  }

  .wa-media-thumb-link:hover .wa-media-thumb {
    transform: scale(1.02);
    opacity: .96;
  }

  .wa-media-thumb-overlay {
    position: absolute;
    right: 10px;
    bottom: 10px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 11px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
    color: #fff;
    background: rgba(0,0,0,.48);
    backdrop-filter: blur(8px);
    opacity: 0;
    transform: translateY(5px);
    transition: .18s ease;
  }

  .wa-media-thumb-link:hover .wa-media-thumb-overlay {
    opacity: 1;
    transform: translateY(0);
  }

  .wa-media-thumb-overlay svg {
    width: 15px;
    height: 15px;
    display: block;
  }

  .wa-media-video {
    width: 100%;
    max-width: 380px;
    border-radius: 16px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(0,0,0,.22);
    display: block;
  }

  .wa-media-audio {
    width: min(380px, 100%);
    display: block;
  }

  .wa-media-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 13px;
  }

  .wa-media-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 38px;
    padding: 0 14px;
    border-radius: 12px;
    text-decoration: none;
    font-size: 13px;
    font-weight: 800;
    color: inherit;
    background: rgba(255,255,255,.06);
    border: 1px solid rgba(255,255,255,.10);
    transition: .16s ease;
  }

  .wa-media-btn:hover {
    transform: translateY(-1px);
    background: rgba(255,255,255,.1);
  }

  .wa-media-btn--primary {
    background: rgba(198,223,32,.14);
    border-color: rgba(198,223,32,.20);
  }

  .wa-media-btn--primary:hover {
    background: rgba(198,223,32,.20);
  }

  .wa-media-btn svg {
    width: 16px;
    height: 16px;
    display: block;
  }

  .wa-reply {
    flex: 0 0 auto;
    padding: 12px 16px 14px;
    border-top: 1px solid rgba(255,255,255,.06);
    background: rgba(10,16,32,.97);
  }

  .wa-compose-status {
    display: none;
    margin-bottom: 10px;
    padding: 10px 12px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.4;
  }

  .wa-compose-status.is-show {
    display: block;
  }

  .wa-compose-status.is-success {
    background: rgba(75,214,120,.12);
    border: 1px solid rgba(75,214,120,.16);
    color: #c8ffd9;
  }

  .wa-compose-status.is-error {
    background: rgba(255,100,100,.12);
    border: 1px solid rgba(255,100,100,.16);
    color: #ffd4d4;
  }

  .wa-compose-status.is-info {
    background: rgba(112,210,255,.10);
    border: 1px solid rgba(112,210,255,.14);
    color: #d7f3ff;
  }

  .wa-reply-preview {
    display: none;
    margin-bottom: 12px;
    padding: 10px 12px;
    border-radius: 14px;
    border-left: 3px solid rgba(198,223,32,.72);
    background: rgba(255,255,255,.05);
  }

  .wa-reply-preview.is-show {
    display: block;
  }

  .wa-reply-preview__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 6px;
  }

  .wa-reply-preview__label {
    font-size: 11px;
    font-weight: 900;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: rgba(255,255,255,.72);
  }

  .wa-reply-preview__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 999px;
    border: 1px solid rgba(255,255,255,.10);
    background: rgba(255,255,255,.04);
    color: #fff;
    cursor: pointer;
  }

  .wa-reply-preview__close svg {
    width: 14px;
    height: 14px;
    display: block;
  }

  .wa-reply-preview__text {
    font-size: 13px;
    line-height: 1.45;
    color: rgba(255,255,255,.92);
    word-break: break-word;
    white-space: pre-wrap;
  }

  .wa-compose-grid {
    display: grid;
    grid-template-columns: 180px minmax(0, 1fr) 190px auto;
    gap: 10px;
    align-items: end;
  }

  .wa-compose-field label {
    display: block;
    margin-bottom: 5px;
    font-size: 12px;
    font-weight: 700;
    opacity: .9;
  }

  .wa-compose-field textarea,
  .wa-compose-field select,
  .wa-compose-field input[type="file"] {
    width: 100%;
    border-radius: 14px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(255,255,255,.03);
    color: inherit;
  }

  .wa-compose-field textarea {
    min-height: 120px;
    max-height: 280px;
    resize: none;
    padding: 14px 14px;
    line-height: 1.55;
    font-size: 14px;
    overflow-y: auto;
  }

  .wa-compose-field select {
    min-height: 46px;
    padding: 0 14px;
  }

  .wa-compose-field input[type="file"] {
    min-height: 46px;
    padding: 10px 12px;
  }

  .wa-upload-name {
    margin-top: 6px;
    font-size: 11px;
    color: rgba(255,255,255,.65);
    min-height: 16px;
  }

  .wa-compose-actions {
    display: flex;
    align-items: end;
    justify-content: flex-end;
  }

  .wa-compose-send-btn {
    min-height: 46px;
    min-width: 112px;
  }

  .wa-side-top {
    display: flex;
    gap: 12px;
    align-items: center;
    margin-bottom: 14px;
  }

  .wa-side-name {
    font-size: 16px;
    font-weight: 900;
    line-height: 1.2;
    word-break: break-word;
  }

  .wa-side-phone {
    margin-top: 4px;
    font-size: 12px;
    color: rgba(255,255,255,.64);
  }

  .wa-side-section {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid rgba(255,255,255,.06);
  }

  .wa-side-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
    font-weight: 900;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: rgba(255,255,255,.54);
    margin-bottom: 10px;
  }

  .wa-side-label svg {
    width: 14px;
    height: 14px;
    display: block;
  }

  .wa-side-line {
    font-size: 13px;
    line-height: 1.5;
    color: rgba(255,255,255,.88);
    word-break: break-word;
    margin-bottom: 8px;
  }

  .wa-current-tags {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
  }

  .wa-current-tag {
    display: inline-flex;
    align-items: center;
    min-height: 28px;
    padding: 0 11px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
    background: rgba(198,223,32,.12);
    border: 1px solid rgba(198,223,32,.18);
  }

  .wa-side-empty {
    font-size: 13px;
    color: rgba(255,255,255,.58);
  }

  .wa-side-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
  }

  .wa-side-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 42px;
    padding: 0 14px;
    border-radius: 14px;
    text-decoration: none;
    font-size: 13px;
    font-weight: 800;
    color: inherit;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.08);
    transition: .16s ease;
    cursor: pointer;
  }

  .wa-side-btn:hover {
    background: rgba(255,255,255,.1);
    transform: translateY(-1px);
  }

  .wa-side-btn--accent {
    background: rgba(198,223,32,.14);
    border-color: rgba(198,223,32,.20);
  }

  .wa-side-btn--accent:hover {
    background: rgba(198,223,32,.20);
  }

  .wa-side-btn svg {
    width: 16px;
    height: 16px;
    display: block;
  }

  .wa-tag-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
  }

  .wa-tag-status {
    display: none;
    padding: 10px 12px;
    border-radius: 12px;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.4;
  }

  .wa-tag-status.is-show {
    display: block;
  }

  .wa-tag-status.is-success {
    background: rgba(75,214,120,.12);
    border: 1px solid rgba(75,214,120,.16);
    color: #c8ffd9;
  }

  .wa-tag-status.is-error {
    background: rgba(255,100,100,.12);
    border: 1px solid rgba(255,100,100,.16);
    color: #ffd4d4;
  }

  .wa-tag-search {
    width: 100%;
    min-height: 40px;
    border-radius: 12px;
    border: 1px solid rgba(255,255,255,.08);
    background: rgba(255,255,255,.03);
    color: inherit;
    padding: 0 12px;
  }

  .wa-tag-options {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    max-height: 210px;
    overflow: auto;
    padding-right: 4px;
  }

  .wa-tag-option {
    position: relative;
  }

  .wa-tag-option input {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
  }

  .wa-tag-chip {
    display: inline-flex;
    align-items: center;
    min-height: 34px;
    padding: 0 12px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 800;
    cursor: pointer;
    transition: .16s ease;
    background: rgba(255,255,255,.05);
    border: 1px solid rgba(255,255,255,.08);
    color: rgba(255,255,255,.86);
    user-select: none;
  }

  .wa-tag-option input:checked + .wa-tag-chip {
    background: rgba(198,223,32,.16);
    border-color: rgba(198,223,32,.24);
    color: #f4ffd4;
    transform: translateY(-1px);
  }

  .wa-tag-actions {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
  }

  .wa-tag-selected {
    font-size: 12px;
    color: rgba(255,255,255,.6);
    font-weight: 700;
  }

  .wa-tag-submit {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 40px;
    padding: 0 14px;
    border-radius: 12px;
    font-size: 13px;
    font-weight: 800;
    border: 1px solid rgba(198,223,32,.22);
    background: rgba(198,223,32,.14);
    color: inherit;
    cursor: pointer;
    transition: .16s ease;
  }

  .wa-tag-submit:hover {
    background: rgba(198,223,32,.20);
    transform: translateY(-1px);
  }

  .wa-tag-submit:disabled {
    opacity: .6;
    cursor: wait;
    transform: none;
  }

  .wa-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1100;
    display: none;
  }

  .wa-lightbox.is-open {
    display: block;
  }

  .wa-lightbox__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(4,8,18,.82);
    backdrop-filter: blur(6px);
  }

  .wa-lightbox__dialog {
    position: relative;
    z-index: 1;
    width: min(1080px, calc(100vw - 32px));
    margin: 3vh auto 0;
    padding: 16px;
    border-radius: 24px;
    background: linear-gradient(180deg, rgba(13,20,40,.96), rgba(8,14,30,.96));
    border: 1px solid rgba(255,255,255,.08);
    box-shadow: 0 24px 80px rgba(0,0,0,.45);
  }

  .wa-lightbox__top {
    display: flex;
    gap: 14px;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 14px;
  }

  .wa-lightbox__title {
    min-width: 0;
  }

  .wa-lightbox__name {
    font-size: 15px;
    font-weight: 800;
    line-height: 1.35;
    word-break: break-word;
  }

  .wa-lightbox__hint {
    font-size: 12px;
    opacity: .72;
    margin-top: 3px;
  }

  .wa-lightbox__actions {
    display: flex;
    gap: 10px;
    align-items: center;
    flex-wrap: wrap;
  }

  .wa-lightbox__link,
  .wa-lightbox__close {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 38px;
    padding: 0 14px;
    border-radius: 12px;
    text-decoration: none;
    font-size: 13px;
    font-weight: 800;
    color: inherit;
    background: rgba(255,255,255,.06);
    border: 1px solid rgba(255,255,255,.10);
    cursor: pointer;
  }

  .wa-lightbox__link:hover,
  .wa-lightbox__close:hover {
    background: rgba(255,255,255,.1);
  }

  .wa-lightbox__body {
    min-height: 280px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 18px;
    overflow: hidden;
    background:
      linear-gradient(45deg, rgba(255,255,255,.02) 25%, transparent 25%, transparent 50%, rgba(255,255,255,.02) 50%, rgba(255,255,255,.02) 75%, transparent 75%, transparent),
      rgba(255,255,255,.02);
    background-size: 22px 22px;
    border: 1px solid rgba(255,255,255,.06);
  }

  .wa-lightbox__img {
    display: block;
    max-width: 100%;
    max-height: 76vh;
    object-fit: contain;
  }

  .wa-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
  }

  .wa-modal__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,.55);
    backdrop-filter: blur(4px);
  }

  .wa-modal__panel {
    position: relative;
    width: min(720px, calc(100vw - 32px));
    margin: 6vh auto 0;
    z-index: 1;
    padding: 18px;
    border-radius: 22px;
  }

  .wa-toast {
    position: fixed;
    top: 18px;
    right: 18px;
    z-index: 99999;
    min-width: 280px;
    max-width: 360px;
    padding: 14px 16px;
    border-radius: 16px;
    background: rgba(10,16,32,.96);
    border: 1px solid rgba(198,223,32,.22);
    box-shadow: 0 18px 40px rgba(0,0,0,.42);
    color: #fff;
    opacity: 0;
    transform: translateY(-14px);
    pointer-events: none;
    transition: all .22s ease;
  }

  .wa-toast.is-show {
    opacity: 1;
    transform: translateY(0);
  }

  .wa-toast__title {
    font-size: 13px;
    font-weight: 900;
    margin-bottom: 4px;
    color: #d8ef49;
  }

  .wa-toast__body {
    font-size: 12px;
    line-height: 1.45;
    color: rgba(255,255,255,.9);
    word-break: break-word;
  }

  @media (max-width: 1180px) {
    .wa-layout {
      grid-template-columns: minmax(0, 1fr) 300px;
    }

    .wa-compose-grid {
      grid-template-columns: 1fr;
    }
  }

  @media (max-width: 1080px) {
    .wa-layout {
      grid-template-columns: 1fr;
    }

    .wa-chat-shell {
      height: calc(100vh - 92px);
      min-height: 0;
    }

    .wa-side-card {
      position: static;
      order: -1;
      max-height: none;
    }
  }

  @media (max-width: 900px) {
    .wa-page-head {
      align-items: flex-start;
      flex-direction: column;
    }

    .wa-side-actions {
      grid-template-columns: 1fr;
    }

    .wa-bubble-wrap {
      max-width: 94%;
    }

    .wa-chat-shell {
      height: auto;
      min-height: 0;
    }

    .wa-chat-body {
      max-height: 52vh;
    }

    .wa-compose-actions {
      justify-content: stretch;
    }

    .wa-compose-send-btn {
      width: 100%;
    }

    .wa-media-thumb,
    .wa-media-thumb-link,
    .wa-media-video {
      max-width: 100%;
    }

    .wa-lightbox__dialog {
      width: calc(100vw - 18px);
      margin-top: 1.5vh;
      padding: 12px;
      border-radius: 18px;
    }

    .wa-lightbox__top {
      align-items: flex-start;
      flex-direction: column;
    }

    .wa-toast {
      left: 12px;
      right: 12px;
      min-width: 0;
      max-width: none;
    }
  }
</style>

<div class="wa-page-head">
  <div>
    <h1 class="wa-page-title">Conversa</h1>
    <p class="wa-page-subtitle">Feed maior, copiar mensagem e resposta rápida</p>
  </div>

  <div>
    <a class="btn btn-secondary" href="<?= e(url_for('/whatsapp/inbox')) ?>">Voltar à Inbox</a>
  </div>
</div>

<div class="wa-layout">
  <div class="wa-chat-shell">
    <div class="wa-chat-topbar">
      <div class="wa-chat-avatar">
        <?= e(strtoupper(mb_substr(trim($contactName), 0, 1, 'UTF-8'))) ?>
      </div>

      <div class="wa-chat-contact">
        <div class="wa-chat-contact-name"><?= e($contactName) ?></div>
        <div class="wa-chat-contact-phone"><?= e($contactPhone ?: '-') ?></div>
      </div>
    </div>

    <div class="wa-chat-body" id="waThread">
      <?php if (empty($messages)): ?>
        <div class="muted">Sem mensagens ainda.</div>
      <?php endif; ?>

      <?php foreach ($messages as $m): ?>
        <?php
          $messageId = (int)($m['id'] ?? 0);
          $dir = (string)($m['direction'] ?? '');
          $isIn = ($dir === 'inbound');
          $text = (string)($m['message_body'] ?? '');
          $who  = $isIn ? 'Cliente' : ((string)($m['user_name'] ?? '') ?: 'Sistema');
          $when = (string)($m['created_at'] ?? '');
          $status = (string)($m['provider_status'] ?? '');

          $mediaType = strtolower(trim((string)($m['media_type'] ?? '')));
          $mediaName = trim((string)($m['media_file_name'] ?? ''));
          $externalMediaId = trim((string)($m['external_media_id'] ?? ''));
          $mimeType = strtolower(trim((string)($m['media_mime_type'] ?? '')));
          $mediaSizeLabel = $formatBytes((int)($m['media_file_size'] ?? 0));

          $hasMedia = ($mediaType !== '' || $externalMediaId !== '');

          $mediaLabel = $mediaName !== ''
              ? $mediaName
              : match ($mediaType) {
                  'image' => 'Imagem',
                  'video' => 'Vídeo',
                  'audio' => 'Áudio',
                  default => 'Documento',
              };

          $mediaOpenUrl = url_for('/whatsapp/media/' . $messageId);
          $mediaDownloadUrl = url_for('/whatsapp/media/' . $messageId . '?download=1');

          $showText = $text !== '';
          if ($hasMedia && preg_match('/^\[(Imagem|Vídeo|Áudio|Documento)/u', $text)) {
              $showText = false;
          }

          $extension = '';
          if ($mediaName !== '' && str_contains($mediaName, '.')) {
              $extension = strtolower((string)pathinfo($mediaName, PATHINFO_EXTENSION));
          }

          $kindLabel = $mediaKindLabel($mediaType);
          $toneClass = $mediaToneClass($mediaType, $extension);
          $showThumb = $hasMedia && $mediaType === 'image';
          $showVideo = $hasMedia && $mediaType === 'video';
          $showAudio = $hasMedia && $mediaType === 'audio';

          $notifyText = $text !== '' ? $text : $mediaLabel;
          $replyPreview = $replyPreviewLabel($m);
          $replyLabel = ((string)($m['reply_direction'] ?? '') === 'inbound') ? 'Respondendo cliente' : 'Respondendo mensagem';
          $copyText = trim($text) !== '' ? $text : $mediaLabel;
        ?>

        <div
          class="wa-row <?= $isIn ? 'in' : 'out' ?>"
          data-message-id="<?= $messageId ?>"
          data-direction="<?= e($dir) ?>"
          data-notify-text="<?= e($notifyText) ?>"
        >
          <div class="wa-bubble-wrap">
            <div class="wa-bubble">
              <?php if ($replyPreview !== ''): ?>
                <div class="wa-quoted">
                  <div class="wa-quoted__label"><?= e($replyLabel) ?></div>
                  <div class="wa-quoted__text"><?= e($replyPreview) ?></div>
                </div>
              <?php endif; ?>

              <?php if ($showText): ?>
                <div class="wa-text"><?= e($text) ?></div>
              <?php endif; ?>

              <?php if ($hasMedia): ?>
                <div class="wa-media-card <?= e($toneClass) ?>">
                  <div class="wa-media-head">
                    <div class="wa-media-icon"><?= $mediaIconSvg($mediaType, $extension) ?></div>

                    <div class="wa-media-meta">
                      <div class="wa-media-title"><?= e($mediaLabel) ?></div>

                      <div class="wa-media-sub">
                        <span class="wa-badge <?= e($toneClass) ?>"><?= e($kindLabel) ?></span>

                        <?php if ($extension !== ''): ?>
                          <span class="wa-badge"><?= e(strtoupper($extension)) ?></span>
                        <?php endif; ?>

                        <?php if ($mediaSizeLabel !== ''): ?>
                          <span class="wa-badge"><?= e($mediaSizeLabel) ?></span>
                        <?php endif; ?>
                      </div>
                    </div>
                  </div>

                  <?php if ($showThumb): ?>
                    <div class="wa-media-thumb-wrap">
                      <a
                        href="<?= e($mediaOpenUrl) ?>"
                        target="_blank"
                        rel="noopener"
                        class="wa-media-thumb-link js-wa-lightbox"
                        data-src="<?= e($mediaOpenUrl) ?>"
                        data-name="<?= e($mediaLabel) ?>"
                        data-download="<?= e($mediaDownloadUrl) ?>"
                      >
                        <img
                          src="<?= e($mediaOpenUrl) ?>"
                          alt="<?= e($mediaLabel) ?>"
                          class="wa-media-thumb"
                          loading="lazy"
                        >
                        <span class="wa-media-thumb-overlay">
                          <?= $iconExpandSvg ?>
                          <span>Ampliar</span>
                        </span>
                      </a>
                    </div>
                  <?php endif; ?>

                  <?php if ($showVideo): ?>
                    <div class="wa-media-video-wrap">
                      <video class="wa-media-video" controls preload="metadata">
                        <source src="<?= e($mediaOpenUrl) ?>" type="<?= e($mimeType !== '' ? $mimeType : 'video/mp4') ?>">
                      </video>
                    </div>
                  <?php endif; ?>

                  <?php if ($showAudio): ?>
                    <div class="wa-media-audio-wrap">
                      <audio class="wa-media-audio" controls preload="none">
                        <source src="<?= e($mediaOpenUrl) ?>" type="<?= e($mimeType !== '' ? $mimeType : 'audio/mpeg') ?>">
                      </audio>
                    </div>
                  <?php endif; ?>

                  <div class="wa-media-actions">
                    <a class="wa-media-btn wa-media-btn--primary" href="<?= e($mediaOpenUrl) ?>" target="_blank" rel="noopener">
                      <?= $iconEyeSvg ?>
                      <span>Abrir</span>
                    </a>

                    <a class="wa-media-btn" href="<?= e($mediaDownloadUrl) ?>">
                      <?= $iconDownloadSvg ?>
                      <span>Baixar</span>
                    </a>
                  </div>
                </div>
              <?php endif; ?>

              <div class="wa-info">
                <span><?= e($who) ?></span>
                <span class="wa-dot">•</span>
                <span><?= e(format_date($when)) ?></span>

                <?php if (!$isIn && $status !== ''): ?>
                  <span class="wa-dot">•</span>
                  <span class="wa-status"><?= e($status) ?></span>
                <?php endif; ?>
              </div>
            </div>

            <div class="wa-bubble-actions">
              <button
                type="button"
                class="wa-action-btn js-reply-message"
                data-message-id="<?= $messageId ?>"
                data-message-text="<?= e($copyText) ?>"
              >
                <?= $iconReplySvg ?>
                <span>Responder</span>
              </button>

              <button
                type="button"
                class="wa-action-btn js-copy-message"
                data-message-text="<?= e($copyText) ?>"
              >
                <?= $iconCopySvg ?>
                <span>Copiar</span>
              </button>
            </div>
          </div>
        </div>
      <?php endforeach; ?>
    </div>

    <div class="wa-reply">
      <div id="waComposeStatus" class="wa-compose-status"></div>

      <div id="waReplyPreview" class="wa-reply-preview">
        <div class="wa-reply-preview__top">
          <div class="wa-reply-preview__label">Respondendo esta mensagem</div>
          <button type="button" class="wa-reply-preview__close" id="waReplyCancelBtn">
            <?= $iconCloseSvg ?>
          </button>
        </div>
        <div class="wa-reply-preview__text" id="waReplyPreviewText"></div>
      </div>

      <form id="waReplyForm" method="post" action="<?= e(url_for('/whatsapp/send')) ?>" enctype="multipart/form-data">
        <?= csrf_field() ?>
        <input type="hidden" name="contact_id" value="<?= (int)$contact['id'] ?>">
        <input type="hidden" name="return_to" value="conversation">
        <input type="hidden" name="reply_to_message_id" id="waReplyToMessageId" value="">

        <div class="wa-compose-grid">
          <div class="wa-compose-field">
            <label for="waTemplateSelect">Template</label>
            <select name="template_id" id="waTemplateSelect">
              <option value="">Manual</option>
              <?php foreach ($templates as $t): ?>
                <option value="<?= (int)$t['id'] ?>"><?= e($t['name']) ?></option>
              <?php endforeach; ?>
            </select>
          </div>

          <div class="wa-compose-field">
            <label for="waMessageField">Mensagem</label>
            <textarea name="message" id="waMessageField" placeholder="Digite sua mensagem..."></textarea>
          </div>

          <div class="wa-compose-field">
            <label for="waAttachmentField">Anexo</label>
            <input
              type="file"
              name="attachment"
              id="waAttachmentField"
              accept="image/*,video/*,audio/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.csv"
            >
            <div class="wa-upload-name" id="waUploadName"></div>
          </div>

          <div class="wa-compose-actions">
            <button class="btn wa-compose-send-btn" type="submit" id="waSendBtn">Enviar</button>
          </div>
        </div>
      </form>
    </div>
  </div>

  <aside class="wa-side-card">
    <div class="wa-side-top">
      <div class="wa-side-avatar">
        <?= e(strtoupper(mb_substr(trim($contactName), 0, 1, 'UTF-8'))) ?>
      </div>

      <div>
        <div class="wa-side-name"><?= e($contactName) ?></div>
        <div class="wa-side-phone"><?= e($contactPhone ?: '-') ?></div>
      </div>
    </div>

    <div class="wa-side-actions">
      <a class="wa-side-btn wa-side-btn--accent" href="<?= e(url_for('/contacts/' . (int)$contact['id'])) ?>">
        <span>Abrir cliente</span>
      </a>

      <a class="wa-side-btn" href="<?= e(url_for('/contacts/' . (int)$contact['id'] . '/edit')) ?>">
        <?= $iconEditSvg ?>
        <span>Editar</span>
      </a>

      <?php if ($waExternalLink !== ''): ?>
        <a class="wa-side-btn" href="<?= e($waExternalLink) ?>" target="_blank" rel="noopener">
          <?= $iconExternalSvg ?>
          <span>WhatsApp</span>
        </a>
      <?php endif; ?>

      <button class="wa-side-btn" type="button" id="btnHandoverSide">
        <span>Funil</span>
      </button>
    </div>

    <div class="wa-side-section">
      <div class="wa-side-label">
        <?= $iconTagSvg ?>
        <span>Tags do cliente</span>
      </div>

      <div id="waCurrentTags" class="wa-current-tags">
        <?php if (!empty($contactTags)): ?>
          <?php foreach ($contactTags as $tag): ?>
            <span class="wa-current-tag" data-tag-id="<?= (int)$tag['id'] ?>"><?= e((string)$tag['name']) ?></span>
          <?php endforeach; ?>
        <?php else: ?>
          <div class="wa-side-empty" id="waCurrentTagsEmpty">Este cliente ainda não possui tags.</div>
        <?php endif; ?>
      </div>
    </div>

    <div class="wa-side-section">
      <div class="wa-side-label">
        <?= $iconTagSvg ?>
        <span>Gerenciar tags</span>
      </div>

      <form id="waTagForm" class="wa-tag-form" method="post" action="<?= e(url_for('/whatsapp/contact-tags/update')) ?>">
        <?= csrf_field() ?>
        <input type="hidden" name="contact_id" value="<?= (int)$contact['id'] ?>">

        <div id="waTagStatus" class="wa-tag-status"></div>

        <input
          type="text"
          id="waTagSearch"
          class="wa-tag-search"
          placeholder="Buscar tag..."
          autocomplete="off"
        >

        <div class="wa-tag-options" id="waTagOptions">
          <?php foreach ($tags as $tag): ?>
            <?php $checked = in_array((int)$tag['id'], $contactTagIds, true); ?>
            <label class="wa-tag-option" data-tag-name="<?= e(mb_strtolower((string)$tag['name'], 'UTF-8')) ?>">
              <input
                type="checkbox"
                name="tag_ids[]"
                value="<?= (int)$tag['id'] ?>"
                <?= $checked ? 'checked' : '' ?>
              >
              <span class="wa-tag-chip"><?= e((string)$tag['name']) ?></span>
            </label>
          <?php endforeach; ?>
        </div>

        <div class="wa-tag-actions">
          <div class="wa-tag-selected" id="waTagSelectedCount"></div>
          <button type="submit" id="waTagSubmit" class="wa-tag-submit">Salvar tags</button>
        </div>
      </form>
    </div>

    <?php if ($contactEmail !== '' || $contactCompany !== '' || $contactPosition !== ''): ?>
      <div class="wa-side-section">
        <div class="wa-side-label">Informações</div>

        <?php if ($contactEmail !== ''): ?>
          <div class="wa-side-line"><strong>E-mail:</strong> <?= e($contactEmail) ?></div>
        <?php endif; ?>

        <?php if ($contactCompany !== ''): ?>
          <div class="wa-side-line"><strong>Empresa:</strong> <?= e($contactCompany) ?></div>
        <?php endif; ?>

        <?php if ($contactPosition !== ''): ?>
          <div class="wa-side-line"><strong>Cargo:</strong> <?= e($contactPosition) ?></div>
        <?php endif; ?>
      </div>
    <?php endif; ?>

    <?php if ($contactObs !== ''): ?>
      <div class="wa-side-section">
        <div class="wa-side-label">Observações</div>
        <div class="wa-side-line"><?= nl2br(e($contactObs)) ?></div>
      </div>
    <?php endif; ?>
  </aside>
</div>

<div class="wa-lightbox" id="waLightbox">
  <div class="wa-lightbox__backdrop"></div>

  <div class="wa-lightbox__dialog">
    <div class="wa-lightbox__top">
      <div class="wa-lightbox__title">
        <div class="wa-lightbox__name" id="waLightboxName">Imagem</div>
        <div class="wa-lightbox__hint">Visualização ampliada</div>
      </div>

      <div class="wa-lightbox__actions">
        <a href="#" target="_blank" rel="noopener" class="wa-lightbox__link" id="waLightboxOpen">
          <?= $iconEyeSvg ?>
          <span>Abrir original</span>
        </a>

        <a href="#" class="wa-lightbox__link" id="waLightboxDownload">
          <?= $iconDownloadSvg ?>
          <span>Baixar</span>
        </a>

        <button type="button" class="wa-lightbox__close" id="waLightboxClose">Fechar</button>
      </div>
    </div>

    <div class="wa-lightbox__body">
      <img src="" alt="" id="waLightboxImage" class="wa-lightbox__img">
    </div>
  </div>
</div>

<div class="wa-modal" id="waHandoverModal" style="display:none;">
  <div class="wa-modal__backdrop"></div>

  <div class="wa-modal__panel card">
    <div class="flex-between" style="margin-bottom:12px;">
      <div>
        <h3 style="margin:0;">Encaminhar para Funil</h3>
        <div class="muted small" style="margin-top:4px;">
          Selecione o funil e a etapa de destino para criar ou posicionar a oportunidade corretamente.
        </div>
      </div>
      <button class="btn btn-secondary" type="button" id="btnCloseHandover">Fechar</button>
    </div>

    <form method="post" action="<?= e(url_for('/whatsapp/handover')) ?>">
      <?= csrf_field() ?>
      <input type="hidden" name="contact_id" value="<?= (int)$contact['id'] ?>">

      <div class="form-grid">
        <div>
          <label>Funil</label>
          <select name="pipeline_id" id="waPipelineSelect" required>
            <option value="">Selecione</option>
            <?php foreach ($pipelines as $pipeline): ?>
              <option value="<?= (int)$pipeline['id'] ?>"><?= e((string)$pipeline['name']) ?></option>
            <?php endforeach; ?>
          </select>
        </div>

        <div>
          <label>Etapa</label>
          <select name="stage_id" id="waStageSelect">
            <option value="">Primeira etapa do funil</option>
          </select>
        </div>

        <div class="full">
          <label>Título da oportunidade</label>
          <input name="title" placeholder="WhatsApp - <?= e($contactName) ?>">
        </div>

        <div>
          <label>Valor (opcional)</label>
          <input type="number" step="0.01" name="value" value="0.00">
        </div>

        <div>
          <label>Tag (opcional)</label>
          <select name="tag_id">
            <option value="">Não aplicar</option>
            <?php foreach ($tags as $tag): ?>
              <option value="<?= (int)$tag['id'] ?>"><?= e($tag['name']) ?></option>
            <?php endforeach; ?>
          </select>
        </div>
      </div>

      <div style="margin-top:14px; display:flex; justify-content:flex-end; gap:10px;">
        <button class="btn" type="submit">Criar oportunidade</button>
      </div>
    </form>
  </div>
</div>

<div class="wa-toast" id="waNotifyToast" aria-live="polite" aria-atomic="true">
  <div class="wa-toast__title">Nova mensagem WhatsApp</div>
  <div class="wa-toast__body" id="waNotifyToastBody">Você recebeu uma nova mensagem.</div>
</div>

<script>
(function () {
  const thread = document.getElementById('waThread');
  if (!thread) return;
  thread.scrollTop = thread.scrollHeight;
})();

(function () {
  const modal = document.getElementById('waHandoverModal');
  const btnOpenSide = document.getElementById('btnHandoverSide');
  const btnClose = document.getElementById('btnCloseHandover');
  const pipelineSelect = document.getElementById('waPipelineSelect');
  const stageSelect = document.getElementById('waStageSelect');
  const stagesMap = <?= json_encode($pipelineStagesMap, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;

  if (!modal || !btnClose) return;

  const backdrop = modal.querySelector('.wa-modal__backdrop');

  function renderStages(pipelineId) {
    if (!stageSelect) return;

    stageSelect.innerHTML = '';

    const firstOption = document.createElement('option');
    firstOption.value = '';
    firstOption.textContent = 'Primeira etapa do funil';
    stageSelect.appendChild(firstOption);

    const stages = stagesMap[String(pipelineId)] || stagesMap[Number(pipelineId)] || [];
    stages.forEach((stage) => {
      const option = document.createElement('option');
      option.value = String(stage.id);
      option.textContent = stage.name;
      stageSelect.appendChild(option);
    });
  }

  function open() {
    modal.style.display = 'block';
  }

  function close() {
    modal.style.display = 'none';
  }

  if (btnOpenSide) btnOpenSide.addEventListener('click', open);
  btnClose.addEventListener('click', close);
  if (backdrop) backdrop.addEventListener('click', close);

  if (pipelineSelect) {
    pipelineSelect.addEventListener('change', function () {
      renderStages(this.value);
    });

    if (pipelineSelect.value) {
      renderStages(pipelineSelect.value);
    }
  }

  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape') close();
  });
})();

(function () {
  const lightbox = document.getElementById('waLightbox');
  const thread = document.getElementById('waThread');
  if (!lightbox || !thread) return;

  const backdrop = lightbox.querySelector('.wa-lightbox__backdrop');
  const closeBtn = document.getElementById('waLightboxClose');
  const image = document.getElementById('waLightboxImage');
  const name = document.getElementById('waLightboxName');
  const openLink = document.getElementById('waLightboxOpen');
  const downloadLink = document.getElementById('waLightboxDownload');

  function openLightbox(src, label, downloadUrl) {
    image.src = src;
    image.alt = label || 'Imagem';
    name.textContent = label || 'Imagem';
    openLink.href = src;
    downloadLink.href = downloadUrl || src;
    lightbox.classList.add('is-open');
    document.body.style.overflow = 'hidden';
  }

  function closeLightbox() {
    lightbox.classList.remove('is-open');
    document.body.style.overflow = '';
    image.src = '';
    image.alt = '';
    openLink.href = '#';
    downloadLink.href = '#';
  }

  thread.addEventListener('click', (event) => {
    const trigger = event.target.closest('.js-wa-lightbox');
    if (!trigger) return;

    event.preventDefault();

    openLightbox(
      trigger.getAttribute('data-src') || trigger.getAttribute('href') || '',
      trigger.getAttribute('data-name') || 'Imagem',
      trigger.getAttribute('data-download') || trigger.getAttribute('href') || ''
    );
  });

  if (backdrop) backdrop.addEventListener('click', closeLightbox);
  if (closeBtn) closeBtn.addEventListener('click', closeLightbox);

  document.addEventListener('keydown', (event) => {
    if (event.key === 'Escape' && lightbox.classList.contains('is-open')) {
      closeLightbox();
    }
  });
})();

(function () {
  const form = document.getElementById('waTagForm');
  const submitBtn = document.getElementById('waTagSubmit');
  const statusBox = document.getElementById('waTagStatus');
  const currentTagsWrap = document.getElementById('waCurrentTags');
  const tagSearch = document.getElementById('waTagSearch');
  const tagOptionsWrap = document.getElementById('waTagOptions');
  const selectedCount = document.getElementById('waTagSelectedCount');

  if (!form || !submitBtn || !statusBox || !currentTagsWrap || !tagOptionsWrap || !selectedCount) return;

  function showStatus(type, message) {
    statusBox.className = 'wa-tag-status is-show ' + (type === 'success' ? 'is-success' : 'is-error');
    statusBox.textContent = message;
  }

  function renderCurrentTags(tags) {
    currentTagsWrap.innerHTML = '';

    if (!tags || tags.length === 0) {
      const empty = document.createElement('div');
      empty.className = 'wa-side-empty';
      empty.id = 'waCurrentTagsEmpty';
      empty.textContent = 'Este cliente ainda não possui tags.';
      currentTagsWrap.appendChild(empty);
      return;
    }

    tags.forEach((tag) => {
      const pill = document.createElement('span');
      pill.className = 'wa-current-tag';
      pill.setAttribute('data-tag-id', String(tag.id));
      pill.textContent = tag.name;
      currentTagsWrap.appendChild(pill);
    });
  }

  function updateSelectedCount() {
    const checked = form.querySelectorAll('input[name="tag_ids[]"]:checked').length;
    selectedCount.textContent = checked === 1 ? '1 tag selecionada' : checked + ' tags selecionadas';
  }

  function filterTags() {
    const term = (tagSearch.value || '').trim().toLowerCase();
    tagOptionsWrap.querySelectorAll('.wa-tag-option').forEach((item) => {
      const tagName = item.getAttribute('data-tag-name') || '';
      item.style.display = term === '' || tagName.includes(term) ? '' : 'none';
    });
  }

  form.querySelectorAll('input[name="tag_ids[]"]').forEach((input) => {
    input.addEventListener('change', updateSelectedCount);
  });

  tagSearch.addEventListener('input', filterTags);
  updateSelectedCount();

  form.addEventListener('submit', async function (event) {
    event.preventDefault();

    submitBtn.disabled = true;
    submitBtn.textContent = 'Salvando...';

    try {
      const response = await fetch(form.action, {
        method: 'POST',
        credentials: 'same-origin',
        headers: {
          'X-Requested-With': 'XMLHttpRequest',
          'Accept': 'application/json'
        },
        body: new FormData(form)
      });

      const data = await response.json();

      if (!response.ok || !data.success) {
        showStatus('error', data.message || 'Não foi possível atualizar as tags.');
        return;
      }

      renderCurrentTags(data.tags || []);
      showStatus('success', data.message || 'Tags atualizadas com sucesso.');
      updateSelectedCount();
    } catch (error) {
      showStatus('error', 'Falha ao salvar as tags.');
    } finally {
      submitBtn.disabled = false;
      submitBtn.textContent = 'Salvar tags';
    }
  });
})();

(function () {
  const attachmentField = document.getElementById('waAttachmentField');
  const uploadName = document.getElementById('waUploadName');
  if (!attachmentField || !uploadName) return;

  attachmentField.addEventListener('change', function () {
    const file = attachmentField.files && attachmentField.files[0] ? attachmentField.files[0] : null;
    uploadName.textContent = file ? ('Arquivo selecionado: ' + file.name) : '';
  });
})();

(function () {
  const textarea = document.getElementById('waMessageField');
  if (!textarea) return;

  function autoResize() {
    textarea.style.height = 'auto';
    textarea.style.height = Math.min(textarea.scrollHeight, 280) + 'px';
  }

  textarea.addEventListener('input', autoResize);
  window.addEventListener('load', autoResize);
  autoResize();
})();

(function () {
  const previewBox = document.getElementById('waReplyPreview');
  const previewText = document.getElementById('waReplyPreviewText');
  const replyInput = document.getElementById('waReplyToMessageId');
  const cancelBtn = document.getElementById('waReplyCancelBtn');
  const textarea = document.getElementById('waMessageField');

  if (!previewBox || !previewText || !replyInput || !cancelBtn) return;

  function openReply(id, text) {
    replyInput.value = String(id);
    previewText.textContent = text || 'Mensagem selecionada';
    previewBox.classList.add('is-show');

    if (textarea) {
      textarea.focus();
    }
  }

  function closeReply() {
    replyInput.value = '';
    previewText.textContent = '';
    previewBox.classList.remove('is-show');
  }

  document.querySelectorAll('.js-reply-message').forEach((btn) => {
    btn.addEventListener('click', function () {
      openReply(this.getAttribute('data-message-id') || '', this.getAttribute('data-message-text') || '');
    });
  });

  cancelBtn.addEventListener('click', closeReply);

  window.waCloseReply = closeReply;
})();

(function () {
  const toast = document.getElementById('waNotifyToast');
  const toastBody = document.getElementById('waNotifyToastBody');

  function showSmallToast(message) {
    if (!toast || !toastBody) return;

    toastBody.textContent = message;
    toast.classList.add('is-show');

    clearTimeout(showSmallToast._timer);
    showSmallToast._timer = setTimeout(() => {
      toast.classList.remove('is-show');
    }, 2200);
  }

  document.querySelectorAll('.js-copy-message').forEach((btn) => {
    btn.addEventListener('click', async function () {
      const text = this.getAttribute('data-message-text') || '';

      try {
        await navigator.clipboard.writeText(text);
        showSmallToast('Mensagem copiada.');
      } catch (e) {
        showSmallToast('Não foi possível copiar a mensagem.');
      }
    });
  });
})();

(function () {
  const thread = document.getElementById('waThread');
  const form = document.getElementById('waReplyForm');
  const textarea = document.getElementById('waMessageField');
  const templateSelect = document.getElementById('waTemplateSelect');
  const attachmentField = document.getElementById('waAttachmentField');
  const sendBtn = document.getElementById('waSendBtn');
  const statusBox = document.getElementById('waComposeStatus');
  const toast = document.getElementById('waNotifyToast');
  const toastBody = document.getElementById('waNotifyToastBody');
  const replyInput = document.getElementById('waReplyToMessageId');

  if (!thread || !form || !sendBtn || !statusBox) return;

  let isPolling = false;
  let isSending = false;
  let stopped = false;
  let lastHtml = thread.innerHTML.trim();

  let waLastInboundId = null;
  let waOriginalTitle = document.title;
  const waAudio = new Audio('/assets/sounds/notification.mp3');
  waAudio.preload = 'auto';

  function showToast(messageText) {
    if (!toast || !toastBody) return;

    toastBody.textContent = messageText || 'Você recebeu uma nova mensagem.';
    toast.classList.add('is-show');

    window.clearTimeout(showToast._timer);
    showToast._timer = window.setTimeout(() => {
      toast.classList.remove('is-show');
    }, 3200);
  }

  function getLastInboundMetaFromRoot(root) {
    const rows = root.querySelectorAll('.wa-row[data-direction="inbound"]');
    if (!rows.length) {
      return null;
    }

    const last = rows[rows.length - 1];
    return {
      id: parseInt(last.getAttribute('data-message-id') || '0', 10),
      text: (last.getAttribute('data-notify-text') || 'Nova mensagem').trim()
    };
  }

  function initNotificationBaseline() {
    const meta = getLastInboundMetaFromRoot(thread);
    waLastInboundId = meta ? meta.id : 0;
  }

  function requestNotificationPermissionSilently() {
    if (!('Notification' in window)) return;

    if (Notification.permission === 'default') {
      Notification.requestPermission().catch(() => {});
    }
  }

  function playNotificationSound() {
    try {
      waAudio.currentTime = 0;
      waAudio.play().catch(() => {});
    } catch (e) {}
  }

  function showBrowserNotification(messageText) {
    if (!('Notification' in window)) return;
    if (Notification.permission !== 'granted') return;

    try {
      const n = new Notification('Nova mensagem WhatsApp', {
        body: messageText || 'Você recebeu uma nova mensagem',
        icon: '/assets/img/logo.png'
      });

      n.onclick = function () {
        window.focus();
        try { n.close(); } catch (e) {}
      };
    } catch (e) {}
  }

  function blinkTitle() {
    let count = 0;
    const interval = window.setInterval(() => {
      document.title = (count % 2 === 0) ? '🔔 Nova mensagem!' : waOriginalTitle;
      count += 1;

      if (count > 6) {
        window.clearInterval(interval);
        document.title = waOriginalTitle;
      }
    }, 800);
  }

  function handleInboundNotificationFromDoc(doc) {
    const newThread = doc.getElementById('waThread');
    if (!newThread) return;

    const meta = getLastInboundMetaFromRoot(newThread);
    if (!meta || meta.id <= 0) return;

    if (waLastInboundId === null) {
      waLastInboundId = meta.id;
      return;
    }

    if (meta.id > waLastInboundId) {
      waLastInboundId = meta.id;
      playNotificationSound();
      showBrowserNotification(meta.text);
      showToast(meta.text);
      blinkTitle();
    }
  }

  function showComposeStatus(type, message) {
    statusBox.className = 'wa-compose-status is-show is-' + type;
    statusBox.textContent = message;
  }

  function clearComposeStatusAfter(ms = 2200) {
    window.setTimeout(() => {
      statusBox.className = 'wa-compose-status';
      statusBox.textContent = '';
    }, ms);
  }

  function isNearBottom(el) {
    return (el.scrollHeight - el.scrollTop - el.clientHeight) < 120;
  }

  function scrollToBottom(el) {
    el.scrollTop = el.scrollHeight;
  }

  function parseHtml(html) {
    const parser = new DOMParser();
    return parser.parseFromString(html, 'text/html');
  }

  function syncHiddenInputsFromDoc(doc) {
    const newForm = doc.getElementById('waReplyForm');
    if (!newForm) return;

    const currentInputs = form.querySelectorAll('input[type="hidden"][name]');
    currentInputs.forEach((input) => {
      const fresh = newForm.querySelector('input[type="hidden"][name="' + input.name + '"]');
      if (fresh && input.name !== 'reply_to_message_id') {
        input.value = fresh.value;
      }
    });
  }

  function notifyInbox(contactId) {
    try {
      localStorage.setItem('stagix_wa_inbox_refresh', JSON.stringify({
        ts: Date.now(),
        contact_id: contactId
      }));
    } catch (e) {}
  }

  function replaceThread(newHtml, forceScroll = false) {
    const keepBottom = isNearBottom(thread);
    const previousTop = thread.scrollTop;

    thread.innerHTML = newHtml;
    lastHtml = newHtml.trim();

    if (forceScroll || keepBottom) {
      scrollToBottom(thread);
    } else {
      thread.scrollTop = previousTop;
    }
  }

  async function refreshThread(forceScroll = false, bypass = false) {
    if (stopped) return;

    if (!bypass) {
      if (isPolling || isSending) return;
      isPolling = true;
    }

    try {
      const url = new URL(window.location.href);
      url.searchParams.set('_wa_poll', String(Date.now()));

      const response = await fetch(url.toString(), {
        method: 'GET',
        credentials: 'same-origin',
        cache: 'no-store',
        headers: {
          'X-Requested-With': 'XMLHttpRequest'
        }
      });

      if (!response.ok) return;

      const html = await response.text();
      const doc = parseHtml(html);
      const newThread = doc.getElementById('waThread');

      if (!newThread) return;

      const newHtml = newThread.innerHTML.trim();
      if (newHtml === lastHtml) return;

      handleInboundNotificationFromDoc(doc);
      replaceThread(newHtml, forceScroll);
      syncHiddenInputsFromDoc(doc);
    } catch (e) {
    } finally {
      if (!bypass) {
        isPolling = false;
      }
    }
  }

  async function submitAjax(event) {
    event.preventDefault();

    if (isSending) return;

    const formData = new FormData(form);
    const messageValue = String(formData.get('message') || '').trim();
    const templateValue = String(formData.get('template_id') || '').trim();
    const hasFile = !!(attachmentField && attachmentField.files && attachmentField.files.length > 0);

    if (!hasFile && messageValue === '' && templateValue === '') {
      showComposeStatus('error', 'Digite uma mensagem, selecione um template ou anexe um arquivo.');
      clearComposeStatusAfter(2600);
      return;
    }

    isSending = true;
    const originalBtnText = sendBtn.textContent;

    sendBtn.disabled = true;
    sendBtn.textContent = hasFile ? 'Enviando anexo...' : 'Enviando...';

    if (textarea) textarea.disabled = true;
    if (templateSelect) templateSelect.disabled = true;
    if (attachmentField) attachmentField.disabled = true;

    showComposeStatus('info', hasFile ? 'Enviando anexo...' : 'Enviando mensagem...');

    try {
      const response = await fetch(form.action, {
        method: 'POST',
        credentials: 'same-origin',
        body: formData,
        headers: {
          'X-Requested-With': 'XMLHttpRequest',
          'Accept': 'application/json'
        }
      });

      const raw = await response.text();
      let data = null;

      try {
        data = JSON.parse(raw);
      } catch (e) {
        data = null;
      }

      if (!response.ok || !data || !data.success) {
        showComposeStatus('error', (data && data.message) ? data.message : 'Falha ao enviar a mensagem.');
        clearComposeStatusAfter(3600);
        return;
      }

      if (textarea) {
        textarea.value = '';
        textarea.dispatchEvent(new Event('input'));
        textarea.focus();
      }

      if (templateSelect) {
        templateSelect.value = '';
      }

      if (attachmentField) {
        attachmentField.value = '';
      }

      if (replyInput) {
        replyInput.value = '';
      }

      if (typeof window.waCloseReply === 'function') {
        window.waCloseReply();
      }

      const uploadName = document.getElementById('waUploadName');
      if (uploadName) uploadName.textContent = '';

      notifyInbox(<?= (int)$contact['id'] ?>);

      await refreshThread(true, true);
      window.setTimeout(() => refreshThread(true, true), 700);
      window.setTimeout(() => refreshThread(true, true), 1600);

      showComposeStatus('success', data.message || (hasFile ? 'Anexo enviado.' : 'Mensagem enviada.'));
      clearComposeStatusAfter();
    } catch (e) {
      showComposeStatus('error', 'Falha ao enviar. Recarregue a página e tente novamente.');
      clearComposeStatusAfter(3600);
    } finally {
      isSending = false;
      sendBtn.disabled = false;
      sendBtn.textContent = originalBtnText;

      if (textarea) textarea.disabled = false;
      if (templateSelect) templateSelect.disabled = false;
      if (attachmentField) attachmentField.disabled = false;
    }
  }

  if (textarea) {
    textarea.addEventListener('keydown', function (e) {
      if (e.key === 'Enter' && !e.shiftKey) {
        e.preventDefault();

        if (isSending) return;

        const hasText = textarea.value.trim() !== '';
        const hasFile = attachmentField && attachmentField.files.length > 0;
        const hasTemplate = templateSelect && templateSelect.value !== '';

        if (!hasText && !hasFile && !hasTemplate) return;

        form.requestSubmit();
      }
    });
  }

  document.addEventListener('visibilitychange', function () {
    if (!document.hidden) {
      document.title = waOriginalTitle;
    }
  });

  requestNotificationPermissionSilently();
  initNotificationBaseline();

  form.addEventListener('submit', submitAjax);

  const intervalId = window.setInterval(() => refreshThread(false, false), 4000);

  window.addEventListener('beforeunload', () => {
    stopped = true;
    window.clearInterval(intervalId);
  });
})();
</script>