<?php
require_once 'auth.php';
include 'db.php';
requireLogin($conn);

$role = $_SESSION['role'] ?? 'user';
$user_department = currentUserDepartment($conn);
$draft_id = (int) ($_GET['id'] ?? 0);
$is_edit = $draft_id > 0;
$current_document_type = 'Surat Rasmi';

if ($is_edit) {
    if (!currentUserCan($conn, 'draft_letter', 'update')) {
        echo "<script>alert('Anda tidak mempunyai kebenaran untuk mengubah surat ini.'); window.location='draft_letters.php';</script>";
        exit();
    }
} else {
    if (!currentUserCan($conn, 'draft_letter', 'create')) {
        echo "<script>alert('Anda tidak mempunyai kebenaran untuk menyediakan surat.'); window.location='draft_letters.php';</script>";
        exit();
    }
}

$folder_sql = "SELECT f.id, f.folder_name, f.folder_code, f.department,
        (SELECT ref_no FROM documents d WHERE d.folder_id = f.id AND d.deleted_at IS NULL ORDER BY d.id DESC LIMIT 1) AS latest_ref_no,
        (SELECT COUNT(*) FROM documents d WHERE d.folder_id = f.id AND d.deleted_at IS NULL) AS document_count
    FROM folders f
    WHERE f.deleted_at IS NULL AND f.closed_at IS NULL AND COALESCE(f.folder_type, 'office') <> 'sendirian'";
$folder_sql .= " AND f.department = ?";
$folder_sql .= " ORDER BY f.department, f.folder_name";
$folder_stmt = mysqli_prepare($conn, $folder_sql);
mysqli_stmt_bind_param($folder_stmt, "s", $user_department);
mysqli_stmt_execute($folder_stmt);
$folder_rows = mysqli_fetch_all(mysqli_stmt_get_result($folder_stmt), MYSQLI_ASSOC);
$folders = [];
foreach ($folder_rows as $folder_row) {
    $folder_row['next_ref_no'] = generateNextDocumentReference($folder_row['folder_code'] ?? '');
    $folder_row['next_file_numbering'] = (string) ((int) ($folder_row['document_count'] ?? 0) + 1);
    $folders[(int) $folder_row['id']] = $folder_row;
}

if (!$is_edit && empty($folders)) {
    echo "<script>alert('Tiada fail office aktif ditemui untuk bahagian anda. Sila wujudkan fail dahulu.'); window.location='list_folder.php';</script>";
    exit();
}

$document_types = [$current_document_type];
$letter_templates = getLetterTemplates($conn);
$memo_position_options = getMemoPositionOptions();
$departments_list = getDepartmentList();
$status_labels = getDraftLetterStatusList();
$current_user_id = (int) ($_SESSION['user_id'] ?? 0);
$department_head_users = getDepartmentHeadOfficerUsers($conn);
$management_signer_users = array_values(array_filter(getRegisteredSupportUsers($conn), function ($user) {
    return isManagementApprovalUser($user);
}));
$other_department_head_users = $department_head_users;
$routing_users = getMemoRoutingUsers($conn);
$surat_rasmi_all_staff_label = 'Semua Kakitangan';
$surat_rasmi_all_kbku_label = 'Semua KBKU';
$surat_rasmi_distribution_recipient_label = 'Seperti dalam Senarai Edaran';
$surat_rasmi_special_recipient_options = [$surat_rasmi_all_staff_label, $surat_rasmi_all_kbku_label, $surat_rasmi_distribution_recipient_label];
$surat_rasmi_recipient_users = [];
$surat_rasmi_recipient_user_stmt = mysqli_prepare($conn, "SELECT id, fullname, email, department, position, role FROM users WHERE status = 'approved' ORDER BY fullname");
if ($surat_rasmi_recipient_user_stmt) {
    mysqli_stmt_execute($surat_rasmi_recipient_user_stmt);
    $surat_rasmi_recipient_users = mysqli_fetch_all(mysqli_stmt_get_result($surat_rasmi_recipient_user_stmt), MYSQLI_ASSOC);
}
$distribution_staff = [];
$distribution_staff_stmt = mysqli_prepare($conn, "SELECT id, name, agency_type, position, department, agency, address FROM staff_distribution_list WHERE deleted_at IS NULL ORDER BY agency_type, name");
if ($distribution_staff_stmt) {
    mysqli_stmt_execute($distribution_staff_stmt);
    $distribution_staff = mysqli_fetch_all(mysqli_stmt_get_result($distribution_staff_stmt), MYSQLI_ASSOC);
}
$selected_distribution_staff = [];
$routing_user_count_by_position = [];
$routing_user_profiles_by_position = [];
$surat_rasmi_signatory_profiles_by_position = [];
foreach ($routing_users as $routing_user) {
    $routing_position = trim((string) ($routing_user['routing_position'] ?? ''));
    if ($routing_position !== '') {
        $routing_user_count_by_position[$routing_position] = ($routing_user_count_by_position[$routing_position] ?? 0) + 1;
        $routing_user_profiles_by_position[$routing_position][] = [
            'id' => (int) ($routing_user['id'] ?? 0),
            'name' => trim((string) ($routing_user['fullname'] ?? '')),
            'position' => trim((string) ($routing_user['position'] ?? $routing_position)),
        ];
        if (!isset($surat_rasmi_signatory_profiles_by_position[$routing_position])) {
            $surat_rasmi_signatory_profiles_by_position[$routing_position] = [
                'id' => (int) ($routing_user['id'] ?? 0),
                'name' => trim((string) ($routing_user['fullname'] ?? '')),
                'position' => getDisplayPositionForUser($routing_user),
                'department' => normalizeDepartmentValue($routing_user['department'] ?? ''),
            ];
        }
    }
}
foreach ($surat_rasmi_special_recipient_options as $special_option) {
    $routing_user_count_by_position[$special_option] = 0;
    $routing_user_profiles_by_position[$special_option] = [];
}
foreach ($surat_rasmi_recipient_users as $recipient_user) {
    $routing_user_count_by_position[$surat_rasmi_all_staff_label]++;
    $routing_user_profiles_by_position[$surat_rasmi_all_staff_label][] = [
        'id' => (int) ($recipient_user['id'] ?? 0),
        'name' => trim((string) ($recipient_user['fullname'] ?? '')),
        'position' => getDisplayPositionForUser($recipient_user),
    ];
    if (isHeadOfficerPosition($recipient_user['position'] ?? '') && normalizeDepartmentValue($recipient_user['department'] ?? '') !== 'Pengurusan') {
        $routing_user_count_by_position[$surat_rasmi_all_kbku_label]++;
        $routing_user_profiles_by_position[$surat_rasmi_all_kbku_label][] = [
            'id' => (int) ($recipient_user['id'] ?? 0),
            'name' => trim((string) ($recipient_user['fullname'] ?? '')),
            'position' => getDisplayPositionForUser($recipient_user),
        ];
    }
}
$current_user_row = null;
$current_user_stmt = mysqli_prepare($conn, "SELECT id, fullname, short_name, email, department, position FROM users WHERE id = ? LIMIT 1");
if ($current_user_stmt) {
    mysqli_stmt_bind_param($current_user_stmt, "i", $current_user_id);
    mysqli_stmt_execute($current_user_stmt);
    $current_user_row = mysqli_fetch_assoc(mysqli_stmt_get_result($current_user_stmt));
}
$current_user_is_head_officer = isHeadOfficerPosition($current_user_row['position'] ?? '');
$attachment_map = [];
$draft = null;
$is_department_officer_revision_editor = false;

if ($is_edit) {
    $draft_sql = "SELECT ld.*, f.folder_name, f.folder_code, f.department AS folder_department, d.id AS document_exists,
            d.file_numbering,
            creator.short_name AS created_by_short_name,
            creator.fullname AS created_by_fullname,
            (SELECT COUNT(*) FROM documents d2 WHERE d2.folder_id = ld.folder_id AND d2.deleted_at IS NULL AND d2.id <= ld.document_id) AS computed_file_numbering
        FROM letter_drafts ld
        INNER JOIN folders f ON f.id = ld.folder_id
        LEFT JOIN documents d ON d.id = ld.document_id AND d.deleted_at IS NULL
        LEFT JOIN users creator ON creator.id = ld.created_by
        WHERE ld.id = ? AND ld.deleted_at IS NULL
        LIMIT 1";
    $draft_stmt = mysqli_prepare($conn, $draft_sql);
    mysqli_stmt_bind_param($draft_stmt, "i", $draft_id);
    mysqli_stmt_execute($draft_stmt);
    $draft = mysqli_fetch_assoc(mysqli_stmt_get_result($draft_stmt));

    if (!$draft) {
        header("Location: draft_letters.php?error=not_found");
        exit();
    }

    if (($draft['approval_status'] ?? '') === 'lulus') {
        header("Location: draft_letter_print.php?id={$draft_id}");
        exit();
    }

    $is_draft_creator = (int) ($draft['created_by'] ?? 0) === $current_user_id;
    $is_department_officer_revision_editor = ($draft['approval_status'] ?? '') === 'sedang_dipinda_ketua_bahagian'
        && (int) ($draft['approval_stage'] ?? 0) === 1
        && (int) ($draft['department_officer_user_id'] ?? 0) === $current_user_id;
    $is_private_draft = ($draft['status'] ?? 'draf') === 'draf' || ($draft['approval_status'] ?? 'draft') === 'draft';
    if ($is_private_draft && !$is_draft_creator && $role !== 'superadmin' && !$is_department_officer_revision_editor) {
        header("Location: draft_letters.php?error=unauthorized");
        exit();
    }
    if (($draft['approval_status'] ?? '') === 'sedang_dipinda_ketua_bahagian' && !$is_department_officer_revision_editor) {
        header("Location: draft_letter_print.php?id={$draft_id}&support_error=revision_locked");
        exit();
    }

    if (!isSameDepartmentDb($conn, $draft['department'] ?? '', $user_department)) {
        header("Location: draft_letters.php?error=unauthorized");
        exit();
    }

    $selected_staff_json = $draft['distribution_staff_list'] ?? '';
    if ($selected_staff_json !== '') {
        $selected_distribution_staff = function_exists('normalizeStaffDistributionIds')
            ? normalizeStaffDistributionIds($selected_staff_json)
            : (json_decode($selected_staff_json, true) ?: []);
    }

    if (!isset($folders[(int) $draft['folder_id']])) {
        $folders[(int) $draft['folder_id']] = [
            'id' => (int) $draft['folder_id'],
            'folder_name' => $draft['folder_name'] ?? 'Fail',
            'folder_code' => $draft['folder_code'] ?? '',
            'department' => $draft['department'] ?? '',
            'latest_ref_no' => $draft['ref_no'] ?? '',
            'next_ref_no' => $draft['ref_no'] ?? '',
            'next_file_numbering' => $draft['file_numbering'] ?? '',
        ];
    }

    $doc_map = getDocumentAttachmentsMap($conn, [['id' => (int) ($draft['document_id'] ?? 0)]]);
    $attachment_map = $doc_map[(int) ($draft['document_id'] ?? 0)] ?? [];
}

$include_distribution_page_checked = ((int) ($draft['include_distribution_page'] ?? 0) === 1)
    && !empty($selected_distribution_staff);
$distribution_page_content_value = (string) ($draft['distribution_page_content'] ?? '');
if (!$include_distribution_page_checked) {
    $selected_distribution_staff = [];
    $distribution_page_content_value = '';
} elseif (function_exists('isStaffDistributionPageContentInvalid') && isStaffDistributionPageContentInvalid($distribution_page_content_value)) {
    $distribution_page_content_value = '';
}

$default_folder = reset($folders);
$selected_folder_id = $is_edit ? (int) ($draft['folder_id'] ?? 0) : (int) ($_GET['folder_id'] ?? ($default_folder['id'] ?? 0));
if (!isset($folders[$selected_folder_id]) && $default_folder) {
    $selected_folder_id = (int) $default_folder['id'];
}
$selected_folder = $folders[$selected_folder_id] ?? $default_folder;
$current_user_signature_path = getUserSignaturePath($conn, (int) ($_SESSION['user_id'] ?? 0));
$selected_department_head_user = getDepartmentHeadOfficerByDepartment($conn, $selected_folder['department'] ?? ($current_user_row['department'] ?? ($_SESSION['department'] ?? '')));
$excluded_approval_route_positions = [];
if ($selected_department_head_user) {
    $selected_head_routing_position = getMemoRoutingPositionForUser($selected_department_head_user);
    if ($selected_head_routing_position !== '') {
        $excluded_approval_route_positions[] = $selected_head_routing_position;
    }
}
$prepared_by_short_name = trim((string) ($is_edit
    ? ($draft['created_by_short_name'] ?? ($draft['created_by_fullname'] ?? ''))
    : ($current_user_row['short_name'] ?? ($_SESSION['short_name'] ?? ($_SESSION['fullname'] ?? '')))
));

$form_values = [
    'folder_id' => $selected_folder_id,
    'template_id' => (int) ($draft['template_id'] ?? ($letter_templates[0]['template_id'] ?? 0)),
    'subject' => $draft['subject'] ?? '',
    'letter_date' => $draft['letter_date'] ?? date('Y-m-d'),
    'doc_type' => $draft['doc_type'] ?? $current_document_type,
    'recipient_name' => $draft['recipient_name'] ?? '',
    'recipient_organization' => $draft['recipient_organization'] ?? '',
    'recipient_address' => $draft['recipient_address'] ?? '',
    'attention_to' => $draft['attention_to'] ?? '',
    'routing_positions' => decodeMemoRoutingPositions($draft['routing_positions'] ?? ''),
    'greeting' => $draft['greeting'] ?? 'Tuan/Puan,',
    'letter_body' => $draft['letter_body'] ?? '',
    'letter_pages' => decodeDraftLetterPages($draft['letter_pages'] ?? '', $draft['letter_body'] ?? ''),
    'approval_page_body' => $draft['approval_page_body'] ?? '',
    'approval_route_bodies' => decodeDraftApprovalRouteBodies($draft['approval_route_bodies'] ?? ''),
    'page_number_position' => in_array($draft['page_number_position'] ?? '', ['none', 'bottom_center', 'bottom_right'], true)
        ? $draft['page_number_position']
        : 'none',
    'page_header_text' => $draft['page_header_text'] ?? '',
    'page_footer_text' => $draft['page_footer_text'] ?? '',
    'closing_text' => $draft['closing_text'] ?? '',
    'signatory_name' => $draft['signatory_name'] ?? ($selected_department_head_user['fullname'] ?? ($_SESSION['fullname'] ?? '')),
    'signatory_position' => $draft['signatory_position'] ?? ($selected_department_head_user['position'] ?? getMemoDepartmentHeadPosition($selected_folder['department'] ?? ($current_user_row['department'] ?? ($_SESSION['department'] ?? '')))),
    'signatory_department' => $draft['signatory_department'] ?? ($selected_department_head_user['department'] ?? ($selected_folder['department'] ?? ($_SESSION['department'] ?? ''))),
    'signatory_signature_path' => $draft['signatory_signature_path'] ?? '',
    'status' => $draft['status'] ?? 'siap',
    'support_user_id' => (int) ($draft['support_user_id'] ?? 0),
    'approval_flow' => 'two_level',
    'department_officer_user_id' => (int) ($draft['department_officer_user_id'] ?? 0),
];
$selected_management_signer_user_id = 0;
$selected_other_department_head_user_id = 0;
if ($is_edit) {
    $existing_approval_recipients = getLetterApprovalRecipients($conn, $draft_id);
    foreach ($existing_approval_recipients as $existing_approval_recipient) {
        $existing_signer_user_id = (int) ($existing_approval_recipient['user_id'] ?? 0);
        if ($existing_signer_user_id <= 0) {
            continue;
        }
        $existing_signer_user = null;
        foreach (array_merge($management_signer_users, $department_head_users) as $candidate_signer_user) {
            if ((int) ($candidate_signer_user['id'] ?? 0) === $existing_signer_user_id) {
                $existing_signer_user = $candidate_signer_user;
                break;
            }
        }
        if ($existing_signer_user && isManagementApprovalUser($existing_signer_user)) {
            $selected_management_signer_user_id = $existing_signer_user_id;
            break;
        }
        if (
            $existing_signer_user
            && isHeadOfficerPosition($existing_signer_user['position'] ?? '')
            && !isSameDepartment($existing_signer_user['department'] ?? '', $selected_folder['department'] ?? '')
        ) {
            $selected_other_department_head_user_id = $existing_signer_user_id;
            break;
        }
    }
}
$signatory_target = 'department_head';
if ($selected_department_head_user && (!$is_edit || trim((string) $form_values['signatory_position']) === '')) {
    $form_values['signatory_name'] = $selected_department_head_user['fullname'] ?? $form_values['signatory_name'];
    $form_values['signatory_department'] = $selected_department_head_user['department'] ?? $form_values['signatory_department'];
    $form_values['signatory_position'] = getDisplayPositionForUser($selected_department_head_user, $form_values['signatory_department']) ?: $form_values['signatory_position'];
    $form_values['department_officer_user_id'] = (int) ($selected_department_head_user['id'] ?? 0);
}
$routing_candidate_positions = $memo_position_options['Ketua Bahagian'] ?? [];
foreach ([$form_values['recipient_organization'], $form_values['attention_to']] as $selected_memo_position) {
    if ($selected_memo_position !== '' && !in_array($selected_memo_position, $routing_candidate_positions, true)) {
        $routing_candidate_positions[] = $selected_memo_position;
    }
}
foreach ($form_values['routing_positions'] as $saved_routing_position) {
    if ($saved_routing_position !== '' && !in_array($saved_routing_position, $routing_candidate_positions, true)) {
        $routing_candidate_positions[] = $saved_routing_position;
    }
}
$routing_candidate_positions = array_values(array_filter($routing_candidate_positions, function ($position) use ($excluded_approval_route_positions) {
    return !in_array($position, $excluded_approval_route_positions, true);
}));
$form_values['routing_positions'] = array_values(array_filter($form_values['routing_positions'], function ($position) use ($excluded_approval_route_positions) {
    return !in_array($position, $excluded_approval_route_positions, true);
}));
$routing_order_by_position = [];
foreach ($form_values['routing_positions'] as $routing_index => $routing_position) {
    $routing_order_by_position[$routing_position] = $routing_index + 1;
}
$routing_order_limit = max(1, count(array_unique(array_column($routing_users, 'routing_position'))));
$display_file_numbering = ($is_edit && (($draft['status'] ?? 'draf') === 'siap'))
    ? (($draft['file_numbering'] ?? '') !== '' && ($draft['file_numbering'] ?? '') !== 'X' && ($draft['file_numbering'] ?? '') !== ($draft['ref_no'] ?? '')
        ? ($draft['file_numbering'] ?? '')
        : ($draft['computed_file_numbering'] ?? ''))
    : 'X';

$current_ref_display = formatDraftLetterReferenceDisplay(
    $form_values['signatory_department'] ?: ($selected_folder['department'] ?? ''),
    $is_edit ? ($draft['ref_no'] ?? '') : ($selected_folder['next_ref_no'] ?? ''),
    $display_file_numbering
);
$selected_template = null;
foreach ($letter_templates as $template_row) {
    if ((int) ($template_row['template_id'] ?? 0) === (int) $form_values['template_id']) {
        $selected_template = $template_row;
        break;
    }
}
if (false && !$is_edit && $selected_template && trim(implode('', array_map('strip_tags', $form_values['letter_pages']))) === '') {
    $initial_template_html = replaceLetterTemplatePlaceholders($selected_template['template_content'] ?? '', [
        'reference_no' => $current_ref_display,
        'date' => formatMalayMemoDate($form_values['letter_date']),
        'receiver_name' => $form_values['recipient_organization'],
        'receiver_department' => 'Majlis Agama Islam Negeri Pulau Pinang',
        'subject' => $form_values['subject'],
        'letter_content' => '',
        'sender_name' => $form_values['signatory_name'],
        'sender_position' => $form_values['signatory_position'],
        'sender_department' => $form_values['signatory_department'],
    ]);
    if (trim(strip_tags($initial_template_html)) !== '') {
        $form_values['letter_body'] = $initial_template_html;
        $form_values['letter_pages'] = [$initial_template_html];
    }
}
$surat_rasmi_first_page_ref_line = htmlspecialchars($current_ref_display ?: '-', ENT_QUOTES);
$surat_rasmi_first_page_date_line = htmlspecialchars(formatMalayMemoDate($form_values['letter_date']), ENT_QUOTES);
$surat_rasmi_first_page_starter_html = '<p data-surat-rasmi-generated-line="ref" contenteditable="false" style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; margin-left: 2.54cm;">' . $surat_rasmi_first_page_ref_line . '</p>'
    . '<p data-surat-rasmi-generated-line="date" contenteditable="false" style="font-family: Arial, Helvetica, sans-serif; font-size: 15.5px; line-height: 1.25; margin-left: 2.54cm;">' . $surat_rasmi_first_page_date_line . '</p>'
    . '<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5;"><br></p>';
if (trim(implode('', array_map('strip_tags', $form_values['letter_pages']))) === '') {
    $form_values['letter_body'] = $surat_rasmi_first_page_starter_html;
    $form_values['letter_pages'] = [$surat_rasmi_first_page_starter_html];
}
$preparer_is_signed = !empty($form_values['signatory_signature_path']) && file_exists(__DIR__ . '/' . $form_values['signatory_signature_path']);
$department_officer_recorded_signature_path = '';
if ($is_edit && $is_department_officer_revision_editor) {
    $recorded_department_signature = trim((string) ($draft['department_officer_signature_path'] ?? ''));
    if ($recorded_department_signature !== '' && is_file(__DIR__ . '/' . $recorded_department_signature)) {
        $department_officer_recorded_signature_path = $recorded_department_signature;
    } else {
        $recorded_signatory_signature = trim((string) ($draft['signatory_signature_path'] ?? ''));
        $department_officer_status = trim((string) ($draft['department_officer_status'] ?? ''));
        if ($department_officer_status === 'lulus' && $recorded_signatory_signature !== '' && is_file(__DIR__ . '/' . $recorded_signatory_signature)) {
            $department_officer_recorded_signature_path = $recorded_signatory_signature;
        }
    }
}

$error_message = '';
if (isset($_GET['error'])) {
    if ($_GET['error'] === 'validation') {
        $error_detail = (string) ($_GET['msg'] ?? '');
        if ($error_detail === 'preparer_signature_required') {
            $error_message = 'Sila klik Tandatangan sebelum menghantar surat.';
        } elseif ($error_detail === 'preparer_signature_missing') {
            $error_message = 'Tandatangan belum didaftarkan dalam profil pengguna.';
        } elseif ($error_detail === 'signature_invalid') {
            $error_message = 'Tandatangan digital tidak sah. Sila cuba semula.';
        } elseif ($error_detail === 'closing_required_before_signature') {
            $error_message = 'Closing perlu dijana terlebih dahulu sebelum tandatangan boleh dibuat.';
        } elseif ($error_detail === 'distribution_recipient_required') {
            $error_message = 'Sila aktifkan dan pilih penerima dalam Senarai Edaran.';
        } else {
            $error_message = 'Sila lengkapkan semua maklumat surat yang wajib.';
        }
    } elseif ($_GET['error'] === 'folder') {
        $error_message = 'Fail yang dipilih tidak sah atau tidak lagi aktif.';
    } elseif ($_GET['error'] === 'folder_closed') {
        $error_message = 'Fail yang dipilih telah ditutup. Surat baharu tidak boleh diwujudkan dalam fail tersebut.';
    } elseif ($_GET['error'] === 'document_missing') {
        $error_message = 'Rekod dokumen berkaitan tidak ditemui. Sila semak semula draf ini.';
    } elseif ($_GET['error'] === 'unauthorized') {
        $error_message = 'Anda tidak mempunyai kebenaran untuk tindakan ini.';
    } elseif ($_GET['error'] === 'system' && isset($_GET['msg'])) {
        $error_message = 'Ralat sistem: ' . urldecode((string) $_GET['msg']);
    } elseif ($_GET['error'] === 'attachment_not_found') {
        $error_message = 'Lampiran sokongan tidak dijumpai.';
    } elseif ($_GET['error'] === 'attachment_delete_failed') {
        $error_message = 'Lampiran sokongan gagal dipadam.';
    }
}

$success_message = '';
if (isset($_GET['success']) && $_GET['success'] === 'attachment_deleted') {
    $success_message = 'Lampiran sokongan berjaya dipadam.';
}

function sanitizeDraftEditorInlineStyle($style) {
    $safe_styles = [];
    foreach (explode(';', (string) $style) as $declaration) {
        $parts = explode(':', $declaration, 2);
        if (count($parts) !== 2) {
            continue;
        }
        $property = strtolower(trim($parts[0]));
        $value = trim($parts[1]);
        if ($property === 'text-align' && preg_match('/^(left|center|right|justify)$/i', $value)) {
            $safe_styles[] = 'text-align: ' . strtolower($value);
        } elseif ($property === 'margin-left' && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = 'margin-left: ' . strtolower($value);
        } elseif (in_array($property, ['height', 'min-height', 'width', 'min-width'], true) && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = $property . ': ' . strtolower($value);
        } elseif ($property === 'display' && strtolower($value) === 'flex') {
            $safe_styles[] = 'display: flex';
        } elseif ($property === 'align-items' && strtolower($value) === 'center') {
            $safe_styles[] = 'align-items: center';
        } elseif ($property === 'justify-content' && in_array(strtolower($value), ['center', 'flex-start'], true)) {
            $safe_styles[] = 'justify-content: ' . strtolower($value);
        } elseif ($property === 'margin' && preg_match('/^(?:0|[0-9]+(?:\.[0-9]+)?(?:cm|mm|pt|px))$/i', $value)) {
            $safe_styles[] = 'margin: ' . strtolower($value);
        } elseif (in_array($property, ['line-height', 'font-size', 'font-family'], true)) {
            continue;
        }
    }

    $safe_styles[] = 'font-family: Arial, Helvetica, sans-serif';
    $safe_styles[] = 'font-size: 16px';
    $safe_styles[] = 'line-height: 1.5';

    return implode('; ', array_unique($safe_styles));
}

function sanitizeDraftEditorImageTags($html) {
    return preg_replace_callback('/<img\b[^>]*>/i', function ($matches) {
        $tag = $matches[0];
        if (!preg_match('/\s+src\s*=\s*(["\'])(.*?)\1/i', $tag, $src_match)) {
            return '';
        }

        $src = str_replace('\\', '/', trim(html_entity_decode($src_match[2], ENT_QUOTES)));
        if (!preg_match('#^uploads/signatures/[A-Za-z0-9._/-]+\.(?:png|jpe?g|gif|webp)$#i', $src)) {
            return '';
        }

        if (!is_file(__DIR__ . '/' . $src)) {
            return '';
        }

        return '<img src="' . htmlspecialchars($src, ENT_QUOTES) . '" alt="Tandatangan Digital" style="max-width:150px;max-height:58px;object-fit:contain;">';
    }, $html);
}

function applyDraftBodyTypography($html) {
    $html = trim((string) $html);
    if ($html === '') {
        return '';
    }

    return preg_replace_callback('/<(p|div|li|td|th|blockquote|h3|h4|span)(\s[^>]*)?>/i', function ($matches) {
        $tag = $matches[1];
        $attrs = $matches[2] ?? '';

        if (preg_match('/style\s*=\s*(["\'])(.*?)\1/i', $attrs, $style_match)) {
            $quote = $style_match[1];
            $safe_style = sanitizeDraftEditorInlineStyle($style_match[2]);
            $attrs = preg_replace(
                '/style\s*=\s*(["\']).*?\1/i',
                'style=' . $quote . htmlspecialchars($safe_style, ENT_QUOTES) . $quote,
                $attrs,
                1
            );
        } else {
            $attrs .= ' style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5"';
        }

        return '<' . $tag . $attrs . '>';
    }, $html);
}

function normalizeQuillListHtml($html) {
    $html = (string) $html;
    if (stripos($html, 'data-list') === false && stripos($html, 'ql-ui') === false) {
        return $html;
    }

    $html = preg_replace('/<span\b(?=[^>]*\bclass\s*=\s*(["\'])[^"\']*\bql-ui\b[^"\']*\1)[^>]*>\s*<\/span>/i', '', $html);
    return preg_replace_callback('/<ol\b([^>]*)>(.*?)<\/ol>/is', function ($matches) {
        $content = $matches[2];
        if (stripos($content, 'data-list') === false) {
            return $matches[0];
        }

        preg_match_all('/<li\b([^>]*)>(.*?)<\/li>/is', $content, $items, PREG_SET_ORDER);
        if (empty($items)) {
            return $matches[0];
        }

        $html_parts = [];
        $current_type = '';
        foreach ($items as $item) {
            $attrs = $item[1] ?? '';
            $item_type = preg_match('/\bdata-list\s*=\s*(["\'])bullet\1/i', $attrs) ? 'ul' : 'ol';
            $attrs = preg_replace('/\s*data-list\s*=\s*(["\']).*?\1/i', '', $attrs);
            $attrs = preg_replace('/\s*data-list\s*=\s*[^\s>]+/i', '', $attrs);
            if ($current_type !== $item_type) {
                if ($current_type !== '') {
                    $html_parts[] = '</' . $current_type . '>';
                }
                $current_type = $item_type;
                $html_parts[] = '<' . $current_type . '>';
            }
            $html_parts[] = '<li' . $attrs . '>' . $item[2] . '</li>';
        }
        if ($current_type !== '') {
            $html_parts[] = '</' . $current_type . '>';
        }

        return implode('', $html_parts);
    }, $html);
}

function renderDraftEditorBody($body) {
    $body = trim((string) $body);
    $default_intro_html = '<p><br></p>';
    $default_body = applyDraftBodyTypography($default_intro_html);
    if ($body === '' || preg_match('/^\s*(?:<p[^>]*>\s*)?-?\s*(?:<\/p>)?\s*$/i', $body)) {
        return $default_body;
    }

    $allowed_tags = '<p><br><strong><b><em><i><u><ol><ul><li><table><thead><tbody><tr><th><td><colgroup><col><blockquote><h3><h4><div><span><img>';
    $body = preg_replace('/(<div\b[^>]*class\s*=\s*(["\'])generated-closing-lock\s+signature-block\2)\s+signature-block(?:"|\')/i', '$1', $body);
    $body = normalizeQuillListHtml($body);
    $sanitized = strip_tags($body, $allowed_tags);
    $sanitized = preg_replace('/\s+on[a-z]+\s*=\s*(".*?"|\'.*?\'|[^\s>]+)/i', '', $sanitized);
    $sanitized = preg_replace_callback('/\s+style\s*=\s*(["\'])(.*?)\1/i', function ($matches) {
        $safe_style = sanitizeDraftEditorInlineStyle($matches[2]);
        return $safe_style !== '' ? ' style="' . htmlspecialchars($safe_style, ENT_QUOTES) . '"' : '';
    }, $sanitized);
    $sanitized = preg_replace('/\s+style\s*=\s*(?!["\'])[^\s>]+/i', '', $sanitized);
    $sanitized = preg_replace('/\s+id\s*=\s*(".*?"|\'.*?\'|[^\s>]+)/i', '', $sanitized);
    $sanitized = preg_replace_callback('/\s+class\s*=\s*(["\'])(.*?)\1/i', function ($matches) {
        $classes = preg_split('/\s+/', trim((string) $matches[2]));
        $allowed_classes = array_values(array_intersect($classes, ['generated-closing-lock', 'signature-block']));
        return !empty($allowed_classes) ? ' class="' . htmlspecialchars(implode(' ', $allowed_classes), ENT_QUOTES) . '"' : '';
    }, $sanitized);
    $sanitized = preg_replace_callback('/\s+class\s*=\s*(?!["\'])([^\s>]+)/i', function ($matches) {
        $classes = preg_split('/\s+/', trim((string) $matches[1]));
        $allowed_classes = array_values(array_intersect($classes, ['generated-closing-lock', 'signature-block']));
        return !empty($allowed_classes) ? ' class="' . htmlspecialchars(implode(' ', $allowed_classes), ENT_QUOTES) . '"' : '';
    }, $sanitized);
    $sanitized = preg_replace('/<div\b(?=[^>]*data-generated-closing\s*=\s*(["\'])1\1)(?![^>]*\sclass\s*=)/i', '<div class="generated-closing-lock signature-block"', $sanitized);
    $sanitized = preg_replace('/javascript\s*:/i', '', $sanitized);
    $sanitized = sanitizeDraftEditorImageTags($sanitized);

    if (strip_tags($body) === $body) {
        $paragraphs = preg_split("/\n\s*\n/", str_replace(["\r\n", "\r"], "\n", $body));
        $html = '';
        foreach ($paragraphs as $paragraph) {
            $paragraph = trim($paragraph);
            if ($paragraph !== '') {
                $html .= '<p style="font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5">' . nl2br(htmlspecialchars($paragraph)) . '</p>';
            }
        }
        $sanitized = $html;
    }

    $sanitized = preg_replace('/^\s*<p[^>]*>\s*-\s*<\/p>\s*/i', '', $sanitized);
    $sanitized = preg_replace('/<p\b([^>]*)>\s*3\.\s*(?:&nbsp;|\s|<br\s*\/?>)*<\/p>/i', '', $sanitized);
    $sanitized = applyDraftBodyTypography($sanitized);

    return $sanitized !== '' ? $sanitized : $default_body;
}

function formatMalayMemoDate($date) {
    $timestamp = strtotime((string) $date);
    if (!$timestamp) {
        return '-';
    }

    $months = [
        1 => 'Januari', 2 => 'Februari', 3 => 'Mac', 4 => 'April',
        5 => 'Mei', 6 => 'Jun', 7 => 'Julai', 8 => 'Ogos',
        9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Disember',
    ];

    return date('d', $timestamp) . ' ' . $months[(int) date('n', $timestamp)] . ' ' . date('Y', $timestamp);
}

function renderMemoPositionSelectOptions($memo_position_options, $selected_value, $special_options = []) {
    $selected_value = trim((string) $selected_value);
    $selected_found = false;

    if (!empty($special_options)) {
        echo '<optgroup label="Pilihan Khas">';
        foreach ($special_options as $special_option) {
            $selected = $selected_value === $special_option ? ' selected' : '';
            if ($selected !== '') {
                $selected_found = true;
            }
            echo '<option value="' . htmlspecialchars($special_option) . '"' . $selected . '>' . htmlspecialchars($special_option) . '</option>';
        }
        echo '</optgroup>';
    }

    foreach ($memo_position_options as $group_label => $positions) {
        echo '<optgroup label="' . htmlspecialchars($group_label) . '">';
        foreach ($positions as $position) {
            $selected = $selected_value === $position ? ' selected' : '';
            if ($selected !== '') {
                $selected_found = true;
            }
            echo '<option value="' . htmlspecialchars($position) . '"' . $selected . '>' . htmlspecialchars($position) . '</option>';
        }
        echo '</optgroup>';
    }

    if ($selected_value !== '' && !$selected_found) {
        echo '<option value="' . htmlspecialchars($selected_value) . '" selected>' . htmlspecialchars($selected_value) . '</option>';
    }
}

function splitMemoPositionValues($value) {
    if (is_array($value)) {
        $items = $value;
    } else {
        $items = preg_split('/\r\n|\r|\n/', (string) $value);
    }

    $normalized = [];
    foreach ($items as $item) {
        $item = trim((string) $item);
        if ($item !== '' && !in_array($item, $normalized, true)) {
            $normalized[] = $item;
        }
    }
    return $normalized;
}

function renderMemoPositionCheckboxDropdown($memo_position_options, $field_id, $field_label, $selected_values, $special_options = []) {
    $selected_values = splitMemoPositionValues($selected_values);
    $selected_lookup = array_fill_keys($selected_values, true);
    $input_name = $field_id . '_checked[]';
    ?>
    <div class="memo-check-dropdown" data-target-select="<?= htmlspecialchars($field_id) ?>">
        <button type="button" class="memo-check-toggle">
            <span class="memo-check-summary">Pilih tambahan</span>
            <i class="fas fa-chevron-down"></i>
        </button>
        <div class="memo-check-menu" aria-label="<?= htmlspecialchars($field_label) ?>">
            <?php if (!empty($special_options)): ?>
            <div class="memo-check-group">Pilihan Khas</div>
            <?php foreach ($special_options as $special_option): ?>
            <label class="memo-check-option">
                <input
                    type="checkbox"
                    name="<?= htmlspecialchars($input_name) ?>"
                    value="<?= htmlspecialchars($special_option) ?>"
                    <?= isset($selected_lookup[$special_option]) ? 'checked' : '' ?>
                >
                <span><?= htmlspecialchars($special_option) ?></span>
            </label>
            <?php endforeach; ?>
            <?php endif; ?>
            <?php foreach ($memo_position_options as $group_label => $positions): ?>
            <div class="memo-check-group"><?= htmlspecialchars($group_label) ?></div>
            <?php foreach ($positions as $position): ?>
            <label class="memo-check-option">
                <input
                    type="checkbox"
                    name="<?= htmlspecialchars($input_name) ?>"
                    value="<?= htmlspecialchars($position) ?>"
                    <?= isset($selected_lookup[$position]) ? 'checked' : '' ?>
                >
                <span><?= htmlspecialchars($position) ?></span>
            </label>
            <?php endforeach; ?>
            <?php endforeach; ?>
        </div>
    </div>
    <?php
}

function renderMemoDisplayValue($value) {
    $positions = splitMemoPositionValues($value);
    if (empty($positions)) {
        return '-';
    }

    $rows = [];
    foreach ($positions as $position) {
        $rows[] = htmlspecialchars($position) . '<br>Majlis Agama Islam Negeri Pulau Pinang';
    }
    return implode('<br>', $rows);
}
?>
<!DOCTYPE html>
<html lang="ms">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><?= $is_edit ? 'Ubah ' . htmlspecialchars($current_document_type) : 'Sediakan ' . htmlspecialchars($current_document_type) ?> | MAINPP WORKSPACE</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="assets/vendor/quill/quill.snow.css">
        <?php renderAppShellAssets(); ?>
    <style>
        :root {
            --primary: #0077b6; --primary-dark: #005f99; --secondary: #00b4d8;
            --superadmin: #6c5ce7; --superadmin-dark: #5b4cdb;
            --bg-light: #f8fbfd; --bg-card: #ffffff; --text-main: #1a3a5c;
            --text-muted: #6c757d; --border: #e0e8f0; --sidebar-width: 240px;
            --success: #1a9955; --danger: #dc3545; --warning: #ffc107;
            --draft: #0f766e;
        }
        * { box-sizing: border-box; margin: 0; padding: 0; font-family: 'Segoe UI', 'Inter', Tahoma, Geneva, Verdana, sans-serif; }
        body { background: linear-gradient(135deg, #e0f7fa 0%, #f1f8e9 100%); min-height: 100vh; display: flex; color: var(--text-main); }

        .sidebar { width: var(--sidebar-width); background: linear-gradient(180deg, #fff 0%, #f8fbfd 100%); border-right: 1px solid var(--border); position: fixed; height: 100vh; padding: 20px 0; overflow-y: auto; overflow-x: hidden; z-index: 1000; box-shadow: 2px 0 10px rgba(0,0,0,0.03); transition: width 0.3s ease; display:flex; flex-direction:column; }
        .sidebar.collapsed { width: 70px; }
        .sidebar-header { text-align: center; padding: 0 20px 20px; border-bottom: 1px solid var(--border); margin-bottom: 20px; white-space: nowrap; overflow: hidden; }
        .sidebar.collapsed .sidebar-header h3, .sidebar.collapsed .sidebar-header p, .sidebar.collapsed .menu-text { display: none; }
        .sidebar-header img { width: 50px; margin-bottom: 10px; transition: margin 0.3s ease; }
        .sidebar.collapsed .sidebar-header img { margin: 0 auto 10px; }
        .sidebar-header h3 { font-size: 1rem; font-weight: 700; color: var(--primary); margin-bottom: 4px; }
        .sidebar-header p { font-size: 0.75rem; color: var(--text-muted); }
        .role-badge { display: inline-block; padding: 3px 10px; border-radius: 12px; font-size: 0.7rem; font-weight: 600; margin-left: 8px; }
        .role-badge.user { background: #e6f4ff; color: var(--primary); }
        .role-badge.admin { background: #d4edda; color: var(--success); }
        .role-badge.superadmin { background: linear-gradient(90deg, var(--superadmin), var(--superadmin-dark)); color: #fff; }
        .sidebar-menu { list-style: none; padding: 0 10px; display:flex; flex-direction:column; flex:1; }
        .sidebar-section { padding: 10px 18px 6px; color: var(--text-muted); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }
        .sidebar-spacer { margin-top: auto; }
        .sidebar-menu li a { display: flex; align-items: center; gap: 12px; padding: 12px 18px; color: var(--text-main); text-decoration: none; border-radius: 8px; margin-bottom: 4px; transition: all 0.2s ease; font-size: 0.9rem; white-space: nowrap; }
        .sidebar-menu li a:hover, .sidebar-menu li a.active { background: linear-gradient(90deg, var(--primary), var(--secondary)); color: #fff; }
        .sidebar-menu li a i { width: 20px; text-align: center; font-size: 1.1rem; }
        .sidebar-menu .dropdown { position: relative; }
        .sidebar-menu .dropdown-toggle { display: flex; align-items: center; justify-content: space-between; width: 100%; padding: 12px 18px; color: var(--text-main); background: none; border: none; border-radius: 8px; cursor: pointer; font-size: 0.9rem; text-align: left; transition: all 0.2s ease; }
        .sidebar-menu .dropdown-toggle:hover, .sidebar-menu .dropdown-toggle.active { background: linear-gradient(90deg, var(--primary), var(--secondary)); color: #fff; }
        .sidebar-menu .dropdown-toggle i.chevron { transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); font-size: 0.8rem; }
        .sidebar-menu .dropdown.active .dropdown-toggle i.chevron { transform: rotate(180deg); }
        .sidebar-menu .dropdown-menu { display: flex; flex-direction: column; padding-left: 42px; margin-top: 4px; max-height: 0; opacity: 0; overflow: hidden; transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.25s ease; }
        .sidebar-menu .dropdown.active .dropdown-menu { max-height: 260px; opacity: 1; }
        .sidebar-menu .dropdown-menu a { padding: 8px 18px; color: var(--text-main); text-decoration: none; border-radius: 6px; font-size: 0.85rem; display: flex; align-items: center; gap: 8px; opacity: 0; transform: translateY(-5px); transition: opacity 0.2s ease, transform 0.2s ease; }
        .sidebar-menu .dropdown.active .dropdown-menu a { opacity: 1; transform: translateY(0); }
        .sidebar-menu .dropdown-menu a:hover, .sidebar-menu .dropdown-menu a.active { background: #e6f4ff; color: var(--primary); }
        .sidebar.collapsed + .main { margin-left: 70px; }
        .sidebar-toggle { position: absolute; right: -12px; top: 20px; width: 24px; height: 24px; background: var(--primary); color: #fff; border: none; border-radius: 50%; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 0.7rem; box-shadow: 0 2px 6px rgba(0,0,0,0.15); transition: transform 0.3s ease; z-index: 1001; }
        .sidebar.collapsed .sidebar-toggle { transform: rotate(180deg); }
        .main { margin-left: var(--sidebar-width); flex: 1; padding: 25px 30px; transition: margin-left 0.3s ease; }
        .top-bar { background: var(--bg-card); padding: 15px 25px; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.04); margin-bottom: 25px; display: flex; justify-content: space-between; align-items: center; border: 1px solid var(--border); }
        .top-bar h2 { color: var(--primary-dark); font-size: 1.35rem; font-weight: 850; display: flex; align-items: center; gap: 10px; }
        .top-bar h2 i { color: var(--secondary); }
        .user-info { display: flex; align-items: center; gap: 15px; font-size: 0.9rem; color: var(--text-muted); }
        .user-info span { color: var(--primary); font-weight: 600; }
        .user-info a { color: var(--danger); text-decoration: none; font-weight: 500; display: flex; align-items: center; gap: 5px; }
        .user-info a:hover { text-decoration: underline; }
        .shell { display: block; max-width: 1220px; margin: 0 auto; }
        .form-card, .side-card { background: var(--bg-card); border-radius: 16px; box-shadow: 0 8px 25px rgba(15, 23, 42, 0.06); border: 1px solid var(--border); }
        .form-card { padding: 26px; }
        .form-header { margin-bottom: 22px; }
        .form-header h1 { font-size: 1.3rem; color: var(--primary); margin-bottom: 6px; }
        .form-header p { color: var(--text-muted); font-size: 0.9rem; line-height: 1.6; }
        .alert { background: #f8d7da; color: #721c24; padding: 12px 14px; border-radius: 10px; margin-bottom: 18px; border-left: 4px solid var(--danger); }
        .draft-stack { display: flex; flex-direction: column; }
        .draft-stack > .signatory-control-group,
        .draft-stack > .department-officer-control,
        .draft-stack > .attachment-control,
        .draft-stack > .preparer-sign-panel { order: 41; }
        .draft-stack > .generate-closing-btn { order: 42; align-self: flex-start; }
        .draft-stack > .btn-row {
            order: 50;
            justify-content: flex-end;
            align-items: center;
            padding-top: 14px;
            border-top: 1px solid var(--border);
            margin-top: 22px;
        }
        .draft-stack > .letter-editor-section { order: 30; }
        .draft-stack > .approval-editor-group { order: 40; }
        .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 15px; }
        .form-group { margin-bottom: 18px; }
        .form-group label { display: block; margin-bottom: 6px; color: var(--text-main); font-weight: 700; font-size: 0.9rem; }
        .form-group input, .form-group select, .form-group textarea { width: 100%; padding: 11px 14px; border: 1px solid var(--border); border-radius: 10px; font-size: 0.95rem; background: #fff; box-sizing: border-box; }
        .form-group input:focus, .form-group select:focus, .form-group textarea:focus { border-color: var(--primary); outline: none; box-shadow: 0 0 0 3px rgba(0,119,182,0.15); }
        .form-group textarea { min-height: 130px; resize: vertical; }
        .hint { font-size: 0.78rem; color: var(--text-muted); margin-top: 5px; line-height: 1.5; }
        .routing-checklist { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: #f8fbfd; }
        .routing-option { display: grid; grid-template-columns: 22px minmax(0, 1fr) 110px; align-items: center; gap: 9px; padding: 9px 10px; border: 1px solid #dbe7ef; border-radius: 6px; background: #fff; cursor: pointer; }
        .routing-option input { width: 16px; height: 16px; margin: 0; }
        .routing-option span { display: block; min-width: 0; font-size: 0.86rem; font-weight: 600; line-height: 1.35; }
        .routing-option small { display: block; color: var(--text-muted); font-size: 0.72rem; margin-top: 3px; }
        .routing-option .routing-source { color: var(--primary); }
        .routing-order-select { width: 100%; padding: 7px 8px; border: 1px solid var(--border); border-radius: 6px; background: #fff; font-size: 0.82rem; }
        .routing-order-select:disabled { background: #eef2f6; color: #94a3b8; }
        .routing-option.is-unavailable { opacity: 0.58; cursor: not-allowed; }
        .approval-disabled { opacity: 0.55; pointer-events: none; }
        .approval-editor-group { margin-top: 28px; }
        .approval-pages-container { display: block; }
        .approval-page-preview { position: relative; width: 21cm; min-width: 21cm; max-width: 21cm; height: 29.7cm; min-height: 29.7cm; max-height: 29.7cm; overflow: hidden; margin: 14px auto 0; background: #fff; border: 1px solid #d7e2ea; box-shadow: 0 12px 30px rgba(15, 23, 42, 0.10); color: #111; font-family: Arial, Helvetica, sans-serif; }
        .approval-page-inner { height: 100%; padding: 2.54cm 1.8cm; overflow: hidden; }
        .approval-route-preview { height: 100%; overflow: hidden; }
        .approval-page-label { font-size: 16px; font-weight: 700; margin-bottom: 28px; }
        .approval-recipient-body:empty::before { content: attr(data-placeholder); color: #94a3b8; font-weight: 400; }
        .approval-recipient-body { min-height: 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; outline: none; margin-bottom: 6px; }
        .approval-recipient-body p { margin: 0; font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; }
        .approval-recipient-body div { font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; }
        .approval-decision-options { display: flex; flex-wrap: wrap; gap: 18px; margin: 6px 0 4px; }
        .approval-decision-option { display: inline-flex; align-items: center; gap: 8px; font-size: 16px; font-weight: 700; color: #111; }
        .approval-decision-box { width: 14px; height: 14px; border: 1.6px solid #444; border-radius: 2px; display: inline-block; flex: 0 0 14px; background: #fff; }
        .approval-route-block { font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5; padding-top: 6px; page-break-inside: avoid; }
        .approval-route-block + .approval-route-block { border-top: 1px solid #111; margin-top: 26px; padding-top: 20px; }
        .approval-route-title { font-weight: 700; text-decoration: underline; margin: 6px 0 14px; line-height: 1.5; }
        .approval-comment-lines { display: grid; gap: calc(1.5em - 1px); margin-bottom: 18px; }
        .approval-comment-lines span { display: block; border-bottom: 1px solid #777; height: 1px; }
        .approval-route-sign-row { display: grid; grid-template-columns: 195px 285px; justify-content: space-between; align-items: start; width: 100%; }
        .approval-route-date { padding-top: 0; line-height: 1.5; white-space: nowrap; }
        .approval-route-signature { width: 285px; min-height: 76px; }
        .approval-route-sign-line { border-bottom: 1px dotted #555; height: 18px; margin: 0 0 5px; }
        .approval-route-signature strong, .approval-route-signature span { display: block; line-height: 1.5; }
        .approval-decision-option { line-height: 1.5; }
        @media (max-width: 1200px) {
            .routing-checklist { grid-template-columns: repeat(2, 1fr); }
        }
        @media (max-width: 768px) {
            .routing-checklist { grid-template-columns: 1fr; }
        }
        @media (max-width: 640px) {
            .routing-option { grid-template-columns: 22px minmax(0, 1fr); }
            .routing-order-select { grid-column: 2; }
            .page-sheet-actions {
                top: 56px;
                right: 8px;
            }
        }
        .readonly-box { padding: 12px 14px; border: 1px dashed #b9d8ea; border-radius: 12px; background: #f9fdff; }
        .readonly-box strong { display: block; color: var(--primary-dark); }
        .readonly-box span { color: var(--text-muted); font-size: 0.82rem; }
        .reference-readonly-box { min-height: 39px; display: flex; align-items: center; }
        .btn-row { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 22px; }
        .btn-row-left { margin-right: auto; }
        .btn { padding: 12px 20px; border: none; border-radius: 10px; text-decoration: none; cursor: pointer; font-size: 0.92rem; display: inline-flex; align-items: center; gap: 8px; font-weight: 700; }
        .btn-primary { background: linear-gradient(90deg, var(--draft), var(--secondary)); color: #fff; }
        .btn-secondary { background: #eef4f8; color: var(--primary-dark); }
        .btn-warning { background: #f59e0b; color: #fff; }
        .btn-danger { background: var(--danger); color: #fff; }
        .btn-sm { padding: 7px 12px; font-size: 0.78rem; border-radius: 8px; }
        .btn[disabled] { opacity: 0.55; cursor: not-allowed; }
        .preparer-sign-panel { margin-top: 18px; border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; background: #f8fbfd; display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
        .preparer-sign-panel strong { display: block; color: var(--primary-dark); margin-bottom: 4px; }
        .preparer-sign-panel span { color: var(--text-muted); font-size: 0.86rem; }
        .preparer-sign-panel.signed { background: #ecfdf3; border-color: #bbf7d0; }
        .preparer-sign-panel.missing { background: #fff7ed; border-color: #fed7aa; }
        .form-card.compact-letter-form { padding: 16px 18px; }
        .compact-letter-form .form-header { margin-bottom: 10px; }
        .compact-letter-form .form-header h1 { font-size: 1.12rem; margin-bottom: 0; }
        .compact-letter-form .draft-stack { gap: 0; }
        .compact-letter-form .grid {
            grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
            gap: 8px 12px;
        }
        .compact-letter-form .letter-primary-grid {
            grid-template-columns: 170px 190px minmax(320px, 1fr);
        }
        .compact-letter-form .form-group { margin-bottom: 9px; }
        .compact-letter-form .form-group label {
            margin-bottom: 3px;
            font-size: 0.8rem;
            line-height: 1.2;
        }
        .compact-letter-form .form-group input,
        .compact-letter-form .form-group select,
        .compact-letter-form .form-group textarea {
            padding: 8px 10px;
            border-radius: 8px;
            font-size: 0.86rem;
        }
        .compact-letter-form .readonly-box {
            padding: 8px 10px;
            border-radius: 9px;
        }
        .compact-letter-form .readonly-box strong {
            line-height: 1.25;
            font-size: 0.86rem;
        }
        .compact-letter-form .readonly-box span,
        .compact-letter-form .hint {
            font-size: 0.72rem;
            line-height: 1.25;
        }
        .compact-letter-form .routing-checklist {
            grid-template-columns: repeat(4, minmax(0, 1fr));
            gap: 6px;
            padding: 8px;
        }
        .compact-letter-form .routing-option {
            grid-template-columns: 18px minmax(0, 1fr) 86px;
            gap: 6px;
            padding: 7px 8px;
            border-radius: 6px;
        }
        .compact-letter-form .routing-option input {
            width: 14px;
            height: 14px;
        }
        .compact-letter-form .routing-option span {
            font-size: 0.72rem;
            line-height: 1.16;
        }
        .compact-letter-form .routing-option small {
            font-size: 0.63rem;
            margin-top: 2px;
            line-height: 1.5;
        }
        .compact-letter-form .routing-order-select {
            padding: 5px 6px;
            font-size: 0.7rem;
            border-radius: 6px;
        }
        .compact-letter-form .attachment-control input[type="file"] {
            padding: 7px 10px;
        }
        .compact-letter-form .preparer-sign-panel {
            margin-top: 8px;
            padding: 10px 12px;
            border-radius: 10px;
            gap: 10px;
        }
        .compact-letter-form .preparer-sign-panel strong {
            margin-bottom: 2px;
            font-size: 0.86rem;
        }
        .compact-letter-form .preparer-sign-panel span {
            font-size: 0.76rem;
            line-height: 1.25;
        }
        .compact-letter-form .btn {
            padding: 9px 14px;
            border-radius: 8px;
            font-size: 0.84rem;
        }
        .compact-letter-form .letter-editor-section {
            position: static;
            background: var(--bg-card);
            padding-top: 4px;
            box-shadow: none;
            border-radius: 12px;
        }
        .compact-letter-form .word-editor-shell {
            margin-top: 2px;
            display: grid;
            grid-template-columns: max-content max-content max-content max-content 220px;
            column-gap: 16px;
            grid-template-rows: auto auto;
            max-height: none;
        }
        .compact-letter-form .word-toolbar-section {
            padding: 6px 8px;
            min-width: 0;
        }
        .compact-letter-form .toolbar-section-label {
            margin-bottom: 4px;
            font-size: 0.66rem;
        }
        .compact-letter-form .word-toolbar {
            gap: 5px;
            flex-wrap: nowrap;
        }
        .compact-letter-form .word-toolbar button {
            width: 30px;
            height: 30px;
            border-radius: 7px;
        }
        .compact-letter-form .word-toolbar select {
            height: 30px;
            padding: 0 7px;
            border-radius: 7px;
            font-size: 0.76rem;
            width: auto;
        }
        .compact-letter-form .word-toolbar .font-family-select { width: 190px; min-width: 190px; }
        .compact-letter-form .word-toolbar .font-size-select { width: 68px; min-width: 68px; }
        .compact-letter-form #table_rows,
        .compact-letter-form #table_cols { width: 92px; min-width: 92px; }
        .compact-letter-form .word-toolbar select.locked-control,
        .compact-letter-form input.locked-control[readonly] {
            background: #eef2f6;
            color: #64748b;
            cursor: not-allowed;
        }
        .compact-letter-form .page-controls-section {
            padding: 6px 8px;
            grid-column: auto;
            min-width: 0;
            align-self: stretch;
            align-items: flex-start;
        }
        .compact-letter-form #letter_pages_container {
            grid-column: 1 / -1;
            min-height: 0;
            max-height: none;
        }
        @media (max-width: 980px) {
            .compact-letter-form .word-editor-shell {
                grid-template-columns: 1fr 1fr;
            }
            .compact-letter-form #letter_pages_container {
                grid-column: 1 / -1;
            }
        }
        @media (max-width: 1180px) {
            .compact-letter-form .routing-checklist { grid-template-columns: repeat(3, minmax(0, 1fr)); }
        }
        @media (max-width: 900px) {
            .compact-letter-form .routing-checklist { grid-template-columns: repeat(2, minmax(0, 1fr)); }
            .compact-letter-form .letter-primary-grid { grid-template-columns: 1fr 1fr; }
            .compact-letter-form .subject-field { grid-column: 1 / -1; }
        }
        @media (max-width: 640px) {
            .form-card.compact-letter-form { padding: 14px; }
            .compact-letter-form .grid { grid-template-columns: 1fr; }
            .compact-letter-form .letter-primary-grid { grid-template-columns: 1fr; }
            .compact-letter-form .routing-checklist { grid-template-columns: 1fr; }
            .compact-letter-form .routing-option { grid-template-columns: 18px minmax(0, 1fr); }
        }
        .side-card { padding: 20px; }
        .memo-check-dropdown {
            position: relative;
            margin-top: 6px;
        }
        .memo-check-toggle {
            width: 100%;
            min-height: 34px;
            border: 1px solid var(--border);
            border-radius: 8px;
            background: #f8fbfd;
            color: var(--text-main);
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 10px;
            padding: 8px 34px 8px 14px;
            cursor: pointer;
            font-size: 0.82rem;
            font-weight: 700;
            text-align: left;
            position: relative;
        }
        .memo-check-toggle::after {
            display: none;
        }
        .memo-check-toggle > i {
            display: block;
            position: absolute;
            right: 13px;
            top: calc(50% - 4px);
            color: #111827;
            font-size: 0.72rem;
            line-height: 1;
            transform: translateY(-50%);
            pointer-events: none;
        }
        .memo-check-menu {
            position: absolute;
            z-index: 80;
            top: calc(100% + 5px);
            left: 0;
            right: 0;
            max-height: 260px;
            overflow: auto;
            display: none;
            background: #fff;
            border: 1px solid var(--border);
            border-radius: 10px;
            box-shadow: 0 12px 26px rgba(15, 23, 42, 0.14);
            padding: 8px;
        }
        .memo-check-dropdown.open .memo-check-menu { display: block; }
        .memo-check-group {
            padding: 7px 8px 4px;
            color: var(--text-muted);
            font-size: 0.68rem;
            font-weight: 800;
            text-transform: uppercase;
            letter-spacing: 0.04em;
        }
        .memo-check-option {
            display: grid;
            grid-template-columns: 18px minmax(0, 1fr);
            gap: 8px;
            align-items: start;
            padding: 7px 8px;
            border-radius: 7px;
            cursor: pointer;
            font-size: 0.78rem;
            line-height: 1.25;
        }
        .memo-check-option:hover { background: #eef8ff; }
        .memo-check-option input { width: 15px; height: 15px; margin-top: 1px; }
        .side-card h3 { color: var(--primary); margin-bottom: 12px; font-size: 1rem; }
        .side-card p { color: var(--text-muted); line-height: 1.6; font-size: 0.88rem; }
        .summary-list { display: flex; flex-direction: column; gap: 10px; margin-top: 14px; }
        .summary-item { background: #f8fbfd; border: 1px solid var(--border); border-radius: 12px; padding: 12px 14px; }
        .summary-item label { display: block; font-size: 0.76rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); margin-bottom: 6px; }
        .summary-item strong { color: var(--primary-dark); }
        .attachment-list { display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }
        .attachment-item { padding: 10px 12px; border-radius: 10px; background: #f8fbfd; border: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
        .attachment-item a { color: var(--primary); text-decoration: none; font-weight: 600; }
        .attachment-item a:hover { text-decoration: underline; }
        .selected-attachment-list { display: none; flex-direction: column; gap: 8px; margin-top: 10px; }
        .selected-attachment-list.active { display: flex; }
        .selected-attachment-title { font-size: 0.82rem; font-weight: 700; color: var(--primary-dark); margin-top: 12px; }
        .attachment-meta { color: var(--text-muted); font-size: 0.78rem; margin-left: 6px; }
        .attachment-remove-btn { border: none; background: #fee2e2; color: var(--danger); border-radius: 8px; padding: 7px 10px; cursor: pointer; font-weight: 700; display: inline-flex; align-items: center; gap: 6px; }
        .attachment-remove-btn:hover { background: #fecaca; }
        .word-editor-shell {
            border: 1px solid rgba(255,255,255,0.62);
            border-radius: 18px;
            overflow: visible;
            background: rgba(255,255,255,0.52);
            box-shadow: 0 22px 54px rgba(2,62,95,0.12);
            backdrop-filter: blur(22px) saturate(1.28);
            -webkit-backdrop-filter: blur(22px) saturate(1.28);
        }
        #letter_pages_container {
            max-height: none;
            min-height: 0;
            overflow: visible;
            padding: 8px 64px 18px 18px;
            background: rgba(238,245,248,0.42);
            border-top: 1px solid rgba(255,255,255,0.52);
            scroll-behavior: smooth;
            --letter-page-zoom: 1;
        }
        
        .toolbar-section-label {
            font-size: 0.75rem;
            font-weight: 700;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.05em;
            margin-bottom: 6px;
            display: block;
        }
        
        /* Page Controls Section */
        .page-controls-section {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 10px;
            padding: 10px 14px;
            background: rgba(255,255,255,0.34);
            border-bottom: 1px solid rgba(255,255,255,0.48);
            flex-wrap: wrap;
        }
        .page-control-left {
            display: flex;
            align-items: center;
            gap: 12px;
            flex-wrap: wrap;
        }
        .compact-letter-form .page-control-left {
            align-items: stretch;
            flex-direction: column;
            gap: 0;
            width: 100%;
        }
        .page-control-right {
            display: flex;
            align-items: center;
            gap: 8px;
            flex-wrap: wrap;
        }
        .page-controls span { 
            color: var(--text-muted); 
            font-size: 0.84rem; 
            font-weight: 700; 
        }
        #page_count_label {
            font-size: 0.66rem;
            font-weight: 700;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.05em;
            margin-bottom: 4px;
            line-height: 1.2;
            display: block;
        }
        .page-controls button { 
            border: 1px solid var(--border); 
            border-radius: 8px; 
            background: #fff; 
            color: var(--primary-dark); 
            padding: 8px 12px; 
            cursor: pointer; 
            font-weight: 700; 
            display: inline-flex; 
            align-items: center; 
            gap: 7px;
            transition: all 0.2s ease;
        }
        .page-controls button:hover { 
            background: #e6f4ff;
            border-color: var(--primary);
        }
        .generate-closing-btn {
            border: 1px solid rgba(0, 116, 179, 0.22);
            background: #ffffff;
            color: var(--primary);
            border-radius: 10px;
            padding: 9px 13px;
            font-weight: 700;
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            gap: 8px;
            box-shadow: 0 6px 14px rgba(0, 116, 179, 0.08);
        }
        .generate-closing-btn:hover {
            background: #eef8ff;
        }
        .page-controls select { 
            height: 36px; 
            border: 1px solid var(--border); 
            border-radius: 8px; 
            padding: 0 10px; 
            background: #fff; 
            color: var(--text-main); 
            font-size: 0.84rem;
            cursor: pointer;
        }
        .page-controls .delete-current-page-btn { 
            color: #b42318; 
            border-color: #f5c2c7;
        }
        .page-controls .delete-current-page-btn:hover {
            background: #fde8e8;
            border-color: #b42318;
        }
        
        .memo-page-preview { 
            position: relative; 
            background: #fff; 
            width: 21cm; 
            min-width: 21cm;
            max-width: 21cm;
            height: 29.7cm; 
            min-height: 29.7cm; 
            max-height: 29.7cm; 
            overflow: hidden; 
            margin: 18px auto; 
            padding: 2.54cm 1.8cm; 
            box-shadow: 0 4px 18px rgba(15, 23, 42, 0.12); 
            border: 1px solid #d8e2ea; 
            color: #111827; 
            font-family: Arial, Helvetica, sans-serif; 
            display: flex; 
            flex-direction: column; 
            zoom: 1;
        }
        .memo-page-preview,
        .approval-page-preview {
            line-height: 1.5;
        }
        .memo-page-preview :not(i),
        .approval-page-preview :not(i) {
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
        }
        .memo-page-preview .memo-editor-fixed,
        .memo-page-preview .memo-editor-fixed td,
        .memo-page-preview .memo-editor-footer,
        .memo-page-preview .memo-editor-footer > div,
        .memo-page-preview .memo-label-grid td,
        .approval-page-preview .approval-route-block,
        .approval-page-preview .approval-route-block p,
        .approval-page-preview .approval-route-block div,
        .approval-page-preview .approval-route-signature strong,
        .approval-page-preview .approval-route-signature span,
        .approval-page-preview .approval-route-title,
        .approval-page-preview .approval-decision-option {
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            line-height: 1.5;
        }
        .memo-page-preview.is-extra-page { 
            height: 29.7cm; 
            min-height: 29.7cm; 
            max-height: 29.7cm; 
        }
        .page-sheet-actions {
            position: absolute;
            top: 2.54cm;
            right: -46px;
            z-index: 5;
            display: flex;
            flex-direction: column;
            gap: 6px;
        }
        .page-sheet-actions button {
            width: 34px;
            height: 34px;
            border: 1px solid #b9d8ea;
            border-radius: 7px;
            background: #fff;
            color: var(--primary-dark);
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 7px rgba(15, 23, 42, 0.10);
        }
        .page-sheet-actions button:hover { background: #e6f4ff; border-color: var(--primary); }
        .page-sheet-actions .page-delete-btn { color: #b42318; border-color: #f5c2c7; }
        .page-sheet-actions .page-delete-btn:hover { background: #fde8e8; border-color: #b42318; }
        .page-sheet-actions button:disabled { opacity: 0.42; cursor: not-allowed; background: #f1f5f9; }
        .memo-custom-header { 
            position: absolute; 
            top: 30px; 
            left: 2.54cm; 
            right: 2.54cm; 
            min-height: 26px; 
            color: #475569; 
            font-size: 16px; 
            line-height: 1.5;
            text-align: center; 
            white-space: pre-wrap; 
        }
        .memo-custom-header:focus,
        .memo-custom-footer:focus {
            outline: 2px dashed var(--primary);
            outline-offset: 4px;
            background: rgba(0, 119, 182, 0.04);
        }
        .memo-custom-header,
        .memo-custom-footer {
            cursor: text;
        }
        .memo-custom-header p,
        .memo-custom-footer p {
            margin: 0;
        }
        .memo-custom-footer { 
            position: absolute; 
            bottom: 30px; 
            left: 2.54cm; 
            right: 2.54cm; 
            min-height: 26px; 
            color: #475569; 
            font-size: 16px; 
            line-height: 1.5;
            text-align: center; 
            white-space: pre-wrap; 
        }
        .memo-page-number { 
            position: absolute; 
            bottom: 38px; 
            min-width: 32px; 
            color: #475569; 
            font-size: 16px; 
            line-height: 1; 
            text-align: center; 
            user-select: none; 
        }
        .memo-page-number.bottom_center { 
            left: 50%; 
            transform: translateX(-50%); 
        }
        .memo-page-number.bottom_right { 
            right: 2.54cm; 
        }
        .memo-page-number.none { 
            display: none; 
        }
        .approval-page-preview .memo-page-number {
            bottom: 38px;
        }
        .memo-editor-fixed { 
            user-select: none; 
        }
        .memo-logo { 
            text-align: center; 
            margin-bottom: 6px; 
        }
        .memo-logo img { 
            width: 130px; 
            height: auto; 
            object-fit: contain; 
        }
        .memo-title { 
            text-align: center; 
            letter-spacing: 0; 
            font-weight: 700; 
            font-size: 16px; 
            margin-bottom: 22px; 
            padding-left: 0; 
        }
        .memo-ref-table { 
            width: 100%; 
            table-layout: fixed;
            border-collapse: collapse; 
            font-size: 16px; 
            margin-bottom: 28px; 
        }
        .memo-ref-table td { 
            border: 1px solid #111; 
            padding: 1mm 2.1mm; 
            vertical-align: top; 
            line-height: 1.2;
        }
        .memo-ref-left { 
            width: 52%; 
            font-weight: 700; 
            line-height: 1.5; 
        }
        .memo-ref-right { 
            width: 48%;
            font-weight: 400;
        }
        .memo-ref-line {
            display: flex;
            align-items: flex-start;
            white-space: nowrap;
            width: 100%;
            line-height: 1.2;
        }
        .memo-ref-label {
            display: inline-block;
            flex: 0 0 17mm;
            line-height: 1.2;
        }
        .memo-ref-colon {
            flex: 0 0 4mm;
            text-align: center;
            line-height: 1.2;
        }
        .memo-ref-value {
            flex: 1 1 auto;
            min-width: 0;
            white-space: nowrap;
            line-height: 1.2; position: relative; top: -0.2mm;
        }
        .memo-label-grid { 
            width: 100%; 
            border-collapse: collapse; 
            margin-bottom: 18px; 
            font-size: 16px; 
        }
        .memo-label-grid td { 
            padding: 7px 0; 
            vertical-align: top; 
        }
        .memo-label { 
            width: 92px; 
            font-weight: 400; 
            letter-spacing: 0.02em; 
        }
        .memo-colon { 
            width: 18px; 
        }
        .memo-value { 
            font-weight: 400; 
        }
        .memo-subject { 
            font-weight: 700; 
            text-transform: uppercase; 
        }
        .word-editor { 
            min-height: 24px; 
            max-height: var(--editor-max-height, 260px);
            overflow: hidden;
            outline: none; 
            line-height: 1.5; 
            font-size: 16px; 
            font-family: Arial, Helvetica, sans-serif; 
            color: #111827; 
            flex: 0 0 auto; 
        }
        .word-editor p { 
            margin: 0;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            line-height: 1.5;
        }
        .word-editor div,
        .word-editor li,
        .word-editor span {
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            line-height: 1.5;
        }
        .word-editor ol, .word-editor ul { 
            margin: 0 0 12px 24px; 
            padding-left: 18px; 
        }
        .word-editor table { 
            width: 100%; 
            table-layout: fixed;
            border-collapse: collapse; 
            margin: 10px 0 14px; 
        }
        .word-editor td, .word-editor th { 
            border: 1px solid #111; 
            padding: 6px 8px; 
            min-width: 80px; 
        }
        .word-editor th { 
            background: #f1f5f9; 
            font-weight: 700; 
        }
        .word-editor:empty:before { 
            content: "Tulis kandungan memo di sini..."; 
            color: #9ca3af; 
        }
        .memo-page-preview:not(.is-extra-page):not(.distribution-page-preview) > .word-editor.letter-page-editor,
        .memo-page-preview:not(.is-extra-page):not(.distribution-page-preview) > .quill-letter-host {
            margin-top: 2.92cm;
        }
        .memo-page-preview:not(.is-extra-page) [data-surat-rasmi-generated-line="ref"] {
            position: relative;
            top: 0.45em;
        }
        .memo-page-preview:not(.is-extra-page) [data-surat-rasmi-generated-line="date"] {
            margin-top: 0.85em !important;
        }
        .quill-letter-host {
            border: 0 !important;
            padding: 0;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            line-height: 1.5;
            flex: 0 0 auto;
            height: auto;
        }
        .quill-letter-host .ql-container {
            height: auto;
            min-height: 24px;
        }
        .quill-letter-host .ql-editor {
            padding: 0;
            min-height: 24px;
            height: auto;
            max-height: var(--editor-max-height, 260px);
            overflow: hidden;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            line-height: 1.5;
            color: #111827;
        }
        .quill-letter-host .ql-editor p {
            margin: 0;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px;
            line-height: 1.5;
        }
        .word-toolbar-section {
            border-bottom: 1px solid rgba(255,255,255,0.48);
            padding: 10px 12px;
            background: rgba(255,255,255,0.34);
            backdrop-filter: blur(18px) saturate(1.2);
            -webkit-backdrop-filter: blur(18px) saturate(1.2);
        }
        .toolbar-section-label {
            font-size: 0.75rem;
            font-weight: 700;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.05em;
            margin-bottom: 6px;
            display: block;
        }
        .word-toolbar {
            display: flex;
            gap: 6px;
            flex-wrap: wrap;
            align-items: center;
        }
        .word-toolbar button {
            width: 34px;
            height: 34px;
            border: 1px solid var(--border);
            border-radius: 8px;
            background: #f8fbfd;
            color: var(--primary-dark);
            cursor: pointer;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            font-weight: 700;
            transition: all 0.2s ease;
        }
        .word-toolbar button:hover {
            background: #e6f4ff;
            color: var(--primary);
            border-color: var(--primary);
        }
        .word-toolbar select {
            height: 34px;
            border: 1px solid var(--border);
            border-radius: 8px;
            padding: 0 8px;
            background: #fff;
            color: var(--text-main);
            font-size: 0.82rem;
            cursor: pointer;
        }
        .word-toolbar select:hover { border-color: var(--primary); }
        .word-toolbar .font-family-select { min-width: 150px; }
        .word-toolbar .font-size-select { width: 82px; }
        .memo-editor-footer { 
            user-select: none; 
            margin-top: 14px; 
            padding-top: 0; 
            line-height: 1.5; 
            font-size: 16px; 
            flex: 0 0 auto; 
        }
        .closing-pledge { 
            margin: 18px 0 14px; 
            line-height: 1.5; 
        }
        .closing-pledge strong { 
            display: block; 
            font-weight: 800; 
            letter-spacing: 0.02em; 
        }
        .signature-block,
        .generated-closing-lock {
            user-select: none;
            cursor: default;
            display: block;
            break-inside: avoid;
            page-break-inside: avoid;
            white-space: normal;
        }
        .signature-block * ,
        .generated-closing-lock * {
            user-select: none;
            white-space: normal;
        }
        .memo-sign-space { 
            height: 58px; 
        }
        .signature-preview-img { 
            max-width: 150px; 
            max-height: 58px; 
            display: block; 
            margin-bottom: 4px; 
            object-fit: contain; 
        }
        .prepared-by-line {
            margin-top: 3px;
            font-family: Arial, Helvetica, sans-serif;
            font-size: 16px !important;
            line-height: 1.5;
            font-weight: 400;
        }
        .page-footer { 
            text-align: center; 
            padding: 20px; 
            color: var(--text-muted); 
            font-size: 0.8rem; 
            margin-top: 30px; 
        }
        :root {
            --primary: #0077b6;
            --primary-dark: #005f99;
            --secondary: #00b4d8;
            --deep-blue: #023e5f;
            --bg-light: rgba(245, 250, 253, 0.72);
            --bg-card: rgba(255,255,255,0.68);
            --text-main: #163447;
            --text-muted: #2d5367;
            --border: rgba(255,255,255,0.48);
            --sidebar-width: 280px;
            --glass: rgba(255,255,255,0.58);
            --glass-strong: rgba(255,255,255,0.76);
            --shadow-soft: 0 24px 70px rgba(2,62,95,0.16);
        }
        body {
            background:
                linear-gradient(135deg, rgba(245,250,253,0.90), rgba(222,246,252,0.76)),
                url('assets/auth-bg.png') center/cover no-repeat fixed;
            color: var(--text-main);
            overflow-x: hidden;
        }
        body::before {
            content: '';
            position: fixed;
            inset: 0;
            background:
                radial-gradient(circle at 18% 18%, rgba(0,180,216,0.22), transparent 28%),
                radial-gradient(circle at 86% 12%, rgba(0,119,182,0.18), transparent 28%),
                linear-gradient(120deg, rgba(255,255,255,0.28), rgba(255,255,255,0.08));
            pointer-events: none;
            z-index: 0;
        }
        body::after {
            content: '';
            position: fixed;
            width: 520px;
            height: 520px;
            right: -180px;
            bottom: -220px;
            background: rgba(0,180,216,0.18);
            filter: blur(8px);
            transform: rotate(18deg);
            border-radius: 42px;
            pointer-events: none;
            z-index: 0;
        }
        .sidebar {
            background: linear-gradient(180deg, rgba(2,62,95,0.94), rgba(0,119,182,0.84));
            border-right: 1px solid rgba(255,255,255,0.22);
            box-shadow: 18px 0 44px rgba(2,38,60,0.20);
            backdrop-filter: blur(18px) saturate(1.25);
        }
        .sidebar-header {
            background: transparent !important;
            border-bottom: 1px solid rgba(255,255,255,0.16);
        }
        .sidebar-header img {
            width: 58px;
            filter: drop-shadow(0 8px 14px rgba(0,0,0,0.22));
        }
        .sidebar-header h3 { color: #fff; font-weight: 800; }
        .sidebar-header p { color: rgba(255,255,255,0.72); }
        .sidebar-section { color: rgba(255,255,255,0.56); }
        .sidebar-menu li a,
        .sidebar-menu .dropdown-toggle {
            color: rgba(255,255,255,0.88);
        }
        .sidebar-menu li a:hover,
        .sidebar-menu li a.active,
        .sidebar-menu .dropdown-toggle:hover,
        .sidebar-menu .dropdown-toggle.active {
            background: rgba(255,255,255,0.18);
            color: #fff;
            box-shadow: inset 0 0 0 1px rgba(255,255,255,0.18);
        }
        .sidebar-menu .dropdown-menu a {
            color: rgba(255,255,255,0.78);
        }
        .sidebar-menu .dropdown-menu a:hover,
        .sidebar-menu .dropdown-menu a.active {
            background: rgba(255,255,255,0.16);
            color: #fff;
        }
        .sidebar-toggle {
            right: 10px;
            top: 28px;
            width: 28px;
            height: 28px;
            background: rgba(255,255,255,0.18);
            border: 1px solid rgba(255,255,255,0.22);
            box-shadow: 0 8px 20px rgba(0,0,0,0.15);
        }
        .main {
            padding: 28px 32px;
            position: relative;
            z-index: 1;
        }
        .top-bar,
        .form-card,
        .side-card,
        .info-panel,
        .summary-card,
        .header-footer-panel {
            background: var(--glass);
            border: 1px solid var(--border);
            box-shadow: var(--shadow-soft);
            backdrop-filter: blur(24px) saturate(1.35);
        }
        .top-bar {
            border-radius: 18px;
            padding: 16px 24px;
        }
        .top-bar h2,
        .form-header h1,
        .section-title {
            color: var(--primary-dark);
            font-weight: 800;
        }
        .form-card,
        .side-card {
            border-radius: 22px;
        }
        .form-group input,
        .form-group select,
        .form-group textarea,
        .readonly-box,
        .routing-option,
        .attachment-control,
        .preparer-sign-panel {
            background: rgba(255,255,255,0.74);
            border-color: rgba(255,255,255,0.62);
        }
        .form-group input:focus,
        .form-group select:focus,
        .form-group textarea:focus {
            border-color: rgba(0,180,216,0.82);
            box-shadow: 0 0 0 4px rgba(0,180,216,0.16);
        }
        .word-editor-shell,
        .page-controls-section,
        .word-toolbar-section {
            background: rgba(255,255,255,0.46);
            border-color: rgba(255,255,255,0.62);
            box-shadow: 0 18px 44px rgba(2,62,95,0.10);
            backdrop-filter: blur(22px) saturate(1.28);
            -webkit-backdrop-filter: blur(22px) saturate(1.28);
        }
        .word-toolbar button,
        .page-controls button,
        .page-controls select,
        .word-toolbar select,
        .word-toolbar input {
            background: rgba(255,255,255,0.78);
            border-color: rgba(0,119,182,0.18);
        }
        .compact-letter-form .letter-editor-section {
            background: rgba(255,255,255,0.30);
            border: 1px solid rgba(255,255,255,0.52);
            box-shadow: 0 22px 54px rgba(2,62,95,0.10);
            backdrop-filter: blur(22px) saturate(1.28);
            -webkit-backdrop-filter: blur(22px) saturate(1.28);
        }
        .compact-letter-form .word-editor-shell {
            background: rgba(255,255,255,0.36);
            border-color: rgba(255,255,255,0.56);
            box-shadow: inset 0 1px 0 rgba(255,255,255,0.72), 0 18px 44px rgba(2,62,95,0.10);
            backdrop-filter: blur(24px) saturate(1.3);
            -webkit-backdrop-filter: blur(24px) saturate(1.3);
        }
        .compact-letter-form .word-toolbar-section,
        .compact-letter-form .page-controls-section {
            background: rgba(255,255,255,0.22);
            border-color: rgba(255,255,255,0.44);
            box-shadow: inset 1px 0 0 rgba(255,255,255,0.34);
            backdrop-filter: blur(20px) saturate(1.25);
            -webkit-backdrop-filter: blur(20px) saturate(1.25);
        }
        .compact-letter-form #letter_pages_container {
            background: rgba(238,245,248,0.24);
            border-color: rgba(255,255,255,0.42);
            position: relative;
            z-index: 1;
            pointer-events: auto;
        }
        #page_number_position {
            background: rgba(255,255,255,0.86);
            border: 1px solid rgba(0,119,182,0.20);
            border-radius: 7px;
            box-shadow: inset 0 1px 0 rgba(255,255,255,0.82), 0 8px 20px rgba(2,62,95,0.06);
            color: var(--text-main);
            font-size: 0.76rem;
            height: 30px;
            min-width: 0;
            width: 210px;
            max-width: 100%;
            padding: 0 7px;
        }
        .compact-letter-form .page-controls-section {
            align-items: flex-start;
            padding: 6px 8px;
        }
        .compact-letter-form .memo-page-preview,
        .compact-letter-form .approval-page-preview,
        .compact-letter-form .letter-page-editor,
        .compact-letter-form .quill-letter-host,
        .compact-letter-form .quill-letter-host .ql-editor {
            position: relative;
            z-index: 2;
            pointer-events: auto;
            user-select: text;
            -webkit-user-select: text;
        }
        .btn-primary { background: linear-gradient(135deg, var(--primary), var(--secondary)); }
        .btn-secondary { background: rgba(255,255,255,0.76); color: var(--primary-dark); border: 1px solid rgba(0,119,182,0.18); }
        .page-footer { color: var(--text-muted); }
        @media (max-width: 1100px) {
            .shell { grid-template-columns: 1fr; }
        }

        @media (max-width: 992px) {
            .sidebar { width: 70px; }
            .sidebar .sidebar-header h3, .sidebar .sidebar-header p, .sidebar .menu-text, .sidebar .role-badge, .sidebar .dropdown-menu, .sidebar .sidebar-section { display: none; }
            .main { margin-left: 70px; }
            .sidebar-toggle { display: none; }
        }
        @media (max-width: 640px) {
            .header-footer-panel { grid-template-columns: 1fr; }
            .page-controls-section { flex-direction: column; align-items: stretch; }
            .page-control-left, .page-control-right { justify-content: space-between; }
        }
        .sidebar {
            overflow: hidden;
        }
        .sidebar-header {
            flex: 0 0 auto;
        }
        .sidebar-menu {
            flex: 1 1 auto;
            min-height: 0;
            overflow-y: auto;
            overflow-x: hidden;
            padding-bottom: 0;
            overscroll-behavior: contain;
            scrollbar-width: thin;
            scrollbar-color: #8f8f8f transparent;
        }
        .sidebar-menu::-webkit-scrollbar {
            width: 10px;
        }
        .sidebar-menu::-webkit-scrollbar-track {
            background: transparent;
        }
        .sidebar-menu::-webkit-scrollbar-thumb {
            background: #8f8f8f;
            border-radius: 999px;
            border: 2px solid transparent;
            background-clip: content-box;
        }
        .sidebar-menu::-webkit-scrollbar-button {
            display: none;
            width: 0;
            height: 0;
        }
    
        /* Button hover animation */
        .main .btn,
        .main .tab-btn,
        .main .action-btn,
        .main .btn-action,
        .main .filter-btn,
        .main .button,
        .main .generate-closing-btn,
        .main .attachment-remove-btn,
        .main .page-add-btn,
        .main .page-delete-btn,
        .main .delete-current-page-btn,
        .main .form-actions a,
        .main .form-actions button,
        .main .filter-actions a,
        .main .filter-actions button,
        .main .document-command a,
        .main .document-command button,
        .main table a[class*="btn"],
        .main table button[class*="btn"],
        .main input[type="submit"],
        .main input[type="button"] {
            transition: transform 0.2s ease, filter 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease, border-color 0.2s ease !important;
            will-change: transform;
        }

        .main .btn:hover:not(:disabled),
        .main .tab-btn:hover:not(:disabled),
        .main .action-btn:hover:not(:disabled),
        .main .btn-action:hover:not(:disabled),
        .main .filter-btn:hover:not(:disabled),
        .main .button:hover:not(:disabled),
        .main .generate-closing-btn:hover:not(:disabled),
        .main .attachment-remove-btn:hover:not(:disabled),
        .main .page-add-btn:hover:not(:disabled),
        .main .page-delete-btn:hover:not(:disabled),
        .main .delete-current-page-btn:hover:not(:disabled),
        .main .form-actions a:hover,
        .main .form-actions button:hover:not(:disabled),
        .main .filter-actions a:hover,
        .main .filter-actions button:hover:not(:disabled),
        .main .document-command a:hover,
        .main .document-command button:hover:not(:disabled),
        .main table a[class*="btn"]:hover,
        .main table button[class*="btn"]:hover:not(:disabled),
        .main input[type="submit"]:hover:not(:disabled),
        .main input[type="button"]:hover:not(:disabled) {
            transform: translateY(-1px);
            filter: brightness(1.04);
            box-shadow: 0 14px 28px rgba(0, 119, 182, 0.18);
        }

        .main .btn:active:not(:disabled),
        .main .tab-btn:active:not(:disabled),
        .main .action-btn:active:not(:disabled),
        .main .btn-action:active:not(:disabled),
        .main .filter-btn:active:not(:disabled),
        .main .button:active:not(:disabled),
        .main .generate-closing-btn:active:not(:disabled),
        .main .attachment-remove-btn:active:not(:disabled),
        .main .page-add-btn:active:not(:disabled),
        .main .page-delete-btn:active:not(:disabled),
        .main .delete-current-page-btn:active:not(:disabled),
        .main .form-actions a:active,
        .main .form-actions button:active:not(:disabled),
        .main .filter-actions a:active,
        .main .filter-actions button:active:not(:disabled),
        .main .document-command a:active,
        .main .document-command button:active:not(:disabled),
        .main table a[class*="btn"]:active,
        .main table button[class*="btn"]:active:not(:disabled),
        .main input[type="submit"]:active:not(:disabled),
        .main input[type="button"]:active:not(:disabled) {
            transform: translateY(0);
            filter: brightness(0.98);
        }</style>
</head>
<body class="role-<?= htmlspecialchars($role) ?>">
    <aside class="sidebar" id="sidebar">
        <button class="sidebar-toggle" id="sidebarToggle" title="Tutup/Buka Menu">
            <i class="fas fa-chevron-left"></i>
        </button>
        <div class="sidebar-header">
            <img src="mainpp.png" alt="Logo MAINPP">
            <h3>MAINPP WORKSPACE</h3>
        </div>
        <ul class="sidebar-menu">
            <?php renderUnifiedSidebarMenu($conn, $role, basename(__FILE__)); ?>
        </ul>
    </aside>

    <main class="main">
        <div class="top-bar">
            <h2><i class="fas fa-file-signature"></i> <?= $is_edit ? 'Ubah ' . htmlspecialchars($current_document_type) : 'Sediakan ' . htmlspecialchars($current_document_type) ?></h2>
            <?php renderTopBarUserMenu($conn, $role, basename(__FILE__)); ?>
        </div>

        <?php
        renderBreadcrumb([
            ['label' => 'Dashboard', 'url' => 'dashboard.php'],
            ['label' => 'Modul Surat', 'url' => 'draft_letters.php'],
            ['label' => 'Sediakan Surat', 'url' => 'draft_letter_form.php'],
            ['label' => ($is_edit ? 'Ubah ' : '') . $current_document_type, 'url' => basename(__FILE__) . ($is_edit ? '?id=' . $draft_id : ''), 'current' => true]
        ]);
        ?>

        <div class="shell">
            <div class="form-card compact-letter-form">
                <div class="form-header">
                    <h1><?= $is_edit ? 'Ubah ' . htmlspecialchars($current_document_type) : htmlspecialchars($current_document_type) . ' Baharu' ?></h1>
                </div>

                <?php if ($error_message !== ''): ?>
                <div class="alert"><?= htmlspecialchars($error_message) ?></div>
                <?php endif; ?>
                <?php if ($success_message !== ''): ?>
                <div class="alert" style="background:#e6fff0;color:var(--success);border-color:#b8ebcd;"><?= htmlspecialchars($success_message) ?></div>
                <?php endif; ?>

                <form method="POST" action="process_draft_letter.php?action=<?= $is_edit ? 'update' : 'add' ?>" enctype="multipart/form-data" class="draft-stack">
                    <?php if ($is_edit): ?>
                    <input type="hidden" name="id" value="<?= $draft_id ?>">
                    <input type="hidden" name="folder_id" value="<?= (int) $form_values['folder_id'] ?>">
                    <?php endif; ?>

                    <div class="grid">
                        <div class="form-group">
                            <label>Fail Office <span style="color:var(--danger);">*</span></label>
                            <?php if ($is_edit): ?>
                            <div class="readonly-box">
                                <strong><?= htmlspecialchars(($selected_folder['folder_name'] ?? '-') . ' (' . ($selected_folder['folder_code'] ?? '-') . ')') ?></strong>
                                <span><?= htmlspecialchars($selected_folder['department'] ?? '-') ?></span>
                            </div>
                            <?php else: ?>
                            <select name="folder_id" id="folder_id" required>
                                <option value="">-- Pilih Fail Office --</option>
                                <?php foreach ($folders as $folder): ?>
                                <option
                                    value="<?= (int) $folder['id'] ?>"
                                    data-folder-code="<?= htmlspecialchars($folder['folder_code']) ?>"
                                    data-folder-name="<?= htmlspecialchars($folder['folder_name']) ?>"
                                    data-department="<?= htmlspecialchars($folder['department']) ?>"
                                    data-next-ref="<?= htmlspecialchars($folder['next_ref_no']) ?>"
                                    data-next-file-numbering="<?= htmlspecialchars($folder['next_file_numbering']) ?>"
                                    <?= (int) $form_values['folder_id'] === (int) $folder['id'] ? 'selected' : '' ?>
                                >
                                    <?= htmlspecialchars($folder['folder_name'] . ' - ' . $folder['folder_code']) ?>
                                </option>
                                <?php endforeach; ?>
                            </select>
                            <div class="hint">Hanya fail office aktif dipaparkan kerana rujukan surat rasmi akan dijana secara automatik.</div>
                            <?php endif; ?>
                        </div>

                        <div class="form-group">
                            <label>No. Rujukan</label>
                            <div class="readonly-box reference-readonly-box">
                                <strong id="ref_preview"><?= htmlspecialchars($current_ref_display) ?></strong>
                            </div>
                            <div class="hint"><?= ($is_edit && (($draft['status'] ?? 'draf') === 'siap')) ? 'Rujukan kekal selepas surat diwujudkan.' : 'Draf akan dipaparkan sebagai X. Nombor rasmi hanya muncul selepas surat disimpan.' ?></div>
                        </div>
                    </div>

                    <input type="hidden" name="template_id" id="template_id" value="<?= (int) $form_values['template_id'] ?>">

                    <div class="grid letter-primary-grid">
                        <div class="form-group">
                            <label>Tarikh Surat <span style="color:var(--danger);">*</span></label>
                            <input type="date" name="letter_date" value="<?= htmlspecialchars($form_values['letter_date']) ?>" required>
                        </div>
                        <div class="form-group">
                            <label>Dokumen <span style="color:var(--danger);">*</span></label>
                            <input type="text" name="doc_type" id="doc_type" class="locked-control" value="<?= htmlspecialchars($form_values['doc_type']) ?>" required readonly>
                        </div>
                        <div class="form-group subject-field">
                            <label>Perkara / Tajuk Surat <span style="color:var(--danger);">*</span></label>
                            <input type="text" name="subject" value="<?= htmlspecialchars($form_values['subject']) ?>" required>
                        </div>
                    </div>

                    <input type="hidden" name="signatory_target" id="signatory_target" value="department_head">
                    <input type="hidden" name="other_department_head_user_id" id="other_department_head_user_id" value="0">
                    <input type="hidden" name="management_signer_user_id" id="management_signer_user_id" value="0">

                    <div class="grid">
                        <div class="form-group">
                            <label>Kepada</label>
                            <input type="hidden" name="recipient_organization" id="recipient_organization" value="<?= htmlspecialchars(implode("\n", splitMemoPositionValues($form_values['recipient_organization']))) ?>">
                            <?php renderMemoPositionCheckboxDropdown($memo_position_options, 'recipient_organization', 'Kepada', $form_values['recipient_organization'], $surat_rasmi_special_recipient_options); ?>
                        </div>
                    </div>

                    <div class="form-group">
                        <label class="distribution-checkbox" style="display: inline-flex; align-items: center; gap: 8px; justify-content: flex-start; cursor: pointer; white-space: nowrap;">
                            <input type="checkbox" name="include_distribution_page" id="include_distribution_page" value="1" <?= $include_distribution_page_checked ? 'checked' : '' ?>>
                            <span>Senarai Edaran</span>
                        </label>
                    </div>

                    <input type="hidden" id="selected_distribution_staff" name="selected_distribution_staff" value="<?= htmlspecialchars(json_encode($selected_distribution_staff, JSON_UNESCAPED_UNICODE), ENT_QUOTES) ?>">
                    <input type="hidden" id="distribution_staff_data" value="<?= htmlspecialchars(json_encode($distribution_staff, JSON_UNESCAPED_UNICODE), ENT_QUOTES) ?>">
                    <input type="hidden" id="distribution_page_content" name="distribution_page_content" value="<?= htmlspecialchars($distribution_page_content_value, ENT_QUOTES) ?>">

                    <div id="distribution_staff_modal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 1000; align-items: flex-start; justify-content: center; padding-top: 48px;" onclick="if (event.target === this) closeDistributionStaffModal()">
                        <div style="background: #fff; border-radius: 12px; width: 90%; max-width: 500px; max-height: 80vh; overflow: hidden; display: flex; flex-direction: column;" onclick="event.stopPropagation()">
                            <div style="padding: 16px 20px; border-bottom: 1px solid #e5e7eb; display: flex; align-items: center; justify-content: space-between;">
                                <h3 style="margin: 0; font-size: 1.1rem; color: #111827;">Pilih Kakitangan untuk Senarai Edaran</h3>
                                <button type="button" onclick="closeDistributionStaffModal()" style="border: none; background: none; font-size: 1.5rem; cursor: pointer; color: #6b7280;">&times;</button>
                            </div>
                            <div style="padding: 20px; overflow-y: auto; flex: 1;">
                                <input type="text" id="distribution_staff_search" placeholder="Cari kakitangan..." style="width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.875rem; margin-bottom: 16px; box-sizing: border-box;">
                                <?php
                                $mainpp_staff = array_filter($distribution_staff, fn($s) => ($s['agency_type'] ?? '') === 'MAINPP');
                                $agensi_luar_staff = array_filter($distribution_staff, fn($s) => ($s['agency_type'] ?? '') === 'AGENSI LUAR');
                                ?>
                                <?php if (!empty($mainpp_staff)): ?>
                                <div style="margin-bottom: 20px;" class="distribution-staff-section" data-section="mainpp">
                                    <div style="font-weight: 700; color: #6b7280; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px;">MAINPP</div>
                                    <?php foreach ($mainpp_staff as $staff): ?>
                                    <label style="display: block; padding: 8px 0; cursor: pointer;" class="distribution-staff-item" data-search-text="<?= htmlspecialchars(strtolower(($staff['name'] ?? '') . ' ' . ($staff['position'] ?? '') . ' ' . ($staff['department'] ?? '') . ' ' . ($staff['address'] ?? '')), ENT_QUOTES) ?>">
                                        <div style="display: flex; align-items: center; gap: 10px;">
                                            <input type="checkbox" name="distribution_staff[]" value="<?= (int) $staff['id'] ?>" <?= in_array((int) $staff['id'], $selected_distribution_staff, true) ? 'checked' : '' ?>>
                                            <span style="font-weight: 500;"><?= htmlspecialchars($staff['name'] ?? '-') ?></span>
                                        </div>
                                        <div style="margin-left: 28px; color: #6b7280; font-size: 0.875rem;"><?= htmlspecialchars($staff['department'] ?? '-') ?></div>
                                    </label>
                                    <?php endforeach; ?>
                                </div>
                                <?php endif; ?>
                                <?php if (!empty($agensi_luar_staff)): ?>
                                <div style="margin-bottom: 20px;" class="distribution-staff-section" data-section="agensi-luar">
                                    <div style="font-weight: 700; color: #6b7280; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 10px;">AGENSI LUAR</div>
                                    <?php foreach ($agensi_luar_staff as $staff): ?>
                                    <label style="display: block; padding: 8px 0; cursor: pointer;" class="distribution-staff-item" data-search-text="<?= htmlspecialchars(strtolower(($staff['name'] ?? '') . ' ' . ($staff['position'] ?? '') . ' ' . ($staff['department'] ?? '') . ' ' . ($staff['agency'] ?? '') . ' ' . ($staff['address'] ?? '')), ENT_QUOTES) ?>">
                                        <div style="display: flex; align-items: center; gap: 10px;">
                                            <input type="checkbox" name="distribution_staff[]" value="<?= (int) $staff['id'] ?>" <?= in_array((int) $staff['id'], $selected_distribution_staff, true) ? 'checked' : '' ?>>
                                            <span style="font-weight: 500;"><?= htmlspecialchars($staff['name'] ?? '-') ?></span>
                                        </div>
                                        <div style="margin-left: 28px; color: #6b7280; font-size: 0.875rem;"><?= htmlspecialchars($staff['agency'] ?? '-') ?></div>
                                    </label>
                                    <?php endforeach; ?>
                                </div>
                                <?php endif; ?>
                                <?php if (empty($distribution_staff)): ?>
                                <p style="color: #6b7280; text-align: center; padding: 20px;">Tiada kakitangan tersedia.</p>
                                <?php endif; ?>
                            </div>
                            <div style="padding: 16px 20px; border-top: 1px solid #e5e7eb; display: flex; gap: 10px; justify-content: flex-end;">
                                <button type="button" onclick="closeDistributionStaffModal()" style="padding: 10px 20px; border: 1px solid #d1d5db; background: #fff; border-radius: 8px; cursor: pointer; font-weight: 600; color: #374151;">Batal</button>
                                <button type="button" onclick="saveDistributionStaffSelection()" style="padding: 10px 20px; border: none; background: #0077b6; border-radius: 8px; cursor: pointer; font-weight: 600; color: #fff;">OK</button>
                            </div>
                        </div>
                    </div>

                    <input type="hidden" name="recipient_name" value="">
                    <input type="hidden" name="recipient_address" value="">
                    <input type="hidden" name="attention_to" id="attention_to" value="">

                    <input type="hidden" name="greeting" value="">

                    <div class="form-group letter-editor-section">
                        <label>Isi Surat <span style="color:var(--danger);">*</span></label>
                        <input type="hidden" name="letter_body" id="letter_body" value="<?= htmlspecialchars($form_values['letter_body'], ENT_QUOTES) ?>">
                        <input type="hidden" name="letter_pages" id="letter_pages" value="<?= htmlspecialchars(json_encode($form_values['letter_pages'], JSON_UNESCAPED_UNICODE), ENT_QUOTES) ?>">
                        <input type="hidden" name="page_header_text" id="page_header_text" value="<?= htmlspecialchars($form_values['page_header_text'], ENT_QUOTES) ?>">
                        <input type="hidden" name="page_footer_text" id="page_footer_text" value="<?= htmlspecialchars($form_values['page_footer_text'], ENT_QUOTES) ?>">
                        <div class="word-editor-shell">
                            <div class="word-toolbar-section">
                                <span class="toolbar-section-label">Font Style</span>
                                <div class="word-toolbar">
                                    <select id="font_family" class="font-family-select locked-control" title="Jenis font" disabled>
                                        <option value="Arial" selected>Arial</option>
                                        <option value="Calibri">Calibri</option>
                                        <option value="Times New Roman">Times New Roman</option>
                                        <option value="Tahoma">Tahoma</option>
                                        <option value="Verdana">Verdana</option>
                                    </select>
                                    <select id="font_size" class="font-size-select locked-control" title="Saiz font" disabled>
                                        <option value="10">10</option>
                                        <option value="11">11</option>
                                        <option value="12">12</option>
                                        <option value="14">14</option>
                                        <option value="16" selected>16</option>
                                        <option value="18">18</option>
                                        <option value="20">20</option>
                                    </select>
                                    <button type="button" data-command="bold" title="Bold"><i class="fas fa-bold"></i></button>
                                    <button type="button" data-command="italic" title="Italic"><i class="fas fa-italic"></i></button>
                                    <button type="button" data-command="underline" title="Underline"><i class="fas fa-underline"></i></button>
                                </div>
                            </div>
                            <div class="word-toolbar-section">
                                <span class="toolbar-section-label">Text Allignment</span>
                                <div class="word-toolbar">
                                    <button type="button" data-command="justifyLeft" title="Align Left"><i class="fas fa-align-left"></i></button>
                                    <button type="button" data-command="justifyCenter" title="Allign Center"><i class="fas fa-align-center"></i></button>
                                    <button type="button" data-command="justifyRight" title="Allign Right"><i class="fas fa-align-right"></i></button>
                                    <button type="button" data-command="justifyFull" title="Justify"><i class="fas fa-align-justify"></i></button>
                                </div>
                            </div>
                            <div class="word-toolbar-section">
                                <span class="toolbar-section-label">List</span>
                                <div class="word-toolbar">
                                    <button type="button" data-command="insertOrderedList" title="Number"><i class="fas fa-list-ol"></i></button>
                                    <button type="button" data-command="insertUnorderedList" title="Bullet"><i class="fas fa-list-ul"></i></button>
                                </div>
                            </div>
                            <div class="word-toolbar-section">
                                <span class="toolbar-section-label">Table</span>
                                <div class="word-toolbar">
                                    <select id="table_rows" title="Total Row">
                                        <?php for ($row_count = 1; $row_count <= 10; $row_count++): ?>
                                        <option value="<?= $row_count ?>" <?= $row_count === 3 ? 'selected' : '' ?>><?= $row_count ?> row</option>
                                        <?php endfor; ?>
                                    </select>
                                    <select id="table_cols" title="Total Column">
                                        <?php for ($col_count = 1; $col_count <= 8; $col_count++): ?>
                                        <option value="<?= $col_count ?>" <?= $col_count === 2 ? 'selected' : '' ?>><?= $col_count ?> col</option>
                                        <?php endfor; ?>
                                    </select>
                                    <button type="button" data-action="insertTable" title="Insert Table"><i class="fas fa-table"></i></button>
                                </div>
                            </div>
                            <div class="page-controls-section">
                                <div class="page-control-left">
                                    <span id="page_count_label">Page Number</span>
                                    <select name="page_number_position" id="page_number_position" title="Kedudukan nombor halaman">
                                        <option value="none" <?= $form_values['page_number_position'] === 'none' ? 'selected' : '' ?>>Tiada Nombor Halaman</option>
                                        <option value="bottom_center" <?= $form_values['page_number_position'] === 'bottom_center' ? 'selected' : '' ?>>Nombor: Bawah Tengah</option>
                                        <option value="bottom_right" <?= $form_values['page_number_position'] === 'bottom_right' ? 'selected' : '' ?>>Nombor: Bawah Kanan</option>
                                    </select>
                                </div>
                            </div>
                            
                            <div id="letter_pages_container">
                            <?php foreach ($form_values['letter_pages'] as $page_index => $page_body): ?>
                            <div class="memo-page-preview <?= $page_index > 0 ? 'is-extra-page' : '' ?>" data-page-index="<?= $page_index ?>" data-page-number="<?= $page_index + 1 ?>">
                                <div class="page-sheet-actions" aria-label="Tindakan halaman">
                                    <button type="button" class="page-add-btn" title="Tambah halaman selepas halaman ini"><i class="fas fa-file-circle-plus"></i></button>
                                    <button type="button" class="page-delete-btn" title="Padam halaman ini" <?= $page_index === 0 ? 'disabled' : '' ?>><i class="fas fa-trash-alt"></i></button>
                                </div>
                                <div class="memo-custom-header" contenteditable="false" data-header-footer="header"><?= renderDraftEditorBody($form_values['page_header_text']) ?></div>
                                <div class="word-editor letter-page-editor" contenteditable="true"><?= renderDraftEditorBody($page_body) ?></div>
                                <div class="memo-custom-footer" contenteditable="false" data-header-footer="footer"><?= renderDraftEditorBody($form_values['page_footer_text']) ?></div>
                                <div class="memo-page-number <?= htmlspecialchars($form_values['page_number_position']) ?>"><?= $page_index + 1 ?></div>
                            </div>
                            <?php endforeach; ?>
                            </div>
                        </div>
                    </div>

                    <input type="hidden" name="closing_text" value="">

                    <input type="hidden" name="approval_page_body" id="approval_page_body" value="">
                    <input type="hidden" name="approval_page_subject" value="">
                    <input type="hidden" name="approval_route_bodies" id="approval_route_bodies" value="{}">
                    <div class="approval-pages-container" id="approval_pages_container" style="display:none;"></div>

                    <div class="grid signatory-control-group">
                        <div class="form-group">
                            <label>Nama Penandatangan</label>
                            <input type="text" name="signatory_name" value="<?= htmlspecialchars($form_values['signatory_name']) ?>">
                        </div>
                        <div class="form-group">
                            <label>Daripada <span style="color:var(--danger);">*</span></label>
                            <select name="signatory_position" id="signatory_position" required>
                                <option value="">-- Pilih Daripada --</option>
                                <?= renderMemoPositionSelectOptions($memo_position_options, $form_values['signatory_position']) ?>
                            </select>
                        </div>
                        <div class="form-group">
                            <label>Bahagian Penandatangan</label>
                            <input type="text" id="signatory_department_display" value="<?= htmlspecialchars($form_values['signatory_department']) ?>" readonly aria-readonly="true">
                        </div>
                    </div>

                    <input type="hidden" name="signatory_department" id="signatory_department" value="<?= htmlspecialchars($form_values['signatory_department']) ?>">

                    <input type="hidden" name="approval_flow" value="two_level">
                    <input type="hidden" name="department_officer_user_id" id="department_officer_user_id" value="<?= (int) $form_values['department_officer_user_id'] ?>">

                    <div class="form-group attachment-control">
                        <label>Lampiran Sokongan</label>
                        <input type="file" name="file_upload[]" id="support_attachment_input" accept=".pdf,.doc,.docx,.xls,.xlsx" multiple>
                        <div class="hint">Boleh tambah lebih daripada satu fail. Format: PDF, DOC, DOCX, XLS, XLSX. Maksimum 10MB setiap fail.</div>
                        <div class="selected-attachment-title" id="selected_attachment_title" style="display:none;">Fail baru dipilih</div>
                        <div class="selected-attachment-list" id="selected_attachment_list"></div>
                        <?php if (!empty($attachment_map)): ?>
                        <div class="attachment-list">
                            <?php foreach ($attachment_map as $attachment): ?>
                            <div class="attachment-item">
                                <div>
                                    <i class="fas fa-paperclip"></i>
                                    <a href="download.php?attachment_id=<?= (int) ($attachment['id'] ?? 0) ?>" target="_blank">
                                        <?= htmlspecialchars($attachment['original_name'] ?: basename($attachment['file_path'])) ?>
                                    </a>
                                </div>
                                <?php if ($is_edit && !empty($attachment['id'])): ?>
                                <a
                                    href="process_draft_letter.php?action=delete_attachment&id=<?= $draft_id ?>&attachment_id=<?= (int) $attachment['id'] ?>"
                                    class="btn btn-danger btn-sm"
                                    onclick="return confirm('Padam lampiran sokongan ini?')"
                                >
                                    <i class="fas fa-trash-alt"></i> Padam
                                </a>
                                <?php endif; ?>
                            </div>
                            <?php endforeach; ?>
                        </div>
                        <?php elseif ($is_edit): ?>
                        <div class="current-file">Tiada lampiran sokongan sedia ada.</div>
                        <?php endif; ?>
                    </div>

                    <input type="hidden" name="preparer_signed" id="preparer_signed" value="<?= $preparer_is_signed ? '1' : '0' ?>">
                    <input type="hidden" name="document_signature_data" id="document_signature_data" value="">
                    <div class="preparer-sign-panel <?= !$current_user_is_head_officer || $preparer_is_signed ? 'signed' : ($current_user_signature_path === '' ? 'missing' : '') ?>" id="preparer_sign_panel">
                        <div>
                            <strong id="preparer_sign_title">
                                <?php if (!$current_user_is_head_officer): ?>
                                    Semakan ketua bahagian diperlukan
                                <?php else: ?>
                                    <?= $preparer_is_signed ? 'Tandatangan penyedia telah dibuat' : 'Tandatangan diperlukan.' ?>
                                <?php endif; ?>
                            </strong>
                            <span id="preparer_sign_hint">
                                <?php if (!$current_user_is_head_officer): ?>
                                    Surat boleh dihantar kepada ketua bahagian untuk disemak dan ditandatangani.
                                <?php elseif ($preparer_is_signed): ?>
                                    Surat ini sudah mempunyai tandatangan penyedia.
                                <?php elseif ($current_user_signature_path === ''): ?>
                                    Tandatangan anda belum didaftarkan dalam profil pengguna.
                                <?php else: ?>
                                    Klik Tandatangan dahulu sebelum surat disimpan.
                                <?php endif; ?>
                            </span>
                        </div>
                        <?php if (!$current_user_is_head_officer): ?>
                        <span class="btn btn-secondary" aria-disabled="true">
                            <i class="fas fa-user-check"></i> Hantar Untuk Semakan
                        </span>
                        <?php else: ?>
                        <?php if ($current_user_signature_path !== ''): ?>
                        <button type="button" class="btn btn-warning" id="preparer_sign_btn" data-signature-path="<?= htmlspecialchars($current_user_signature_path) ?>">
                            <i class="fas fa-signature"></i> <?= $preparer_is_signed ? 'Tandatangan Semula' : 'Tandatangan' ?>
                        </button>
                        <?php else: ?>
                        <button type="button" class="btn btn-warning" id="preparer_sign_btn" data-signature-path="">
                            <i class="fas fa-signature"></i> <?= $preparer_is_signed ? 'Tandatangan Semula' : 'Tandatangan' ?>
                        </button>
                        <a href="profile_pengguna.php" class="btn btn-secondary">
                            <i class="fas fa-user-pen"></i> Daftar Tandatangan
                        </a>
                        <?php endif; ?>
                        <?php endif; ?>
                    </div>
                    <button type="button" class="generate-closing-btn" id="generate_closing_btn">
                        <i class="fas fa-wand-magic-sparkles"></i> Generate Closing
                    </button>
                    <button type="button" class="generate-closing-btn remove-closing-btn" id="remove_closing_btn">
                        <i class="fas fa-trash"></i> Padam Closing
                    </button>

                    <div class="btn-row">
                        <a href="draft_letter_form.php" class="btn btn-secondary btn-row-left">
                            <i class="fas fa-arrow-left"></i> Kembali
                        </a>
                        <button type="submit" class="btn btn-secondary" name="status" value="draf" id="save_draft_btn">
                            <i class="fas fa-save"></i> Simpan Draf
                        </button>
                        <button type="submit" class="btn btn-primary" name="status" value="siap" id="submit_draft_btn">
                            <i class="fas fa-paper-plane"></i> Simpan &amp; Hantar Surat Rasmi
                        </button>
                    </div>
                </form>
            </div>

        </div>

        <div class="page-footer">
            Hakcipta Terpelihara &copy; <?= date('Y') ?> Majlis Agama Islam Negeri Pulau Pinang.
        </div>
    </main>

    <script src="assets/vendor/quill/quill.js"></script>
    <script src="assets/js/editor-table-resize.js"></script>
    <script src="assets/js/document-digital-signature.js"></script>
    <script>
                const sidebar = document.getElementById('sidebar');
        const toggleBtn = document.getElementById('sidebarToggle');
        if (toggleBtn) {
            toggleBtn.addEventListener('click', () => sidebar.classList.toggle('collapsed'));
        }
        if (window.innerWidth < 992) sidebar.classList.add('collapsed');

        document.querySelectorAll('.sidebar-menu .dropdown-toggle, .dropdown-toggle').forEach(btn => {
            btn.addEventListener('click', function(e) {
                e.preventDefault();
                const dropdown = this.parentElement;
                const isActive = dropdown.classList.contains('active');
                document.querySelectorAll('.sidebar-menu .dropdown, .dropdown').forEach(item => {
                    if (item !== dropdown) item.classList.remove('active');
                });
                dropdown.classList.toggle('active', !isActive);
            });
        });
        function confirmLogout() {
            return confirm("Adakah anda pasti ingin log keluar?");
        }

        const folderSelect = document.getElementById('folder_id');
        const templateSelect = document.getElementById('template_id');
        const refPreview = document.getElementById('ref_preview');
        const signatoryDepartmentInput = document.getElementById('signatory_department');
        const signatoryDepartmentDisplay = document.getElementById('signatory_department_display');
        const letterBodyInput = document.getElementById('letter_body');
        const letterPagesInput = document.getElementById('letter_pages');
        const letterPagesContainer = document.getElementById('letter_pages_container');
        const pageCountLabel = document.getElementById('page_count_label');
        const addPageBtn = document.getElementById('add_page_btn');
        const pageHeaderInput = document.getElementById('page_header_text');
        const pageFooterInput = document.getElementById('page_footer_text');
        const deleteCurrentPageBtn = document.getElementById('delete_current_page_btn');
        const pageNumberPositionSelect = document.getElementById('page_number_position');
        const generateClosingBtn = document.getElementById('generate_closing_btn');
        const removeClosingBtn = document.getElementById('remove_closing_btn');
        const memoRefPreview = document.getElementById('memo_ref_preview');
        const memoDatePreview = document.getElementById('memo_date_preview');
        const memoFromPreview = document.getElementById('memo_from_preview');
        const memoToPreview = document.getElementById('memo_to_preview');
        const memoThroughPreview = document.getElementById('memo_through_preview');
        const memoSignatoryPreview = document.getElementById('memo_signatory_preview');
        const memoDocTypePreview = document.getElementById('memo_doc_type_preview');
        const memoSignaturePreview = document.getElementById('memo_signature_preview');
        const letterDateInput = document.querySelector('input[name="letter_date"]');
        const subjectInput = document.querySelector('input[name="subject"]');
        const recipientInput = document.querySelector('input[name="recipient_organization"]');
        const throughInput = document.querySelector('select[name="attention_to"]');
        const routingChecklist = document.getElementById('routing_positions');
        const includeDistributionPageCheckbox = document.getElementById('include_distribution_page');
        const suratRasmiDistributionRecipientLabel = <?= json_encode($surat_rasmi_distribution_recipient_label, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const approvalRouteGroup = document.querySelector('.approval-route-group');
        const approvalEditorGroup = document.getElementById('approval_editor_group');
        const routingAvailability = <?= json_encode($routing_user_count_by_position, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const routingUserProfiles = <?= json_encode($routing_user_profiles_by_position, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const routingHeadPositions = new Set(<?= json_encode(array_values($memo_position_options['Ketua Bahagian'] ?? []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>);
        const excludedApprovalRoutePositions = new Set(<?= json_encode($excluded_approval_route_positions, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>);
        const routingOrderLimit = <?= (int) $routing_order_limit ?>;
        const docTypeInput = document.querySelector('[name="doc_type"]');
        const signatoryNameInput = document.querySelector('input[name="signatory_name"]');
        const signatoryPositionInput = document.querySelector('[name="signatory_position"]');
        const signatoryTargetSelect = document.getElementById('signatory_target');
        const managementSignerGroup = document.getElementById('management_signer_group');
        const managementSignerSelect = document.getElementById('management_signer_user_id');
        const otherDepartmentHeadGroup = document.getElementById('other_department_head_group');
        const otherDepartmentHeadSelect = document.getElementById('other_department_head_user_id');
        const draftBodyStyle = 'font-family: Arial, Helvetica, sans-serif; font-size: 16px; line-height: 1.5';
        const letterUndoStack = [];
        const letterRedoStack = [];
        let isRestoringLetterSnapshot = false;
        const maxLetterUndoSnapshots = 80;
        function getSuratRasmiFirstPageStarterHtml() {
            const referenceNo = refPreview ? refPreview.textContent.trim() : '-';
            const letterDate = letterDateInput ? formatMemoDate(letterDateInput.value) : '-';
            return '<p data-surat-rasmi-generated-line="ref" contenteditable="false" style="' + draftBodyStyle + '; margin-left: 2.54cm">' + escapeHtml(referenceNo || '-') + '</p>'
                + '<p data-surat-rasmi-generated-line="date" contenteditable="false" style="font-family: Arial, Helvetica, sans-serif; font-size: 15.5px; line-height: 1.25; margin-left: 2.54cm">' + escapeHtml(letterDate || '-') + '</p>'
                + '<p style="' + draftBodyStyle + '"><br></p>';
        }
        function getSuratRasmiGeneratedLinesHtml() {
            const holder = document.createElement('div');
            holder.innerHTML = getSuratRasmiFirstPageStarterHtml();
            return Array.from(holder.querySelectorAll('[data-surat-rasmi-generated-line]')).map(node => node.outerHTML).join('');
        }
        function createSuratRasmiBlankLine() {
            const blankLine = document.createElement('p');
            blankLine.setAttribute('style', draftBodyStyle);
            blankLine.innerHTML = '<br>';
            return blankLine;
        }
        function isSuratRasmiBlankLine(node) {
            return !!(node
                && node.nodeType === Node.ELEMENT_NODE
                && ['P', 'DIV'].includes(node.tagName)
                && !node.hasAttribute('data-surat-rasmi-generated-line')
                && (node.textContent || '').replace(/\s+/g, '').trim() === '');
        }
        function ensureSuratRasmiGeneratedSpacing(firstEditor) {
            const refLine = firstEditor.querySelector('[data-surat-rasmi-generated-line="ref"]');
            const dateLine = firstEditor.querySelector('[data-surat-rasmi-generated-line="date"]');
            if (!refLine || !dateLine || refLine.parentNode !== dateLine.parentNode) return;

            let previous = refLine.previousSibling;
            while (isSuratRasmiBlankLine(previous)) {
                const removeCandidate = previous;
                previous = previous.previousSibling;
                removeCandidate.remove();
            }

            let current = refLine.nextSibling;
            while (current && current !== dateLine) {
                const next = current.nextSibling;
                if (isSuratRasmiBlankLine(current)) {
                    current.remove();
                }
                current = next;
            }

            current = dateLine.nextSibling;
            let blankCountAfterDate = 0;
            while (isSuratRasmiBlankLine(current)) {
                blankCountAfterDate++;
                current = current.nextSibling;
            }
            if (blankCountAfterDate === 0) {
                dateLine.insertAdjacentElement('afterend', createSuratRasmiBlankLine());
            }
        }
        function updateSuratRasmiGeneratedLines() {
            const firstEditor = getLetterEditors()[0];
            if (!firstEditor) return;
            const lockGeneratedLines = () => {
                firstEditor.querySelectorAll('[data-surat-rasmi-generated-line]').forEach(line => {
                    line.setAttribute('contenteditable', 'false');
                });
            };
            const isGeneratedLikeLine = paragraph => {
                const text = (paragraph?.textContent || '').replace(/\s+/g, ' ').trim().toLowerCase();
                return text.startsWith('ruj. kami') || text.startsWith('tarikh');
            };
            const removeGeneratedLikeDuplicates = () => {
                const paragraphs = getEditorParagraphs(firstEditor);
                const referenceNo = (refPreview ? refPreview.textContent : '').replace(/\s+/g, ' ').trim().toLowerCase();
                const dateShort = (letterDateInput ? formatMemoDate(letterDateInput.value) : '').replace(/\s+/g, ' ').trim().toLowerCase();
                const dateLong = (letterDateInput ? new Date(letterDateInput.value + 'T00:00:00').toLocaleDateString('ms-MY', { day: '2-digit', month: 'long', year: 'numeric' }) : '').replace(/\s+/g, ' ').trim().toLowerCase();
                let refSeen = false;
                let dateSeen = false;
                paragraphs.forEach(paragraph => {
                    const text = (paragraph.textContent || '').replace(/\s+/g, ' ').trim().toLowerCase();
                    if (paragraph.dataset.suratRasmiGeneratedLine === 'ref') {
                        refSeen = true;
                        return;
                    }
                    if (paragraph.dataset.suratRasmiGeneratedLine === 'date') {
                        dateSeen = true;
                        return;
                    }
                    if (refSeen && text.startsWith('ruj. kami')) paragraph.remove();
                    if (dateSeen && text.startsWith('tarikh')) paragraph.remove();
                    if (refSeen && referenceNo && text === referenceNo) paragraph.remove();
                    if (dateSeen && ((dateShort && text === dateShort) || (dateLong && text === dateLong))) paragraph.remove();
                });
            };
            const existingGenerated = firstEditor.querySelectorAll('[data-surat-rasmi-generated-line]');
            if (existingGenerated.length) {
                const hasRefLine = !!firstEditor.querySelector('[data-surat-rasmi-generated-line="ref"]');
                const hasDateLine = !!firstEditor.querySelector('[data-surat-rasmi-generated-line="date"]');
                if (!hasRefLine || !hasDateLine || existingGenerated.length < 2) {
                    existingGenerated.forEach(line => line.remove());
                    firstEditor.insertAdjacentHTML('afterbegin', getSuratRasmiFirstPageStarterHtml());
                    removeGeneratedLikeDuplicates();
                    lockGeneratedLines();
                    normalizeSuratRasmiLineIndents(firstEditor);
                    return;
                }
                const holder = document.createElement('div');
                holder.innerHTML = getSuratRasmiGeneratedLinesHtml();
                const nextRef = holder.querySelector('[data-surat-rasmi-generated-line="ref"]');
                const nextDate = holder.querySelector('[data-surat-rasmi-generated-line="date"]');
                const refLine = firstEditor.querySelector('[data-surat-rasmi-generated-line="ref"]');
                const dateLine = firstEditor.querySelector('[data-surat-rasmi-generated-line="date"]');
                if (nextRef && refLine) refLine.innerHTML = nextRef.innerHTML;
                if (nextDate && dateLine) dateLine.innerHTML = nextDate.innerHTML;
                ensureSuratRasmiGeneratedSpacing(firstEditor);
                removeGeneratedLikeDuplicates();
                lockGeneratedLines();
                normalizeSuratRasmiLineIndents(firstEditor);
                return;
            }
            const paragraphs = getEditorParagraphs(firstEditor);
            let removedLegacyGeneratedLine = false;
            paragraphs.slice(0, 2).forEach(paragraph => {
                const text = (paragraph.textContent || '').replace(/\s+/g, ' ').trim().toLowerCase();
                const referenceNo = (refPreview ? refPreview.textContent : '').replace(/\s+/g, ' ').trim().toLowerCase();
                const dateShort = (letterDateInput ? formatMemoDate(letterDateInput.value) : '').replace(/\s+/g, ' ').trim().toLowerCase();
                const dateLong = (letterDateInput ? new Date(letterDateInput.value + 'T00:00:00').toLocaleDateString('ms-MY', { day: '2-digit', month: 'long', year: 'numeric' }) : '').replace(/\s+/g, ' ').trim().toLowerCase();
                const isOldBlankStarter = paragraph.textContent.replace(/\s+/g, '').trim() === ''
                    && (paragraph.style.marginLeft || '').toLowerCase() === '2.54cm';
                const isOldGeneratedValue = (referenceNo && text === referenceNo)
                    || (dateShort && text === dateShort)
                    || (dateLong && text === dateLong);
                if (isOldBlankStarter || isGeneratedLikeLine(paragraph) || isOldGeneratedValue) {
                    if (isGeneratedLikeLine(paragraph) || isOldGeneratedValue) {
                        removedLegacyGeneratedLine = true;
                    }
                    paragraph.remove();
                }
            });
            if (isDepartmentOfficerRevisionEditor && !removedLegacyGeneratedLine) {
                normalizeSuratRasmiLineIndents(firstEditor);
                return;
            }
            firstEditor.insertAdjacentHTML('afterbegin', getSuratRasmiFirstPageStarterHtml());
            removeGeneratedLikeDuplicates();
            lockGeneratedLines();
            normalizeSuratRasmiLineIndents(firstEditor);
        }
        function getSuratRasmiUserContentText() {
            const holder = document.createElement('div');
            holder.innerHTML = getLetterEditors().map(editor => editor.innerHTML).join('');
            holder.querySelectorAll('[data-surat-rasmi-generated-line], [data-generated-closing="1"]').forEach(node => node.remove());
            return (holder.textContent || '').replace(/\s+/g, '').trim();
        }
        const fontFamilySelect = document.getElementById('font_family');
        const fontSizeSelect = document.getElementById('font_size');
        const tableRowsSelect = document.getElementById('table_rows');
        const tableColsSelect = document.getElementById('table_cols');
        const draftForm = document.querySelector('form[action^="process_draft_letter.php"]');
        const draftStatusSelect = document.getElementById('draft_status');
        const preparerSignedInput = document.getElementById('preparer_signed');
        const documentSignatureDataInput = document.getElementById('document_signature_data');
        const preparerSignBtn = document.getElementById('preparer_sign_btn');
        const preparerSignPanel = document.getElementById('preparer_sign_panel');
        const preparerSignTitle = document.getElementById('preparer_sign_title');
        const preparerSignHint = document.getElementById('preparer_sign_hint');
        const submitDraftBtn = document.getElementById('submit_draft_btn');
        const supportAttachmentInput = document.getElementById('support_attachment_input');
        const selectedAttachmentTitle = document.getElementById('selected_attachment_title');
        const selectedAttachmentList = document.getElementById('selected_attachment_list');
        const signatoryTargetDepartmentOption = document.getElementById('signatory_target_department_option');
        const approvalPageBodyInput = document.getElementById('approval_page_body');
        const approvalRouteBodiesInput = document.getElementById('approval_route_bodies');
        const approvalPagesContainer = document.getElementById('approval_pages_container');
        const currentUserId = <?= (int) $current_user_id ?>;
        const currentUserIsHeadOfficer = <?= $current_user_is_head_officer ? 'true' : 'false' ?>;
        const isDepartmentOfficerRevisionEditor = <?= $is_department_officer_revision_editor ? 'true' : 'false' ?>;
        const currentUserSignaturePath = <?= json_encode($current_user_signature_path, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const departmentOfficerRecordedSignaturePath = <?= json_encode($department_officer_recorded_signature_path, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const preparedByShortName = <?= json_encode($prepared_by_short_name, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const suratRasmiSignatoryProfilesByPosition = <?= json_encode($surat_rasmi_signatory_profiles_by_position, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const departmentHeadsByDepartment = <?= json_encode(array_reduce($department_head_users, function ($carry, $user) {
            $department = normalizeDepartmentValue($user['department'] ?? '');
            if ($department !== '' && !isset($carry[$department])) {
                $carry[$department] = [
                    'id' => (int) ($user['id'] ?? 0),
                    'name' => trim((string) ($user['fullname'] ?? ($user['email'] ?? ''))),
                    'position' => trim((string) ($user['position'] ?? 'Ketua Pegawai')),
                    'department' => $department,
                ];
            }
            return $carry;
        }, []), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        const letterTemplates = <?= json_encode(array_map(static function ($template) {
            return [
                'id' => (int) ($template['template_id'] ?? 0),
                'name' => (string) ($template['template_name'] ?? ''),
                'content' => (string) ($template['template_content'] ?? ''),
            ];
        }, $letter_templates), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        let approvalRouteBodies = <?= json_encode($form_values['approval_route_bodies'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
        let activeLetterEditor = null;
        let savedEditorRange = null;
        let isPaginating = false;
        let isRepaginating = false;
        let isInsertingSignature = false;
        let scheduledRepaginationFrame = null;
        let scheduledRepaginationEditor = null;
        let generatedClosingRestoreTimer = null;
        let isRebalancingGeneratedClosing = false;
        let allLetterPagesSelected = false;
        let routingSequenceCounter = 0;

        function isReadyToSendStatus() {
            return true;
        }

        function updateApprovalControlsForStatus() {
            const readyToSend = isReadyToSendStatus();
            approvalRouteGroup?.classList.toggle('approval-disabled', !readyToSend);
            approvalEditorGroup?.classList.toggle('approval-disabled', !readyToSend);

            document.querySelectorAll('.routing-checkbox').forEach(checkbox => {
                const availableCount = parseInt(checkbox.closest('.routing-option')?.dataset.availableCount || '1', 10);
                checkbox.disabled = !readyToSend || availableCount <= 0;
            });

            document.querySelectorAll('.routing-order-select').forEach(select => {
                const checkbox = select.closest('.routing-option')?.querySelector('.routing-checkbox');
                select.disabled = !readyToSend || !checkbox || !checkbox.checked;
            });

            if (typeof departmentOfficerSelect !== 'undefined' && departmentOfficerSelect) {
                departmentOfficerSelect.disabled = !readyToSend;
            }

            if (submitDraftBtn) {
                submitDraftBtn.disabled = false;
            }

            if (preparerSignPanel) {
                preparerSignPanel.classList.toggle('approval-disabled', !readyToSend);
            }
        }

        function formatFileSize(bytes) {
            const size = Number(bytes) || 0;
            if (size >= 1024 * 1024) {
                return (size / (1024 * 1024)).toFixed(1) + ' MB';
            }
            if (size >= 1024) {
                return Math.ceil(size / 1024) + ' KB';
            }
            return size + ' B';
        }

        function getCheckedMemoPositions(selectElement) {
            if (!selectElement) return [];
            const dropdown = document.querySelector('.memo-check-dropdown[data-target-select="' + selectElement.id + '"]');
            if (!dropdown) {
                return [selectElement.value.trim()].filter(Boolean);
            }
            return Array.from(dropdown.querySelectorAll('input[type="checkbox"]:checked'))
                .map(input => input.value.trim())
                .filter(Boolean);
        }

        function renderMemoPreviewPositions(selectElement) {
            const values = getCheckedMemoPositions(selectElement);
            if (!values.length) return '-';
            return values.map(value => {
                return value.toLowerCase() === suratRasmiDistributionRecipientLabel.toLowerCase()
                    ? escapeHtml(value)
                    : escapeHtml(value) + '<br>Majlis Agama Islam Negeri Pulau Pinang';
            }).join('<br>');
        }

        function syncMemoCheckboxDropdown(dropdown) {
            if (!dropdown) return;
            const select = document.getElementById(dropdown.dataset.targetSelect || '');
            const checked = Array.from(dropdown.querySelectorAll('input[type="checkbox"]:checked'));
            const values = checked.map(input => input.value.trim()).filter(Boolean);
            const summary = dropdown.querySelector('.memo-check-summary');

            if (summary) {
                if (dropdown.dataset.targetSelect === 'recipient_organization' && values.length === 1) {
                    summary.textContent = values[0];
                } else {
                    summary.textContent = values.length ? values.length + ' dipilih' : 'Pilih tambahan';
                }
            }

            if (select) {
                if (values.length && (!select.value || !values.includes(select.value))) {
                    select.value = values[0];
                }
                if (!values.length) {
                    select.value = '';
                }
            }
        }

        function selectedMemoDisplayPositions() {
            return [
                ...getCheckedMemoPositions(recipientInput),
                ...getCheckedMemoPositions(throughInput),
            ].filter((value, index, values) => value && values.indexOf(value) === index);
        }

        function setSupportAttachmentFiles(files) {
            if (!supportAttachmentInput) return;
            const transfer = new DataTransfer();
            files.forEach(file => transfer.items.add(file));
            supportAttachmentInput.files = transfer.files;
        }

        function renderSelectedAttachments() {
            if (!supportAttachmentInput || !selectedAttachmentList || !selectedAttachmentTitle) return;
            const files = Array.from(supportAttachmentInput.files || []);
            selectedAttachmentList.innerHTML = '';
            selectedAttachmentTitle.style.display = files.length ? 'block' : 'none';
            selectedAttachmentList.classList.toggle('active', files.length > 0);

            files.forEach((file, index) => {
                const item = document.createElement('div');
                item.className = 'attachment-item';

                const details = document.createElement('div');
                details.innerHTML = '<i class="fas fa-paperclip"></i> ';
                const name = document.createElement('strong');
                name.textContent = file.name;
                const meta = document.createElement('span');
                meta.className = 'attachment-meta';
                meta.textContent = formatFileSize(file.size);
                details.appendChild(name);
                details.appendChild(meta);

                const removeButton = document.createElement('button');
                removeButton.type = 'button';
                removeButton.className = 'attachment-remove-btn';
                removeButton.innerHTML = '<i class="fas fa-trash-alt"></i> Padam';
                removeButton.addEventListener('click', () => {
                    const updatedFiles = Array.from(supportAttachmentInput.files || []).filter((_, fileIndex) => fileIndex !== index);
                    setSupportAttachmentFiles(updatedFiles);
                    renderSelectedAttachments();
                });

                item.appendChild(details);
                item.appendChild(removeButton);
                selectedAttachmentList.appendChild(item);
            });
        }

        if (supportAttachmentInput) {
            supportAttachmentInput.addEventListener('change', renderSelectedAttachments);
        }

        function getRoutingSourceLabel(position) {
            if (getCheckedMemoPositions(recipientInput).includes(position)) return 'Pilihan Kepada';
            if (getCheckedMemoPositions(throughInput).includes(position)) return 'Pilihan';
            return 'Ketua Bahagian';
        }

        function nextAvailableRoutingOrder(excludedCheckbox = null) {
            const used = new Set(Array.from(document.querySelectorAll('.routing-checkbox:checked')).filter(checkbox => checkbox !== excludedCheckbox).map(checkbox => {
                const select = checkbox.closest('.routing-option')?.querySelector('.routing-order-select');
                return select ? parseInt(select.value, 10) : 0;
            }).filter(Boolean));
            for (let order = 1; order <= routingOrderLimit; order++) {
                if (!used.has(order)) return order;
            }
            return Math.min(routingOrderLimit, used.size + 1);
        }

        function normalizeRoutingOrder(changedSelect = null) {
            const checkedRows = Array.from(document.querySelectorAll('.routing-checkbox:checked'))
                .map((checkbox, index) => {
                    const row = checkbox.closest('.routing-option');
                    const select = row?.querySelector('.routing-order-select');
                    const sequence = parseInt(checkbox.dataset.checkedSequence || '', 10);
                    return { checkbox, row, select, index, sequence: Number.isFinite(sequence) ? sequence : index + 1 };
                })
                .filter(item => item.select);

            if (checkedRows.length === 0) return;

            const changedItem = changedSelect
                ? checkedRows.find(item => item.select === changedSelect)
                : null;
            const desiredOrder = changedItem
                ? Math.max(1, Math.min(routingOrderLimit, parseInt(changedSelect.value, 10) || 1))
                : 0;

            const ordered = checkedRows
                .filter(item => item !== changedItem)
                .sort((left, right) => {
                    return left.sequence - right.sequence || left.index - right.index;
                });

            if (changedItem) {
                ordered.splice(Math.min(desiredOrder - 1, ordered.length), 0, changedItem);
            }

            ordered.forEach((item, index) => {
                item.select.disabled = false;
                item.select.value = String(Math.min(index + 1, routingOrderLimit));
                item.checkbox.dataset.checkedSequence = String(index + 1);
            });
            routingSequenceCounter = ordered.length;
        }

        function addRoutingCandidate(position) {
            position = (position || '').trim();
            if (!routingChecklist || !position) return;
            if (excludedApprovalRoutePositions.has(position)) return;
            const existing = Array.from(routingChecklist.querySelectorAll('.routing-option')).find(row => row.dataset.position === position);
            if (existing) {
                const source = existing.querySelector('.routing-source');
                if (source) source.textContent = getRoutingSourceLabel(position);
                return;
            }

            const availableCount = parseInt(routingAvailability[position] || 0, 10);
            const row = document.createElement('label');
            row.className = 'routing-option' + (availableCount === 0 ? ' is-unavailable' : '');
            row.dataset.position = position;
            row.dataset.availableCount = String(availableCount);

            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.className = 'routing-checkbox';
            checkbox.name = 'routing_positions[]';
            checkbox.value = position;
            checkbox.disabled = availableCount === 0;

            const details = document.createElement('span');
            details.appendChild(document.createTextNode(position));
            const source = document.createElement('small');
            source.className = 'routing-source';
            source.textContent = getRoutingSourceLabel(position);
            const availability = document.createElement('small');
            availability.textContent = availableCount > 0 ? availableCount + ' pengguna berdaftar' : 'Belum ada pengguna berdaftar';
            details.appendChild(source);
            details.appendChild(availability);

            const orderSelect = document.createElement('select');
            orderSelect.className = 'routing-order-select';
            orderSelect.name = 'routing_order[' + position + ']';
            orderSelect.disabled = true;
            orderSelect.setAttribute('aria-label', 'Turutan ' + position);
            for (let order = 1; order <= routingOrderLimit; order++) {
                const option = document.createElement('option');
                option.value = String(order);
                option.textContent = 'Pilihan ' + order;
                orderSelect.appendChild(option);
            }

            row.appendChild(checkbox);
            row.appendChild(details);
            row.appendChild(orderSelect);
            routingChecklist.appendChild(row);
            updateApprovalControlsForStatus();
        }

        function syncRoutingCandidates() {
            if (!routingChecklist) return;
            const selectedDisplayPositions = new Set(selectedMemoDisplayPositions());
            selectedDisplayPositions.forEach(addRoutingCandidate);

            routingChecklist.querySelectorAll('.routing-option').forEach(row => {
                const position = row.dataset.position || '';
                if (excludedApprovalRoutePositions.has(position)) {
                    row.remove();
                    return;
                }
                const source = row.querySelector('.routing-source');
                if (source) source.textContent = getRoutingSourceLabel(position);
                const checkbox = row.querySelector('.routing-checkbox');
                if (!routingHeadPositions.has(position) && !selectedDisplayPositions.has(position) && checkbox && !checkbox.checked) {
                    row.remove();
                }
            });
        }

        if (routingChecklist) {
            routingChecklist.addEventListener('change', event => {
                const checkbox = event.target.closest('.routing-checkbox');
                if (checkbox) {
                    const orderSelect = checkbox.closest('.routing-option')?.querySelector('.routing-order-select');
                    if (!orderSelect) return;
                    orderSelect.disabled = !checkbox.checked;
                    if (checkbox.checked) {
                        checkbox.dataset.checkedSequence = String(++routingSequenceCounter);
                        normalizeRoutingOrder();
                    } else {
                        delete checkbox.dataset.checkedSequence;
                        orderSelect.value = '1';
                        normalizeRoutingOrder();
                    }
                }
                const orderSelect = event.target.closest('.routing-order-select');
                if (orderSelect) {
                    normalizeRoutingOrder(orderSelect);
                }
                updateApprovalPagePreview();
                updateApprovalControlsForStatus();
            });
        }

        function getSelectedApprovalRoutes() {
            return Array.from(document.querySelectorAll('.routing-checkbox:checked')).map(checkbox => {
                const row = checkbox.closest('.routing-option');
                const orderSelect = row?.querySelector('.routing-order-select');
                return {
                    position: checkbox.value,
                    order: orderSelect ? parseInt(orderSelect.value, 10) || 999 : 999
                };
            }).sort((left, right) => left.order - right.order || left.position.localeCompare(right.position));
        }

        function getSelectedApprovalRecipients() {
            const recipients = [];
            getSelectedApprovalRoutes().forEach(route => {
                const profiles = routingUserProfiles[route.position] || [];
                profiles.forEach(profile => recipients.push({ ...route, profile }));
            });
            return recipients;
        }

        function captureApprovalRouteBodies() {
            const capturedBodies = {};
            document.querySelectorAll('.approval-recipient-body[data-recipient-key]').forEach(editor => {
                const key = editor.dataset.recipientKey;
                capturedBodies[key] = (capturedBodies[key] || '') + editor.innerHTML.trim();
            });
            approvalRouteBodies = { ...approvalRouteBodies, ...capturedBodies };
        }

        function renderApprovalRouteBlock(route) {
            const profiles = routingUserProfiles[route.position] || [];
            const profile = route.profile || profiles[0] || { id: 0, name: '', position: route.position };
            const name = (profile.name || '').trim();
            const position = (profile.position || route.position || 'Pelulus').trim();
            const recipientKey = profile.id ? 'user:' + profile.id : 'position:' + route.position;
            const savedBody = approvalRouteBodies[recipientKey] || approvalRouteBodies['position:' + route.position] || '';
            const decisionOptions = route.isLast
                ? ['Diluluskan', 'Tidak Diluluskan']
                : ['Disokong', 'Tidak Disokong'];
            return `
                <section class="approval-route-block">
                    <div
                        class="approval-recipient-body"
                        contenteditable="true"
                        data-recipient-key="${escapeHtml(recipientKey)}"
                        data-placeholder="Tulis kandungan untuk penerima ini bermula di sini..."
                    >${savedBody}</div>
                    <div class="approval-decision-options">
                        ${decisionOptions.map(label => `
                            <div class="approval-decision-option">
                                <span class="approval-decision-box" aria-hidden="true"></span>
                                <span>${escapeHtml(label)}</span>
                            </div>
                        `).join('')}
                    </div>
                    <div class="approval-route-title">Ulasan ${escapeHtml(route.position)} MAINPP:</div>
                    <div class="approval-comment-lines"><span></span><span></span></div>
                    <div class="approval-route-sign-row">
                        <div class="approval-route-date">Tarikh: .................... ..........</div>
                        <div class="approval-route-signature">
                            <div class="approval-route-sign-line"></div>
                            ${name ? `<strong>(${escapeHtml(name.toUpperCase())})</strong>` : ''}
                            <span>${escapeHtml(position)}</span>
                            <span>Majlis Agama Islam Negeri Pulau Pinang</span>
                        </div>
                    </div>
                </section>
            `;
        }

        function getHeaderFooterHtml(type) {
            const selector = type === 'footer' ? '.memo-custom-footer' : '.memo-custom-header';
            const source = document.querySelector(selector);
            return source ? source.innerHTML.trim() : '';
        }

        function syncHeaderFooterInputs() {
            if (pageHeaderInput) pageHeaderInput.value = getHeaderFooterHtml('header');
            if (pageFooterInput) pageFooterInput.value = getHeaderFooterHtml('footer');
        }

        function applyHeaderFooterToAll(type, html) {
            const selector = type === 'footer' ? '.memo-custom-footer' : '.memo-custom-header';
            document.querySelectorAll(selector).forEach(element => {
                if (element.innerHTML !== html) {
                    element.innerHTML = html;
                }
            });
            syncHeaderFooterInputs();
        }

        function createApprovalPreviewPage() {
            const page = document.createElement('div');
            page.className = 'approval-page-preview';
            const headerHtml = pageHeaderInput ? pageHeaderInput.value : '';
            const footerHtml = pageFooterInput ? pageFooterInput.value : '';
            const position = pageNumberPositionSelect ? pageNumberPositionSelect.value : 'none';
            page.innerHTML = `
                <div class="memo-custom-header">${headerHtml}</div>
                <div class="approval-page-inner"><div class="approval-route-preview"></div></div>
                <div class="memo-custom-footer">${footerHtml}</div>
                <div class="memo-page-number ${position}"></div>
            `;
            approvalPagesContainer.appendChild(page);
            renumberApprovalPages();
            return page.querySelector('.approval-route-preview');
        }

        function renumberApprovalPages() {
            const mainPageCount = document.querySelectorAll('.memo-page-preview[data-page-index]').length;
            document.querySelectorAll('.approval-page-preview').forEach((page, index) => {
                const number = page.querySelector('.memo-page-number');
                if (number) number.textContent = String(mainPageCount + index + 1);
            });
        }

        function splitOversizedApprovalBlock(preview, block, route) {
            if (preview.scrollHeight <= preview.clientHeight + 2) return;
            const sourceBody = block.querySelector('.approval-recipient-body');
            if (!sourceBody) return;

            const continuationHolder = document.createElement('div');
            continuationHolder.innerHTML = renderApprovalRouteBlock(route);
            const continuationBlock = continuationHolder.firstElementChild;
            const continuationBody = continuationBlock.querySelector('.approval-recipient-body');
            continuationBody.innerHTML = '';

            Array.from(block.children).forEach(child => {
                if (child !== sourceBody) child.remove();
            });

            while (preview.scrollHeight > preview.clientHeight + 2 && sourceBody.lastChild) {
                continuationBody.insertBefore(sourceBody.lastChild, continuationBody.firstChild);
            }

            const continuationPreview = createApprovalPreviewPage();
            continuationPreview.appendChild(continuationBlock);
            if (continuationPreview.scrollHeight > continuationPreview.clientHeight + 2 && continuationBody.childNodes.length > 1) {
                splitOversizedApprovalBlock(continuationPreview, continuationBlock, route);
            }
        }

        function updateApprovalPagePreview() {
            captureApprovalRouteBodies();
            if (approvalPagesContainer) {
                const recipients = getSelectedApprovalRecipients().map((recipient, index, array) => ({
                    ...recipient,
                    isLast: recipient.order === Math.max(...array.map(item => item.order || 0))
                }));
                approvalPagesContainer.innerHTML = '';
                let currentPreview = createApprovalPreviewPage();
                if (recipients.length === 0) {
                    currentPreview.innerHTML = '';
                } else {
                    recipients.forEach(route => {
                        const holder = document.createElement('div');
                        holder.innerHTML = renderApprovalRouteBlock(route);
                        const block = holder.firstElementChild;
                        currentPreview.appendChild(block);
                        if (currentPreview.scrollHeight > currentPreview.clientHeight + 2 && currentPreview.children.length > 1) {
                            block.remove();
                            currentPreview = createApprovalPreviewPage();
                            currentPreview.appendChild(block);
                        }
                        splitOversizedApprovalBlock(currentPreview, block, route);
                    });
                }
            }
            syncApprovalPageContent();
            document.querySelectorAll('.approval-recipient-body').forEach(ensureEditorTypography);
        }

        function syncApprovalPageContent() {
            captureApprovalRouteBodies();
            if (approvalRouteBodiesInput) {
                approvalRouteBodiesInput.value = JSON.stringify(approvalRouteBodies);
            }
            if (approvalPageBodyInput) approvalPageBodyInput.value = '';
        }

        function syncActiveEditorContent(editor) {
            if (editor && editor.classList && editor.classList.contains('approval-recipient-body')) {
                syncApprovalPageContent();
            } else {
                if (editor && editor.classList && editor.classList.contains('letter-page-editor') && !isDistributionEditor(editor) && !isPaginating && !isRepaginating && !isInsertingSignature) {
                    scheduleFullLetterPagination(editor);
                }
                syncEditorBody();
            }
            syncHeaderFooterInputs();
        }

        function getLetterEditors() {
            return Array.from(document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview) .letter-page-editor'));
        }

        function isDistributionPage(page) {
            return !!page && page.classList && page.classList.contains('distribution-page-preview');
        }

        function isDistributionEditor(editor) {
            return !!(editor && editor.closest && editor.closest('.distribution-page-preview'));
        }

        function getDistributionEditors() {
            return Array.from(document.querySelectorAll('.distribution-page-preview .letter-page-editor'));
        }

        function getSiblingEditors(editor) {
            return isDistributionEditor(editor) ? getDistributionEditors() : getLetterEditors();
        }

        function getEditorQuill(editor) {
            return editor && editor.__quillInstance ? editor.__quillInstance : null;
        }

        function registerWordLikeQuillFormats() {
            if (!window.Quill || window.__wordLikeQuillFormatsRegistered) return;

            const Embed = Quill.import('blots/embed');
            class SoftBreakBlot extends Embed {
                static create() {
                    return document.createElement('br');
                }

                static value() {
                    return true;
                }
            }
            SoftBreakBlot.blotName = 'softbreak';
            SoftBreakBlot.tagName = 'BR';
            Quill.register(SoftBreakBlot, true);
            const BlockEmbed = Quill.import('blots/block/embed');
            class GeneratedClosingBlot extends BlockEmbed {
                static create(value) {
                    const node = super.create();
                    node.setAttribute('data-generated-closing', '1');
                    node.setAttribute('data-signature-block', '1');
                    node.setAttribute('contenteditable', 'false');
                    node.classList.add('signature-block', 'generated-closing-lock');
                    node.innerHTML = value || '';
                    return node;
                }

                static value(node) {
                    return node.innerHTML || '';
                }
            }
            GeneratedClosingBlot.blotName = 'generatedClosing';
            GeneratedClosingBlot.tagName = 'div';
            GeneratedClosingBlot.className = 'generated-closing-lock';
            Quill.register(GeneratedClosingBlot, true);
            window.__wordLikeQuillFormatsRegistered = true;
        }

        function getQuillLineFormats(quill, index) {
            const safeIndex = Math.max(0, Math.min(index || 0, Math.max(0, quill.getLength() - 1)));
            const formats = quill.getFormat(safeIndex);
            return {
                align: formats.align || false,
                indent: formats.indent || false,
                list: formats.list || false
            };
        }

        function applyQuillLineFormats(quill, index, formats) {
            Object.entries(formats || {}).forEach(([name, value]) => {
                if (value) quill.formatLine(index, 1, name, value, 'silent');
            });
        }

        function isQuillRangeOnSuratRasmiGeneratedLine(quill, range) {
            if (!quill || !range) return false;
            const line = quill.getLine(Math.max(0, range.index || 0));
            const node = line && line[0] && line[0].domNode ? line[0].domNode : null;
            return !!(node && node.closest && node.closest('[data-surat-rasmi-generated-line]'));
        }

        function isSuratRasmiGeneratedLineInteraction(event) {
            if (event?.target?.closest && event.target.closest('[data-surat-rasmi-generated-line]')) {
                return true;
            }
            const selection = window.getSelection();
            if (!selection || selection.rangeCount === 0) return false;
            const node = selection.getRangeAt(0).commonAncestorContainer;
            const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
            return !!(element && element.closest('[data-surat-rasmi-generated-line]'));
        }

        function scheduleWordLikeEditorSync(editor) {
            if (!editor) return;
            window.requestAnimationFrame(() => {
                if (!document.body.contains(editor)) return;
                ensureEditorTypography(editor);
                normalizeSuratRasmiLineIndents(editor);
                if (!isPaginating) {
                    paginateEditorAndFollowing(editor);
                    reflowEditorContentUp(editor);
                }
                syncActiveEditorContent(editor);
                rememberEditorSelection(editor);
            });
        }

        function scheduleEnterPagination(editor) {
            if (!editor) return;
            window.requestAnimationFrame(() => {
                if (!document.body.contains(editor)) return;
                ensureEditorTypography(editor);
                normalizeSuratRasmiLineIndents(editor);
                refreshEditorPageHeights();
                if (!isPaginating) {
                    paginateEditorOverflow(editor);
                    paginateEditorAndFollowing(editor);
                }
                if (isCaretInPageBreakZone(editor) && editor.scrollHeight <= editor.clientHeight + 2) {
                    continueEnterToNextPage(editor);
                }
                syncActiveEditorContent(editor);
                rememberEditorSelection(editor);
            });
        }

        function paginateEditorAndFollowing(startEditor) {
            if (!startEditor || isPaginating) return;

            const startIndex = Math.max(0, getLetterEditors().indexOf(startEditor));
            let pass = 0;
            let hadOverflow = true;
            while (hadOverflow && pass < 30) {
                hadOverflow = false;
                const editors = getLetterEditors();
                for (let index = startIndex; index < editors.length; index++) {
                    const editor = editors[index];
                    if (!editor || !document.body.contains(editor)) continue;
                    refreshEditorPageHeights();
                    if (editor.scrollHeight > editor.clientHeight + 2) {
                        hadOverflow = true;
                        paginateEditorOverflow(editor);
                    }
                }
                pass += 1;
            }
        }

        function repaginate(editor = null) {
            const targetEditor = editor || activeLetterEditor || getLetterEditors()[0];
            if (!targetEditor || isPaginating || isRepaginating) return;

            isRepaginating = true;
            try {
                preserveQuillSelection(targetEditor, () => {
                    if (!document.body.contains(targetEditor)) return;
                    ensureEditorTypography(targetEditor);
                    normalizeSuratRasmiLineIndents(targetEditor);
                    refreshEditorPageHeights();
                    arrangeSignatureBlocks(targetEditor);
                    paginateEditorAndFollowing(targetEditor);
                    arrangeSignatureBlocks(targetEditor);
                    syncEditorBody();
                });
            } finally {
                isRepaginating = false;
            }
        }

        function scheduleFullLetterPagination(editor) {
            if (!editor) return;
            scheduledRepaginationEditor = editor;
            if (scheduledRepaginationFrame !== null || isRepaginating || isInsertingSignature) return;

            scheduledRepaginationFrame = window.requestAnimationFrame(() => {
                const targetEditor = scheduledRepaginationEditor;
                scheduledRepaginationFrame = null;
                scheduledRepaginationEditor = null;
                if (!targetEditor || !document.body.contains(targetEditor) || isPaginating) return;
                repaginate(targetEditor);
            });
        }

        function schedulePastePagination(editor) {
            if (!editor) return;
            window.requestAnimationFrame(() => {
                window.requestAnimationFrame(() => {
                    if (!document.body.contains(editor)) return;
                    ensureEditorTypography(editor);
                    updateSuratRasmiGeneratedLines();
                    normalizeSuratRasmiLineIndents(editor);
                    refreshEditorPageHeights();
                    if (!isPaginating && !isRepaginating && !isInsertingSignature) {
                        repaginate(editor);
                        reflowEditorContentUp(editor);
                        repaginate(editor);
                    } else {
                        scheduleFullLetterPagination(editor);
                    }
                    syncEditorBody();
                    rememberEditorSelection(editor);
                });
            });
        }

        function scheduleBackspaceReflow(editor) {
            if (!editor) return;
            window.requestAnimationFrame(() => {
                if (!document.body.contains(editor)) return;
                if (!isSelectionAtStartOfEditor(editor)) {
                    syncActiveEditorContent(editor);
                    return;
                }
                const previousEditor = getPreviousLetterEditor(editor);
                const reflowStart = previousEditor || editor;
                reflowEditorContentUp(reflowStart);
                if (previousEditor && !document.body.contains(editor)) {
                    focusEditorEnd(previousEditor);
                }
                normalizeSuratRasmiLineIndents(previousEditor || editor);
                scheduleFullLetterPagination(previousEditor || editor);
                syncEditorBody();
            });
        }

        function createWordLikeKeyboardBindings(editor) {
            const resolveEditor = () => editor && editor.__quillRoot ? editor.__quillRoot : editor;
            return {
                wordTab: {
                    key: 9,
                    shiftKey: false,
                    handler(range) {
                        const targetEditor = resolveEditor();
                        const quill = getEditorQuill(targetEditor) || getEditorQuill(editor);
                        if (!quill || !range) return false;
                        const tabText = '\u2003\u2003\u2003';
                        pushLetterUndoSnapshot();
                        if (range.length) quill.deleteText(range.index, range.length, 'user');
                        quill.insertText(range.index, tabText, 'user');
                        quill.setSelection(range.index + tabText.length, 0, 'silent');
                        scheduleWordLikeEditorSync(targetEditor);
                        return false;
                    }
                },
                wordShiftTab: {
                    key: 9,
                    shiftKey: true,
                    handler(range) {
                        const targetEditor = resolveEditor();
                        const quill = getEditorQuill(targetEditor) || getEditorQuill(editor);
                        if (!quill || !range) return false;
                        const tabText = '\u2003\u2003\u2003';
                        pushLetterUndoSnapshot();
                        const before = quill.getText(Math.max(0, range.index - tabText.length), tabText.length);
                        if (before === tabText) {
                            quill.deleteText(range.index - tabText.length, tabText.length, 'user');
                            quill.setSelection(range.index - tabText.length, 0, 'silent');
                        }
                        scheduleWordLikeEditorSync(targetEditor);
                        return false;
                    }
                },
                wordEnter: {
                    key: 'Enter',
                    shiftKey: false,
                    handler(range) {
                        const targetEditor = resolveEditor();
                        const quill = getEditorQuill(targetEditor) || getEditorQuill(editor);
                        if (!quill || !range) return true;
                        if (isQuillRangeOnSuratRasmiGeneratedLine(quill, range)) return false;
                        pushLetterUndoSnapshot();

                        const inlineFormats = quill.getFormat(range.index);
                        const lineFormats = getQuillLineFormats(quill, range.index);
                        if (range.length) quill.deleteText(range.index, range.length, 'user');
                        quill.insertText(range.index, '\n', inlineFormats, 'user');
                        applyQuillLineFormats(quill, range.index + 1, lineFormats);
                        quill.setSelection(range.index + 1, 0, 'silent');
                        scheduleEnterPagination(targetEditor);
                        return false;
                    }
                },
                wordShiftEnter: {
                    key: 'Enter',
                    shiftKey: true,
                    handler(range) {
                        const targetEditor = resolveEditor();
                        const quill = getEditorQuill(targetEditor) || getEditorQuill(editor);
                        if (!quill || !range) return false;
                        if (isQuillRangeOnSuratRasmiGeneratedLine(quill, range)) return false;
                        pushLetterUndoSnapshot();

                        if (range.length) quill.deleteText(range.index, range.length, 'user');
                        quill.insertEmbed(range.index, 'softbreak', true, 'user');
                        quill.setSelection(range.index + 1, 0, 'silent');
                        scheduleWordLikeEditorSync(targetEditor);
                        return false;
                    }
                },
                wordBackspace: {
                    key: 'Backspace',
                    handler(range, context) {
                        const targetEditor = resolveEditor();
                        const quill = getEditorQuill(targetEditor) || getEditorQuill(editor);
                        if (isQuillRangeOnSuratRasmiGeneratedLine(quill, range)) return false;
                        if (!isSelectionAtStartOfEditor(targetEditor)) {
                            return true;
                        }
                        scheduleBackspaceReflow(targetEditor);
                        return true;
                    }
                },
                wordDelete: {
                    key: 'Delete',
                    handler(range) {
                        const targetEditor = resolveEditor();
                        const quill = getEditorQuill(targetEditor) || getEditorQuill(editor);
                        if (isQuillRangeOnSuratRasmiGeneratedLine(quill, range)) return false;
                        window.requestAnimationFrame(() => scheduleWordLikeEditorSync(resolveEditor()));
                        return true;
                    }
                }
            };
        }
        function handleWordLikeTab(quill, targetEditor, shiftKey) {
            if (!quill || !targetEditor) return false;
            const range = quill.getSelection(true);
            if (!range) return false;
            const tabText = '\u2003\u2003\u2003';
            pushLetterUndoSnapshot();
            if (shiftKey) {
                const start = Math.max(0, range.index - tabText.length);
                const before = quill.getText(start, tabText.length);
                if (before === tabText) {
                    quill.deleteText(start, tabText.length, 'user');
                    quill.setSelection(start, 0, 'silent');
                }
            } else {
                if (range.length) quill.deleteText(range.index, range.length, 'user');
                quill.insertText(range.index, tabText, 'user');
                quill.setSelection(range.index + tabText.length, 0, 'silent');
            }
            scheduleWordLikeEditorSync(targetEditor);
            return true;
        }

        function normalizePastedPlainText(text) {
            return String(text || '')
                .replace(/\r\n/g, '\n')
                .replace(/\r/g, '\n')
                .replace(/[ \t]+\n/g, '\n')
                .replace(/\n[ \t]+/g, '\n')
                .replace(/\n{2,}/g, '\n');
        }

        function handleSuratRasmiPaste(editorRoot, event) {
            if (!editorRoot || !event?.clipboardData) return false;
            if (event.__suratRasmiPasteHandled) return true;
            if (isGeneratedClosingInteraction(event) || isSuratRasmiGeneratedLineInteraction(event)) {
                event.preventDefault();
                event.__suratRasmiPasteHandled = true;
                return true;
            }

            const text = normalizePastedPlainText(event.clipboardData.getData('text/plain'));
            if (!text) return false;

            const quill = getEditorQuill(editorRoot);
            if (!quill) return false;

            event.preventDefault();
            event.stopPropagation();
            event.__suratRasmiPasteHandled = true;
            pushLetterUndoSnapshot();

            const range = quill.getSelection(true) || { index: Math.max(0, quill.getLength() - 1), length: 0 };
            if (range.length) quill.deleteText(range.index, range.length, 'user');
            quill.insertText(range.index, text, quill.getFormat(range.index), 'user');
            quill.setSelection(range.index + text.length, 0, 'silent');

            ensureEditorTypography(editorRoot);
            updateSuratRasmiGeneratedLines();
            schedulePastePagination(editorRoot);
            syncActiveEditorContent(editorRoot);
            rememberEditorSelection(editorRoot);
            return true;
        }

        function attachWordLikeTabHandler(editorRoot, quill) {
            if (!editorRoot || editorRoot.dataset.wordTabHandlerAttached === '1') return;
            editorRoot.dataset.wordTabHandlerAttached = '1';
            editorRoot.addEventListener('keydown', event => {
                if (event.key !== 'Tab') return;
                event.preventDefault();
                event.stopPropagation();
                handleWordLikeTab(quill, editorRoot, event.shiftKey);
            }, true);
        }

        function enhanceEditorWithQuill(editor) {
            if (!editor || editor.__quillInstance || !window.Quill) {
                return editor;
            }
            registerWordLikeQuillFormats();
            const initialHtml = editor.innerHTML;
            editor.innerHTML = '';
            const quill = new Quill(editor, {
                theme: 'snow',
                modules: {
                    toolbar: false,
                    table: true,
                    history: {
                        userOnly: true
                    },
                    keyboard: {
                        bindings: createWordLikeKeyboardBindings(editor)
                    }
                }
            });
            editor.classList.add('quill-letter-host');
            quill.root.classList.add('word-editor', 'letter-page-editor');
            quill.root.__quillInstance = quill;
            editor.__quillInstance = quill;
            editor.__quillRoot = quill.root;
            editor.classList.remove('word-editor', 'letter-page-editor');
            editor.removeAttribute('contenteditable');
            if (initialHtml.trim()) {
                quill.clipboard.dangerouslyPasteHTML(0, initialHtml, 'silent');
            }
            attachEditorEvents(quill.root);
            attachWordLikeTabHandler(quill.root, quill);
            if (window.attachResizableEditorTables) {
                attachResizableEditorTables(quill.root, {
                    onResizeEnd(resizedEditor) {
                        ensureEditorTypography(resizedEditor);
                        syncActiveEditorContent(resizedEditor);
                        if (!isPaginating && !isRepaginating && !isInsertingSignature) {
                            scheduleFullLetterPagination(resizedEditor);
                        }
                    }
                });
            }
            quill.on('text-change', () => {
                ensureEditorTypography(quill.root);
                updateSuratRasmiGeneratedLines();
                syncActiveEditorContent(quill.root);
                if (quill.root.dataset.generatedClosingHtml) {
                    restoreGeneratedClosingIfNeeded(quill.root, quill.root.dataset.generatedClosingHtml);
                }
                if (!isPaginating && !isRepaginating && !isInsertingSignature) {
                    scheduleFullLetterPagination(quill.root);
                }
            });
            return quill.root;
        }

        function editorHasContent(editor) {
            if (!editor) return false;
            return editor.textContent.replace(/\s+/g, '').trim() !== '' || !!editor.querySelector('img, table');
        }

        function isManagedMemoFooter(node) {
            return node && node.nodeType === Node.ELEMENT_NODE && node.id === 'memo_editor_footer';
        }

        function isGeneratedClosingNode(node) {
            return !!(node && node.nodeType === Node.ELEMENT_NODE
                && (node.matches('[data-generated-closing="1"], .generated-closing-lock')
                    || node.querySelector('[data-generated-closing="1"], .generated-closing-lock')));
        }

        function getEditableChildNodes(editor) {
            return Array.from(editor ? editor.childNodes : []).filter(node => !isManagedMemoFooter(node));
        }

        function getTextOffsetWithinNode(root, container, offset) {
            if (!root || !container) return 0;
            if (root.nodeType === Node.TEXT_NODE) {
                return container === root ? Math.min(offset, root.textContent.length) : 0;
            }
            let total = 0;
            const sumNodeText = node => (node && node.textContent ? node.textContent.length : 0);
            if (container === root) {
                for (let index = 0; index < Math.min(offset, root.childNodes.length); index++) {
                    total += sumNodeText(root.childNodes[index]);
                }
                return total;
            }
            const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
            let current;
            while ((current = walker.nextNode())) {
                if (current === container) {
                    return total + Math.min(offset, current.textContent.length);
                }
                total += current.textContent.length;
            }
            return total;
        }

        function placeCaretByTextOffset(root, offset) {
            const selection = window.getSelection();
            if (!selection || !root) return;
            const range = document.createRange();
            const targetOffset = Math.max(0, offset);
            if (root.nodeType === Node.TEXT_NODE) {
                range.setStart(root, Math.min(targetOffset, root.textContent.length));
            } else {
                let remaining = targetOffset;
                const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
                let current;
                let lastText = null;
                while ((current = walker.nextNode())) {
                    lastText = current;
                    const length = current.textContent.length;
                    if (remaining <= length) {
                        range.setStart(current, remaining);
                        selection.removeAllRanges();
                        selection.addRange(range);
                        return;
                    }
                    remaining -= length;
                }
                if (!lastText) {
                    lastText = document.createTextNode('');
                    root.appendChild(lastText);
                }
                range.setStart(lastText, lastText.textContent.length);
            }
            selection.removeAllRanges();
            selection.addRange(range);
        }

        function getEditorPage(editor) {
            return editor ? editor.closest('.memo-page-preview') : null;
        }

        function getEditorHostElement(editor) {
            if (!editor) return null;
            return editor.closest('.quill-letter-host') || editor;
        }

        function getPreviousLetterEditor(editor) {
            const editors = getSiblingEditors(editor);
            const index = editors.indexOf(editor);
            return index > 0 ? editors[index - 1] : null;
        }

        function getNextLetterEditor(editor) {
            const editors = getSiblingEditors(editor);
            const index = editors.indexOf(editor);
            return index >= 0 && index < editors.length - 1 ? editors[index + 1] : null;
        }

        function getSelectionLetterEditor() {
            const selection = window.getSelection();
            if (!selection || selection.rangeCount === 0) return null;
            const node = selection.getRangeAt(0).startContainer;
            const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
            return element ? element.closest('.letter-page-editor') : null;
        }

        function captureLetterSnapshot() {
            const editors = getLetterEditors();
            return {
                pages: editors.map(editor => editor.innerHTML),
                activeIndex: Math.max(0, editors.indexOf(activeLetterEditor || getSelectionLetterEditor() || editors[0]))
            };
        }

        function serializeLetterSnapshot(snapshot) {
            return JSON.stringify(snapshot ? snapshot.pages : []);
        }

        function pushLetterUndoSnapshot() {
            if (isRestoringLetterSnapshot) return;
            const snapshot = captureLetterSnapshot();
            const serialized = serializeLetterSnapshot(snapshot);
            const last = letterUndoStack[letterUndoStack.length - 1];
            if (last && serializeLetterSnapshot(last) === serialized) return;
            letterUndoStack.push(snapshot);
            if (letterUndoStack.length > maxLetterUndoSnapshots) letterUndoStack.shift();
            letterRedoStack.length = 0;
        }

        function setEditorSnapshotHtml(editor, html) {
            if (!editor) return;
            const safeHtml = html && html.trim() ? html : '<p style="' + draftBodyStyle + '"><br></p>';
            const quill = getEditorQuill(editor);
            if (quill) {
                quill.setText('', 'silent');
                quill.clipboard.dangerouslyPasteHTML(0, safeHtml, 'silent');
            } else {
                editor.innerHTML = safeHtml;
            }
            ensureEditorTypography(editor);
        }

        function restoreLetterSnapshot(snapshot, pushRedo = true) {
            if (!snapshot || !Array.isArray(snapshot.pages)) return false;
            isRestoringLetterSnapshot = true;
            try {
                if (pushRedo) letterRedoStack.push(captureLetterSnapshot());
                let editors = getLetterEditors();
                while (editors.length < snapshot.pages.length) {
                    const pages = document.querySelectorAll('.memo-page-preview');
                    const lastPage = pages[pages.length - 1];
                    addLetterPage(lastPage, false);
                    editors = getLetterEditors();
                }
                while (editors.length > Math.max(1, snapshot.pages.length)) {
                    const lastEditor = editors[editors.length - 1];
                    const page = getEditorPage(lastEditor);
                    if (!page || page.dataset.pageIndex === '0') break;
                    moveFooterBeforePageDelete(page);
                    page.remove();
                    editors = getLetterEditors();
                }
                editors = getLetterEditors();
                editors.forEach((editor, index) => setEditorSnapshotHtml(editor, snapshot.pages[index] || ''));
                moveFooterToLastPage();
                renumberPages();
                refreshEditorPageHeights();
                syncEditorBody();
                updateSuratRasmiGeneratedLines();
                const focusEditor = getLetterEditors()[Math.min(snapshot.activeIndex || 0, getLetterEditors().length - 1)];
                if (focusEditor) focusEditorEnd(focusEditor);
                window.requestAnimationFrame(() => {
                    updateSuratRasmiGeneratedLines();
                    getLetterEditors().forEach(editor => {
                        ensureEditorTypography(editor);
                        normalizeSuratRasmiLineIndents(editor);
                    });
                    refreshEditorPageHeights();
                    syncEditorBody();
                });
                return true;
            } finally {
                isRestoringLetterSnapshot = false;
            }
        }

        function undoLetterSnapshot() {
            const snapshot = letterUndoStack.pop();
            if (!snapshot) return false;
            return restoreLetterSnapshot(snapshot, true);
        }

        function redoLetterSnapshot() {
            const snapshot = letterRedoStack.pop();
            if (!snapshot) return false;
            letterUndoStack.push(captureLetterSnapshot());
            return restoreLetterSnapshot(snapshot, false);
        }

        function handleLetterUndoRedoShortcut(event) {
            const key = (event.key || '').toLowerCase();
            const isModifier = event.ctrlKey || event.metaKey;
            if (!isModifier) return false;
            if (key === 'z' && !event.shiftKey) {
                event.preventDefault();
                event.stopPropagation();
                undoLetterSnapshot();
                return true;
            }
            if (key === 'y' || (key === 'z' && event.shiftKey)) {
                event.preventDefault();
                event.stopPropagation();
                redoLetterSnapshot();
                return true;
            }
            return false;
        }
        function focusEditorStart(editor) {
            if (!editor) return;
            editor.focus();
            const range = document.createRange();
            range.selectNodeContents(editor);
            range.collapse(true);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            activeLetterEditor = editor;
            rememberEditorSelection(editor);
        }

        function getEditorParagraphs(editor) {
            if (!editor) return [];
            return Array.from(editor.children).filter(child => {
                return child && child.nodeType === Node.ELEMENT_NODE && ['P', 'DIV'].includes(child.tagName);
            });
        }

        function normalizeSuratRasmiLineIndents(editor) {
            if (!editor) return;
            const page = getEditorPage(editor);
            const isFirstPage = !page || page.dataset.pageIndex === '0';
            getEditorParagraphs(editor).forEach(paragraph => {
                if (isFirstPage && paragraph.hasAttribute('data-surat-rasmi-generated-line')) {
                    paragraph.style.marginLeft = '2.54cm';
                } else {
                    paragraph.style.marginLeft = '';
                }
            });
        }

        function focusSuratRasmiFirstLine(editor) {
            if (!editor) return;
            normalizeSuratRasmiLineIndents(editor);
            const firstParagraph = getEditorParagraphs(editor)[0] || editor;
            editor.focus();
            const range = document.createRange();
            range.selectNodeContents(firstParagraph);
            range.collapse(true);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            activeLetterEditor = editor;
            rememberEditorSelection(editor);
        }

        function isSuratRasmiStarterOnly(editor) {
            if (!editor) return false;
            return (editor.textContent || '').replace(/\s+/g, '').trim() === '';
        }

        function removeExtraLetterPages() {
            getLetterEditors().slice(1).forEach(editor => {
                const page = getEditorPage(editor);
                if (page) page.remove();
            });
        }

        function clearAllLetterPages() {
            const firstEditor = getLetterEditors()[0];
            if (!firstEditor) return;
            removeExtraLetterPages();
            firstEditor.innerHTML = getSuratRasmiFirstPageStarterHtml();
            allLetterPagesSelected = false;
            activeLetterEditor = firstEditor;
            moveFooterToLastPage();
            renumberPages();
            refreshEditorPageHeights();
            firstEditor.focus();
            const range = document.createRange();
            range.selectNodeContents(firstEditor);
            range.collapse(true);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            rememberEditorSelection(firstEditor);
        }

        function selectAllLetterPages() {
            const editors = getLetterEditors();
            if (!editors.length) return;
            const firstEditor = editors[0];
            const lastEditor = editors[editors.length - 1];
            const range = document.createRange();
            range.setStart(firstEditor, 0);
            range.setEnd(lastEditor, lastEditor.childNodes.length);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            allLetterPagesSelected = true;
            activeLetterEditor = firstEditor;
            firstEditor.focus();
        }

        function selectionTouchesEditor(selection, editor) {
            if (!selection || !editor || selection.rangeCount === 0) return false;
            const range = selection.getRangeAt(0);
            try {
                return range.intersectsNode(editor);
            } catch (error) {
                return false;
            }
        }

        function getSelectedLetterEditors() {
            const selection = window.getSelection();
            if (allLetterPagesSelected) return getLetterEditors();
            return getLetterEditors().filter(editor => selectionTouchesEditor(selection, editor));
        }

        function isSelectionAtStartOfEditor(editor) {
            const selection = window.getSelection();
            if (!editor || !selection || selection.rangeCount === 0 || !selection.isCollapsed) return false;
            const range = selection.getRangeAt(0);
            if (!editor.contains(range.startContainer) && range.startContainer !== editor) return false;
            const beforeRange = document.createRange();
            beforeRange.setStart(editor, 0);
            beforeRange.setEnd(range.startContainer, range.startOffset);
            const beforeFragment = beforeRange.cloneContents();
            if (beforeFragment.querySelectorAll) {
                beforeFragment.querySelectorAll('[data-surat-rasmi-generated-line], [data-generated-closing="1"]').forEach(node => node.remove());
            }
            return (beforeFragment.textContent || '').replace(/\s+/g, '').trim().length === 0;
        }

        function focusEditorEnd(editor) {
            if (!editor) return;
            editor.focus();
            const range = document.createRange();
            range.selectNodeContents(editor);
            range.collapse(false);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
            activeLetterEditor = editor;
            rememberEditorSelection(editor);
        }

        function getCollapsedCaretRect(range) {
            if (!range) return null;
            let rect = range.getBoundingClientRect();
            if (rect && (rect.width || rect.height || rect.top || rect.bottom)) return rect;

            const node = range.startContainer;
            const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
            return element ? element.getBoundingClientRect() : null;
        }

        function isCaretNearEditorBottom(editor) {
            const selection = window.getSelection();
            if (!editor || !selection || selection.rangeCount === 0 || !selection.isCollapsed) return false;
            const range = selection.getRangeAt(0);
            if (!editor.contains(range.startContainer) && range.startContainer !== editor) return false;

            const caretRect = getCollapsedCaretRect(range.cloneRange());
            const editorRect = editor.getBoundingClientRect();
            if (!caretRect || !editorRect) return false;
            return caretRect.bottom >= editorRect.bottom - 8;
        }

        function isCaretInPageBreakZone(editor) {
            const selection = window.getSelection();
            if (!editor || !selection || selection.rangeCount === 0 || !selection.isCollapsed) return false;
            const range = selection.getRangeAt(0);
            if (!editor.contains(range.startContainer) && range.startContainer !== editor) return false;

            const caretRect = getCollapsedCaretRect(range.cloneRange());
            const editorRect = editor.getBoundingClientRect();
            if (!caretRect || !editorRect) return false;
            const editorStyle = window.getComputedStyle(editor);
            const lineHeight = parseFloat(editorStyle.lineHeight) || 16;
            const maxHeight = parseFloat(editorStyle.maxHeight);
            const editorLimitBottom = Number.isFinite(maxHeight) && maxHeight > 0
                ? editorRect.top + maxHeight
                : editorRect.bottom;
            return caretRect.bottom >= editorLimitBottom - Math.max(18, lineHeight + 4);
        }

        function continueEnterToNextPage(editor) {
            if (!editor) return;
            const page = getEditorPage(editor);
            if (!page) return;

            const currentIsDistribution = isDistributionPage(page);
            const nextPage = page.nextElementSibling
                && page.nextElementSibling.classList.contains('memo-page-preview')
                && isDistributionPage(page.nextElementSibling) === currentIsDistribution
                ? page.nextElementSibling
                : null;
            const nextEditor = nextPage ? nextPage.querySelector('.letter-page-editor') : getNextLetterEditor(editor);
            focusEditorStart(nextEditor || (currentIsDistribution ? addDistributionPage(page) : addLetterPage(page)));
        }

        function handleEditorEnterKey(editor, event) {
            if (event.key !== 'Enter' || event.ctrlKey || event.altKey || event.metaKey) return;
            refreshEditorPageHeights();

            window.requestAnimationFrame(() => {
                if (!document.body.contains(editor)) return;

                normalizeSuratRasmiLineIndents(editor);
                refreshEditorPageHeights();
                if (editor.scrollHeight > editor.clientHeight + 2) {
                    paginateEditorOverflow(editor);
                    window.requestAnimationFrame(() => {
                        const selectedEditor = getSelectionLetterEditor();
                        if (selectedEditor && selectedEditor !== editor) {
                            activeLetterEditor = selectedEditor;
                            rememberEditorSelection(selectedEditor);
                            return;
                        }
                        if (isCaretNearEditorBottom(editor) && editor.scrollHeight > editor.clientHeight + 2) {
                            continueEnterToNextPage(editor);
                        }
                    });
                } else if (isCaretInPageBreakZone(editor)) {
                    continueEnterToNextPage(editor);
                }
                syncEditorBody();
            });
        }

        function removeEmptyLetterPage(editor) {
            const previousEditor = getPreviousLetterEditor(editor);
            const page = getEditorPage(editor);
            if (!page || page.dataset.pageIndex === '0') {
                return previousEditor || editor;
            }

            moveFooterBeforePageDelete(page);
            page.remove();
            moveFooterToLastPage();
            renumberPages();
            refreshEditorPageHeights();
            return previousEditor || getSiblingEditors(editor)[0] || null;
        }

        function handleEditorBackspaceKey(editor, event) {
            if (event.key !== 'Backspace' || event.ctrlKey || event.altKey || event.metaKey) return;
            if (!isSelectionAtStartOfEditor(editor)) {
                scheduleBackspaceReflow(editor);
                return;
            }

            const previousEditor = getPreviousLetterEditor(editor);
            if (!previousEditor) return;

            event.preventDefault();

            if (!editorHasContent(editor)) {
                const focusEditor = removeEmptyLetterPage(editor);
                if (focusEditor) focusEditorEnd(focusEditor);
                syncEditorBody();
                return;
            }

            if (removeLeadingEmptyEditorUnit(editor)) {
                if (!editorHasContent(editor)) {
                    const focusEditor = removeEmptyLetterPage(editor);
                    if (focusEditor) focusEditorEnd(focusEditor);
                } else {
                    focusEditorStart(editor);
                }
                syncEditorBody();
                return;
            }

            mergeEditorIntoPreviousPage(editor);
            syncEditorBody();
        }

        function mergeEditorIntoPreviousPage(editor) {
            const previousEditor = getPreviousLetterEditor(editor);
            const page = getEditorPage(editor);
            if (!previousEditor || !page) return false;
            const hasContent = editorHasContent(editor);
            while (getEditableChildNodes(editor).length > 0) {
                previousEditor.appendChild(getEditableChildNodes(editor)[0]);
            }
            moveFooterBeforePageDelete(page);
            page.remove();
            moveFooterToLastPage();
            renumberPages();
            refreshEditorPageHeights();
            focusEditorEnd(previousEditor);
            if (hasContent) window.requestAnimationFrame(() => paginateEditorOverflow(previousEditor));
            return true;
        }

        function deleteLastEditorUnit(editor) {
            if (!editor) return false;

            const deleteLastUnitFrom = container => {
                for (let index = container.childNodes.length - 1; index >= 0; index--) {
                    const child = container.childNodes[index];

                    if (child.nodeType === Node.TEXT_NODE) {
                        const text = child.textContent || '';
                        if (text.length > 0) {
                            child.textContent = text.slice(0, -1);
                            if (child.textContent.length === 0) child.remove();
                            return true;
                        }
                        child.remove();
                        continue;
                    }

                    if (child.nodeType !== Node.ELEMENT_NODE) {
                        child.remove();
                        continue;
                    }

                    if (child.tagName === 'BR') {
                        child.remove();
                        return true;
                    }

                    if (deleteLastUnitFrom(child)) {
                        if (child !== editor
                            && child.childNodes.length === 0
                            && !child.matches('img, table, tbody, thead, tfoot, tr, td, th')) {
                            child.remove();
                        }
                        return true;
                    }

                    if (!child.firstChild && !child.matches('img, table')) {
                        child.remove();
                        return true;
                    }
                }

                return false;
            };

            return deleteLastUnitFrom(editor);
        }

        function isEmptyEditorLineNode(node) {
            if (!node) return false;
            if (node.nodeType === Node.TEXT_NODE) {
                return (node.textContent || '').replace(/\u00a0/g, ' ').trim() === '';
            }
            if (node.nodeType !== Node.ELEMENT_NODE) return false;
            if (node.matches('img, table')) return false;
            return (node.textContent || '').replace(/\u00a0/g, ' ').trim() === ''
                && !node.querySelector('img, table');
        }

        function removeLeadingEmptyEditorUnit(editor) {
            if (!editor) return false;
            const page = editor.closest('.memo-page-preview');
            const isFirstSuratPage = page && parseInt(page.dataset.pageIndex || '0', 10) === 0;
            if (isFirstSuratPage && !editorHasContent(editor)) {
                editor.innerHTML = getSuratRasmiFirstPageStarterHtml();
                return false;
            }

            while (editor.firstChild && isEmptyEditorLineNode(editor.firstChild)) {
                editor.firstChild.remove();
                if (!editor.firstChild) {
                    editor.innerHTML = isFirstSuratPage ? getSuratRasmiFirstPageStarterHtml() : '<p style="' + draftBodyStyle + '"><br></p>';
                    return true;
                }
                return true;
            }

            return false;
        }

        function removeEmptyTrailingEditorPages() {
            const editors = getLetterEditors();
            for (let index = editors.length - 1; index > 0; index--) {
                const editor = editors[index];
                if (editorHasContent(editor)) break;
                const page = getEditorPage(editor);
                if (page) {
                    moveFooterBeforePageDelete(page);
                    page.remove();
                }
            }
        }

        function pullNextEditorContentInto(editor) {
            const nextEditor = getNextLetterEditor(editor);
            if (!editor || !nextEditor || !editorHasContent(nextEditor)) return false;

            let movedContent = false;
            refreshEditorPageHeights();

            while (getEditableChildNodes(nextEditor).length > 0) {
                const nodeToMove = getEditableChildNodes(nextEditor)[0];
                editor.appendChild(nodeToMove);
                refreshEditorPageHeights();

                if (editor.scrollHeight > editor.clientHeight + 2) {
                    nextEditor.insertBefore(nodeToMove, nextEditor.firstChild);
                    refreshEditorPageHeights();
                    break;
                }

                movedContent = true;
            }

            return movedContent;
        }

        function reflowEditorContentUp(startEditor) {
            if (!startEditor || isPaginating) return;

            isPaginating = true;
            try {
                moveFooterToLastPage();
                refreshEditorPageHeights();

                const editors = getLetterEditors();
                const startIndex = Math.max(0, editors.indexOf(startEditor));
                for (let index = startIndex; index < editors.length - 1; index++) {
                    const editor = editors[index];
                    while (pullNextEditorContentInto(editor)) {
                        // Keep pulling until the current page is full or the next page is empty.
                    }
                }

                removeEmptyTrailingEditorPages();
            } finally {
                isPaginating = false;
                moveFooterToLastPage();
                renumberPages();
                refreshEditorPageHeights();
            }
        }

        function rememberEditorSelection(editor) {
            const selection = window.getSelection();
            if (!editor || !selection || selection.rangeCount === 0) return;
            const range = selection.getRangeAt(0);
            if ((editor.contains(range.startContainer) || range.startContainer === editor)
                && (editor.contains(range.endContainer) || range.endContainer === editor)) {
                savedEditorRange = range.cloneRange();
                allLetterPagesSelected = false;
            }
        }

        function normalizeEditorFontTags(editor) {
            if (!editor) return;
            editor.querySelectorAll('font').forEach(font => {
                const span = document.createElement('span');
                span.innerHTML = font.innerHTML;
                font.replaceWith(span);
            });
        }

        function ensureEditorTypography(editor) {
            if (!editor) return;
            normalizeEditorFontTags(editor);
            getAllEditableBlocks(editor).forEach(target => {
                if (target.nodeType !== Node.ELEMENT_NODE) return;
                if (!target.style.fontFamily) target.style.fontFamily = 'Arial, Helvetica, sans-serif';
                if (!target.style.fontSize) target.style.fontSize = '16px';
                if (!target.style.lineHeight) target.style.lineHeight = '1.5';
                if (!target.hasAttribute('data-surat-rasmi-generated-line')) {
                    target.style.marginTop = '0';
                    target.style.marginBottom = '0';
                    target.style.paddingTop = '0';
                    target.style.paddingBottom = '0';
                }
            });
            if (!editor.style.fontFamily) editor.style.fontFamily = 'Arial, Helvetica, sans-serif';
            if (!editor.style.fontSize) editor.style.fontSize = '16px';
            if (!editor.style.lineHeight) editor.style.lineHeight = '1.5';
        }

        function ensureAllDocumentTypography() {
            getLetterEditors().forEach(ensureEditorTypography);
            document.querySelectorAll('.approval-recipient-body').forEach(ensureEditorTypography);
        }
        function normalizeQuillLineStylesForSave(editor) {
            if (!editor) return;
            editor.querySelectorAll('.ql-align-center, .ql-align-right, .ql-align-justify').forEach(block => {
                if (block.classList.contains('ql-align-center')) block.style.textAlign = 'center';
                if (block.classList.contains('ql-align-right')) block.style.textAlign = 'right';
                if (block.classList.contains('ql-align-justify')) block.style.textAlign = 'justify';
            });
        }

        function applyQuillToolbarCommand(editor, quill, command) {
            if (!editor || !quill || !command) return false;
            const range = quill.getSelection(true);
            if (!range) return false;
            if (typeof isQuillRangeOnSuratRasmiGeneratedLine === 'function' && isQuillRangeOnSuratRasmiGeneratedLine(quill, range)) {
                return true;
            }

            const length = Math.max(range.length || 0, 1);
            if (command === 'justifyLeft' || command === 'justifyCenter' || command === 'justifyRight' || command === 'justifyFull') {
                const alignMap = {
                    justifyLeft: false,
                    justifyCenter: 'center',
                    justifyRight: 'right',
                    justifyFull: 'justify'
                };
                quill.formatLine(range.index, length, 'align', alignMap[command], 'user');
            } else if (command === 'insertOrderedList' || command === 'insertUnorderedList') {
                const listValue = command === 'insertOrderedList' ? 'ordered' : 'bullet';
                const currentFormats = quill.getFormat(range.index, length);
                quill.formatLine(range.index, length, 'list', currentFormats.list === listValue ? false : listValue, 'user');
            } else {
                return false;
            }

            quill.setSelection(range.index, range.length, 'silent');
            normalizeQuillLineStylesForSave(editor);
            rememberEditorSelection(editor);
            syncActiveEditorContent(editor);
            if (typeof paginateEditorOverflow === 'function') {
                window.requestAnimationFrame(() => paginateEditorOverflow(editor));
            }
            return true;
        }

        function execEditorCommand(command) {
            const editor = activeLetterEditor || document.querySelector('.letter-page-editor');
            if (!editor || !command) return;
            pushLetterUndoSnapshot();
            activeLetterEditor = editor;
            const quill = getEditorQuill(editor);
            if (quill && applyQuillToolbarCommand(editor, quill, command)) return;
            editor.focus();
            if (savedEditorRange) {
                const selection = window.getSelection();
                selection.removeAllRanges();
                selection.addRange(savedEditorRange);
            }
            document.execCommand(command, false, null);
            rememberEditorSelection(editor);
            syncActiveEditorContent(editor);
        }
        function applyStyleToSelection(styleProperty, styleValue) {
            const editor = activeLetterEditor || document.querySelector('.letter-page-editor');
            if (!editor || !styleProperty || !styleValue) return;
            editor.focus();
            if (savedEditorRange) {
                const selection = window.getSelection();
                selection.removeAllRanges();
                selection.addRange(savedEditorRange);
            }

            const selection = window.getSelection();
            const range = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
            if (!range || (!editor.contains(range.commonAncestorContainer) && range.commonAncestorContainer !== editor)) {
                editor.style[styleProperty] = styleValue;
            } else if (range.collapsed) {
                const target = getClosestEditableBlock(editor, range.startContainer) || editor;
                target.style[styleProperty] = styleValue;
            } else {
                getEditableBlocksInRange(editor, range).forEach(target => {
                    target.style[styleProperty] = styleValue;
                });
            }

            rememberEditorSelection(editor);
            syncActiveEditorContent(editor);
        }

        function applyEditorFontFamily() {
            const family = fontFamilySelect ? fontFamilySelect.value : 'Arial';
            applyStyleToSelection('fontFamily', family + ', sans-serif');
        }

        function applyEditorFontSize() {
            const size = fontSizeSelect ? parseInt(fontSizeSelect.value, 10) : 16;
            applyStyleToSelection('fontSize', (Number.isFinite(size) ? size : 16) + 'px');
        }

        function getEditableBlocksInRange(editor, range) {
            const blockSelector = 'p, div, li, td, th, blockquote, h1, h2, h3, h4, h5, h6';
            const blocks = Array.from(editor.querySelectorAll(blockSelector)).filter(element => {
                if (element === editor || !editor.contains(element)) return false;
                try {
                    return range.intersectsNode(element);
                } catch (error) {
                    return false;
                }
            });
            return blocks.filter(element => !blocks.some(other => other !== element && other.contains(element)));
        }

        function getClosestEditableBlock(editor, node) {
            const blockSelector = 'p, div, li, td, th, blockquote, h1, h2, h3, h4, h5, h6';
            const element = node && node.nodeType === Node.ELEMENT_NODE ? node : node?.parentElement;
            if (!element) return null;
            const block = element.closest(blockSelector);
            return block && editor.contains(block) && block !== editor ? block : null;
        }

        function getAllEditableBlocks(editor) {
            const blocks = Array.from(editor.querySelectorAll('p, div, li, td, th, blockquote, h1, h2, h3, h4, h5, h6'))
                .filter(element => element !== editor);
            return blocks.length ? blocks : [editor];
        }

        function applyEditorIndent(editor, direction) {
            if (!editor) return;
            pushLetterUndoSnapshot();
            editor.focus();
            const selection = window.getSelection();
            const range = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
            let targets = [];

            if (range && (editor.contains(range.startContainer) || range.startContainer === editor)) {
                targets = range.collapsed
                    ? [getClosestEditableBlock(editor, range.startContainer) || editor]
                    : getEditableBlocksInRange(editor, range);
            }

            if (targets.length === 0) targets = [editor];

            targets.forEach(target => {
                if (target.nodeType !== Node.ELEMENT_NODE) return;
                const current = parseFloat(target.style.marginLeft || window.getComputedStyle(target).marginLeft) || 0;
                const next = Math.max(0, current + (direction * 36));
                target.style.marginLeft = next ? next + 'px' : '';
            });

            rememberEditorSelection(editor);
            syncActiveEditorContent(editor);
        }

        function ensureEditorLineSpacing(editor) {
            ensureEditorTypography(editor);
        }

        function ensureAllDocumentLineSpacing() {
            ensureAllDocumentTypography();
        }

        function applyEditorLineSpacing() {
            const editor = activeLetterEditor || document.querySelector('.letter-page-editor');
            if (!editor) return;
            pushLetterUndoSnapshot();
            const selectedEditors = getSelectedLetterEditors();
            if (allLetterPagesSelected || selectedEditors.length > 1) {
                (selectedEditors.length ? selectedEditors : getLetterEditors()).forEach(selectedEditor => {
                    ensureEditorTypography(selectedEditor);
                });
                refreshEditorPageHeights();
                getLetterEditors().forEach(selectedEditor => {
                    if (!isPaginating) window.requestAnimationFrame(() => paginateEditorOverflow(selectedEditor));
                });
                syncEditorBody();
                return;
            }

            editor.focus();

            if (savedEditorRange) {
                const selection = window.getSelection();
                selection.removeAllRanges();
                selection.addRange(savedEditorRange);
            }

            const selection = window.getSelection();
            const range = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
            let targets = [];

            if (range && (editor.contains(range.startContainer) || range.startContainer === editor)) {
                targets = range.collapsed
                    ? [getClosestEditableBlock(editor, range.startContainer)].filter(Boolean)
                    : getEditableBlocksInRange(editor, range);
            }

            if (targets.length === 0) {
                targets = getAllEditableBlocks(editor);
            }

            ensureEditorTypography(editor);
            rememberEditorSelection(editor);
            syncActiveEditorContent(editor);
        }

        function buildEditorTableHtml(rows, cols) {
            const colWidth = (100 / cols).toFixed(4) + '%';
            let tableHtml = '<table style="width:100%;"><colgroup>';
            for (let col = 0; col < cols; col++) {
                tableHtml += '<col style="width:' + colWidth + ';">';
            }
            tableHtml += '</colgroup><tbody>';
            for (let row = 0; row < rows; row++) {
                tableHtml += '<tr>';
                for (let col = 0; col < cols; col++) {
                    tableHtml += row === 0 ? '<th>Tajuk ' + (col + 1) + '</th>' : '<td>&nbsp;</td>';
                }
                tableHtml += '</tr>';
            }
            return tableHtml + '</tbody></table><p style="' + draftBodyStyle + '"><br></p>';
        }

        function insertHtmlAtEditorSelection(editor, html) {
            if (savedEditorRange) {
                const selection = window.getSelection();
                selection.removeAllRanges();
                selection.addRange(savedEditorRange);
            }
            const selection = window.getSelection();
            let range = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
            if (!range || !editor.contains(range.startContainer)) {
                range = document.createRange();
                range.selectNodeContents(editor);
                range.collapse(false);
            }
            range.deleteContents();
            const fragment = range.createContextualFragment(html);
            const lastNode = fragment.lastChild;
            range.insertNode(fragment);
            if (lastNode) {
                range.setStartAfter(lastNode);
                range.collapse(true);
                selection.removeAllRanges();
                selection.addRange(range);
            }
            const quill = getEditorQuill(editor);
            if (quill) quill.update('user');
        }

        function insertEditorTable() {
            const editor = activeLetterEditor || document.querySelector('.letter-page-editor');
            if (!editor) return;
            const rows = Math.max(1, Math.min(10, parseInt(tableRowsSelect ? tableRowsSelect.value : '3', 10) || 3));
            const cols = Math.max(1, Math.min(8, parseInt(tableColsSelect ? tableColsSelect.value : '2', 10) || 2));
            editor.focus();
            const quill = getEditorQuill(editor);
            const tableModule = quill && quill.getModule ? quill.getModule('table') : null;
            if (tableModule && typeof tableModule.insertTable === 'function') {
                quill.focus();
                const range = quill.getSelection(true) || { index: Math.max(0, quill.getLength() - 1), length: 0 };
                if (range.length) quill.deleteText(range.index, range.length, 'user');
                quill.setSelection(range.index, 0, 'silent');
                tableModule.insertTable(rows, cols);
                quill.update('user');
            } else {
                insertHtmlAtEditorSelection(editor, buildEditorTableHtml(rows, cols));
            }
            rememberEditorSelection(editor);
            syncActiveEditorContent(editor);
        }

        function getParagraphForNode(node, editor) {
            if (!node || !editor) return null;
            const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
            if (!element) return null;
            const paragraph = element.closest('p, div');
            return paragraph && editor.contains(paragraph) ? paragraph : null;
        }

        function isEmptyDefaultNumberLine(paragraph, number) {
            if (!paragraph) return false;
            const text = paragraph.textContent.replace(/\u00a0/g, ' ').trim();
            return text === number + '.';
        }

        function placeCaretAtEnd(element) {
            if (!element) return;
            const range = document.createRange();
            range.selectNodeContents(element);
            range.collapse(false);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
        }

        function focusNumberTwoLine(editor, event) {
            if (isSuratRasmiStarterOnly(editor)) {
                event.preventDefault();
                focusSuratRasmiFirstLine(editor);
                return;
            }
            const paragraph = getParagraphForNode(event.target, editor);
            if (!isEmptyDefaultNumberLine(paragraph, '2')) return;
            paragraph.innerHTML = '2. &nbsp;&nbsp;&nbsp;&nbsp;';
            window.requestAnimationFrame(() => {
                placeCaretAtEnd(paragraph);
                rememberEditorSelection(editor);
            });
        }

        function removeEmptyNumberThreeLines(editor) {
            if (!editor) return;
            Array.from(editor.querySelectorAll('p, div')).forEach(paragraph => {
                if (isEmptyDefaultNumberLine(paragraph, '3')) {
                    paragraph.remove();
                }
            });
        }

        function syncEditorBody() {
            const editors = getLetterEditors();
            editors.forEach(removeEmptyNumberThreeLines);
            const pages = editors.map(editor => editor.innerHTML.trim()).filter(html => {
                const temp = document.createElement('div');
                temp.innerHTML = html;
                return temp.textContent.replace(/\s+/g, '').trim() !== '';
            });
            if (letterBodyInput) letterBodyInput.value = pages[0] || '';
            if (letterPagesInput) letterPagesInput.value = JSON.stringify(pages.length ? pages : ['']);
            if (pageCountLabel) pageCountLabel.textContent = 'Page Number';
        }

        function renumberPages() {
            document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview)[data-page-index]').forEach((page, index) => {
                page.dataset.pageIndex = String(index);
                page.dataset.pageNumber = String(index + 1);
                const number = page.querySelector('.memo-page-number');
                if (number) number.textContent = String(index + 1);
                const deleteButton = page.querySelector('.page-delete-btn');
                if (deleteButton) deleteButton.disabled = index === 0;
            });
            getLetterEditors().forEach(normalizeSuratRasmiLineIndents);
            renumberDistributionPages();
            renumberApprovalPages();
            syncEditorBody();
        }

        function updatePageNumberPosition() {
            const position = pageNumberPositionSelect ? pageNumberPositionSelect.value : 'none';
            document.querySelectorAll('.memo-page-number').forEach(number => {
                number.classList.remove('none', 'bottom_center', 'bottom_right');
                number.classList.add(position);
            });
        }

        function updateHeaderFooterPreview() {
            const headerHtml = pageHeaderInput ? pageHeaderInput.value : '';
            const footerHtml = pageFooterInput ? pageFooterInput.value : '';
            document.querySelectorAll('.memo-custom-header').forEach(header => {
                header.innerHTML = headerHtml;
            });
            document.querySelectorAll('.memo-custom-footer').forEach(footer => {
                footer.innerHTML = footerHtml;
            });
        }

        function updateLetterPageFitScale() {
            if (!letterPagesContainer) return;
            letterPagesContainer.style.setProperty('--letter-page-zoom', '1');
        }

        function refreshEditorPageHeights() {
            updateLetterPageFitScale();
            document.querySelectorAll('.memo-page-preview').forEach(page => {
                const editor = page.querySelector('.letter-page-editor');
                if (!editor) return;

                const pageStyle = window.getComputedStyle(page);
                const paddingBottom = parseFloat(pageStyle.paddingBottom) || 0;
                const pageRect = page.getBoundingClientRect();
                const editorRect = editor.getBoundingClientRect();
                const editorTop = Math.max(0, editorRect.top - pageRect.top);
                const memoFooter = page.querySelector('#memo_editor_footer');
                const memoFooterHeight = memoFooter ? memoFooter.getBoundingClientRect().height : 0;
                const footerGap = memoFooter ? 14 : 0;
                const pageNumber = page.querySelector('.memo-page-number:not(.none)');
                const bottomGuard = pageNumber ? 24 : 12;
                const maxHeight = Math.max(24, page.clientHeight - paddingBottom - editorTop - memoFooterHeight - footerGap - bottomGuard);
                editor.style.setProperty('--editor-max-height', maxHeight + 'px');
                editor.style.maxHeight = maxHeight + 'px';
                editor.style.minHeight = maxHeight + 'px';
                const quillHost = editor.closest('.quill-letter-host');
                if (quillHost) {
                    quillHost.style.setProperty('--editor-max-height', maxHeight + 'px');
                    quillHost.style.maxHeight = maxHeight + 'px';
                    quillHost.style.minHeight = maxHeight + 'px';
                    const quillContainer = quillHost.querySelector('.ql-container');
                    if (quillContainer) {
                        quillContainer.style.maxHeight = maxHeight + 'px';
                        quillContainer.style.minHeight = maxHeight + 'px';
                        quillContainer.style.overflow = 'hidden';
                    }
                    const quillEditor = quillHost.querySelector('.ql-editor');
                    if (quillEditor) {
                        quillEditor.style.maxHeight = maxHeight + 'px';
                        quillEditor.style.minHeight = maxHeight + 'px';
                    }
                }
            });
        }

        function attachEditorEvents(editor) {
            ensureEditorTypography(editor);
            editor.addEventListener('focus', () => {
                activeLetterEditor = editor;
                rememberEditorSelection(editor);
            });
            editor.addEventListener('beforeinput', event => {
                pushLetterUndoSnapshot();
                if (isGeneratedClosingInteraction(event)) {
                    event.preventDefault();
                    return;
                }
                if (isSuratRasmiGeneratedLineInteraction(event)) {
                    event.preventDefault();
                    updateSuratRasmiGeneratedLines();
                    return;
                }
                const inputType = event.inputType || '';
                if (inputType === 'insertParagraph' || inputType === 'insertLineBreak' || inputType.indexOf('delete') === 0) {
                    window.requestAnimationFrame(() => {
                        if (!document.body.contains(editor)) return;
                        ensureEditorTypography(editor);
                        updateSuratRasmiGeneratedLines();
                        syncActiveEditorContent(editor);
                    });
                }
            });
            editor.addEventListener('keydown', event => {
                if (handleLetterUndoRedoShortcut(event)) return;
                if (isGeneratedClosingInteraction(event)) {
                    event.preventDefault();
                    return;
                }
                if (isSuratRasmiGeneratedLineInteraction(event)) {
                    event.preventDefault();
                    updateSuratRasmiGeneratedLines();
                    return;
                }
                handleEditorBackspaceKey(editor, event);
            }, true);
            editor.addEventListener('click', event => focusNumberTwoLine(editor, event));
            editor.addEventListener('mouseup', () => rememberEditorSelection(editor));
            editor.addEventListener('keyup', () => rememberEditorSelection(editor));
            editor.addEventListener('paste', event => {
                if (handleSuratRasmiPaste(editor, event)) return;
                pushLetterUndoSnapshot();
                schedulePastePagination(editor);
            }, true);
            editor.addEventListener('drop', () => {
                pushLetterUndoSnapshot();
                scheduleFullLetterPagination(editor);
            });
            editor.addEventListener('input', () => {
                rememberEditorSelection(editor);
                ensureEditorTypography(editor);
                normalizeSuratRasmiLineIndents(editor);
                removeEmptyNumberThreeLines(editor);
                if (!isPaginating) {
                    scheduleFullLetterPagination(editor);
                }
                syncEditorBody();
            });
            editor.addEventListener('blur', syncEditorBody);
        }

        function attachHeaderFooterEvents(element) {
            element.addEventListener('dblclick', () => {
                element.contentEditable = 'true';
                element.focus();
                activeLetterEditor = element;
                rememberEditorSelection(element);
            });
            element.addEventListener('focus', () => {
                if (element.contentEditable !== 'true') return;
                activeLetterEditor = element;
                rememberEditorSelection(element);
            });
            element.addEventListener('mouseup', () => rememberEditorSelection(element));
            element.addEventListener('keyup', () => rememberEditorSelection(element));
            element.addEventListener('input', () => {
                rememberEditorSelection(element);
                const type = element.dataset.headerFooter === 'footer' ? 'footer' : 'header';
                applyHeaderFooterToAll(type, element.innerHTML);
            });
            element.addEventListener('blur', () => {
                syncHeaderFooterInputs();
                element.contentEditable = 'false';
            });
        }

        if (approvalPagesContainer) {
            approvalPagesContainer.addEventListener('focusin', event => {
                const editor = event.target.closest('.approval-recipient-body');
                if (!editor) return;
                activeLetterEditor = editor;
                rememberEditorSelection(editor);
            });
            approvalPagesContainer.addEventListener('mouseup', event => {
                const editor = event.target.closest('.approval-recipient-body');
                if (editor) rememberEditorSelection(editor);
            });
            approvalPagesContainer.addEventListener('keyup', event => {
                const editor = event.target.closest('.approval-recipient-body');
                if (editor) rememberEditorSelection(editor);
            });
            approvalPagesContainer.addEventListener('input', event => {
                const editor = event.target.closest('.approval-recipient-body');
                if (!editor) return;
                rememberEditorSelection(editor);
                ensureEditorTypography(editor);
                syncApprovalPageContent();
            });
            approvalPagesContainer.addEventListener('blur', event => {
                const editor = event.target.closest('.approval-recipient-body');
                if (editor) syncApprovalPageContent();
            }, true);
        }

        function moveFooterToLastPage() {
            const footer = document.getElementById('memo_editor_footer');
            const pages = document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview)');
            const lastPage = pages[pages.length - 1];
            const lastEditor = lastPage ? lastPage.querySelector('.letter-page-editor') : null;
            if (footer && lastPage && lastEditor) {
                const editorHost = getEditorHostElement(lastEditor);
                (editorHost || lastEditor).insertAdjacentElement('afterend', footer);
            }
            refreshEditorPageHeights();
        }

        function moveFooterBeforePageDelete(page) {
            const footer = document.getElementById('memo_editor_footer');
            if (!footer || !page || footer.parentElement !== page) return;

            const pages = Array.from(document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview)'));
            const fallbackPage = pages.filter(item => item !== page).pop();
            if (fallbackPage) {
                const fallbackEditor = fallbackPage.querySelector('.letter-page-editor');
                if (fallbackEditor) {
                    const editorHost = getEditorHostElement(fallbackEditor);
                    (editorHost || fallbackEditor).insertAdjacentElement('afterend', footer);
                } else {
                    fallbackPage.appendChild(footer);
                }
            }
        }

        function addLetterPage(afterPage = null, focusEditor = true) {
            if (!letterPagesContainer) return null;
            const page = document.createElement('div');
            page.className = 'memo-page-preview is-extra-page';
            const mainPages = document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview)');
            page.dataset.pageIndex = String(mainPages.length);
            page.dataset.pageNumber = String(mainPages.length + 1);

            const pageActions = document.createElement('div');
            pageActions.className = 'page-sheet-actions';
            pageActions.setAttribute('aria-label', 'Tindakan halaman');
            pageActions.innerHTML = `
                <button type="button" class="page-add-btn" title="Tambah halaman selepas halaman ini"><i class="fas fa-file-circle-plus"></i></button>
                <button type="button" class="page-delete-btn" title="Padam halaman ini"><i class="fas fa-trash-alt"></i></button>
            `;
            page.appendChild(pageActions);
            const customHeader = document.createElement('div');
            customHeader.className = 'memo-custom-header';
            customHeader.contentEditable = 'false';
            customHeader.dataset.headerFooter = 'header';
            customHeader.innerHTML = pageHeaderInput ? pageHeaderInput.value : '';
            attachHeaderFooterEvents(customHeader);
            page.appendChild(customHeader);
            const editor = document.createElement('div');
            editor.className = 'word-editor letter-page-editor';
            editor.contentEditable = 'true';
            editor.innerHTML = '<p style="' + draftBodyStyle + '"><br></p>';
            page.appendChild(editor);
            const customFooter = document.createElement('div');
            customFooter.className = 'memo-custom-footer';
            customFooter.contentEditable = 'false';
            customFooter.dataset.headerFooter = 'footer';
            customFooter.innerHTML = pageFooterInput ? pageFooterInput.value : '';
            attachHeaderFooterEvents(customFooter);
            page.appendChild(customFooter);
            const pageNumber = document.createElement('div');
            pageNumber.className = 'memo-page-number ' + (pageNumberPositionSelect ? pageNumberPositionSelect.value : 'none');
            pageNumber.textContent = page.dataset.pageNumber;
            page.appendChild(pageNumber);
            if (afterPage && afterPage.parentElement === letterPagesContainer) {
                afterPage.insertAdjacentElement('afterend', page);
            } else {
                const firstDistributionPage = letterPagesContainer.querySelector('.distribution-page-preview');
                if (firstDistributionPage) {
                    letterPagesContainer.insertBefore(page, firstDistributionPage);
                } else {
                    letterPagesContainer.appendChild(page);
                }
            }
            moveFooterToLastPage();
            renumberPages();
            const enhancedEditor = enhanceEditorWithQuill(editor);
            if (focusEditor) focusEditorStart(enhancedEditor);
            return enhancedEditor;
        }

        function addDistributionPage(afterPage = null, focusEditor = true, includeTitle = false) {
            if (!letterPagesContainer) return null;

            const distributionPages = document.querySelectorAll('.distribution-page-preview');
            const mainPages = document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview)');
            const page = document.createElement('div');
            page.className = 'memo-page-preview distribution-page-preview';
            page.dataset.pageIndex = String(mainPages.length + distributionPages.length);
            page.dataset.pageNumber = String(mainPages.length + distributionPages.length + 1);
            page.dataset.isDistribution = 'true';

            const pageActions = document.createElement('div');
            pageActions.className = 'page-sheet-actions';
            pageActions.setAttribute('aria-label', 'Tindakan halaman');
            pageActions.innerHTML = `
                <button type="button" class="page-add-btn" title="Tambah halaman selepas halaman ini"><i class="fas fa-file-circle-plus"></i></button>
                <button type="button" class="page-delete-btn" title="Padam halaman ini"><i class="fas fa-trash-alt"></i></button>
            `;
            page.appendChild(pageActions);

            const customHeader = document.createElement('div');
            customHeader.className = 'memo-custom-header';
            customHeader.contentEditable = 'false';
            customHeader.dataset.headerFooter = 'header';
            customHeader.innerHTML = pageHeaderInput ? pageHeaderInput.value : '';
            attachHeaderFooterEvents(customHeader);
            page.appendChild(customHeader);

            if (includeTitle) {
                const titleDiv = document.createElement('div');
                titleDiv.style.textAlign = 'center';
                titleDiv.style.fontWeight = 'bold';
                titleDiv.style.fontFamily = 'Arial, Helvetica, sans-serif';
                titleDiv.style.fontSize = '16px';
                titleDiv.style.lineHeight = '1.5';
                titleDiv.style.margin = '0';
                titleDiv.style.padding = '10px 0';
                titleDiv.contentEditable = 'false';
                titleDiv.textContent = 'SENARAI EDARAN';
                page.appendChild(titleDiv);
            }

            const editor = document.createElement('div');
            editor.className = 'word-editor letter-page-editor';
            editor.contentEditable = 'true';
            editor.innerHTML = '<p style="' + draftBodyStyle + '"><br></p>';
            page.appendChild(editor);

            const customFooter = document.createElement('div');
            customFooter.className = 'memo-custom-footer';
            customFooter.contentEditable = 'false';
            customFooter.dataset.headerFooter = 'footer';
            customFooter.innerHTML = pageFooterInput ? pageFooterInput.value : '';
            attachHeaderFooterEvents(customFooter);
            page.appendChild(customFooter);

            const pageNumber = document.createElement('div');
            pageNumber.className = 'memo-page-number ' + (pageNumberPositionSelect ? pageNumberPositionSelect.value : 'none');
            pageNumber.textContent = page.dataset.pageNumber;
            page.appendChild(pageNumber);

            if (afterPage && afterPage.parentElement === letterPagesContainer) {
                afterPage.insertAdjacentElement('afterend', page);
            } else {
                letterPagesContainer.appendChild(page);
            }

            renumberDistributionPages();
            const enhancedEditor = enhanceEditorWithQuill(editor);
            if (focusEditor) focusEditorStart(enhancedEditor);
            return enhancedEditor;
        }

        function renderDistributionPage() {
            if (!letterPagesContainer) return null;
            if (!includeDistributionPageCheckbox || !includeDistributionPageCheckbox.checked) {
                removeDistributionPage();
                return null;
            }
            document.querySelectorAll('.distribution-page-preview').forEach(page => page.remove());

            const selectedStaffInput = document.getElementById('selected_distribution_staff');
            let selectedStaffIds = [];
            try {
                selectedStaffIds = selectedStaffInput ? JSON.parse(selectedStaffInput.value || '[]') : [];
            } catch (error) {
                selectedStaffIds = [];
            }
            const selectedStaffIdSet = new Set(
                (Array.isArray(selectedStaffIds) ? selectedStaffIds : [])
                    .map(id => parseInt(id, 10))
                    .filter(id => Number.isFinite(id) && id > 0)
            );
            const staffData = JSON.parse(document.getElementById('distribution_staff_data')?.value || '[]');
            const selectedStaff = staffData.filter(staff => selectedStaffIdSet.has(parseInt(staff.id, 10)));
            const mainppStaff = selectedStaff.filter(staff => (staff.agency_type || '') === 'MAINPP');
            const agensiLuarStaff = selectedStaff.filter(staff => (staff.agency_type || '') === 'AGENSI LUAR');
            const savedContent = document.getElementById('distribution_page_content')?.value || '';
            const savedContentText = String(savedContent || '').replace(/<[^>]*>/g, '').replace(/&nbsp;/g, ' ').trim();
            const hasUsableSavedContent = savedContentText !== '' && savedContentText !== '0';

            const firstEditor = addDistributionPage(null, false, true);
            if (!firstEditor) return null;

            const quill = getEditorQuill(firstEditor);
            if (hasUsableSavedContent) {
                if (quill) {
                    quill.root.innerHTML = savedContent;
                    window.requestAnimationFrame(() => paginateEditorOverflow(firstEditor));
                }
                return firstEditor;
            }

            let contentHtml = '';
            mainppStaff.forEach((staff, index) => {
                contentHtml += '<div style="margin-bottom: 20px;">';
                contentHtml += '<div>' + escapeHtml(staff.name || '-') + '</div>';
                contentHtml += '<div>' + escapeHtml(staff.position || '-') + '</div>';
                contentHtml += '<div>' + escapeHtml(staff.department || '-') + '</div>';
                contentHtml += '</div>';
                if (index < mainppStaff.length - 1 || agensiLuarStaff.length > 0) contentHtml += '<p><br></p>';
            });
            agensiLuarStaff.forEach((staff, index) => {
                contentHtml += '<div style="margin-bottom: 20px;">';
                contentHtml += '<div>' + escapeHtml(staff.name || '-') + '</div>';
                contentHtml += '<div>' + escapeHtml(staff.position || '-') + '</div>';
                contentHtml += '<div>' + escapeHtml(staff.department || '-') + '</div>';
                contentHtml += '<div>' + escapeHtml(staff.agency || '-') + '</div>';
                contentHtml += '<div>' + escapeHtml(staff.address || '-') + '</div>';
                contentHtml += '</div>';
                if (index < agensiLuarStaff.length - 1) contentHtml += '<p><br></p>';
            });
            if (quill) {
                if (contentHtml !== '') {
                    quill.clipboard.dangerouslyPasteHTML(0, contentHtml);
                } else {
                    quill.setText('Tiada kakitangan dipilih.');
                }
                window.requestAnimationFrame(() => paginateEditorOverflow(firstEditor));
            }
            return firstEditor;
        }

        function renumberDistributionPages() {
            const distributionPages = document.querySelectorAll('.distribution-page-preview');
            const mainPages = document.querySelectorAll('.memo-page-preview:not(.distribution-page-preview)');
            const mainPageCount = mainPages.length;
            const position = pageNumberPositionSelect ? pageNumberPositionSelect.value : 'none';

            distributionPages.forEach((page, index) => {
                page.dataset.pageNumber = String(mainPageCount + index + 1);
                const pageNumber = page.querySelector('.memo-page-number');
                if (pageNumber) {
                    pageNumber.textContent = String(mainPageCount + index + 1);
                    pageNumber.className = 'memo-page-number ' + position;
                }
            });
        }

        function openDistributionStaffModal() {
            const modal = document.getElementById('distribution_staff_modal');
            if (modal) modal.style.display = 'flex';
        }

        function closeDistributionStaffModal(clearData = true) {
            const modal = document.getElementById('distribution_staff_modal');
            if (modal) modal.style.display = 'none';
            if (!clearData) return;

            if (includeDistributionPageCheckbox) includeDistributionPageCheckbox.checked = false;
            document.querySelectorAll('input[name="distribution_staff[]"]').forEach(checkbox => {
                checkbox.checked = false;
            });
            const selectedStaffInput = document.getElementById('selected_distribution_staff');
            if (selectedStaffInput) selectedStaffInput.value = '[]';
            const contentInput = document.getElementById('distribution_page_content');
            if (contentInput) contentInput.value = '';
            document.querySelectorAll('.distribution-page-preview').forEach(page => page.remove());
            renumberPages();
        }

        function saveDistributionStaffSelection() {
            const selectedIds = Array.from(document.querySelectorAll('input[name="distribution_staff[]"]:checked'))
                .map(checkbox => parseInt(checkbox.value, 10))
                .filter(Number.isFinite);
            const selectedStaffInput = document.getElementById('selected_distribution_staff');
            if (selectedStaffInput) selectedStaffInput.value = JSON.stringify(selectedIds);
            closeDistributionStaffModal(false);
            renderDistributionPage();
        }

        function removeDistributionPage() {
            document.querySelectorAll('.distribution-page-preview').forEach(page => page.remove());
            renumberPages();
        }

        function addPageAfterCurrent() {
            const currentPage = activeLetterEditor ? activeLetterEditor.closest('.memo-page-preview') : null;
            pushLetterUndoSnapshot();
            if (isDistributionPage(currentPage)) {
                addDistributionPage(currentPage);
            } else {
                addLetterPage(currentPage);
            }
        }

        if (letterPagesContainer) {
            letterPagesContainer.addEventListener('click', event => {
                const addButton = event.target.closest('.page-add-btn');
                const deleteButton = event.target.closest('.page-delete-btn');
                const page = event.target.closest('.memo-page-preview');
                if (!page) return;

                if (addButton) {
                    pushLetterUndoSnapshot();
                    const editor = isDistributionPage(page) ? addDistributionPage(page) : addLetterPage(page);
                    if (editor) activeLetterEditor = editor;
                    return;
                }
                if (deleteButton && !deleteButton.disabled) {
                    pushLetterUndoSnapshot();
                    deleteLetterPage(page);
                    return;
                }

                if (!event.target.closest('.letter-page-editor, .ql-editor, .page-sheet-actions, button, select, input, textarea, a')) {
                    const editor = page.querySelector('.letter-page-editor');
                    if (editor) {
                        if (page.dataset.pageIndex === '0' && isSuratRasmiStarterOnly(editor)) {
                            focusSuratRasmiFirstLine(editor);
                        } else {
                            focusEditorEnd(editor);
                        }
                    }
                }
            });
        }

        function splitOverflowTextNodeToNextPage(editor, nextEditor, node) {
            if (isGeneratedClosingNode(node)) return false;

            const sourceText = (node.textContent || '').replace(/\u00a0/g, ' ');
            if (!sourceText || sourceText.length < 2) return false;
            const selection = window.getSelection();
            const activeRange = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
            const caretInNode = !!(activeRange && activeRange.collapsed
                && (activeRange.startContainer === node
                    || (node.nodeType === Node.ELEMENT_NODE && node.contains(activeRange.startContainer))));
            const caretOffset = caretInNode
                ? getTextOffsetWithinNode(node, activeRange.startContainer, activeRange.startOffset)
                : null;

            const writeText = value => {
                if (node.nodeType === Node.TEXT_NODE) {
                    node.textContent = value;
                    return;
                }
                node.textContent = value;
            };

            let low = 1;
            let high = sourceText.length - 1;
            let bestFit = 0;

            while (low <= high) {
                const mid = Math.floor((low + high) / 2);
                writeText(sourceText.slice(0, mid));
                refreshEditorPageHeights();

                if (editor.scrollHeight <= editor.clientHeight + 2) {
                    bestFit = mid;
                    low = mid + 1;
                } else {
                    high = mid - 1;
                }
            }

            if (bestFit < 1) {
                writeText(sourceText);
                return false;
            }

            let splitAt = bestFit;
            const previousSpace = sourceText.lastIndexOf(' ', bestFit);
            if (previousSpace > 0) splitAt = previousSpace;

            const currentText = sourceText.slice(0, splitAt).trimEnd();
            const rawOverflowText = sourceText.slice(splitAt);
            const leadingOverflowTrim = rawOverflowText.length - rawOverflowText.trimStart().length;
            const overflowText = rawOverflowText.trimStart();
            if (!overflowText) {
                writeText(sourceText);
                return false;
            }

            writeText(currentText || '\u00a0');

            const overflowNode = node.nodeType === Node.TEXT_NODE
                ? document.createTextNode(overflowText)
                : node.cloneNode(false);
            if (overflowNode.nodeType !== Node.TEXT_NODE) {
                overflowNode.textContent = overflowText;
            }
            nextEditor.insertBefore(overflowNode, nextEditor.firstChild);
            if (caretInNode) {
                if (caretOffset > splitAt) {
                    placeCaretByTextOffset(overflowNode, caretOffset - splitAt - leadingOverflowTrim);
                    activeLetterEditor = nextEditor;
                } else {
                    placeCaretByTextOffset(node, caretOffset);
                    activeLetterEditor = editor;
                }
            }
            return true;
        }

        function paginateEditorOverflow(editor) {
            if (!editor || isPaginating) return;
            const page = editor.closest('.memo-page-preview');
            if (!page) return;

            isPaginating = true;
            let overflowEditor = null;
            let movedContent = false;
            let continuePagination = true;
            try {
                moveFooterToLastPage();
                refreshEditorPageHeights();
                const currentIsDistribution = isDistributionPage(page);
                let nextPage = page.nextElementSibling
                    && page.nextElementSibling.classList.contains('memo-page-preview')
                    && isDistributionPage(page.nextElementSibling) === currentIsDistribution
                    ? page.nextElementSibling
                    : null;
                let nextEditor = nextPage ? nextPage.querySelector('.letter-page-editor') : null;

                while (editor.scrollHeight > editor.clientHeight + 2 && getEditableChildNodes(editor).length > 0) {
                    if (!nextEditor) {
                        nextEditor = currentIsDistribution ? addDistributionPage(page, false) : addLetterPage(page, false);
                        nextPage = nextEditor ? nextEditor.closest('.memo-page-preview') : null;
                        refreshEditorPageHeights();
                    }
                    if (!nextEditor) break;

                    const editableNodes = getEditableChildNodes(editor);
                    const nodeToMove = editableNodes[editableNodes.length - 1];
                    if (!nodeToMove) break;
                    const splitMoved = splitOverflowTextNodeToNextPage(editor, nextEditor, nodeToMove);
                    movedContent = splitMoved;
                    if (!splitMoved) {
                        nextEditor.insertBefore(nodeToMove, nextEditor.firstChild);
                        movedContent = true;
                    }
                    refreshEditorPageHeights();
                    if (editableNodes.length === 1 && movedContent && !splitMoved) {
                        continuePagination = false;
                        break;
                    }
                }

                if (movedContent && nextEditor && continuePagination) {
                    overflowEditor = nextEditor;
                }
            } finally {
                isPaginating = false;
                moveFooterToLastPage();
                renumberPages();
                refreshEditorPageHeights();
                if (hasGeneratedClosing() && !isRepaginating) {
                    window.requestAnimationFrame(rebalanceGeneratedClosingPlacement);
                }
                if (overflowEditor && !isRepaginating) {
                    window.requestAnimationFrame(() => paginateEditorOverflow(overflowEditor));
                }
            }
        }

        function deleteLetterPage(page) {
            if (!page) return;

            const pages = document.querySelectorAll('.memo-page-preview');
            if (pages.length <= 1 || page.dataset.pageIndex === '0') {
                alert('Halaman pertama tidak boleh dipadam.');
                return;
            }

            const editor = page.querySelector('.letter-page-editor');
            const hasContent = editor && editor.textContent.replace(/\s+/g, '').trim() !== '';
            if (hasContent && !confirm('Padam halaman ini beserta kandungannya?')) {
                return;
            }

            moveFooterBeforePageDelete(page);
            page.remove();
            moveFooterToLastPage();
            renumberPages();
        }

        function formatMemoDate(value) {
            if (!value) return '-';
            const date = new Date(value + 'T00:00:00');
            if (Number.isNaN(date.getTime())) return value;
            const months = [
                'Januari', 'Februari', 'Mac', 'April', 'Mei', 'Jun',
                'Julai', 'Ogos', 'September', 'Oktober', 'November', 'Disember'
            ];
            return String(date.getDate()).padStart(2, '0') + ' ' + months[date.getMonth()] + ' ' + date.getFullYear();
        }

        function escapeHtml(value) {
            return String(value).replace(/[&<>"']/g, char => ({
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#039;'
            }[char]));
        }

        function getPreparedClosingHtml() {
            return getPreparedSignatureGroups().join('');
        }

        function getPreparedSignatureGroups() {
            const signatoryName = (signatoryNameInput?.value || <?= json_encode($_SESSION['fullname'] ?? '', JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>).trim();
            const displayName = signatoryName ? signatoryName.toUpperCase() : '';
            const signatoryPosition = (signatoryPositionInput?.value || '').trim();
            const signaturePath = (preparerSignedInput?.value === '1' && preparerSignBtn?.dataset.signaturePath)
                ? preparerSignBtn.dataset.signaturePath
                : '';
            const sloganStyle = draftBodyStyle + '; margin:0';
            const closingNameStyle = draftBodyStyle + '; margin:0';
            const signatureSpaceStyle = draftBodyStyle + '; min-height:72px; height:72px; width:150px; display:flex; align-items:center; justify-content:center; margin:0';
            const signatureHtml = signaturePath
                ? '<p data-generated-signature="1" style="' + signatureSpaceStyle + '"><img src="' + escapeHtml(signaturePath) + '" alt="Tandatangan Digital" style="max-width:150px;max-height:58px;object-fit:contain;display:block;"></p>'
                : '<p data-generated-signature="1" style="' + signatureSpaceStyle + '"><br></p>';

            return [
                '<p style="' + sloganStyle + '"><strong>"MALAYSIA MADANI"</strong></p>',
                '<p style="' + sloganStyle + '"><strong>"BERKHIDMAT UNTUK NEGARA"</strong></p>',
                '<p style="' + sloganStyle + '; margin:0 0 24px 0"><strong>"CEKAP, AKAUNTABILITI, TELUS"</strong></p>',
                '<p style="' + closingNameStyle + '">Saya yang menjalankan amanah,</p>',
                signatureHtml + '<p style="' + closingNameStyle + '"><strong>(' + escapeHtml(displayName) + ')</strong><br>' + escapeHtml(signatoryPosition || '') + '<br>Majlis Agama Islam Negeri Pulau Pinang</p>'
            ];
        }

        function lockGeneratedClosingBlocks() {
            document.querySelectorAll('[data-generated-closing="1"]').forEach(block => {
                block.setAttribute('contenteditable', 'false');
                block.setAttribute('data-signature-block', '1');
                block.classList.add('signature-block', 'generated-closing-lock');
                block.querySelectorAll('*').forEach(child => child.setAttribute('contenteditable', 'false'));
            });
        }

        function getSignatureBlocks() {
            return Array.from(document.querySelectorAll('[data-signature-block="1"], [data-generated-closing="1"]'))
                .filter((block, index, blocks) => blocks.indexOf(block) === index);
        }

        function editorHasMeaningfulNonSignatureContent(editor) {
            if (!editor) return false;
            const clone = editor.cloneNode(true);
            clone.querySelectorAll('[data-signature-block="1"], [data-generated-closing="1"], [data-surat-rasmi-generated-line]').forEach(node => node.remove());
            return clone.textContent.replace(/\s+/g, '').trim() !== '' || !!clone.querySelector('img, table');
        }

        function getSignatureStartEditor(fallbackEditor = null) {
            const editors = getLetterEditors();
            let lastContentEditor = null;
            editors.forEach(editor => {
                if (editorHasMeaningfulNonSignatureContent(editor)) {
                    lastContentEditor = editor;
                }
            });
            return lastContentEditor || fallbackEditor || editors[0] || null;
        }

        function getOrCreateNextEditor(editor) {
            const page = getEditorPage(editor);
            let nextEditor = getNextLetterEditor(editor);
            if (!nextEditor) {
                nextEditor = addLetterPage(page, false);
            }
            return nextEditor;
        }

        function editorHasRoomForNode(editor, node) {
            if (!editor || !node) return false;
            return editor.scrollHeight <= editor.clientHeight + 2;
        }

        function appendSignatureBlockToEditor(editor, block) {
            if (!editor || !block) return false;
            editor.appendChild(block);
            lockGeneratedClosingBlocks();
            refreshEditorPageHeights();
            return editorHasRoomForNode(editor, block);
        }

        function removeEmptySignaturePages() {
            getLetterEditors().slice(1).forEach(editor => {
                if (editorHasContent(editor)) return;
                const page = getEditorPage(editor);
                if (page) page.remove();
            });
        }

        function preserveQuillSelection(editor, callback) {
            const selectedEditor = getSelectionLetterEditor() || activeLetterEditor || editor;
            const quill = getEditorQuill(selectedEditor);
            const selection = quill ? quill.getSelection() : null;
            const result = callback();
            const currentSelectionEditor = getSelectionLetterEditor();
            if (currentSelectionEditor && currentSelectionEditor !== selectedEditor) {
                activeLetterEditor = currentSelectionEditor;
                rememberEditorSelection(currentSelectionEditor);
                return result;
            }
            if (quill && selection && document.body.contains(selectedEditor)) {
                const maxIndex = Math.max(0, quill.getLength() - 1);
                const nextIndex = Math.min(selection.index, maxIndex);
                const nextLength = Math.min(selection.length || 0, Math.max(0, maxIndex - nextIndex));
                quill.setSelection(nextIndex, nextLength, 'silent');
            }
            return result;
        }

        function arrangeSignatureBlocks(startEditor = null) {
            const blocks = getSignatureBlocks();
            if (!blocks.length) return;

            const targetStart = getSignatureStartEditor(startEditor);
            if (!targetStart) return;

            blocks.forEach(block => block.remove());
            let targetEditor = targetStart;

            blocks.forEach(block => {
                let placed = appendSignatureBlockToEditor(targetEditor, block);
                if (!placed) {
                    block.remove();
                    targetEditor = getOrCreateNextEditor(targetEditor);
                    if (targetEditor) {
                        const placedOnNextPage = appendSignatureBlockToEditor(targetEditor, block);
                        if (!placedOnNextPage && editorHasOnlyGeneratedClosing(targetEditor)) {
                            lockGeneratedClosingBlocks();
                        }
                    }
                }
            });

            lockGeneratedClosingBlocks();
            removeEmptyTrailingEditorPages();
            removeEmptySignaturePages();
            renumberPages();
            refreshEditorPageHeights();
        }

        function isGeneratedClosingInteraction(event) {
            if (event?.target?.closest && event.target.closest('[data-generated-closing="1"]')) {
                return true;
            }
            const selection = window.getSelection();
            if (!selection || selection.rangeCount === 0) return false;
            const node = selection.getRangeAt(0).commonAncestorContainer;
            const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
            return !!(element && element.closest('[data-generated-closing="1"]'));
        }

        function removeGeneratedClosings() {
            document.querySelectorAll('[data-generated-closing="1"]').forEach(block => {
                const editor = block.closest('.letter-page-editor');
                const quill = getEditorQuill(editor);
                if (quill && window.Quill) {
                    const blot = Quill.find(block);
                    if (blot) {
                        const index = quill.getIndex(blot);
                        quill.deleteText(index, 1, 'silent');
                        return;
                    }
                }
                block.remove();
            });
        }

        function removeGeneratedClosingOnRequest() {
            if (!hasGeneratedClosing()) {
                alert('Tiada penutup surat untuk dipadam.');
                return;
            }
            if (!confirm('Padam penutup surat sedia ada?')) {
                return;
            }
            pushLetterUndoSnapshot();
            removeGeneratedClosings();
            if (preparerSignedInput) {
                preparerSignedInput.value = '0';
            }
            if (documentSignatureDataInput) {
                documentSignatureDataInput.value = '';
            }
            removeEmptyTrailingEditorPages();
            renumberPages();
            refreshEditorPageHeights();
            syncEditorBody();
            updateSuratRasmiSignPermission();
        }

        function hasGeneratedClosing() {
            return !!document.querySelector('[data-generated-closing="1"]');
        }

        function getGeneratedClosingInsertIndex(quill) {
            if (!quill) return 0;
            const text = quill.getText();
            const contentEnd = text.replace(/\s+$/g, '').length;
            const trailingLength = Math.max(0, quill.getLength() - 1 - contentEnd);
            if (trailingLength > 0) {
                quill.deleteText(contentEnd, trailingLength, 'silent');
            }
            return contentEnd;
        }

        function insertGeneratedClosing(editor, html, source = 'silent') {
            if (!editor || !html) return false;
            const groups = Array.isArray(html) ? html.filter(Boolean) : [html].filter(Boolean);
            if (!groups.length) return false;
            const quill = getEditorQuill(editor);
            if (quill) {
                const insertAt = getGeneratedClosingInsertIndex(quill);
                quill.insertText(insertAt, '\n', source);
                let insertIndex = insertAt + 1;
                groups.forEach(groupHtml => {
                    quill.insertEmbed(insertIndex, 'generatedClosing', groupHtml, source);
                    insertIndex += 1;
                });
            } else {
                while (editor.lastElementChild && !editor.lastElementChild.textContent.trim() && !editor.lastElementChild.querySelector('img, table, [data-generated-closing="1"]')) {
                    editor.lastElementChild.remove();
                }
                editor.insertAdjacentHTML('beforeend', '<p style="' + draftBodyStyle + '"><br></p>' + groups.map(groupHtml => '<div data-generated-closing="1" data-signature-block="1" class="signature-block generated-closing-lock" contenteditable="false">' + groupHtml + '</div>').join(''));
            }
            editor.dataset.generatedClosingHtml = groups.join('');
            lockGeneratedClosingBlocks();
            return true;
        }

        function editorHasOnlyGeneratedClosing(editor) {
            if (!editor) return false;
            const meaningfulNodes = getEditableChildNodes(editor).filter(node => {
                if (node.nodeType === Node.TEXT_NODE) {
                    return node.textContent.replace(/\s+/g, '').trim() !== '';
                }
                if (node.nodeType !== Node.ELEMENT_NODE) return false;
                if (node.matches('[data-generated-closing="1"]')) return false;
                if (node.querySelector('[data-generated-closing="1"]')) {
                    const clone = node.cloneNode(true);
                    clone.querySelectorAll('[data-generated-closing="1"]').forEach(item => item.remove());
                    return clone.textContent.replace(/\s+/g, '').trim() !== '' || !!clone.querySelector('img, table');
                }
                return node.textContent.replace(/\s+/g, '').trim() !== '' || !!node.querySelector('img, table');
            });
            return meaningfulNodes.length === 0;
        }

        function rebalanceGeneratedClosingPlacement() {
            if (isRebalancingGeneratedClosing || isPaginating) return;
            const closing = document.querySelector('[data-generated-closing="1"]');
            const currentEditor = closing ? closing.closest('.letter-page-editor') : null;
            if (!closing || !currentEditor) {
                lockGeneratedClosingBlocks();
                return;
            }

            isRebalancingGeneratedClosing = true;
            try {
                arrangeSignatureBlocks(currentEditor);
            } finally {
                isRebalancingGeneratedClosing = false;
                lockGeneratedClosingBlocks();
                removeEmptyTrailingEditorPages();
                renumberPages();
                refreshEditorPageHeights();
                syncEditorBody();
            }
        }
        function restoreGeneratedClosingIfNeeded(editor, html) {
            if (!editor || !html) return;
            window.clearTimeout(generatedClosingRestoreTimer);
            generatedClosingRestoreTimer = window.setTimeout(() => {
                if (!document.body.contains(editor)) return;
                if (editor.querySelector('[data-generated-closing="1"]')) {
                    lockGeneratedClosingBlocks();
                    rebalanceGeneratedClosingPlacement();
                }
            }, 0);
        }

        function insertSignature(editor = null) {
            const editors = getLetterEditors();
            const targetEditor = editor && editor.classList && editor.classList.contains('letter-page-editor')
                ? editor
                : (activeLetterEditor && activeLetterEditor.classList.contains('letter-page-editor') ? activeLetterEditor : editors[editors.length - 1]);
            if (!targetEditor) return false;

            isInsertingSignature = true;
            try {
                removeGeneratedClosings();
                insertGeneratedClosing(targetEditor, getPreparedSignatureGroups(), 'user');
            } finally {
                isInsertingSignature = false;
            }
            repaginate(targetEditor);
            syncEditorBody();
            return true;
        }

        function generatePreparedClosing() {
            if (hasGeneratedClosing()) {
                alert('Penutup surat sudah wujud pada kertas. Padam penutup sedia ada dahulu jika mahu jana semula.');
                rebalanceGeneratedClosingPlacement();
                return;
            }
            if (!confirm('Adakah ini line terakhir ayat anda?')) {
                return;
            }
            pushLetterUndoSnapshot();
            const editors = getLetterEditors();
            const targetEditor = activeLetterEditor && activeLetterEditor.classList.contains('letter-page-editor')
                ? activeLetterEditor
                : editors[editors.length - 1];
            if (!targetEditor) return;

            insertSignature(targetEditor);
            activeLetterEditor = targetEditor;
        }
        function applySignatureToExistingClosing(signaturePath, markSigned = false) {
            if (!signaturePath) return false;
            const generatedClosing = document.querySelector('[data-generated-closing="1"]');
            if (!generatedClosing) return false;
            const signatureParagraph = document.querySelector('[data-generated-closing="1"] [data-generated-signature="1"], [data-generated-signature="1"]');
            if (!signatureParagraph) return false;
            let changed = false;
            const currentSignatureImage = signatureParagraph.querySelector('img');
            if (!currentSignatureImage || currentSignatureImage.getAttribute('src') !== signaturePath) {
                signatureParagraph.innerHTML = '<img src="' + escapeHtml(signaturePath) + '" alt="Tandatangan Digital" style="max-width:150px;max-height:58px;object-fit:contain;">';
                changed = true;
            }
            if (markSigned && preparerSignedInput) {
                preparerSignedInput.value = '1';
            }
            if (markSigned && memoSignaturePreview && signaturePath !== '') {
                memoSignaturePreview.src = signaturePath;
                memoSignaturePreview.style.display = 'block';
            }
            if (markSigned && submitDraftBtn) {
                submitDraftBtn.disabled = false;
            }
            if (markSigned && preparerSignPanel) {
                preparerSignPanel.classList.add('signed');
                preparerSignPanel.classList.remove('missing');
            }
            if (markSigned && preparerSignTitle) {
                preparerSignTitle.textContent = 'Tandatangan penyedia telah dibuat';
            }
            if (markSigned && preparerSignHint) {
                preparerSignHint.textContent = 'Surat ini sudah mempunyai tandatangan penyedia dan boleh dihantar.';
            }
            lockGeneratedClosingBlocks();
            syncEditorBody();
            return changed || markSigned;
        }
        function applyDepartmentOfficerRevisionSignatureAfterEditorReady() {
            if (!isDepartmentOfficerRevisionEditor) return;
            const signaturePath = (departmentOfficerRecordedSignaturePath || '').trim();
            if (!signaturePath) return;
            queueMicrotask(() => {
                requestAnimationFrame(() => {
                    applySignatureToExistingClosing(signaturePath, false);
                });
            });
        }
        function updateMemoPreview() {
            if (memoDatePreview && letterDateInput) memoDatePreview.textContent = formatMemoDate(letterDateInput.value);
            if (memoDocTypePreview && docTypeInput) memoDocTypePreview.textContent = (docTypeInput.value || '-').toUpperCase();
            if (memoFromPreview && signatoryPositionInput) {
                memoFromPreview.innerHTML = signatoryPositionInput.value.trim()
                    ? escapeHtml(signatoryPositionInput.value.trim()) + '<br>Majlis Agama Islam Negeri Pulau Pinang'
                    : '-';
            }
            if (memoToPreview && recipientInput) {
                memoToPreview.innerHTML = renderMemoPreviewPositions(recipientInput);
            }
            if (memoThroughPreview && throughInput) {
                memoThroughPreview.innerHTML = renderMemoPreviewPositions(throughInput);
            }
            if (memoSignatoryPreview && signatoryNameInput) {
                const signatoryName = signatoryNameInput.value.trim();
                memoSignatoryPreview.textContent = signatoryName ? '(' + signatoryName.toUpperCase() + ')' : '-';
            }
            updateSuratRasmiGeneratedLines();
        }

        function getCurrentTemplatePlaceholderData() {
            return {
                reference_no: refPreview ? refPreview.textContent.trim() : '',
                date: memoDatePreview ? memoDatePreview.textContent.trim() : (letterDateInput ? letterDateInput.value : ''),
                receiver_name: getCheckedMemoPositions(recipientInput).join(', '),
                receiver_department: 'Majlis Agama Islam Negeri Pulau Pinang',
                subject: subjectInput ? subjectInput.value.trim() : '',
                letter_content: '',
                sender_name: signatoryNameInput ? signatoryNameInput.value.trim() : '',
                sender_position: signatoryPositionInput ? signatoryPositionInput.value.trim() : '',
                sender_department: signatoryDepartmentInput ? signatoryDepartmentInput.value.trim() : ''
            };
        }

        function replaceTemplatePlaceholders(content, data) {
            let output = String(content || '');
            Object.keys(data).forEach(key => {
                const safeValue = String(data[key] || '')
                    .replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;')
                    .replace(/"/g, '&quot;')
                    .replace(/'/g, '&#039;');
                output = output.split('{{' + key + '}}').join(safeValue);
            });
            return output;
        }

        function selectedLetterTemplate() {
            const selectedId = templateSelect ? parseInt(templateSelect.value, 10) : 0;
            return letterTemplates.find(template => template.id === selectedId) || letterTemplates[0] || null;
        }

        function applySelectedTemplateToEditor(force = false) {
            const template = selectedLetterTemplate();
            const firstEditor = document.querySelector('.letter-page-editor');
            if (!template || !firstEditor) return;
            const currentPlain = firstEditor.textContent.replace(/\s+/g, '').trim();
            if (!force && currentPlain !== '') return;
            if (force && currentPlain !== '' && !confirm('Guna template ini akan menggantikan kandungan halaman pertama. Teruskan?')) {
                return;
            }

            clearAllLetterPages();
            const targetEditor = document.querySelector('.letter-page-editor');
            if (!targetEditor) return;
            targetEditor.innerHTML = replaceTemplatePlaceholders(template.content, getCurrentTemplatePlaceholderData());
            ensureEditorTypography(targetEditor);
            activeLetterEditor = targetEditor;
            moveFooterToLastPage();
            renumberPages();
            refreshEditorPageHeights();
            syncEditorBody();
        }

        document.querySelectorAll('.word-toolbar button[data-command]').forEach(button => {
            button.addEventListener('mousedown', event => event.preventDefault());
            button.addEventListener('click', () => execEditorCommand(button.dataset.command));
        });

        if (fontFamilySelect) {
            fontFamilySelect.value = 'Arial';
            fontFamilySelect.disabled = true;
        }

        if (fontSizeSelect) {
            fontSizeSelect.value = '16';
            fontSizeSelect.disabled = true;
        }

        const tableButton = document.querySelector('.word-toolbar button[data-action="insertTable"]');
        if (tableButton) {
            tableButton.addEventListener('click', insertEditorTable);
        }

        if (templateSelect) {
            templateSelect.addEventListener('change', () => applySelectedTemplateToEditor(true));
        }

        document.querySelectorAll('.memo-check-dropdown').forEach(dropdown => {
            const toggle = dropdown.querySelector('.memo-check-toggle');
            const select = document.getElementById(dropdown.dataset.targetSelect || '');
            syncMemoCheckboxDropdown(dropdown);

            if (toggle) {
                toggle.addEventListener('click', event => {
                    event.preventDefault();
                    document.querySelectorAll('.memo-check-dropdown.open').forEach(openDropdown => {
                        if (openDropdown !== dropdown) openDropdown.classList.remove('open');
                    });
                    dropdown.classList.toggle('open');
                });
            }

            dropdown.addEventListener('change', event => {
                if (!event.target.matches('input[type="checkbox"]')) return;
                syncMemoCheckboxDropdown(dropdown);
                updateMemoPreview();
                syncRoutingCandidates();
                updateApprovalPagePreview();
            });

            if (select) {
                select.addEventListener('change', () => {
                    const matchingCheckbox = Array.from(dropdown.querySelectorAll('input[type="checkbox"]')).find(input => input.value === select.value);
                    if (matchingCheckbox) matchingCheckbox.checked = true;
                    syncMemoCheckboxDropdown(dropdown);
                    updateMemoPreview();
                    syncRoutingCandidates();
                    updateApprovalPagePreview();
                });
            }
        });

        document.addEventListener('click', event => {
            if (event.target.closest('.memo-check-dropdown')) return;
            document.querySelectorAll('.memo-check-dropdown.open').forEach(dropdown => dropdown.classList.remove('open'));
        });

        document.querySelectorAll('.letter-page-editor').forEach(enhanceEditorWithQuill);
        document.querySelectorAll('.letter-page-editor').forEach(normalizeSuratRasmiLineIndents);
        document.querySelectorAll('.memo-custom-header[data-header-footer], .memo-custom-footer[data-header-footer]').forEach(attachHeaderFooterEvents);
        ensureAllDocumentTypography();
        if (addPageBtn) addPageBtn.addEventListener('click', addPageAfterCurrent);
        if (deleteCurrentPageBtn) {
            deleteCurrentPageBtn.addEventListener('click', () => {
                const currentPage = activeLetterEditor ? activeLetterEditor.closest('.memo-page-preview') : null;
                pushLetterUndoSnapshot();
                deleteLetterPage(currentPage);
            });
        }
        if (pageNumberPositionSelect) {
            pageNumberPositionSelect.addEventListener('change', updatePageNumberPosition);
        }
        moveFooterToLastPage();
        updatePageNumberPosition();
        updateHeaderFooterPreview();
        syncHeaderFooterInputs();
        syncEditorBody();
        refreshEditorPageHeights();
        applyDepartmentOfficerRevisionSignatureAfterEditorReady();
        window.addEventListener('resize', refreshEditorPageHeights);

        const departmentOfficerSelect = document.getElementById('department_officer_user_id');
        function selectedSuratRasmiSignatoryProfile() {
            const selectedPosition = signatoryPositionInput ? signatoryPositionInput.value.trim() : '';
            return selectedPosition ? (suratRasmiSignatoryProfilesByPosition[selectedPosition] || null) : null;
        }

        function suratRasmiSelectedSignatoryIsCurrentUser() {
            const profile = selectedSuratRasmiSignatoryProfile();
            return !!(profile && parseInt(profile.id, 10) === currentUserId);
        }

        function clearGeneratedSignatureImages() {
            document.querySelectorAll('[data-generated-signature="1"]').forEach(slot => {
                slot.innerHTML = '';
            });
            if (preparerSignedInput) {
                preparerSignedInput.value = '0';
            }
            syncEditorBody();
        }

        function updateSuratRasmiSignPermission() {
            const profile = selectedSuratRasmiSignatoryProfile();
            const signerIsCurrentUser = suratRasmiSelectedSignatoryIsCurrentUser();
            let signed = preparerSignedInput && preparerSignedInput.value === '1';
            const closingReady = hasGeneratedClosing();
            if (preparerSignBtn) {
                preparerSignBtn.style.display = signerIsCurrentUser ? '' : 'none';
                preparerSignBtn.disabled = !signerIsCurrentUser || !closingReady;
                preparerSignBtn.title = signerIsCurrentUser && !closingReady ? 'Closing perlu dijana terlebih dahulu sebelum tandatangan boleh dibuat.' : '';
            }
            if (!signerIsCurrentUser && signed) {
                clearGeneratedSignatureImages();
            }
            if (signerIsCurrentUser && !closingReady && signed) {
                clearGeneratedSignatureImages();
                signed = false;
            }
            if (!preparerSignPanel || !preparerSignTitle || !preparerSignHint) return;

            if (!profile) {
                preparerSignPanel.classList.remove('signed', 'missing');
                preparerSignTitle.textContent = 'Pilih Daripada';
                preparerSignHint.textContent = 'Pilih jawatan/bahagian penandatangan untuk menentukan laluan tandatangan surat.';
                return;
            }

            if (signerIsCurrentUser) {
                preparerSignPanel.classList.toggle('signed', signed);
                preparerSignPanel.classList.toggle('missing', !signed && currentUserSignaturePath === '');
                preparerSignTitle.textContent = signed ? 'Tandatangan penyedia telah dibuat' : 'Tandatangan diperlukan.';
                preparerSignHint.textContent = !closingReady
                    ? 'Closing perlu dijana terlebih dahulu sebelum tandatangan boleh dibuat.'
                    : (signed
                    ? 'Surat ini sudah mempunyai tandatangan penyedia.'
                    : 'Klik Tandatangan dahulu sebelum surat disimpan.');
                return;
            }

            preparerSignPanel.classList.add('signed');
            preparerSignPanel.classList.remove('missing');
            preparerSignTitle.textContent = 'Tandatangan penandatangan diperlukan';
            preparerSignHint.textContent = 'Surat akan dihantar kepada ' + (profile.name || profile.position || 'penandatangan dipilih') + ' untuk tandatangan selepas disimpan.';
        }

        function syncSuratRasmiSignatoryFromPosition() {
            const profile = selectedSuratRasmiSignatoryProfile();
            if (profile) {
                if (signatoryNameInput) signatoryNameInput.value = profile.name || '';
                if (signatoryDepartmentInput) signatoryDepartmentInput.value = profile.department || '';
                if (signatoryDepartmentDisplay) signatoryDepartmentDisplay.value = profile.department || '';
                if (departmentOfficerSelect) departmentOfficerSelect.value = String(profile.id || 0);
            } else {
                if (signatoryNameInput) signatoryNameInput.value = '';
                if (signatoryDepartmentInput) signatoryDepartmentInput.value = '';
                if (signatoryDepartmentDisplay) signatoryDepartmentDisplay.value = '';
                if (departmentOfficerSelect) departmentOfficerSelect.value = '0';
            }
            updateSuratRasmiSignPermission();
            updateMemoPreview();
        }
        if (draftStatusSelect) {
            draftStatusSelect.addEventListener('change', () => {
                updateApprovalControlsForStatus();
                updateApprovalPagePreview();
                syncApprovalPageContent();
            });
        }

        [letterDateInput, subjectInput, recipientInput, throughInput, docTypeInput, signatoryDepartmentInput, signatoryNameInput].forEach(input => {
            if (input) input.addEventListener('input', updateMemoPreview);
            if (input) input.addEventListener('change', updateMemoPreview);
        });
        if (signatoryPositionInput) {
            signatoryPositionInput.addEventListener('change', syncSuratRasmiSignatoryFromPosition);
        }
        if (approvalPagesContainer) {
            approvalPagesContainer.addEventListener('input', syncApprovalPageContent);
            approvalPagesContainer.addEventListener('blur', () => {
                syncApprovalPageContent();
                updateApprovalPagePreview();
            }, true);
        }
        document.querySelectorAll('.routing-order-select').forEach(select => {
            select.addEventListener('change', () => {
                normalizeRoutingOrder(select);
                updateApprovalPagePreview();
            });
        });
        if (recipientInput) recipientInput.addEventListener('change', syncRoutingCandidates);
        if (throughInput) throughInput.addEventListener('change', syncRoutingCandidates);
        syncSuratRasmiSignatoryFromPosition();
        syncRoutingCandidates();
        document.querySelectorAll('.routing-checkbox:checked').forEach(checkbox => {
            const select = checkbox.closest('.routing-option')?.querySelector('.routing-order-select');
            const order = select ? parseInt(select.value, 10) || 0 : 0;
            checkbox.dataset.checkedSequence = String(order || ++routingSequenceCounter);
        });
        normalizeRoutingOrder();
        updateApprovalPagePreview();
        syncApprovalPageContent();
        updateApprovalControlsForStatus();

        if (generateClosingBtn) {
            generateClosingBtn.addEventListener('click', function () {
                generatePreparedClosing();
                setTimeout(updateSuratRasmiSignPermission, 0);
            });
        }

        if (removeClosingBtn) {
            removeClosingBtn.addEventListener('click', removeGeneratedClosingOnRequest);
        }

        if (preparerSignBtn && preparerSignedInput) {
            preparerSignBtn.addEventListener('click', function () {
                if (!suratRasmiSelectedSignatoryIsCurrentUser()) {
                    alert('Surat ini perlu ditandatangani oleh penandatangan yang dipilih pada field Daripada.');
                    return;
                }
                if (!hasGeneratedClosing()) {
                    alert('Closing perlu dijana terlebih dahulu sebelum tandatangan boleh dibuat.');
                    generateClosingBtn?.focus();
                    updateSuratRasmiSignPermission();
                    return;
                }
                MainppDigitalSignature.open({
                    profileSignaturePath: this.dataset.signaturePath || '',
                    onUseSignature: (signatureValue, signatureType) => {
                        if (!confirm('Adakah anda pasti untuk sign surat ini?')) {
                            return;
                        }
                        pushLetterUndoSnapshot();
                        if (documentSignatureDataInput) {
                            documentSignatureDataInput.value = signatureType === 'digital' ? signatureValue : '';
                        }
                        applySignatureToExistingClosing(signatureValue, true);
                        this.innerHTML = '<i class="fas fa-signature"></i> Tandatangan Semula';
                        updateSuratRasmiSignPermission();
                    }
                });
            });
        }

        const distributionSearchInput = document.getElementById('distribution_staff_search');
        if (distributionSearchInput) {
            distributionSearchInput.addEventListener('input', function () {
                const searchTerm = this.value.toLowerCase().trim();
                document.querySelectorAll('.distribution-staff-item').forEach(item => {
                    const searchText = item.dataset.searchText || '';
                    item.style.display = searchTerm === '' || searchText.includes(searchTerm) ? 'block' : 'none';
                });
                document.querySelectorAll('.distribution-staff-section').forEach(section => {
                    const visibleCount = Array.from(section.querySelectorAll('.distribution-staff-item'))
                        .filter(item => item.style.display !== 'none').length;
                    section.style.display = visibleCount > 0 ? 'block' : 'none';
                });
            });
        }

        if (includeDistributionPageCheckbox) {
            includeDistributionPageCheckbox.addEventListener('change', function () {
                if (this.checked) {
                    openDistributionStaffModal();
                } else {
                    removeDistributionPage();
                    const selectedStaffInput = document.getElementById('selected_distribution_staff');
                    if (selectedStaffInput) selectedStaffInput.value = '[]';
                    const contentInput = document.getElementById('distribution_page_content');
                    if (contentInput) contentInput.value = '';
                }
            });

            if (includeDistributionPageCheckbox.checked) {
                const selectedStaffInput = document.getElementById('selected_distribution_staff');
                let selectedIds = [];
                try {
                    selectedIds = JSON.parse(selectedStaffInput ? selectedStaffInput.value || '[]' : '[]');
                } catch (error) {
                    selectedIds = [];
                }
                selectedIds = (Array.isArray(selectedIds) ? selectedIds : [])
                    .map(id => parseInt(id, 10))
                    .filter(id => Number.isFinite(id) && id > 0);
                if (selectedStaffInput) selectedStaffInput.value = JSON.stringify(selectedIds);
                if (selectedIds.length > 0) renderDistributionPage();
            }
        }

        if (draftForm) {
            draftForm.addEventListener('submit', function (event) {
                syncEditorBody();
                syncHeaderFooterInputs();
                syncApprovalPageContent();
                const selectedRecipients = getCheckedMemoPositions(recipientInput);
                if (selectedRecipients.includes(suratRasmiDistributionRecipientLabel)) {
                    const selectedStaffInput = document.getElementById('selected_distribution_staff');
                    let selectedStaffIds = [];
                    try {
                        selectedStaffIds = JSON.parse(selectedStaffInput ? selectedStaffInput.value || '[]' : '[]');
                    } catch (error) {
                        selectedStaffIds = [];
                    }
                    selectedStaffIds = (Array.isArray(selectedStaffIds) ? selectedStaffIds : [])
                        .map(id => parseInt(id, 10))
                        .filter(id => Number.isFinite(id) && id > 0);
                    if (selectedStaffInput) selectedStaffInput.value = JSON.stringify(selectedStaffIds);
                    if (!includeDistributionPageCheckbox || !includeDistributionPageCheckbox.checked || !Array.isArray(selectedStaffIds) || selectedStaffIds.length === 0) {
                        event.preventDefault();
                        alert('Sila aktifkan dan pilih penerima dalam Senarai Edaran.');
                        return;
                    }
                }
                const distributionPages = document.querySelectorAll('.distribution-page-preview');
                const distributionContentInput = document.getElementById('distribution_page_content');
                if (distributionContentInput && distributionPages.length > 0) {
                    distributionContentInput.value = Array.from(distributionPages).map(page => {
                        const editor = page.querySelector('.letter-page-editor');
                        const quill = editor ? getEditorQuill(editor) : null;
                        return quill ? quill.root.innerHTML : (editor ? editor.innerHTML : '');
                    }).join('');
                }
                const readyToSend = isReadyToSendStatus();
                if (readyToSend && isDepartmentOfficerRevisionEditor && !hasGeneratedClosing()) {
                    event.preventDefault();
                    alert('Closing perlu dijana terlebih dahulu sebelum tandatangan boleh dibuat.');
                    generateClosingBtn?.focus();
                    preparerSignPanel?.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    return;
                }
                if (readyToSend && isDepartmentOfficerRevisionEditor && preparerSignedInput && preparerSignedInput.value !== '1') {
                    event.preventDefault();
                    alert('Sila klik Tandatangan sebelum menghantar surat.');
                    preparerSignPanel?.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    return;
                }
                if (readyToSend && suratRasmiSelectedSignatoryIsCurrentUser() && !isDepartmentOfficerRevisionEditor && !hasGeneratedClosing()) {
                    event.preventDefault();
                    alert('Closing perlu dijana terlebih dahulu sebelum tandatangan boleh dibuat.');
                    generateClosingBtn?.focus();
                    preparerSignPanel?.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    return;
                }
                if (readyToSend && suratRasmiSelectedSignatoryIsCurrentUser() && !isDepartmentOfficerRevisionEditor && preparerSignedInput && preparerSignedInput.value !== '1') {
                    event.preventDefault();
                    alert('Sila klik Tandatangan sebelum menghantar surat.');
                    preparerSignPanel?.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    return;
                }
                if (readyToSend && !selectedSuratRasmiSignatoryProfile()) {
                    event.preventDefault();
                    alert('Sila pilih Daripada untuk menentukan penandatangan surat.');
                    signatoryPositionInput?.focus();
                    return;
                }
                const plainText = getSuratRasmiUserContentText();
                if (plainText === '') {
                    event.preventDefault();
                    alert('Sila isi kandungan surat terlebih dahulu.');
                    const firstEditor = document.querySelector('.letter-page-editor');
                    if (firstEditor) firstEditor.focus();
                    return;
                }
                if (readyToSend && departmentOfficerSelect && departmentOfficerSelect.required && !departmentOfficerSelect.value) {
                    event.preventDefault();
                    alert('Sila pilih Ketua Pegawai sebelum menyimpan memo.');
                    departmentOfficerSelect.focus();
                    return;
                }
            });
        }

        const referencePreviewUsesActualNumber = <?= json_encode($is_edit && (($draft['status'] ?? 'draf') === 'siap'), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;

        function updateFolderSummary() {
            if (!folderSelect) return;
            const option = folderSelect.options[folderSelect.selectedIndex];
            if (!option || !option.value) return;

            const department = option.dataset.department || '';
            const nextRef = option.dataset.nextRef || '-';
            const nextFileNumbering = option.dataset.nextFileNumbering || '';
            const refDisplay = referencePreviewUsesActualNumber
                ? (nextRef + '(' + (nextFileNumbering || 'X') + ')')
                : (nextRef && nextRef !== '-' ? (nextRef + '(X)') : '-');

            refPreview.textContent = refDisplay || '-';
            if (memoRefPreview) memoRefPreview.textContent = refDisplay || '-';
            if (signatoryDepartmentInput && !signatoryDepartmentInput.value.trim()) {
                signatoryDepartmentInput.value = department || '';
                if (signatoryDepartmentDisplay) signatoryDepartmentDisplay.value = department || '';
            }
            syncSuratRasmiSignatoryFromPosition();
            updateMemoPreview();
        }

        function syncDepartmentOfficerOptions(department) {
            if (!departmentOfficerSelect) return;
            if (departmentOfficerSelect.tagName !== 'SELECT') return;
            const selectedValue = departmentOfficerSelect.value;
            let selectedStillVisible = false;
            Array.from(departmentOfficerSelect.options).forEach(option => {
                if (!option.value) {
                    option.hidden = false;
                    return;
                }
                const sameDepartment = !department || (option.dataset.department || '') === department;
                option.hidden = !sameDepartment;
                if (sameDepartment && option.value === selectedValue) {
                    selectedStillVisible = true;
                }
            });
            if (selectedValue && !selectedStillVisible) {
                departmentOfficerSelect.value = '';
            }
            if (!departmentOfficerSelect.value) {
                const head = departmentHeadsByDepartment[department || ''];
                if (head && head.id) {
                    const headOption = Array.from(departmentOfficerSelect.options).find(option => parseInt(option.value, 10) === head.id);
                    if (headOption && !headOption.hidden) {
                        departmentOfficerSelect.value = String(head.id);
                    }
                }
            }
        }

        if (folderSelect) {
            folderSelect.addEventListener('change', updateFolderSummary);
            updateFolderSummary();
        }
        updateMemoPreview();
    </script>
    <?php renderSessionTimeoutScript(); ?>
</body>
</html>
