<?php
use App\Core\Auth;
$cu        = Auth::user();
$validatorType = strtolower(trim((string)($cu['technician_type'] ?? '')));
$isAdmin   = in_array($cu['role_key'] ?? '', ['admin','agent','manager','superviseur','supervisor']);
$isSuperv  = in_array($cu['role_key'] ?? '', ['admin','manager'], true)
  || (in_array($cu['role_key'] ?? '', ['agent','superviseur','supervisor'], true) && $validatorType === 'maintenance_ftth');
$isTech    = in_array($cu['role_key'] ?? '', ['technicien','technician']);
$isRaccordementClients = str_contains((string)($_SERVER['REQUEST_URI'] ?? ''), '/raccordement-clients');
$moduleBasePath = $isRaccordementClients ? '/raccordement-clients' : '/maintenance-ftth';
$raccordementWorkflowData = ($isRaccordementClients && isset($raccordementWorkflow) && is_array($raccordementWorkflow)) ? $raccordementWorkflow : [];
$raccordementPhase = (string)($raccordementWorkflowData['phase'] ?? 'study');
$isRaccordementStudyPhase = $isRaccordementClients && $raccordementPhase === 'study';
$isRaccordementInstallationPhase = $isRaccordementClients && $raccordementPhase !== 'study';
$raccordementStudyCanEdit = (bool)($raccordementWorkflowData['study_can_edit'] ?? false);
$raccordementInstallationCanEdit = (bool)($raccordementWorkflowData['installation_can_edit'] ?? false);
$raccordementSelectedBox = $raccordementWorkflowData['selected_box'] ?? null;
$raccordementPortOptions = is_array($raccordementWorkflowData['port_options'] ?? null) ? $raccordementWorkflowData['port_options'] : [];
$raccordementPortsByBox = is_array($raccordementWorkflowData['ports_by_box'] ?? null) ? $raccordementWorkflowData['ports_by_box'] : [];
$raccordementOtbRecommendation = is_array($raccordementWorkflowData['otb'] ?? null) ? $raccordementWorkflowData['otb'] : [];
$raccordementOtbCandidates = [];
foreach (array_merge($raccordementOtbRecommendation['candidates'] ?? [], $raccordementOtbRecommendation['out_of_radius'] ?? [], $raccordementSelectedBox ? [$raccordementSelectedBox] : []) as $candidateBox) {
  $candidateId = (int)($candidateBox['id'] ?? 0);
  if ($candidateId <= 0 || isset($raccordementOtbCandidates[$candidateId])) {
    continue;
  }
  $raccordementOtbCandidates[$candidateId] = $candidateBox;
}
$raccordementRecommendedBoxId = (int)($raccordementOtbRecommendation['recommended']['id'] ?? $report['recommended_otb_id'] ?? 0);
$raccordementSelectedBoxId = (int)($report['selected_otb_id'] ?? $raccordementRecommendedBoxId);
$raccordementSelectedPort = (int)($report['selected_otb_port_number'] ?? 0);
$raccordementSelectedPortStatus = (string)($report['selected_otb_port_status'] ?? 'none');
$raccordementSelectedBoxData = null;
if ($raccordementSelectedBoxId > 0) {
  $raccordementSelectedBoxData = is_array($raccordementSelectedBox)
    ? $raccordementSelectedBox
    : ($raccordementOtbCandidates[$raccordementSelectedBoxId] ?? null);
} elseif ($raccordementRecommendedBoxId > 0) {
  $raccordementSelectedBoxData = $raccordementOtbCandidates[$raccordementRecommendedBoxId] ?? ($raccordementOtbRecommendation['recommended'] ?? null);
}
$raccordementStudyAccuracy = (string)($report['study_gps_accuracy_meters'] ?? '');
$raccordementStudyLat = (string)($report['study_gps_lat'] ?? '');
$raccordementStudyLng = (string)($report['study_gps_lng'] ?? '');
$raccordementZoneLabel = (string)($ticket['dispatch_zone_label'] ?? $raccordementWorkflowData['zone_setting']['zone_label'] ?? 'Zone non définie');
$raccordementTeamLabel = !empty($raccordementWorkflowData['zone_setting']['team_label']) ? (string)$raccordementWorkflowData['zone_setting']['team_label'] : 'Équipe raccordement';
$raccordementDistanceMeters = is_numeric($raccordementSelectedBoxData['distance_meters'] ?? null)
  ? round((float)$raccordementSelectedBoxData['distance_meters'], 2)
  : (is_numeric($report['otb_distance_meters'] ?? null)
      ? round((float)$report['otb_distance_meters'], 2)
      : (is_numeric($raccordementOtbRecommendation['recommended']['distance_meters'] ?? null)
          ? round((float)$raccordementOtbRecommendation['recommended']['distance_meters'], 2)
          : null));
$raccordementStudyTechnician = $raccordementWorkflowData['study_technician'] ?? null;
$raccordementInstallationTechnician = $raccordementWorkflowData['installation_technician'] ?? null;

// Le technicien courant est-il assigné ?
$isAssigned = false;
foreach ($assignments as $a) {
    if ((int)($a['technician_id'] ?? 0) === (int)$cu['id']) { $isAssigned = true; break; }
}

// Peut-il saisir/modifier la fiche terrain ?
$canFill = ($isAssigned && in_array($ticket['status'], ['assigné','en_cours','attente_planification'], true))
         || ($isAdmin && in_array($ticket['status'], ['assigné','en_cours','attente_planification'], true));
$reportEditable = $canFill && (!$report || in_array($report['status'] ?? '', ['brouillon','rejeté'], true));

$priColor = ['Urgent'=>'danger','Haute'=>'warning','Moyenne'=>'primary','Basse'=>'secondary'][$ticket['priority']] ?? 'secondary';
$stColor  = ['nouveau'=>'primary','assigné'=>'warning','en_cours'=>'info','attente_planification'=>'dark','traité'=>'success','validé'=>'success','clôturé'=>'secondary'][$ticket['status']] ?? 'secondary';
$rpColor  = $report ? (['brouillon'=>'secondary','soumis'=>'warning','validé'=>'success','rejeté'=>'danger'][$report['status']] ?? 'secondary') : null;

$equipItems = json_decode($report['impacted_equipment'] ?? '[]', true) ?: [];
$matItems   = json_decode($report['materials_used']     ?? '[]', true) ?: [];
$satLabels  = ['très_satisfait'=>'Très satisfait','satisfait'=>'Satisfait','peu_satisfait'=>'Peu satisfait','non_satisfait'=>'Non satisfait'];
$reportStatusLabelMap = ['brouillon' => 'Brouillon', 'soumis' => 'Soumis', 'validé' => 'Validé', 'rejeté' => 'Rejeté'];
$reportStatusLabel = $report ? ($reportStatusLabelMap[$report['status'] ?? ''] ?? ucfirst((string)($report['status'] ?? ''))) : 'Aucune fiche';
$ticketStatusLabels = ['nouveau' => 'Nouveau', 'assigné' => 'Assigné', 'en_cours' => 'En cours', 'attente_planification' => 'En attente de planification', 'traité' => 'Traité', 'validé' => 'Validé', 'clôturé' => 'Clôturé'];
$interventionStatusDisplay = $ticketStatusLabels[$ticket['status'] ?? ''] ?? ucfirst(str_replace('_', ' ', (string)($ticket['status'] ?? '')));
$clientVisitStatusLabels = [
  'intervention_effectuee' => 'Intervention réalisée',
  'client_indisponible' => 'Client indisponible',
  'reprogrammation_demandee' => 'Reprogrammation demandée',
];
$clientVisitStatusColors = [
  'intervention_effectuee' => 'success',
  'client_indisponible' => 'warning',
  'reprogrammation_demandee' => 'info',
];
$clientVisitStatus = (string)($report['client_visit_status'] ?? 'intervention_effectuee');
$clientVisitStatusLabel = $clientVisitStatusLabels[$clientVisitStatus] ?? 'Situation non renseignée';
$clientVisitStatusColor = $clientVisitStatusColors[$clientVisitStatus] ?? 'secondary';
$canCloseManual = $isSuperv && (($ticket['status'] ?? '') !== 'clôturé') && ((($ticket['status'] ?? '') === 'validé') || (($report['status'] ?? '') === 'validé'));
$assignmentLocked = in_array(($ticket['status'] ?? ''), ['validé', 'clôturé'], true);
$plannedInterventionDisplay = '';
if (!empty($report['planned_intervention_date'])) {
  $plannedInterventionDisplay = date('d/m/Y', strtotime((string)$report['planned_intervention_date']));
  if (!empty($report['planned_intervention_time'])) {
    $plannedInterventionDisplay .= ' à ' . substr((string)$report['planned_intervention_time'], 0, 5);
  }
}
$lastReportSavedAt = '';
if (!empty($report)) {
  $reportSavedAtSource = (string)($report['report_updated_at'] ?? $report['updated_at'] ?? $report['created_at'] ?? '');
  if ($reportSavedAtSource !== '') {
    $timestamp = strtotime($reportSavedAtSource);
    if ($timestamp !== false) {
      $lastReportSavedAt = date('d/m/Y à H:i', $timestamp);
    }
  }
}
$visibleExtraFields = [];
$normalizeExtraFieldKey = static function (string $value): string {
  $value = trim($value);
  if ($value === '') {
    return '';
  }
  $ascii = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value);
  if ($ascii !== false) {
    $value = $ascii;
  }
  $value = strtolower($value);
  $value = preg_replace('/[^a-z0-9]+/', ' ', $value) ?? $value;
  return trim($value);
};
$findImportedField = static function (array $fields, array $candidates) use ($normalizeExtraFieldKey): array {
  $normalizedCandidates = array_map($normalizeExtraFieldKey, $candidates);
  foreach ($fields as $label => $value) {
    if ($value === null || trim((string)$value) === '') {
      continue;
    }
    $normalizedLabel = $normalizeExtraFieldKey((string)$label);
    foreach ($normalizedCandidates as $candidate) {
      if ($candidate !== '' && ($normalizedLabel === $candidate || str_contains($normalizedLabel, $candidate))) {
        return ['label' => (string)$label, 'value' => trim((string)$value)];
      }
    }
  }
  return ['label' => null, 'value' => null];
};
$parseGpsCoordinates = static function (?string $rawValue): ?array {
  $rawValue = trim((string)$rawValue);
  if ($rawValue === '') {
    return null;
  }
  preg_match_all('/-?\d+(?:[\.,]\d+)?/', $rawValue, $matches);
  $parts = $matches[0] ?? [];
  if (count($parts) < 2) {
    return null;
  }
  $lat = (float) str_replace(',', '.', $parts[0]);
  $lng = (float) str_replace(',', '.', $parts[1]);
  if ($lat < -90 || $lat > 90 || $lng < -180 || $lng > 180) {
    return null;
  }
  return [$lat, $lng];
};
$formatImportedDateValue = static function ($rawValue): string {
  $rawValue = trim((string)$rawValue);
  if ($rawValue === '') {
    return '';
  }

  if (preg_match('/^\d+(?:[\.,]\d+)?$/', $rawValue)) {
    $normalizedNumber = (float) str_replace(',', '.', $rawValue);
    if ($normalizedNumber >= 20000 && $normalizedNumber <= 70000) {
      $days = (int) floor($normalizedNumber);
      $seconds = (int) round(($normalizedNumber - $days) * 86400);
      $baseDate = new DateTimeImmutable('1899-12-30 00:00:00');
      $formattedDate = $baseDate->modify('+' . $days . ' days');
      if ($formattedDate !== false) {
        if ($seconds > 0) {
          $formattedDate = $formattedDate->modify('+' . $seconds . ' seconds');
        }
        return $seconds > 0 ? $formattedDate->format('d/m/Y H:i') : $formattedDate->format('d/m/Y');
      }
    }
  }

  $timestamp = strtotime($rawValue);
  if ($timestamp !== false) {
    return date('d/m/Y', $timestamp);
  }

  return $rawValue;
};
$normalizeDateInputValue = static function ($rawValue): string {
  $rawValue = trim((string)$rawValue);
  if ($rawValue === '') {
    return '';
  }

  if (preg_match('/^\d+(?:[\.,]\d+)?$/', $rawValue)) {
    $normalizedNumber = (float) str_replace(',', '.', $rawValue);
    if ($normalizedNumber >= 20000 && $normalizedNumber <= 70000) {
      $days = (int) floor($normalizedNumber);
      $seconds = (int) round(($normalizedNumber - $days) * 86400);
      $baseDate = new DateTimeImmutable('1899-12-30 00:00:00');
      $formattedDate = $baseDate->modify('+' . $days . ' days');
      if ($formattedDate !== false) {
        if ($seconds > 0) {
          $formattedDate = $formattedDate->modify('+' . $seconds . ' seconds');
        }
        return $formattedDate->format('Y-m-d');
      }
    }
  }

  foreach (['Y-m-d', 'd/m/Y', 'd-m-Y', 'd.m.Y'] as $format) {
    $date = DateTimeImmutable::createFromFormat($format, $rawValue);
    if ($date instanceof DateTimeImmutable) {
      return $date->format('Y-m-d');
    }
  }

  $timestamp = strtotime($rawValue);
  return $timestamp !== false ? date('Y-m-d', $timestamp) : '';
};
$hiddenExtraFieldKeys = [
    'id', 'ticket_id', 'ref_code', 'status', 'statut', 'priority', 'priorite',
    'client_name', 'nom_client', 'raison_sociale', 'client_code', 'numero_abonnement', 'n_abonnement',
    'client_phone', 'telephone', 'telephone_1', 'contact_1',
    'client_phone2', 'telephone_2', 'contact_2',
    'client_email', 'email', 'client_address', 'adresse', 'localisation',
    'site_name', 'site', 'description', 'commentaire', 'nature_intervention',
    'avancement', 'equipes', 'equipes_excel', 'date_cloture',
    'fixed_line', 'ligne fixe', 'sro client', 'jdv client', 'pco client',
    'company_name', 'entreprise porteur d action', 'commentaire cause', 'commentaire_cause',
    'numero de requete', 'numero requete', 'reference', 'ref',
    'contact client 1', 'contact client 2', 'contact client et localisation',
    'numero abonnement', 'code client', 'gps', 'coordonnees gps',
    'date de cloture', 'date cloture', 'nature intervention', 'type intervention',
    'liste tech', 'technicien', 'techniciens', 'soudeur', 'etat',
    'ville', 'commune', 'nomclient', 'contact1', 'contact2', 'latitude terrai', 'longitude terrain',
    'plaque', 'jdv', 'pco', 'snont', 'nd', 'date enregistrement instances', 'duree attente j',
    'date envoi instances prestataires', 'etude technique', 'besoin en poteau betons',
    'besoin en poteau metalliques', 'realisation survey', 'realisation implantation poteau beton',
    'date previsionnelle raccordement client', 'equipe raccordement', 'distance pco client',
    'entrepriseftth', 'problemes', 'commentaires', 'programme de deploiement', 'digitaux entreprise',
    'olt pon',
    'imported_at', 'created_at', 'updated_at'
];
foreach ($extraFields as $column => $value) {
  $normalizedKey = $normalizeExtraFieldKey((string)$column);
    if ($value === null || $value === '') {
        continue;
    }
    if (in_array($normalizedKey, $hiddenExtraFieldKeys, true)) {
        continue;
    }
    $visibleExtraFields[$column] = $value;
}
  $displayInterventionDate = !empty($report['intervention_date']) ? (string)$report['intervention_date'] : date('Y-m-d');
  $displayInterventionStart = !empty($report['intervention_start']) ? substr((string)$report['intervention_start'], 0, 5) : date('H:i');
  $displayInterventionEnd = !empty($report['intervention_end']) ? substr((string)$report['intervention_end'], 0, 5) : '';
  $constatPhotos = array_values(array_filter($photos ?? [], fn($photo) => ($photo['tab_type'] ?? '') === 'constat'));
  $interventionPhotos = array_values(array_filter($photos ?? [], fn($photo) => ($photo['tab_type'] ?? '') === 'intervention'));
  $briefTerrain = trim((string)($report['constat_comments'] ?? ''));
$assignedTechnicianNames = array_values(array_filter(array_map(
  fn($assignment) => trim((string)($assignment['tech_name'] ?? '')),
  $assignments ?? []
)));
$assignedTechnicians = array_values(array_map(static function (array $assignment): array {
  return [
    'name' => trim((string)($assignment['tech_name'] ?? '')),
    'email' => trim((string)($assignment['tech_email'] ?? '')),
    'phone' => trim((string)($assignment['tech_phone'] ?? '')),
    'avatar_url' => trim((string)($assignment['tech_avatar_url'] ?? '')),
    'initials' => trim((string)($assignment['tech_initials'] ?? 'FT')),
    'assigned_at' => $assignment['assigned_at'] ?? null,
    'notes' => $assignment['notes'] ?? null,
  ];
}, $assignments ?? []));
$primaryAssignedTechnician = $assignedTechnicians[0] ?? null;
$importedAddressField = $findImportedField($extraFields ?? [], ['LOCALISATION', 'Localisation', 'Contact client et localisation', 'Adresse intervention']);
$importedNatureField = $findImportedField($extraFields ?? [], ['Nature intervention', 'Type intervention', 'Intervention', 'Type de maintenance']);
$importedSiteField = $findImportedField($extraFields ?? [], ['Site', 'Nom du site', 'Site concerné', 'Localisation site']);
$importedProgressField = $findImportedField($extraFields ?? [], ['Avancement', 'Progression']);
$importedTeamField = $findImportedField($extraFields ?? [], ['equipes', 'Équipes', 'Equipe', 'Interruption/equipes', 'Liste Tech', 'Soudeur', 'Technicien']);
$importedCommentField = $findImportedField($extraFields ?? [], ['Commentaire', 'Commentaires', 'Observation', 'Observations', 'Avertissement du client']);
$importedGpsField = $findImportedField($extraFields ?? [], ['GPS', 'Coordonnées GPS', 'Coordonnees GPS']);
$importedStatusField = $findImportedField($extraFields ?? [], ['Statut', 'Status', 'Etat', 'État']);
$importedFixedLineField = $findImportedField($extraFields ?? [], ['Ligne fixe', 'Ligne Fixe', 'Ligne']);
$importedCityField = $findImportedField($extraFields ?? [], ['Ville']);
$importedCommuneField = $findImportedField($extraFields ?? [], ['Commune']);
$importedSubscriptionField = $findImportedField($extraFields ?? [], ['NumeroAbonnement', 'Numéro Abonnement', 'Numero Abonnement']);
$importedCustomerNameField = $findImportedField($extraFields ?? [], ['NomClient', 'Nom client', 'Nom du client']);
$importedPrimaryContactField = $findImportedField($extraFields ?? [], ['Contact1', 'CONTACT CLIENT 1', 'Contact client 1']);
$importedSecondaryContactField = $findImportedField($extraFields ?? [], ['Contact2', 'CONTACT CLIENT 2', 'Contact client 2']);
$importedPlaqueField = $findImportedField($extraFields ?? [], ['PLAQUE']);
$importedSroField = $findImportedField($extraFields ?? [], ['SRO CLIENT', 'SRO Client', 'SRO']);
$importedJdvField = $findImportedField($extraFields ?? [], ['JDV', 'JDV CLIENT', 'JDV Client']);
$importedPcoField = $findImportedField($extraFields ?? [], ['PCO', 'PCO CLIENT', 'PCO Client']);
$importedSnontField = $findImportedField($extraFields ?? [], ['SNONT']);
$importedNdField = $findImportedField($extraFields ?? [], ['ND']);
$importedInstanceRegistrationDateField = $findImportedField($extraFields ?? [], ['Date_Enregistrement_Instances']);
$importedWaitDurationField = $findImportedField($extraFields ?? [], ['Duree_attente_j']);
$importedProviderSendDateField = $findImportedField($extraFields ?? [], ['Date_Envoi_Instances_Prestataires']);
$importedTechnicalStudyField = $findImportedField($extraFields ?? [], ['Etude_Technique']);
$importedPlannedConnectionDateField = $findImportedField($extraFields ?? [], ['Date_previsionnelle_raccordement_ client']);
$importedRaccordementTeamField = $findImportedField($extraFields ?? [], ['Equipe_raccordement']);
$importedDistanceField = $findImportedField($extraFields ?? [], ['Distance_PCO-Client']);
$importedCompanyField = $findImportedField($extraFields ?? [], ['Entreprise/porteur d\'action', 'Entreprise porteur d action', 'Entreprise', 'Porteur d action']);
$importedEntrepriseFtthField = $findImportedField($extraFields ?? [], ['EntrepriseFTTH']);
$importedProblemsField = $findImportedField($extraFields ?? [], ['Problèmes', 'Problemes']);
$importedCommentsField = $findImportedField($extraFields ?? [], ['Commentaires']);
$importedDeploymentProgramField = $findImportedField($extraFields ?? [], ['PROGRAMME_DE_DEPLOIEMENT']);
$importedDigitalField = $findImportedField($extraFields ?? [], ['DIGITAUX / ENTREPRISE']);
$importedOltPonField = $findImportedField($extraFields ?? [], ['OLT_PON']);
$importedCutTypeField = $findImportedField($extraFields ?? [], ['cut_type', 'Type de coupure']);
$importedTransportZoneField = $findImportedField($extraFields ?? [], ['Zone']);
$importedTransportOltField = $findImportedField($extraFields ?? [], ['OLT de rattachement', 'OLT']);
$importedTransportSignalField = $findImportedField($extraFields ?? [], ['Détail de la signalisation', 'Detail de la signalisation', 'Signalisation']);
$natureDisplayValue = trim((string)($ticket['nature_intervention'] ?? ''));
$siteDisplayValue = trim((string)($ticket['site_name'] ?? ''));
$progressDisplayValue = trim((string)($ticket['avancement'] ?? ''));
$fixedLineDisplayValue = trim((string)($ticket['fixed_line'] ?? ($importedFixedLineField['value'] ?? '')));
$sroDisplayValue = trim((string)($ticket['sro_client'] ?? ($importedSroField['value'] ?? '')));
$jdvDisplayValue = trim((string)($ticket['jdv_client'] ?? ($importedJdvField['value'] ?? '')));
$pcoDisplayValue = trim((string)($ticket['pco_client'] ?? ($importedPcoField['value'] ?? '')));
$companyDisplayValue = trim((string)($ticket['company_name'] ?? ($importedCompanyField['value'] ?? '')));
$causeDisplayValue = trim((string)($ticket['cause_comment'] ?? ''));
$cutTypeDisplayValue = trim((string)($importedCutTypeField['value'] ?? 'client'));
$transportZoneDisplayValue = trim((string)($importedTransportZoneField['value'] ?? ''));
$transportOltDisplayValue = trim((string)($importedTransportOltField['value'] ?? ''));
$transportSignalDisplayValue = trim((string)($importedTransportSignalField['value'] ?? ''));
$gpsRawDisplayValue = trim((string)($importedGpsField['value'] ?? ''));
$statusRawDisplayValue = trim((string)($importedStatusField['value'] ?? ''));
$teamRawDisplayValue = trim((string)($importedTeamField['value'] ?? ''));
$addressCardLabel = $importedAddressField['label'] ?: 'Adresse d\'intervention';
$natureCardLabel = $importedNatureField['label'] ?: 'Nature d\'intervention';
$siteCardLabel = $importedSiteField['label'] ?: 'Site concerné';
$progressCardLabel = $importedProgressField['label'] ?: 'Avancement';
$teamCardLabel = !empty($assignedTechnicians)
  ? 'Équipe terrain'
  : 'Équipe';
$briefLabel = 'Constat terrain';
$displayedTeam = !empty($assignedTechnicianNames)
  ? implode(', ', $assignedTechnicianNames)
  : trim((string)($ticket['equipes'] ?? ($teamRawDisplayValue ?: '')));
$showImportedTeamChip = false;
$showAssignedTechnicianChip = $primaryAssignedTechnician !== null;
$showDisplayedTeamChip = $displayedTeam !== '' && !$showAssignedTechnicianChip;
$structuredGpsLat = isset($ticket['client_lat']) && $ticket['client_lat'] !== null && $ticket['client_lat'] !== '' ? (float) $ticket['client_lat'] : null;
$structuredGpsLng = isset($ticket['client_lng']) && $ticket['client_lng'] !== null && $ticket['client_lng'] !== '' ? (float) $ticket['client_lng'] : null;
$parsedImportedGps = $parseGpsCoordinates($gpsRawDisplayValue);
$formatDistanceDisplay = static function ($distanceMeters): string {
  if (!is_numeric($distanceMeters)) {
    return '';
  }

  $distanceMeters = (float)$distanceMeters;
  if ($distanceMeters < 0) {
    return '';
  }

  if ($distanceMeters >= 1000) {
    return number_format($distanceMeters / 1000, 2, ',', ' ') . ' km';
  }

  $decimals = abs($distanceMeters - floor($distanceMeters)) > 0.0001 ? 2 : 0;
  return number_format($distanceMeters, $decimals, ',', ' ') . ' m';
};
$computedDistanceDisplayValue = $formatDistanceDisplay($raccordementDistanceMeters);
$distanceDisplayValue = trim((string)($computedDistanceDisplayValue !== '' ? $computedDistanceDisplayValue : ($importedDistanceField['value'] ?? '')));
$gpsMapLat = $structuredGpsLat;
$gpsMapLng = $structuredGpsLng;
if (($gpsMapLat === null || $gpsMapLng === null) && $parsedImportedGps !== null) {
  [$gpsMapLat, $gpsMapLng] = $parsedImportedGps;
}
$gpsMapAvailable = $gpsMapLat !== null && $gpsMapLng !== null;
$gpsExternalUrl = $gpsMapAvailable ? 'https://www.google.com/maps?q=' . rawurlencode((string)$gpsMapLat . ',' . (string)$gpsMapLng) : '';
$heroKickerDisplay = $isRaccordementClients
  ? 'Raccordement client'
  : ($cutTypeDisplayValue === 'transport' ? 'Coupure transport' : 'Coupure client');
$heroTitleDisplay = $isRaccordementClients
  ? trim((string)($ticket['client_code'] ?: ($importedSubscriptionField['value'] ?? ($ticket['ref_code'] ?: 'Raccordement #' . $ticket['id']))))
  : (string)($ticket['ref_code'] ?: 'Ticket #' . $ticket['id']);
$heroClientDisplay = $isRaccordementClients
  ? trim((string)(($importedCustomerNameField['value'] ?? '') ?: $ticket['client_name']))
  : (string)$ticket['client_name'];
$heroAddressDisplay = $isRaccordementClients
  ? trim((string)(($importedAddressField['value'] ?? '') ?: $ticket['client_address']))
  : (string)$ticket['client_address'];
$heroSubscriptionDisplay = trim((string)(($importedSubscriptionField['value'] ?? '') ?: $ticket['client_code']));
$heroProgressDisplay = $isRaccordementClients
  ? trim((string)(($importedProgressField['value'] ?? '') ?: $ticket['avancement']))
  : '';
$kpiClientLabel = $isRaccordementClients ? 'Abonnement' : 'Client';
$kpiClientValue = $isRaccordementClients
  ? ($heroSubscriptionDisplay !== '' ? $heroSubscriptionDisplay : $heroClientDisplay)
  : (string)$ticket['client_name'];
$kpiOperationLabel = $isRaccordementClients ? 'Avancement' : 'Intervention';
$kpiOperationValue = $isRaccordementClients
  ? ($heroProgressDisplay !== '' ? $heroProgressDisplay : 'Raccordement client')
  : (string)($ticket['nature_intervention'] ?: 'Maintenance FTTH');
$moduleEntityLabel = $isRaccordementClients ? 'dossier raccordement' : 'ticket';
$moduleEntityLabelPlural = $isRaccordementClients ? 'dossiers raccordement' : 'tickets';
$moduleImportLabel = $isRaccordementClients ? 'Import RACCORDES' : 'Import FTTH';
$moduleMissionTabLabel = $isRaccordementClients ? 'Raccordement' : 'Mission';
$moduleFieldFormLabel = $isRaccordementClients ? 'Suivi terrain' : 'Fiche terrain';
$moduleOperationFormLabel = $isRaccordementClients ? 'Type de passage' : 'Type d\'opération';
$raccordementEditData = [
  'ref_code' => (string)($ticket['ref_code'] ?? ''),
  'client_code' => (string)(($ticket['client_code'] ?? '') ?: ($importedSubscriptionField['value'] ?? '')),
  'client_name' => (string)$heroClientDisplay,
  'client_phone' => (string)(($ticket['client_phone'] ?? '') ?: ($importedPrimaryContactField['value'] ?? '')),
  'client_phone2' => (string)(($ticket['client_phone2'] ?? '') ?: ($importedSecondaryContactField['value'] ?? '')),
  'client_address' => (string)$heroAddressDisplay,
  'raccordement_city' => (string)($importedCityField['value'] ?? ''),
  'raccordement_commune' => (string)($importedCommuneField['value'] ?? ''),
  'raccordement_latitude' => (string)(($ticket['client_lat'] ?? '') ?: ($findImportedField($extraFields ?? [], ['Latitude_Terrai'])['value'] ?? '')),
  'raccordement_longitude' => (string)(($ticket['client_lng'] ?? '') ?: ($findImportedField($extraFields ?? [], ['Longitude_Terrain'])['value'] ?? '')),
  'sro_client' => (string)(($ticket['sro_client'] ?? '') ?: ($importedPlaqueField['value'] ?? '')),
  'jdv_client' => (string)(($ticket['jdv_client'] ?? '') ?: ($importedJdvField['value'] ?? '')),
  'pco_client' => (string)(($ticket['pco_client'] ?? '') ?: ($importedPcoField['value'] ?? '')),
  'company_name' => (string)(($ticket['company_name'] ?? '') ?: ($importedEntrepriseFtthField['value'] ?? '')),
  'raccordement_snont' => (string)($importedSnontField['value'] ?? ''),
  'raccordement_nd' => (string)($importedNdField['value'] ?? ''),
  'raccordement_date_enregistrement' => $normalizeDateInputValue($importedInstanceRegistrationDateField['value'] ?? ''),
  'raccordement_date_envoi_prestataires' => $normalizeDateInputValue($importedProviderSendDateField['value'] ?? ''),
  'raccordement_duree_attente' => (string)($importedWaitDurationField['value'] ?? ''),
  'raccordement_team' => (string)($importedRaccordementTeamField['value'] ?? ''),
  'raccordement_etude_technique' => (string)($importedTechnicalStudyField['value'] ?? ''),
  'avancement' => (string)(($ticket['avancement'] ?? '') ?: $heroProgressDisplay),
  'priority' => (string)($ticket['priority'] ?? 'Moyenne'),
  'status' => (string)($ticket['status'] ?? 'nouveau'),
  'description' => (string)(($ticket['description'] ?? '') ?: ($importedCommentsField['value'] ?? '')),
  'cause_comment' => (string)(($ticket['cause_comment'] ?? '') ?: ($importedProblemsField['value'] ?? '')),
];
$historyEvents = [];
$pushHistoryEvent = static function (array &$events, ?string $dateValue, string $title, string $icon, string $tone = 'secondary', ?string $detail = null): void {
  $dateValue = $dateValue ? trim($dateValue) : '';
  if ($dateValue === '') {
    return;
  }
  $timestamp = strtotime($dateValue);
  if ($timestamp === false) {
    return;
  }
  $detail = $detail !== null ? trim($detail) : null;
  $events[] = [
    'timestamp' => $timestamp,
    'date_label' => date('d/m/Y H:i', $timestamp),
    'title' => $title,
    'icon' => $icon,
    'tone' => $tone,
    'detail' => $detail !== '' ? $detail : null,
  ];
};
$pushHistoryEvent(
  $historyEvents,
  $ticket['created_at'] ?? null,
  $isRaccordementClients ? 'Dossier raccordement créé' : 'Ticket créé',
  'ticket',
  'primary',
  trim((string)($ticket['ref_code'] ?: ($isRaccordementClients ? 'Dossier #' : 'Ticket #') . ($ticket['id'] ?? '')))
);
if (!empty($ticket['imported_at']) && ($ticket['imported_at'] !== ($ticket['created_at'] ?? null) || !empty($ticket['imported_by_name']))) {
  $pushHistoryEvent(
    $historyEvents,
    $ticket['imported_at'],
    $isRaccordementClients ? 'Import du dossier' : 'Import du ticket',
    'file-import',
    'info',
    !empty($ticket['imported_by_name']) ? 'Importé par ' . trim((string)$ticket['imported_by_name']) : $moduleImportLabel
  );
}
foreach ($assignments as $assignment) {
  $detailParts = [];
  if (!empty($assignment['tech_name'])) {
    $detailParts[] = 'Technicien: ' . trim((string)$assignment['tech_name']);
  }
  if (!empty($assignment['notes'])) {
    $detailParts[] = trim((string)$assignment['notes']);
  }
  $pushHistoryEvent(
    $historyEvents,
    $assignment['assigned_at'] ?? null,
    'Technicien assigné',
    'user-plus',
    'warning',
    implode(' • ', $detailParts)
  );
}
if ($report) {
  $pushHistoryEvent(
    $historyEvents,
    $report['created_at'] ?? null,
    'Fiche terrain créée',
    'clipboard',
    'secondary',
    !empty($report['technician_name']) ? 'Par ' . trim((string)$report['technician_name']) : null
  );
  if (!empty($report['submitted_at'])) {
    $pushHistoryEvent(
      $historyEvents,
      $report['submitted_at'],
      'Fiche terrain soumise',
      'paper-plane',
      'success',
      !empty($report['technician_name']) ? 'Soumise par ' . trim((string)$report['technician_name']) : null
    );
  }
  if (in_array($clientVisitStatus, ['client_indisponible', 'reprogrammation_demandee'], true)) {
    $historyDetailParts = [$clientVisitStatusLabel];
    if ($plannedInterventionDisplay !== '') {
      $historyDetailParts[] = 'Créneau proposé : ' . $plannedInterventionDisplay;
    }
    if (!empty($report['planning_comment'])) {
      $historyDetailParts[] = trim((string)$report['planning_comment']);
    }
    $pushHistoryEvent(
      $historyEvents,
      $report['updated_at'] ?? $report['created_at'] ?? null,
      'Retour client à replanifier',
      'calendar-days',
      'warning',
      implode(' • ', $historyDetailParts)
    );
  }
  if (!empty($report['updated_at']) && ($report['updated_at'] !== ($report['created_at'] ?? null)) && ($report['updated_at'] !== ($report['submitted_at'] ?? null)) && ($report['updated_at'] !== ($report['validated_at'] ?? null))) {
    $pushHistoryEvent(
      $historyEvents,
      $report['updated_at'],
      'Fiche terrain mise à jour',
      'pen-to-square',
      'info',
      !empty($report['technician_name']) ? 'Dernière modification par ' . trim((string)$report['technician_name']) : null
    );
  }
  if (!empty($report['validated_at']) && ($report['status'] ?? '') === 'validé') {
    $pushHistoryEvent(
      $historyEvents,
      $report['validated_at'],
      'Rapport validé',
      'check-double',
      'success',
      !empty($report['validated_by_name']) ? 'Validé par ' . trim((string)$report['validated_by_name']) : null
    );
  }
  if (($report['status'] ?? '') === 'rejeté') {
    $pushHistoryEvent(
      $historyEvents,
      $report['updated_at'] ?? $report['submitted_at'] ?? null,
      'Rapport rejeté',
      'triangle-exclamation',
      'danger',
      !empty($report['rejection_reason']) ? trim((string)$report['rejection_reason']) : 'Motif non renseigné'
    );
  }
}
if (!empty($ticket['updated_at']) && ($ticket['updated_at'] !== ($ticket['created_at'] ?? null)) && ($ticket['updated_at'] !== ($ticket['imported_at'] ?? null))) {
  $pushHistoryEvent(
    $historyEvents,
    $ticket['updated_at'],
    'Ticket mis à jour',
    'clock-rotate-left',
    'secondary',
    'Dernière mise à jour des informations du ticket'
  );
}
foreach (($ticketEvents ?? []) as $event) {
  $detail = trim((string)($event['detail'] ?? ''));
  $actorName = trim((string)($event['actor_name'] ?? ''));
  if ($actorName !== '') {
    $detail = $detail !== '' ? $detail . ' • Par ' . $actorName : 'Par ' . $actorName;
  }
  $pushHistoryEvent(
    $historyEvents,
    $event['created_at'] ?? null,
    (string)($event['title'] ?? 'Événement'),
    (string)($event['icon'] ?? 'clock-rotate-left'),
    (string)($event['tone'] ?? 'secondary'),
    $detail !== '' ? $detail : null
  );
}
usort($historyEvents, static fn(array $left, array $right): int => $right['timestamp'] <=> $left['timestamp']);
?>

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="">

<style>
:root{
  --ftth-ink:#12344d;
  --ftth-surface:#f4f8fb;
  --ftth-panel:#ffffff;
  --ftth-border:#dbe7ef;
  --ftth-accent:#1f7a8c;
  --ftth-accent-soft:#dff3f4;
  --ftth-highlight:#f4b942;
}
/* ── Hero ── */
.ftth-hero{background:linear-gradient(135deg,var(--ftth-ink) 0%,var(--ftth-accent) 58%,#76c893 100%);color:#fff;padding:1.5rem 0 0;position:relative;overflow:hidden}
.ftth-hero::after{content:'';position:absolute;right:-60px;top:-60px;width:220px;height:220px;border-radius:50%;background:rgba(255,255,255,.06)}
.ftth-hero .badge{font-size:.78rem;padding:.35em .7em}
.ftth-hero-grid{display:grid;grid-template-columns:minmax(0,1.2fr) minmax(260px,.8fr);gap:1rem;align-items:start}
.ftth-hero-kicker{display:inline-flex;align-items:center;gap:.55rem;padding:.38rem .72rem;border-radius:999px;background:rgba(255,255,255,.14);font-size:.74rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase}
.ftth-hero-title{font-size:clamp(1.75rem,3vw,2.45rem);font-weight:800;line-height:1.05;margin:.95rem 0 .45rem}
.ftth-hero-subline{display:flex;flex-wrap:wrap;gap:.55rem .9rem;color:rgba(255,255,255,.86);font-size:.9rem}
.ftth-hero-summary{display:grid;gap:.85rem}
.ftth-hero-panel-card{padding:1rem 1.05rem;border-radius:1rem;background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.14);backdrop-filter:blur(12px)}
.ftth-hero-panel-card strong{display:block;font-size:.78rem;text-transform:uppercase;letter-spacing:.05em;color:rgba(255,255,255,.78);margin-bottom:.35rem}
.ftth-hero-panel-card span{display:block;font-size:1rem;font-weight:700;color:#fff}
/* ── Nav pills ── */
.ftth-nav{background:#fff;border-bottom:1px solid #e9ecef;position:sticky;top:56px;z-index:100;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none}
.ftth-nav::-webkit-scrollbar{display:none}
.ftth-nav .nav-link{color:#6c757d;padding:.65rem 1.1rem;font-size:.875rem;border-radius:0;border-bottom:3px solid transparent}
.ftth-nav .nav-link.active{color:var(--ftth-accent);border-bottom-color:var(--ftth-accent);background:transparent;font-weight:600}
/* ── Cards ── */
.info-row{display:grid;grid-template-columns:minmax(120px,38%) 1fr;gap:.25rem .75rem;padding:.45rem 1rem;border-bottom:1px solid #f3f4f6;font-size:.875rem}
.info-row:last-child{border-bottom:none}
.info-row dt{color:#6c757d;font-weight:400;margin:0}
.info-row dd{margin:0;font-weight:500;word-break:break-word}
.mission-kpi-card{background:var(--ftth-panel);border:1px solid var(--ftth-border);border-radius:1rem;box-shadow:0 .5rem 1.25rem rgba(18,52,77,.06)}
.mission-kpi-card .icon-wrap{width:48px;height:48px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:var(--ftth-accent-soft);color:var(--ftth-accent)}
.surface-card{background:var(--ftth-panel);border:1px solid var(--ftth-border);border-radius:1rem;box-shadow:0 .5rem 1.25rem rgba(18,52,77,.06)}
.surface-card .card-header{background:transparent;border-bottom:0;padding-bottom:0}
.mission-panel{background:linear-gradient(180deg,#ffffff 0%,#f8fbfd 100%);border:1px solid var(--ftth-border);border-radius:1.15rem;box-shadow:0 .75rem 1.6rem rgba(18,52,77,.06)}
.mission-panel-head{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;flex-wrap:wrap;margin-bottom:1rem}
.mission-panel-title{display:flex;align-items:center;gap:.75rem}
.mission-panel-title i{width:42px;height:42px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:#e9f5f6;color:var(--ftth-accent)}
.mission-panel-title h6{margin:0;font-size:.8rem;font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:#12344d}
.mission-panel-title p{margin:.15rem 0 0;color:#6b7f8c;font-size:.85rem}
.mission-spotlight{padding:1rem 1.05rem;border-radius:1rem;border:1px solid rgba(31,122,140,.14);background:linear-gradient(180deg,#ffffff 0%,#eef7f8 100%)}
.mission-spotlight-label{font-size:.75rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:#5d7281;margin-bottom:.35rem}
.mission-spotlight-value{font-size:1rem;color:#12344d;font-weight:700}
.mission-grid{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:1rem}
.meta-chip.is-highlight{background:linear-gradient(180deg,#ffffff 0%,#eef7f8 100%);border-color:rgba(31,122,140,.18)}
.meta-stack{display:grid;gap:.85rem}
.meta-chip{display:flex;gap:.75rem;align-items:flex-start;padding:.9rem 1rem;border:1px solid var(--ftth-border);border-radius:.9rem;background:linear-gradient(180deg,#fff 0%,#f8fbfd 100%)}
.meta-chip i{color:var(--ftth-accent);margin-top:.2rem}
.meta-chip strong{display:block;color:var(--ftth-ink);font-size:.86rem}
.meta-chip span{display:block;color:#5d7281;font-size:.84rem;word-break:break-word}
.meta-chip .gps-map-trigger{display:inline-flex;align-items:center;gap:.5rem;padding:0;border:0;background:transparent;color:var(--ftth-accent);font-weight:700;text-align:left;text-decoration:none}
.meta-chip .gps-map-trigger:hover{text-decoration:underline;color:#185d6b}
.meta-chip .gps-map-trigger:focus-visible{outline:2px solid rgba(31,122,140,.35);outline-offset:4px;border-radius:.4rem}
.gps-map-hint{margin-top:.25rem;font-size:.74rem;color:#6b7f8c}
.gps-map-shell{overflow:hidden}
.gps-map-toolbar{display:flex;justify-content:space-between;align-items:flex-start;gap:1rem;flex-wrap:wrap;margin-bottom:1rem}
.gps-map-toolbar-actions{display:flex;gap:.75rem;flex-wrap:wrap}
.gps-map-frame{height:420px;border-radius:.9rem;overflow:hidden;border:1px solid var(--ftth-border);background:#eef4f7}
.gps-route-status{padding:.85rem 1rem;border-radius:.9rem;border:1px solid var(--ftth-border);background:#f8fbfd;color:#5d7281;font-size:.84rem}
.gps-route-status.is-success{border-color:rgba(25,135,84,.2);background:rgba(25,135,84,.08);color:#146c43}
.gps-route-status.is-warning{border-color:rgba(255,193,7,.25);background:rgba(255,193,7,.1);color:#8a6d03}
.gps-route-summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:.75rem;margin-top:1rem}
.gps-route-summary-card{padding:.95rem 1rem;border:1px solid var(--ftth-border);border-radius:.95rem;background:#fff}
.gps-route-summary-card strong{display:block;font-size:.73rem;text-transform:uppercase;letter-spacing:.05em;color:#6b7f8c;margin-bottom:.35rem}
.gps-route-summary-card span{display:block;font-size:1rem;font-weight:700;color:var(--ftth-ink)}
.history-timeline{display:grid;gap:1rem}
.history-item{display:grid;grid-template-columns:52px 1fr;gap:1rem;align-items:flex-start;padding:1rem 1.1rem;border:1px solid var(--ftth-border);border-radius:1rem;background:linear-gradient(180deg,#fff 0%,#f8fbfd 100%)}
.history-icon{width:52px;height:52px;border-radius:16px;display:flex;align-items:center;justify-content:center;background:#eef4f7;color:var(--ftth-accent);font-size:1rem}
.history-item.tone-primary .history-icon{background:rgba(13,110,253,.12);color:#0d6efd}
.history-item.tone-info .history-icon{background:rgba(13,202,240,.14);color:#0aa2c0}
.history-item.tone-warning .history-icon{background:rgba(255,193,7,.16);color:#9a6d00}
.history-item.tone-success .history-icon{background:rgba(25,135,84,.14);color:#198754}
.history-item.tone-danger .history-icon{background:rgba(220,53,69,.14);color:#dc3545}
.history-date{font-size:.76rem;text-transform:uppercase;letter-spacing:.05em;color:#6b7f8c;margin-bottom:.25rem}
.history-title{font-weight:700;color:var(--ftth-ink);margin-bottom:.2rem}
.history-detail{color:#5d7281;font-size:.88rem;white-space:pre-line}
.tech-avatar{width:52px;height:52px;border-radius:16px;flex:0 0 52px;display:flex;align-items:center;justify-content:center;overflow:hidden;position:relative;background:linear-gradient(135deg,var(--ftth-accent-soft) 0%,#c7ebef 100%);color:var(--ftth-accent);font-weight:800;font-size:1rem;box-shadow:0 .5rem 1rem rgba(18,52,77,.10)}
.tech-avatar img{width:100%;height:100%;object-fit:cover;display:block;position:absolute;inset:0}
.tech-avatar span{line-height:1}
.assigned-identity{display:flex;align-items:center;gap:.9rem}
.assigned-summary{display:flex;flex-wrap:wrap;gap:.45rem;margin-top:.35rem}
.assigned-summary .badge{font-size:.72rem;padding:.38rem .58rem;border-radius:999px}
.assignment-card{display:flex;align-items:flex-start;gap:1rem;padding:1rem 1.1rem;border-bottom:1px solid #edf3f6}
.assignment-card:last-child{border-bottom:none}
.assignment-card-body{display:grid;gap:.3rem;min-width:0;flex:1}
.assignment-meta{display:flex;flex-wrap:wrap;gap:.45rem .75rem;color:#6b7f8c;font-size:.82rem}
.assignment-notes{padding:.65rem .8rem;border-radius:.9rem;background:#f8fbfd;border:1px solid var(--ftth-border);color:#5d7281;font-size:.82rem}
.ftth-cta-panel{background:linear-gradient(180deg,#ffffff 0%,#eef7f8 100%);border:1px solid rgba(31,122,140,.18);border-radius:1rem}
.ftth-address{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.form-modern-shell{background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);border:1px solid var(--ftth-border);border-radius:1rem;box-shadow:0 .5rem 1.25rem rgba(18,52,77,.06)}
.form-modern-shell .form-label{font-size:.75rem;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#5d7281}
.input-soft,.input-soft.form-control,.input-soft.form-select{border-radius:.95rem;border:1px solid var(--ftth-border);background:#fcfeff;min-height:48px;box-shadow:inset 0 1px 2px rgba(18,52,77,.03)}
.input-soft.form-control:focus,.input-soft.form-select:focus{border-color:rgba(31,122,140,.5);box-shadow:0 0 0 .2rem rgba(31,122,140,.12)}
.auto-meta-note{display:flex;align-items:center;gap:.75rem;padding:.95rem 1rem;border:1px solid rgba(31,122,140,.14);background:rgba(31,122,140,.06);border-radius:1rem}
.auto-meta-note i{width:40px;height:40px;border-radius:12px;background:#fff;color:var(--ftth-accent);display:flex;align-items:center;justify-content:center;box-shadow:0 .25rem .75rem rgba(18,52,77,.08)}
.step-pane-grid{display:grid;gap:1rem}
.step-pane-panel{padding:1rem 1rem 1.1rem;border:1px solid var(--ftth-border);border-radius:1rem;background:linear-gradient(180deg,#ffffff 0%,#f8fbfd 100%);box-shadow:0 .4rem 1rem rgba(18,52,77,.05)}
.step-pane-panel h6{margin:0 0 .9rem;font-size:.86rem;font-weight:700;color:var(--ftth-ink)}
.step-pane-panel p{margin:0;color:#6b7f8c;font-size:.84rem}
.upload-preview-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:.9rem;margin-top:1rem}
.upload-preview-card{padding:.85rem;border:1px solid var(--ftth-border);border-radius:1rem;background:#fff;box-shadow:0 .4rem 1rem rgba(18,52,77,.05)}
.upload-preview-thumb{width:100%;height:132px;object-fit:cover;border-radius:.85rem;margin-bottom:.75rem;background:#eef4f7}
.upload-preview-card textarea{min-height:88px;resize:vertical}
.existing-photo-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:.75rem}
.existing-photo-card{padding:.75rem;border:1px solid var(--ftth-border);border-radius:.95rem;background:#fff}
.existing-photo-card img{width:100%;height:110px;object-fit:cover;border-radius:.8rem;margin-bottom:.55rem}
.existing-photo-card .photo-thumb{width:100%;height:110px;border-width:0;transform:none}
.gps-passive-card{display:flex;align-items:flex-start;gap:.9rem;padding:1rem;border:1px solid rgba(31,122,140,.15);background:linear-gradient(180deg,#ffffff 0%,#eef7f8 100%);border-radius:1rem}
.gps-passive-card i{width:42px;height:42px;display:flex;align-items:center;justify-content:center;border-radius:14px;background:#fff;color:var(--ftth-accent);box-shadow:0 .35rem 1rem rgba(18,52,77,.08)}
.submit-status{font-size:.84rem;color:#5d7281}
.submit-status.is-busy{color:var(--ftth-accent)}
.submit-status.is-success{color:var(--success-color)}
.submit-status.is-warning{color:#b78103}
/* ── Fiche stepper ── */
.step-tabs .nav-link{display:flex;flex-direction:column;align-items:center;gap:2px;font-size:.78rem;color:#6c757d;padding:.5rem .4rem;border-radius:8px;position:relative}
.step-tabs .nav-link .step-num{width:28px;height:28px;border-radius:50%;background:#e9ecef;color:#6c757d;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:.8rem;transition:.2s}
.step-tabs .nav-link.active .step-num{background:var(--ftth-accent);color:#fff}
.step-tabs .nav-link.active{color:var(--ftth-accent);font-weight:600}
.step-flow-actions{display:flex;align-items:center;gap:.65rem;flex-wrap:wrap}
.step-flow-actions .btn{min-width:150px}
/* ── Photo grid ── */
.photo-thumb{width:80px;height:80px;object-fit:cover;border-radius:8px;cursor:zoom-in;border:2px solid transparent;transition:.15s}
.photo-thumb:hover{border-color:var(--ftth-accent);transform:scale(1.04)}
/* ── Signature canvas ── */
.sig-canvas{border:2px dashed #dee2e6;border-radius:8px;background:#fafbfc;touch-action:none;cursor:crosshair;width:100%;height:160px}
.sig-canvas.has-data{border-color:var(--ftth-accent);background:#fff}
/* ── Satisfaction ── */
.sat-radio input[type=radio]{display:none}
.sat-radio label{cursor:pointer;padding:.3rem .7rem;border:2px solid #dee2e6;border-radius:20px;font-size:.8rem;transition:.15s;white-space:nowrap}
.sat-radio input[type=radio]:checked + label{border-color:var(--ftth-accent);background:#e7f7f9;color:var(--ftth-accent);font-weight:600}
.satisfaction-hero{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding:1.1rem 1.15rem;border:1px solid rgba(31,122,140,.16);border-radius:1.1rem;background:linear-gradient(135deg,rgba(31,122,140,.08) 0%,rgba(118,200,147,.12) 100%);box-shadow:0 .65rem 1.4rem rgba(18,52,77,.06)}
.satisfaction-hero-copy{display:grid;gap:.35rem;max-width:760px}
.satisfaction-hero-copy h6{margin:0;font-size:1rem;font-weight:800;color:var(--ftth-ink)}
.satisfaction-hero-copy p{margin:0;color:#5f7482;font-size:.9rem;line-height:1.55}
.satisfaction-hero-badge{display:inline-flex;align-items:center;gap:.55rem;padding:.55rem .85rem;border-radius:999px;background:#fff;border:1px solid rgba(31,122,140,.14);color:var(--ftth-accent);font-size:.78rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;box-shadow:0 .35rem .9rem rgba(18,52,77,.05)}
.satisfaction-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;margin-top:1rem}
.satisfaction-card{padding:1rem 1.05rem;border:1px solid var(--ftth-border);border-radius:1.05rem;background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);box-shadow:0 .45rem 1rem rgba(18,52,77,.05)}
.satisfaction-card-head{display:flex;align-items:flex-start;gap:.8rem;margin-bottom:.9rem}
.satisfaction-card-icon{width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:rgba(31,122,140,.1);color:var(--ftth-accent);box-shadow:0 .35rem .85rem rgba(18,52,77,.06)}
.satisfaction-card-head strong{display:block;color:var(--ftth-ink);font-size:.92rem;margin-bottom:.18rem}
.satisfaction-card-head span{display:block;color:#6b7f8c;font-size:.82rem;line-height:1.45}
.satisfaction-options{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.65rem}
.satisfaction-option input[type=radio]{display:none}
.satisfaction-option label{display:flex;align-items:center;gap:.6rem;min-height:56px;padding:.8rem .9rem;border:1px solid #dbe7ef;border-radius:.95rem;background:#fff;cursor:pointer;transition:border-color .18s ease, box-shadow .18s ease, transform .18s ease;color:#425866;font-size:.84rem;font-weight:700;box-shadow:0 .2rem .65rem rgba(18,52,77,.04)}
.satisfaction-option label::before{content:'';width:12px;height:12px;border-radius:50%;border:2px solid #bfd1db;flex:0 0 12px;transition:.18s ease;background:#fff}
.satisfaction-option input[type=radio]:checked + label{border-color:rgba(31,122,140,.45);background:linear-gradient(180deg,#ffffff 0%,#eef7f8 100%);color:var(--ftth-accent);box-shadow:0 .5rem 1rem rgba(31,122,140,.12);transform:translateY(-1px)}
.satisfaction-option input[type=radio]:checked + label::before{border-color:var(--ftth-accent);background:var(--ftth-accent)}
.satisfaction-side-grid{display:grid;grid-template-columns:minmax(240px,.9fr) minmax(0,1.1fr);gap:1rem;margin-top:1rem}
.service-restore-card,.client-remarks-card{padding:1rem 1.05rem;border:1px solid var(--ftth-border);border-radius:1.05rem;background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);box-shadow:0 .45rem 1rem rgba(18,52,77,.05)}
.service-restore-card h6,.client-remarks-card h6{margin:0 0 .35rem;font-size:.9rem;font-weight:800;color:var(--ftth-ink)}
.service-restore-card p,.client-remarks-card p{margin:0 0 .9rem;color:#6b7f8c;font-size:.83rem;line-height:1.5}
.service-restore-toggle{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:.75rem}
.service-restore-toggle input[type=radio]{display:none}
.service-restore-toggle label{display:flex;align-items:center;justify-content:center;min-height:64px;padding:.9rem;border:1px solid var(--ftth-border);border-radius:1rem;background:#fff;cursor:pointer;font-weight:800;font-size:.92rem;transition:.18s ease;box-shadow:0 .2rem .65rem rgba(18,52,77,.04)}
.service-restore-toggle input[type=radio]:checked + label{transform:translateY(-1px);box-shadow:0 .55rem 1rem rgba(18,52,77,.08)}
.service-restore-toggle input[type=radio][value="1"]:checked + label{border-color:rgba(25,135,84,.35);background:rgba(25,135,84,.08);color:#198754}
.service-restore-toggle input[type=radio][value="0"]:checked + label{border-color:rgba(220,53,69,.28);background:rgba(220,53,69,.08);color:#dc3545}
.client-identity-card{display:flex;align-items:center;gap:.85rem;padding:.9rem 1rem;border:1px solid rgba(31,122,140,.14);border-radius:1rem;background:linear-gradient(180deg,#ffffff 0%,#eef7f8 100%);margin-bottom:.95rem}
.client-identity-icon{width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:#fff;color:var(--ftth-accent);box-shadow:0 .35rem .9rem rgba(18,52,77,.07)}
.client-identity-card strong{display:block;font-size:.74rem;letter-spacing:.06em;text-transform:uppercase;color:#6b7f8c;margin-bottom:.15rem}
.client-identity-card span{display:block;font-size:.98rem;font-weight:700;color:var(--ftth-ink)}
.constat-hero,.intervention-hero{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding:1.1rem 1.15rem;border:1px solid rgba(31,122,140,.16);border-radius:1.1rem;box-shadow:0 .65rem 1.4rem rgba(18,52,77,.06)}
.constat-hero{background:linear-gradient(135deg,rgba(31,122,140,.08) 0%,rgba(244,185,66,.10) 100%)}
.intervention-hero{background:linear-gradient(135deg,rgba(18,52,77,.06) 0%,rgba(31,122,140,.08) 48%,rgba(118,200,147,.10) 100%)}
.constat-hero-copy,.intervention-hero-copy{display:grid;gap:.35rem;max-width:760px}
.constat-hero-copy h6,.intervention-hero-copy h6{margin:0;font-size:1rem;font-weight:800;color:var(--ftth-ink)}
.constat-hero-copy p,.intervention-hero-copy p{margin:0;color:#5f7482;font-size:.9rem;line-height:1.55}
.step-hero-badge{display:inline-flex;align-items:center;gap:.55rem;padding:.55rem .85rem;border-radius:999px;background:#fff;border:1px solid rgba(31,122,140,.14);color:var(--ftth-accent);font-size:.78rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase;box-shadow:0 .35rem .9rem rgba(18,52,77,.05)}
.constat-grid,.intervention-grid{display:grid;grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr);gap:1rem;margin-top:1rem}
.step-feature-card{padding:1rem 1.05rem;border:1px solid var(--ftth-border);border-radius:1.05rem;background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);box-shadow:0 .45rem 1rem rgba(18,52,77,.05)}
.step-feature-head{display:flex;align-items:flex-start;gap:.8rem;margin-bottom:.9rem}
.step-feature-icon{width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:rgba(31,122,140,.1);color:var(--ftth-accent);box-shadow:0 .35rem .85rem rgba(18,52,77,.06)}
.step-feature-head strong{display:block;color:var(--ftth-ink);font-size:.92rem;margin-bottom:.18rem}
.step-feature-head span{display:block;color:#6b7f8c;font-size:.82rem;line-height:1.45}
.step-inline-hint{display:flex;align-items:flex-start;gap:.7rem;padding:.8rem .9rem;border:1px solid rgba(31,122,140,.12);background:rgba(31,122,140,.05);border-radius:.95rem;margin-top:.9rem;color:#5f7482;font-size:.82rem}
.step-inline-hint i{width:34px;height:34px;border-radius:12px;background:#fff;color:var(--ftth-accent);display:flex;align-items:center;justify-content:center;box-shadow:0 .25rem .75rem rgba(18,52,77,.08)}
.eq-input-shell,.material-input-shell{margin-top:.95rem}
.photo-stage-card{padding:1rem 1.05rem;border:1px solid var(--ftth-border);border-radius:1.05rem;background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);box-shadow:0 .45rem 1rem rgba(18,52,77,.05);margin-top:1rem}
.photo-stage-head{display:flex;align-items:flex-start;gap:.8rem;margin-bottom:.9rem}
.photo-stage-head strong{display:block;color:var(--ftth-ink);font-size:.92rem;margin-bottom:.18rem}
.photo-stage-head span{display:block;color:#6b7f8c;font-size:.82rem;line-height:1.45}
.photo-stage-icon{width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:rgba(25,135,84,.1);color:#198754;box-shadow:0 .35rem .85rem rgba(18,52,77,.06)}
.signature-hero{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding:1.1rem 1.15rem;border:1px solid rgba(31,122,140,.16);border-radius:1.1rem;background:linear-gradient(135deg,rgba(18,52,77,.06) 0%,rgba(31,122,140,.08) 55%,rgba(118,200,147,.10) 100%);box-shadow:0 .65rem 1.4rem rgba(18,52,77,.06)}
.signature-hero-copy{display:grid;gap:.35rem;max-width:760px}
.signature-hero-copy h6{margin:0;font-size:1rem;font-weight:800;color:var(--ftth-ink)}
.signature-hero-copy p{margin:0;color:#5f7482;font-size:.9rem;line-height:1.55}
.signature-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1rem;margin-top:1rem}
.signature-card{padding:1rem 1.05rem;border:1px solid var(--ftth-border);border-radius:1.05rem;background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);box-shadow:0 .45rem 1rem rgba(18,52,77,.05)}
.signature-card-head{display:flex;align-items:flex-start;gap:.8rem;margin-bottom:.9rem}
.signature-card-icon{width:44px;height:44px;border-radius:14px;display:flex;align-items:center;justify-content:center;background:rgba(31,122,140,.1);color:var(--ftth-accent);box-shadow:0 .35rem .85rem rgba(18,52,77,.06)}
.signature-card-head strong{display:block;color:var(--ftth-ink);font-size:.92rem;margin-bottom:.18rem}
.signature-card-head span{display:block;color:#6b7f8c;font-size:.82rem;line-height:1.45}
.signature-card-actions{display:flex;align-items:center;gap:.65rem;flex-wrap:wrap;margin-top:.9rem}
.signature-gps-card{margin-top:1rem;padding:1rem 1.05rem;border:1px solid var(--ftth-border);border-radius:1.05rem;background:linear-gradient(180deg,#ffffff 0%,#f7fbfd 100%);box-shadow:0 .45rem 1rem rgba(18,52,77,.05)}
.signature-gps-meta{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:.9rem}
.signature-gps-meta h6{margin:0 0 .35rem;font-size:.9rem;font-weight:800;color:var(--ftth-ink)}
.signature-gps-meta p{margin:0;color:#6b7f8c;font-size:.83rem;line-height:1.5}
.signature-gps-pill{display:inline-flex;align-items:center;gap:.5rem;padding:.55rem .85rem;border-radius:999px;background:#fff;border:1px solid rgba(31,122,140,.14);color:var(--ftth-accent);font-size:.78rem;font-weight:800;letter-spacing:.04em;text-transform:uppercase}
/* ── GPS btn ── */
.gps-btn{position:relative}
.gps-btn.captured{color:#198754!important;border-color:#198754!important}
/* ── Lightbox ── */
#lb{display:none;position:fixed;inset:0;background:rgba(0,0,0,.88);z-index:9999;cursor:zoom-out;align-items:center;justify-content:center}
.ftth-sticky-actions{position:fixed;left:0;right:0;bottom:0;z-index:1050;padding:.85rem 1rem calc(.85rem + env(safe-area-inset-bottom));background:rgba(255,255,255,.96);backdrop-filter:blur(12px);border-top:1px solid var(--ftth-border);box-shadow:0 -8px 24px rgba(18,52,77,.08)}
.ftth-sticky-actions .btn{min-height:48px}
@media (max-width: 991.98px){
  .content{padding-bottom:6.5rem}
  .ftth-nav .nav-link{white-space:nowrap}
  .gps-map-frame{height:340px}
  .history-item{grid-template-columns:44px 1fr;padding:.9rem}
  .history-icon{width:44px;height:44px;border-radius:14px}
  .ftth-hero-grid,.mission-grid{grid-template-columns:1fr}
  .constat-grid,.intervention-grid,.satisfaction-grid,.satisfaction-side-grid,.satisfaction-options,.service-restore-toggle,.signature-grid{grid-template-columns:1fr}
}
</style>

<!-- ══════════════════════════════════════════════════════ HERO -->
<div class="content-header p-0">
<div class="ftth-hero">
  <div class="container-fluid px-3 px-lg-4">
    <div class="ftth-hero-grid pb-3">
      <div>
        <a href="<?= htmlspecialchars(route_url($moduleBasePath)) ?>" class="btn btn-sm btn-light btn-light opacity-75 mb-3">
          <i class="fas fa-arrow-left me-1"></i>Retour
        </a>
        <div class="ftth-hero-kicker"><i class="fas fa-bolt"></i><?= htmlspecialchars($heroKickerDisplay) ?></div>
        <h1 class="ftth-hero-title"><?= htmlspecialchars($heroTitleDisplay) ?></h1>
        <div class="fw-semibold fs-5 opacity-90 mb-2"><?= htmlspecialchars($heroClientDisplay) ?></div>
        <div class="ftth-hero-subline">
          <?php if ($heroSubscriptionDisplay !== ''): ?><span><i class="fas fa-id-badge me-1"></i>Abonnement <?= htmlspecialchars($heroSubscriptionDisplay) ?></span><?php endif; ?>
          <?php if ($heroAddressDisplay !== ''): ?><span><i class="fas fa-location-dot me-1"></i><?= htmlspecialchars($heroAddressDisplay) ?></span><?php endif; ?>
          <?php if ($isRaccordementClients && ($importedCityField['value'] || $importedCommuneField['value'])): ?><span><i class="fas fa-map-pin me-1"></i><?= htmlspecialchars(trim(((string)($importedCityField['value'] ?? '')) . ' ' . ((string)($importedCommuneField['value'] ?? '')))) ?></span><?php endif; ?>
          <span><i class="fas fa-clock me-1"></i><?= date('d/m/Y H:i', strtotime($ticket['imported_at'] ?: $ticket['created_at'])) ?></span>
        </div>
        <div class="d-flex gap-2 flex-wrap mt-3">
          <span class="badge bg-<?= $priColor ?>"><i class="fas fa-flag me-1"></i><?= htmlspecialchars($ticket['priority']) ?></span>
          <span class="badge bg-<?= $stColor ?>"><i class="fas fa-circle me-1" style="font-size:.55rem"></i><?= htmlspecialchars($interventionStatusDisplay) ?></span>
          <?php if ($rpColor): ?><span class="badge bg-<?= $rpColor ?>"><i class="fas fa-clipboard-check me-1"></i>Fiche <?= htmlspecialchars($reportStatusLabel) ?></span><?php endif; ?>
          <?php if ($report): ?><span class="badge bg-<?= $clientVisitStatusColor ?><?= in_array($clientVisitStatusColor, ['warning','info'], true) ? ' text-dark' : '' ?>"><i class="fas fa-user-clock me-1"></i><?= htmlspecialchars($clientVisitStatusLabel) ?></span><?php endif; ?>
          <?php if ($plannedInterventionDisplay !== ''): ?><span class="badge bg-light text-dark border"><i class="fas fa-calendar-days me-1"></i><?= htmlspecialchars($plannedInterventionDisplay) ?></span><?php endif; ?>
          <?php if ($ticket['client_phone']): ?>
          <a href="tel:<?= htmlspecialchars($ticket['client_phone']) ?>" class="badge bg-white text-dark text-decoration-none">
            <i class="fas fa-phone me-1 text-success"></i><?= htmlspecialchars($ticket['client_phone']) ?>
          </a>
          <?php endif; ?>
        </div>
      </div>

      <div class="ftth-hero-summary">
        <div class="ftth-hero-panel-card">
          <strong>Techniciens terrain</strong>
          <span><?= count($assignments) ?> technicien<?= count($assignments) > 1 ? 's' : '' ?></span>
        </div>
        <div class="ftth-hero-panel-card">
          <strong>Rapport terrain</strong>
          <span><?= htmlspecialchars($reportStatusLabel) ?></span>
        </div>
        <?php if ($lastReportSavedAt !== ''): ?>
        <div class="ftth-hero-panel-card">
          <strong>Dernier enregistrement</strong>
          <span><?= htmlspecialchars($lastReportSavedAt) ?></span>
        </div>
        <?php endif; ?>
        <?php if ($report): ?>
        <div class="ftth-hero-panel-card">
          <strong>Situation client</strong>
          <span><?= htmlspecialchars($clientVisitStatusLabel) ?><?= $plannedInterventionDisplay !== '' ? ' • ' . htmlspecialchars($plannedInterventionDisplay) : '' ?></span>
        </div>
        <?php endif; ?>
        <div class="d-flex gap-2 flex-wrap justify-content-start justify-content-lg-end">
          <?php if ($isAdmin): ?>
          <?php if ($isRaccordementClients): ?>
          <button type="button" class="btn btn-sm btn-light opacity-90" data-bs-toggle="modal" data-bs-target="#modalEditRaccordementDetail">
            <i class="fas fa-pen me-1"></i>Modifier
          </button>
          <button type="button" class="btn btn-sm btn-outline-light" data-bs-toggle="modal" data-bs-target="#modalPriorityRaccordementDetail">
            <i class="fas fa-bolt me-1"></i>Criticité
          </button>
          <?php endif; ?>
          <?php if (empty($assignments)): ?>
          <button class="btn btn-sm btn-light opacity-90" data-bs-toggle="modal" data-bs-target="#modalAssignHero">
            <i class="fas fa-user-plus me-1"></i>Assigner
          </button>
          <?php elseif (!$assignmentLocked): ?>
          <form id="ftthUnassignAllHeroForm" method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/unassign')) ?>">
            <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
            <input type="hidden" name="redirect_to" value="detail">
            <button type="button" class="btn btn-sm btn-light opacity-90 js-ftth-confirm-trigger" data-ftth-confirm-form="ftthUnassignAllHeroForm" data-ftth-confirm-title="Désassigner le ticket" data-ftth-confirm-message="Retirer toutes les assignations de ce ticket ?" data-ftth-confirm-button="Désassigner" data-ftth-confirm-button-class="btn-outline-danger">
              <i class="fas fa-user-minus me-1"></i>Désassigner
            </button>
          </form>
          <?php endif; ?>
          <?php if ($canCloseManual): ?>
          <form id="ftthCloseTicketForm" method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/close')) ?>">
            <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
            <button type="button" class="btn btn-sm btn-success opacity-90 js-ftth-confirm-trigger" data-ftth-confirm-form="ftthCloseTicketForm" data-ftth-confirm-title="<?= $isRaccordementClients ? 'Clôturer le dossier' : 'Clôturer le ticket' ?>" data-ftth-confirm-message="<?= htmlspecialchars($isRaccordementClients ? 'Clôturer manuellement ce dossier raccordement validé ?' : 'Clôturer manuellement ce ticket FTTH validé ?') ?>" data-ftth-confirm-button="Clôturer" data-ftth-confirm-button-class="btn-success">
              <i class="fas fa-lock me-1"></i>Clôturer
            </button>
          </form>
          <?php endif; ?>
          <form id="ftthDeleteTicketForm" method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/delete')) ?>">
            <input type="hidden" name="id" value="<?= (int)$ticket['id'] ?>">
            <button type="button" class="btn btn-sm btn-danger opacity-90 js-ftth-confirm-trigger" data-ftth-confirm-form="ftthDeleteTicketForm" data-ftth-confirm-title="<?= $isRaccordementClients ? 'Supprimer le dossier' : 'Supprimer le ticket' ?>" data-ftth-confirm-message="<?= htmlspecialchars($isRaccordementClients ? 'Supprimer définitivement ce dossier raccordement ?' : 'Supprimer définitivement ce ticket FTTH ?') ?>" data-ftth-confirm-button="Supprimer" data-ftth-confirm-button-class="btn-danger"><i class="fas fa-trash"></i></button>
          </form>
          <?php elseif ($isAssigned): ?>
          <button type="button" class="btn btn-sm btn-light opacity-90" onclick="document.querySelector('[data-bs-target=\'#tabFiche\']')?.click()">
            <i class="fas fa-clipboard-check me-1"></i><?= $reportEditable ? 'Continuer la fiche' : 'Voir la fiche' ?>
          </button>
          <?php if ($ticket['client_phone']): ?>
          <a href="tel:<?= htmlspecialchars($ticket['client_phone']) ?>" class="btn btn-sm btn-outline-light">
            <i class="fas fa-phone me-1"></i>Appeler
          </a>
          <?php endif; ?>
          <?php endif; ?>
        </div>
      </div>
    </div>

    <!-- Onglets hero -->
    <ul class="nav ftth-nav mt-1 border-0" id="mainTabs">
      <li class="nav-item"><button type="button" class="nav-link active" data-bs-toggle="tab" data-bs-target="#tabClient">
        <i class="fas fa-building me-1"></i><?= htmlspecialchars($moduleMissionTabLabel) ?>
      </button></li>
      <?php if ($gpsMapAvailable): ?>
      <li class="nav-item"><button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#tabCarte">
        <i class="fas fa-map-location-dot me-1"></i>Carte
      </button></li>
      <?php endif; ?>
      <li class="nav-item"><button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#tabEquipe">
        <i class="fas fa-users me-1"></i>Équipe
        <?php if (!empty($assignments)): ?><span class="badge bg-warning text-dark ms-1"><?= count($assignments) ?></span><?php endif; ?>
      </button></li>
      <li class="nav-item"><button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#tabFiche">
        <i class="fas fa-clipboard-list me-1"></i>Fiche terrain
        <?php if ($rpColor): ?><span class="badge bg-<?= $rpColor ?> ms-1"><i class="fas fa-circle" style="font-size:.5rem"></i></span><?php endif; ?>
      </button></li>
      <li class="nav-item"><button type="button" class="nav-link" data-bs-toggle="tab" data-bs-target="#tabHistorique">
        <i class="fas fa-clock-rotate-left me-1"></i>Historique
      </button></li>
    </ul>
  </div>
</div>
</div>

<section class="content">
<div class="container-fluid px-3 px-lg-4 py-3">

  <!-- Flash alerts -->
  <?php foreach (['created'=>['success','Déclaration créée.','plus-circle'], 'saved'=>['success','Fiche enregistrée.','check-circle'], 'assigned'=>['success','Assigné et notifié.','user-check'], 'validated'=>['success','Rapport mis à jour.','check-double'], 'closed'=>['success','Ticket clôturé manuellement.','lock'], 'err'=>['danger', htmlspecialchars($_GET['err'] ?? ''), 'exclamation-circle']] as $k=>[$cls,$msg,$ico]): ?>
  <?php if (isset($_GET[$k]) && $msg): ?>
  <div class="alert alert-<?= $cls ?> alert-dismissible fade show py-2 small">
    <i class="fas fa-<?= $ico ?> me-1"></i><?= $msg ?>
    <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
  </div>
  <?php endif; endforeach; ?>
  <?php if (isset($_GET['unassigned'])): ?>
  <div class="alert alert-success alert-dismissible fade show py-2 small">
    <i class="fas fa-user-minus me-1"></i>Assignation retirée avec succès.
    <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
  </div>
  <?php endif; ?>

  <div class="row g-3 mb-3">
    <div class="col-12 col-sm-6 col-xl-3">
      <div class="mission-kpi-card p-3 h-100">
        <div class="d-flex align-items-center gap-3">
          <div class="icon-wrap"><i class="fas fa-user-check"></i></div>
          <div>
            <div class="text-muted small"><?= htmlspecialchars($kpiClientLabel) ?></div>
            <div class="fw-semibold"><?= htmlspecialchars($kpiClientValue) ?></div>
          </div>
        </div>
      </div>
    </div>
    <div class="col-12 col-sm-6 col-xl-3">
      <div class="mission-kpi-card p-3 h-100">
        <div class="d-flex align-items-center gap-3">
          <div class="icon-wrap"><i class="fas fa-bolt"></i></div>
          <div>
            <div class="text-muted small"><?= htmlspecialchars($kpiOperationLabel) ?></div>
            <div class="fw-semibold"><?= htmlspecialchars($kpiOperationValue) ?></div>
          </div>
        </div>
      </div>
    </div>
    <div class="col-12 col-sm-6 col-xl-3">
      <div class="mission-kpi-card p-3 h-100">
        <div class="d-flex align-items-center gap-3">
          <div class="icon-wrap"><i class="fas fa-users"></i></div>
          <div>
            <div class="text-muted small">Équipe terrain</div>
            <div class="fw-semibold"><?= count($assignments) ?> technicien<?= count($assignments) > 1 ? 's' : '' ?></div>
          </div>
        </div>
      </div>
    </div>
    <div class="col-12 col-sm-6 col-xl-3">
      <div class="mission-kpi-card p-3 h-100">
        <div class="d-flex align-items-center gap-3">
          <div class="icon-wrap"><i class="fas fa-clipboard-list"></i></div>
          <div>
            <div class="text-muted small"><?= htmlspecialchars($moduleFieldFormLabel) ?></div>
            <div class="fw-semibold"><?= htmlspecialchars($reportStatusLabel) ?></div>
            <?php if ($lastReportSavedAt !== ''): ?>
            <div class="small text-muted mt-1">Dernier enregistrement : <?= htmlspecialchars($lastReportSavedAt) ?></div>
            <?php endif; ?>
          </div>
        </div>
      </div>
    </div>
  </div>

  <div class="tab-content">

    <!-- ══════════════════════════════════════ TAB CLIENT -->
    <div class="tab-pane fade show active" id="tabClient">
      <div class="mission-grid">

        <div class="mission-panel p-3 p-lg-4">
          <div class="mission-panel-head">
            <div class="mission-panel-title">
              <i class="fas fa-id-card"></i>
              <div>
                <h6><?= $isRaccordementClients ? 'Entête client' : 'Client et accès' ?></h6>
                <p><?= $isRaccordementClients ? 'Données d’entête issues de l’onglet RACCORDES pour préparer le raccordement terrain.' : 'Informations de contact, d’adresse et de repérage pour la prise en charge terrain.' ?></p>
              </div>
            </div>
            <div class="mission-spotlight">
              <div class="mission-spotlight-label"><?= $isRaccordementClients ? 'Abonnement' : 'Client concerné' ?></div>
              <div class="mission-spotlight-value"><?= htmlspecialchars($isRaccordementClients ? ($heroSubscriptionDisplay !== '' ? $heroSubscriptionDisplay : $heroClientDisplay) : $ticket['client_name']) ?></div>
            </div>
          </div>

          <div class="meta-stack">
              <?php if ($isRaccordementClients): ?>
              <div class="meta-chip is-highlight">
                <i class="fas fa-user"></i>
                <div>
                  <strong>Nom client</strong>
                  <span><?= htmlspecialchars($heroClientDisplay !== '' ? $heroClientDisplay : 'Non renseigné') ?></span>
                </div>
              </div>
              <?php if ($importedPrimaryContactField['value'] || $ticket['client_phone']): ?>
              <div class="meta-chip">
                <i class="fas fa-phone-alt"></i>
                <div>
                  <strong>Contact 1</strong>
                  <span><a href="tel:<?= htmlspecialchars((string)(($ticket['client_phone'] ?: '') ?: ($importedPrimaryContactField['value'] ?? ''))) ?>" class="text-decoration-none"><?= htmlspecialchars((string)(($ticket['client_phone'] ?: '') ?: ($importedPrimaryContactField['value'] ?? ''))) ?></a></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedSecondaryContactField['value'] || $ticket['client_phone2']): ?>
              <div class="meta-chip">
                <i class="fas fa-phone-volume"></i>
                <div>
                  <strong>Contact 2</strong>
                  <span><a href="tel:<?= htmlspecialchars((string)(($ticket['client_phone2'] ?: '') ?: ($importedSecondaryContactField['value'] ?? ''))) ?>" class="text-decoration-none"><?= htmlspecialchars((string)(($ticket['client_phone2'] ?: '') ?: ($importedSecondaryContactField['value'] ?? ''))) ?></a></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($heroAddressDisplay !== ''): ?>
              <div class="meta-chip">
                <i class="fas fa-map-marker-alt"></i>
                <div>
                  <strong><?= htmlspecialchars($addressCardLabel) ?></strong>
                  <span class="ftth-address"><?= nl2br(htmlspecialchars($heroAddressDisplay)) ?></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedCityField['value'] || $importedCommuneField['value']): ?>
              <div class="meta-chip">
                <i class="fas fa-city"></i>
                <div>
                  <strong>Ville / Commune</strong>
                  <span><?= htmlspecialchars(trim(((string)($importedCityField['value'] ?? '')) . ' / ' . ((string)($importedCommuneField['value'] ?? '')), ' /')) ?></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($gpsRawDisplayValue !== ''): ?>
              <div class="meta-chip">
                <i class="fas fa-location-crosshairs"></i>
                <div>
                  <strong><?= htmlspecialchars($importedGpsField['label'] ?: 'Coordonnées terrain') ?></strong>
                  <?php if ($gpsMapAvailable): ?>
                  <button type="button" class="gps-map-trigger js-open-map-tab">
                    <span><?= htmlspecialchars($gpsRawDisplayValue) ?></span>
                    <i class="fas fa-map-marked-alt"></i>
                  </button>
                  <div class="gps-map-hint">Appuyez pour afficher la carte.</div>
                  <?php else: ?>
                  <span><?= htmlspecialchars($gpsRawDisplayValue) ?></span>
                  <?php endif; ?>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedDeploymentProgramField['value']): ?>
              <div class="meta-chip">
                <i class="fas fa-diagram-project"></i>
                <div>
                  <strong>Programme de déploiement</strong>
                  <span><?= htmlspecialchars((string)$importedDeploymentProgramField['value']) ?></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedDigitalField['value']): ?>
              <div class="meta-chip">
                <i class="fas fa-briefcase"></i>
                <div>
                  <strong>Segment</strong>
                  <span><?= htmlspecialchars((string)$importedDigitalField['value']) ?></span>
                </div>
              </div>
              <?php endif; ?>
              <?php else: ?>
              <?php if ($fixedLineDisplayValue !== ''): ?>
              <div class="meta-chip is-highlight">
                <i class="fas fa-phone"></i>
                <div>
                  <strong>Ligne fixe</strong>
                  <span><?= htmlspecialchars($fixedLineDisplayValue) ?></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($ticket['client_phone']): ?>
              <div class="meta-chip">
                <i class="fas fa-phone-alt"></i>
                <div>
                  <strong>Contact principal</strong>
                  <span><a href="tel:<?= htmlspecialchars($ticket['client_phone']) ?>" class="text-decoration-none"><?= htmlspecialchars($ticket['client_phone']) ?></a></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if (!empty($ticket['client_phone2'])): ?>
              <div class="meta-chip">
                <i class="fas fa-phone-volume"></i>
                <div>
                  <strong>Contact secondaire</strong>
                  <span><a href="tel:<?= htmlspecialchars($ticket['client_phone2']) ?>" class="text-decoration-none"><?= htmlspecialchars($ticket['client_phone2']) ?></a></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($ticket['client_email']): ?>
              <div class="meta-chip">
                <i class="fas fa-envelope"></i>
                <div>
                  <strong>Email</strong>
                  <span><a href="mailto:<?= htmlspecialchars($ticket['client_email']) ?>"><?= htmlspecialchars($ticket['client_email']) ?></a></span>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($ticket['client_address']): ?>
              <div class="meta-chip">
                <i class="fas fa-map-marker-alt"></i>
                <div>
                  <strong><?= htmlspecialchars($addressCardLabel) ?></strong>
                  <span class="ftth-address"><?= nl2br(htmlspecialchars($ticket['client_address'])) ?></span>
                </div>
              </div>
              <?php endif; ?>
              <?php endif; ?>
            </div>

            <?php if ($briefTerrain !== ''): ?>
            <div class="ftth-cta-panel p-3 mt-3">
              <div class="small text-uppercase text-muted fw-semibold mb-2"><?= htmlspecialchars($briefLabel) ?></div>
              <div class="small text-secondary mb-0"><?= nl2br(htmlspecialchars($briefTerrain)) ?></div>
            </div>
            <?php endif; ?>
        </div>

        <div class="mission-panel p-3 p-lg-4">
          <div class="mission-panel-head">
            <div class="mission-panel-title">
              <i class="fas fa-layer-group"></i>
              <div>
                <h6><?= $isRaccordementClients ? 'Entête RACCORDES' : 'Vue opérationnelle' ?></h6>
                <p><?= $isRaccordementClients ? 'Colonnes de suivi raccordement importées depuis le modèle Wandoo.' : 'Topologie réseau, statut de traitement, affectation terrain et éléments de qualification.' ?></p>
              </div>
            </div>
            <div class="mission-spotlight">
              <div class="mission-spotlight-label"><?= $isRaccordementClients ? 'Avancement' : 'Nature de l’intervention' ?></div>
              <div class="mission-spotlight-value"><?= htmlspecialchars($isRaccordementClients ? ($heroProgressDisplay !== '' ? $heroProgressDisplay : 'Non renseigné') : ($natureDisplayValue !== '' ? $natureDisplayValue : 'Maintenance FTTH')) ?></div>
            </div>
          </div>

          <div>
            <div class="row g-3">
              <?php if ($isRaccordementClients): ?>
              <?php if ($importedPlaqueField['value'] || $sroDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100 is-highlight">
                  <i class="fas fa-network-wired"></i>
                  <div>
                    <strong>PLAQUE</strong>
                    <span><?= htmlspecialchars((string)(($importedPlaqueField['value'] ?? '') ?: $sroDisplayValue)) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($jdvDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-circle-nodes"></i>
                  <div>
                    <strong>JDV</strong>
                    <span><?= htmlspecialchars($jdvDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($pcoDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-ethernet"></i>
                  <div>
                    <strong>PCO</strong>
                    <span><?= htmlspecialchars($pcoDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedSnontField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-barcode"></i>
                  <div>
                    <strong>SNONT</strong>
                    <span><?= htmlspecialchars((string)$importedSnontField['value']) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedNdField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-fingerprint"></i>
                  <div>
                    <strong>ND</strong>
                    <span><?= htmlspecialchars((string)$importedNdField['value']) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedEntrepriseFtthField['value'] || $companyDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-building"></i>
                  <div>
                    <strong>Entreprise FTTH</strong>
                    <span><?= htmlspecialchars((string)(($importedEntrepriseFtthField['value'] ?? '') ?: $companyDisplayValue)) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedTechnicalStudyField['value'] || $natureDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-compass-drafting"></i>
                  <div>
                    <strong>Étude technique</strong>
                    <span><?= htmlspecialchars((string)(($importedTechnicalStudyField['value'] ?? '') ?: $natureDisplayValue)) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedRaccordementTeamField['value'] || $displayedTeam !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-users"></i>
                  <div>
                    <strong>Équipe raccordement</strong>
                    <span><?= htmlspecialchars((string)(($importedRaccordementTeamField['value'] ?? '') ?: $displayedTeam)) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($distanceDisplayValue !== ''): ?>
              <div class="col-12 col-md-6" id="otbDistanceCard">
                <div class="meta-chip h-100">
                  <i class="fas fa-ruler-combined"></i>
                  <div>
                    <strong>Distance PCO-Client</strong>
                    <span id="otbDistanceDisplay"><?= htmlspecialchars((string)$distanceDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedInstanceRegistrationDateField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-calendar-plus"></i>
                  <div>
                    <strong>Date enregistrement instances</strong>
                    <span><?= htmlspecialchars($formatImportedDateValue($importedInstanceRegistrationDateField['value'])) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedProviderSendDateField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-share-from-square"></i>
                  <div>
                    <strong>Date envoi prestataires</strong>
                    <span><?= htmlspecialchars($formatImportedDateValue($importedProviderSendDateField['value'])) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedWaitDurationField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-hourglass-half"></i>
                  <div>
                    <strong>Durée d'attente</strong>
                    <span><?= htmlspecialchars((string)$importedWaitDurationField['value']) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedPlannedConnectionDateField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-calendar-day"></i>
                  <div>
                    <strong>Date prévisionnelle raccordement</strong>
                    <span><?= htmlspecialchars($formatImportedDateValue($importedPlannedConnectionDateField['value'])) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedOltPonField['value']): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-server"></i>
                  <div>
                    <strong>OLT / PON</strong>
                    <span><?= htmlspecialchars((string)$importedOltPonField['value']) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-traffic-light"></i>
                  <div>
                    <strong>Statut intervention</strong>
                    <span><?= htmlspecialchars($interventionStatusDisplay) ?></span>
                  </div>
                </div>
              </div>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-cloud-upload-alt"></i>
                  <div>
                    <strong>Import</strong>
                    <span><?= htmlspecialchars($moduleImportLabel) ?> · <?= date('d/m/Y H:i', strtotime($ticket['imported_at'] ?: $ticket['created_at'])) ?><?php if ($ticket['imported_by_name']): ?> par <?= htmlspecialchars($ticket['imported_by_name']) ?><?php endif; ?></span>
                  </div>
                </div>
              </div>
              <?php if ($importedProblemsField['value']): ?>
              <div class="col-12">
                <div class="meta-chip h-100">
                  <i class="fas fa-triangle-exclamation"></i>
                  <div>
                    <strong>Problèmes</strong>
                    <span><?= nl2br(htmlspecialchars((string)$importedProblemsField['value'])) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($importedCommentsField['value'] || $desc = trim((string)($ticket['description'] ?? ''))): ?>
              <div class="col-12">
                <div class="meta-chip h-100">
                  <i class="fas fa-notes-medical"></i>
                  <div>
                    <strong>Commentaires</strong>
                    <span><?= nl2br(htmlspecialchars((string)(($importedCommentsField['value'] ?? '') ?: ($ticket['description'] ?? '')))) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php else: ?>
              <?php if ($natureDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100 is-highlight">
                  <i class="fas fa-bolt"></i>
                  <div>
                    <strong><?= htmlspecialchars($natureCardLabel) ?></strong>
                    <span><?= htmlspecialchars($natureDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($siteDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-sitemap"></i>
                  <div>
                    <strong><?= htmlspecialchars($siteCardLabel) ?></strong>
                    <span><?= htmlspecialchars($siteDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($progressDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-route"></i>
                  <div>
                    <strong><?= htmlspecialchars($progressCardLabel) ?></strong>
                    <span><?= htmlspecialchars($progressDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-bolt"></i>
                  <div>
                    <strong>Type de coupure</strong>
                    <span><?= htmlspecialchars($cutTypeDisplayValue === 'transport' ? 'Coupure transport' : 'Coupure client') ?></span>
                  </div>
                </div>
              </div>
              <?php if ($gpsRawDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-location-crosshairs"></i>
                  <div>
                    <strong><?= htmlspecialchars($importedGpsField['label'] ?: 'GPS importé') ?></strong>
                    <?php if ($gpsMapAvailable): ?>
                    <button type="button" class="gps-map-trigger js-open-map-tab">
                      <span><?= htmlspecialchars($gpsRawDisplayValue) ?></span>
                      <i class="fas fa-map-marked-alt"></i>
                    </button>
                    <div class="gps-map-hint">Appuyez pour afficher la carte.</div>
                    <?php else: ?>
                    <span><?= htmlspecialchars($gpsRawDisplayValue) ?></span>
                    <?php endif; ?>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($transportZoneDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-draw-polygon"></i>
                  <div>
                    <strong>Zone</strong>
                    <span><?= htmlspecialchars($transportZoneDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($transportOltDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-server"></i>
                  <div>
                    <strong>OLT de rattachement</strong>
                    <span><?= htmlspecialchars($transportOltDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($statusRawDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-signal"></i>
                  <div>
                    <strong>Statut initial</strong>
                    <span><?= htmlspecialchars($statusRawDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-traffic-light"></i>
                  <div>
                    <strong>Statut intervention</strong>
                    <span><?= htmlspecialchars($interventionStatusDisplay) ?></span>
                  </div>
                </div>
              </div>
              <?php if ($sroDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-diagram-project"></i>
                  <div>
                    <strong>SRO CLIENT</strong>
                    <span><?= htmlspecialchars($sroDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($jdvDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-circle-nodes"></i>
                  <div>
                    <strong>JDV CLIENT</strong>
                    <span><?= htmlspecialchars($jdvDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($pcoDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-ethernet"></i>
                  <div>
                    <strong>PCO CLIENT</strong>
                    <span><?= htmlspecialchars($pcoDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($companyDisplayValue !== ''): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-building"></i>
                  <div>
                    <strong>Entreprise/porteur d'action</strong>
                    <span><?= htmlspecialchars($companyDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($showImportedTeamChip): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-people-group"></i>
                  <div>
                    <strong><?= htmlspecialchars($importedTeamField['label'] ?: 'Équipe importée') ?></strong>
                    <span><?= htmlspecialchars($teamRawDisplayValue) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($showAssignedTechnicianChip): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <div class="assigned-identity">
                    <div class="tech-avatar" aria-hidden="true">
                      <span><?= htmlspecialchars($primaryAssignedTechnician['initials']) ?></span>
                      <?php if ($primaryAssignedTechnician['avatar_url'] !== ''): ?>
                      <img src="<?= htmlspecialchars($primaryAssignedTechnician['avatar_url']) ?>" alt="<?= htmlspecialchars($primaryAssignedTechnician['name']) ?>" onerror="this.remove()">
                      <?php endif; ?>
                    </div>
                    <div>
                      <strong><?= count($assignedTechnicians) > 1 ? 'Technicien principal' : 'Technicien assigné' ?></strong>
                      <span><?= htmlspecialchars($primaryAssignedTechnician['name']) ?></span>
                      <div class="assigned-summary">
                        <?php if ($primaryAssignedTechnician['email'] !== ''): ?><span class="badge text-bg-light border"><i class="fas fa-envelope me-1 text-muted"></i><?= htmlspecialchars($primaryAssignedTechnician['email']) ?></span><?php endif; ?>
                        <?php if ($primaryAssignedTechnician['phone'] !== ''): ?><span class="badge text-bg-light border"><i class="fas fa-phone me-1 text-success"></i><?= htmlspecialchars($primaryAssignedTechnician['phone']) ?></span><?php endif; ?>
                        <?php if (count($assignedTechnicians) > 1): ?><span class="badge text-bg-warning">+<?= count($assignedTechnicians) - 1 ?> autre<?= count($assignedTechnicians) > 2 ? 's' : '' ?></span><?php endif; ?>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($showDisplayedTeamChip): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-users"></i>
                  <div>
                    <strong><?= htmlspecialchars($teamCardLabel) ?></strong>
                    <span><?= htmlspecialchars($displayedTeam) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-cloud-upload-alt"></i>
                  <div>
                    <strong>Import</strong>
                    <span><?= date('d/m/Y H:i', strtotime($ticket['imported_at'] ?: $ticket['created_at'])) ?><?php if ($ticket['imported_by_name']): ?> par <?= htmlspecialchars($ticket['imported_by_name']) ?><?php endif; ?></span>
                  </div>
                </div>
              </div>
              <?php if (!empty($ticket['date_cloture'])): ?>
              <div class="col-12 col-md-6">
                <div class="meta-chip h-100">
                  <i class="fas fa-calendar-check"></i>
                  <div>
                    <strong>Date de clôture importée</strong>
                    <span><?= htmlspecialchars($ticket['date_cloture']) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($causeDisplayValue !== ''): ?>
              <div class="col-12">
                <div class="meta-chip h-100">
                  <i class="fas fa-notes-medical"></i>
                  <div>
                    <strong>Commentaire_cause</strong>
                    <span><?= nl2br(htmlspecialchars($causeDisplayValue)) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php if ($transportSignalDisplayValue !== ''): ?>
              <div class="col-12">
                <div class="meta-chip h-100">
                  <i class="fas fa-wave-square"></i>
                  <div>
                    <strong>Détail de la signalisation</strong>
                    <span><?= nl2br(htmlspecialchars($transportSignalDisplayValue)) ?></span>
                  </div>
                </div>
              </div>
              <?php endif; ?>
              <?php endif; ?>
            </div>
          </div>

          <?php if (!$gpsMapAvailable): ?>
          <div class="surface-card d-flex align-items-center justify-content-center text-muted" style="min-height:200px">
            <div class="text-center p-4">
              <i class="fas fa-map-marker-alt fa-2x mb-2 opacity-25"></i>
              <p class="small mb-0"><?= $isRaccordementClients ? 'Pas de coordonnées terrain disponibles.<br>Réimportez le fichier RACCORDES ou complétez la mission pour les obtenir.' : 'Pas de coordonnées GPS.<br>Re-importez le fichier pour les obtenir.' ?></p>
            </div>
          </div>
          <?php endif; ?>
        </div>

      </div>
    </div>

    <?php if ($gpsMapAvailable): ?>
    <div class="tab-pane fade" id="tabCarte">
      <div class="surface-card p-3 p-lg-4 gps-map-shell">
        <div class="gps-map-toolbar">
          <div>
            <h6 class="fw-bold mb-1 text-uppercase text-muted" style="font-size:.72rem;letter-spacing:.08em">
              <i class="fas fa-map me-2 text-info"></i>Navigation terrain
            </h6>
            <div class="fw-semibold"><?= $isRaccordementClients ? 'Destination GPS du raccordement' : 'Destination GPS du ticket' ?></div>
            <div class="small text-muted"><?= htmlspecialchars(number_format((float)$gpsMapLat, 6, '.', '')) ?>, <?= htmlspecialchars(number_format((float)$gpsMapLng, 6, '.', '')) ?></div>
          </div>
          <div class="gps-map-toolbar-actions">
            <button type="button" class="btn btn-primary btn-sm" id="startRouteBtn">
              <i class="fas fa-route me-1"></i>Démarrer l'itinéraire
            </button>
            <button type="button" class="btn btn-outline-secondary btn-sm" id="centerDestinationBtn">
              <i class="fas fa-crosshairs me-1"></i>Centrer sur la destination
            </button>
            <a href="<?= htmlspecialchars($gpsExternalUrl) ?>" target="_blank" rel="noopener" class="btn btn-outline-secondary btn-sm">
              <i class="fas fa-up-right-from-square me-1"></i>Ouvrir dans Maps
            </a>
          </div>
        </div>

        <div id="routeStatus" class="gps-route-status"><?= $isRaccordementClients ? 'La carte affiche la destination du raccordement. Utilisez Démarrer l\'itinéraire pour tracer le chemin depuis votre position actuelle.' : 'La carte affiche la destination. Utilisez Démarrer l\'itinéraire pour tracer le chemin depuis votre position actuelle.' ?></div>

        <div class="gps-route-summary" id="routeSummary" hidden>
          <div class="gps-route-summary-card">
            <strong>Distance</strong>
            <span id="routeDistanceValue">-</span>
          </div>
          <div class="gps-route-summary-card">
            <strong>Durée estimée</strong>
            <span id="routeDurationValue">-</span>
          </div>
          <div class="gps-route-summary-card">
            <strong>Mode</strong>
            <span>Routier</span>
          </div>
        </div>

        <div id="clientMap" class="gps-map-frame mt-3"></div>
      </div>
    </div>
    <?php endif; ?>

    <!-- ══════════════════════════════════════ TAB ÉQUIPE -->
    <div class="tab-pane fade" id="tabEquipe">
      <div class="row g-3">
        <div class="col-12 col-lg-7">
          <div class="surface-card">
            <div class="card-header border-0 bg-transparent pt-3 pb-0">
              <h6 class="fw-bold text-muted text-uppercase mb-0" style="font-size:.72rem;letter-spacing:.08em">
                <i class="fas fa-hard-hat me-2 text-warning"></i>Techniciens assignés
              </h6>
            </div>
            <div class="card-body p-0 mt-2">
              <?php if (!empty($assignments)): ?>
              <?php foreach ($assignments as $a): ?>
              <div class="assignment-card">
                <div class="tech-avatar" aria-hidden="true">
                  <span><?= htmlspecialchars($a['tech_initials'] ?? 'FT') ?></span>
                  <?php if (!empty($a['tech_avatar_url'])): ?>
                  <img src="<?= htmlspecialchars($a['tech_avatar_url']) ?>" alt="<?= htmlspecialchars($a['tech_name']) ?>" onerror="this.remove()">
                  <?php endif; ?>
                </div>
                <div class="assignment-card-body">
                  <div class="fw-semibold"><?= htmlspecialchars($a['tech_name']) ?></div>
                  <div class="assignment-meta">
                    <?php if (!empty($a['tech_email'])): ?><span><i class="fas fa-envelope me-1"></i><?= htmlspecialchars($a['tech_email']) ?></span><?php endif; ?>
                    <?php if (!empty($a['tech_phone'])): ?><span><i class="fas fa-phone me-1"></i><?= htmlspecialchars($a['tech_phone']) ?></span><?php endif; ?>
                    <span><i class="fas fa-clock me-1"></i><?= date('d/m/Y H:i', strtotime($a['assigned_at'])) ?></span>
                  </div>
                  <?php if ($a['notes']): ?><div class="assignment-notes"><?= nl2br(htmlspecialchars($a['notes'])) ?></div><?php endif; ?>
                  <?php if ($isAdmin && !$assignmentLocked): ?>
                  <div class="mt-2">
                    <form id="ftthUnassignTechForm-<?= (int)$a['technician_id'] ?>" method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/unassign')) ?>">
                      <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
                      <input type="hidden" name="technician_id" value="<?= (int)$a['technician_id'] ?>">
                      <input type="hidden" name="redirect_to" value="detail">
                      <button type="button" class="btn btn-outline-danger btn-sm js-ftth-confirm-trigger" data-ftth-confirm-form="ftthUnassignTechForm-<?= (int)$a['technician_id'] ?>" data-ftth-confirm-title="Retirer un technicien" data-ftth-confirm-message="Retirer ce technicien du ticket ?" data-ftth-confirm-button="Désassigner" data-ftth-confirm-button-class="btn-outline-danger"><i class="fas fa-user-minus me-1"></i>Désassigner</button>
                    </form>
                  </div>
                  <?php endif; ?>
                </div>
              </div>
              <?php endforeach; ?>
              <?php else: ?>
              <div class="text-center py-5 text-muted">
                <i class="fas fa-user-slash fa-2x mb-2 opacity-25"></i>
                <p class="small mb-0">Aucun technicien assigné.</p>
              </div>
              <?php endif; ?>
            </div>
          </div>
        </div>

        <?php if ($isAdmin): ?>
        <div class="col-12 col-lg-5">
          <div class="surface-card border-start border-4 border-warning">
            <div class="card-body">
              <?php if (empty($assignments)): ?>
              <h6 class="fw-bold mb-3"><i class="fas fa-user-plus text-warning me-2"></i>Assigner un technicien</h6>
              <form method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/assign')) ?>">
                <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
                <div class="mb-3">
                  <label class="form-label small fw-semibold">Technicien(s) <span class="text-danger">*</span></label>
                  <select name="technician_ids[]" class="form-select" multiple size="<?= min(7, max(3, count($technicians))) ?>" required>
                    <?php foreach ($technicians as $tech): ?>
                    <option value="<?= (int)$tech['id'] ?>"
                      <?php foreach ($assignments as $a): if ((int)$a['technician_id'] === (int)$tech['id']) echo 'selected'; endforeach; ?>>
                      <?= htmlspecialchars($tech['name']) ?>
                    </option>
                    <?php endforeach; ?>
                  </select>
                  <div class="form-text">Ctrl+clic pour sélection multiple</div>
                </div>
                <div class="mb-3">
                  <label class="form-label small fw-semibold">Notes / Instructions</label>
                  <textarea name="notes" class="form-control" rows="3" placeholder="Matériel à apporter, accès site…"></textarea>
                </div>
                <button type="submit" class="btn btn-warning w-100">
                  <i class="fas fa-paper-plane me-1"></i>Assigner & Notifier
                </button>
              </form>
              <?php elseif (!$assignmentLocked): ?>
              <h6 class="fw-bold mb-3"><i class="fas fa-user-minus text-danger me-2"></i>Désassigner le ticket</h6>
              <p class="small text-muted">Une nouvelle assignation n’est pas proposée tant que le ticket conserve une équipe terrain active.</p>
              <form id="ftthUnassignAllPanelForm" method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/unassign')) ?>">
                <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
                <input type="hidden" name="redirect_to" value="detail">
                <button type="button" class="btn btn-outline-danger w-100 js-ftth-confirm-trigger" data-ftth-confirm-form="ftthUnassignAllPanelForm" data-ftth-confirm-title="Désassigner le ticket" data-ftth-confirm-message="Retirer toutes les assignations de ce ticket ?" data-ftth-confirm-button="Désassigner" data-ftth-confirm-button-class="btn-outline-danger">
                  <i class="fas fa-user-minus me-1"></i>Désassigner tous les techniciens
                </button>
              </form>
              <?php endif; ?>
            </div>
          </div>
        </div>
        <?php endif; ?>
      </div>
    </div>

    <!-- ══════════════════════════════════════ TAB FICHE TERRAIN -->
    <div class="tab-pane fade" id="tabFiche">

    <?php if ($reportEditable): ?>
    <!-- ─────── FORMULAIRE SAISIE TERRAIN ─────── -->
    <form method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/report/save')) ?>"
          enctype="multipart/form-data" id="ficheForm">
      <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
      <input type="hidden" name="action_type" id="formActionType" value="draft">
      <input type="hidden" name="gps_lat" id="gpsLatInput">
      <input type="hidden" name="gps_lng" id="gpsLngInput">
      <input type="hidden" name="study_gps_lat" id="studyGpsLatInput" value="<?= htmlspecialchars($raccordementStudyLat) ?>">
      <input type="hidden" name="study_gps_lng" id="studyGpsLngInput" value="<?= htmlspecialchars($raccordementStudyLng) ?>">
      <input type="hidden" name="study_gps_accuracy_meters" id="studyGpsAccuracyInput" value="<?= htmlspecialchars($raccordementStudyAccuracy) ?>">
      <input type="hidden" name="recommended_otb_id" id="recommendedOtbIdInput" value="<?= (int)$raccordementRecommendedBoxId ?>">
      <input type="hidden" name="otb_distance_meters" id="otbDistanceInput" value="<?= htmlspecialchars((string)$raccordementDistanceMeters) ?>">
      <input type="hidden" name="otb_selection_mode" id="otbSelectionModeInput" value="<?= htmlspecialchars((string)($report['otb_selection_mode'] ?? 'auto')) ?>">
      <input type="hidden" name="client_signature_data" id="clientSigData">
      <input type="hidden" name="agent_signature_data" id="agentSigData">
      <input type="hidden" name="impacted_equipment" id="impactedEqInput" value="[]">
      <input type="hidden" name="materials_used" id="materialsInput" value="[]">

      <?php if ($lastReportSavedAt !== ''): ?>
      <div class="alert alert-light border d-flex align-items-center gap-2 mb-3">
        <i class="fas fa-clock-rotate-left text-info"></i>
        <div>
          <strong>Dernier enregistrement du formulaire</strong><br>
          <small class="text-muted"><?= htmlspecialchars($lastReportSavedAt) ?></small>
        </div>
      </div>
      <?php endif; ?>

      <?php if ($report && $report['status'] === 'rejeté'): ?>
      <div class="alert alert-danger d-flex align-items-center gap-2 mb-3">
        <i class="fas fa-times-circle fa-lg"></i>
        <div><strong>Rapport rejeté</strong> — <?= htmlspecialchars($report['rejection_reason'] ?? '') ?><br><small class="opacity-75">Corrigez et soumettez à nouveau.</small></div>
      </div>
      <?php endif; ?>

      <!-- En-tête fiche -->
      <div class="form-modern-shell mb-3">
        <div class="card-body p-3 p-lg-4">
          <div class="row g-3 align-items-end">
            <div class="col-12 col-lg-4">
              <label class="form-label">Type d'opération</label>
              <select name="operation_type" class="form-select input-soft">
                <?php foreach (['maintenance'=>'Maintenance','travaux'=>'Travaux','autres'=>'Autres'] as $v=>$l): ?>
                <option value="<?= $v ?>" <?= ($report['operation_type'] ?? 'maintenance') === $v ? 'selected' : '' ?>><?= $l ?></option>
                <?php endforeach; ?>
              </select>
            </div>
            <div class="col-12 col-lg-8">
              <div class="auto-meta-note">
                <i class="fas fa-stopwatch"></i>
                <div>
                  <div class="fw-semibold text-dark mb-1">Horodatage terrain automatisé</div>
                  <div class="small text-muted">La date et l'heure de début sont préremplies dès l'ouverture de la fiche. La fin d'intervention et le GPS sont ajoutés automatiquement lors de la soumission.</div>
                </div>
              </div>
            </div>
            <div class="col-12 col-md-4">
              <label class="form-label">Date d'intervention</label>
              <input type="date" name="intervention_date" id="interventionDateInput" class="form-control input-soft" value="<?= htmlspecialchars($displayInterventionDate) ?>" readonly>
            </div>
            <div class="col-6 col-md-4">
              <label class="form-label">Début d'intervention</label>
              <input type="time" name="intervention_start" id="interventionStartInput" class="form-control input-soft" value="<?= htmlspecialchars($displayInterventionStart) ?>" readonly>
            </div>
            <div class="col-6 col-md-4">
              <label class="form-label">Fin d'intervention</label>
              <input type="time" name="intervention_end" id="interventionEndInput" class="form-control input-soft" value="<?= htmlspecialchars($displayInterventionEnd) ?>" readonly>
            </div>
            <div class="col-12">
              <div class="alert alert-light border mb-0 small">
                <strong>Disponibilité client</strong> : si le client est absent ou demande un nouveau rendez-vous, renseignez l'étape 3 pour basculer le ticket en attente de planification avec un créneau proposé.
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Stepper tabs -->
      <div class="surface-card">
        <div class="card-header border-0 bg-transparent pt-3">
          <ul class="nav step-tabs gap-1 justify-content-center" id="stepsTab">
            <li class="nav-item"><button type="button" class="nav-link active" data-bs-toggle="tab" data-bs-target="#step1"><span class="step-num">1</span><?= $isRaccordementClients ? 'Étude' : 'Constat' ?></button></li>
            <li class="nav-item"><button type="button" class="nav-link"        data-bs-toggle="tab" data-bs-target="#step2"><span class="step-num">2</span><?= $isRaccordementClients ? 'Installation' : 'Intervention' ?></button></li>
            <li class="nav-item"><button type="button" class="nav-link"        data-bs-toggle="tab" data-bs-target="#step3"><span class="step-num">3</span>Appréciation</button></li>
            <li class="nav-item"><button type="button" class="nav-link"        data-bs-toggle="tab" data-bs-target="#step4"><span class="step-num">4</span>Signatures</button></li>
          </ul>
        </div>
        <div class="tab-content card-body">

          <!-- Étape 1 : Constat -->
          <div class="tab-pane fade show active" id="step1">
            <div class="constat-hero">
              <div class="constat-hero-copy">
                <h6><i class="fas fa-search-location text-primary me-2"></i><?= $isRaccordementClients ? 'Étude terrain et préparation du raccordement' : 'Constat terrain et qualification initiale' ?></h6>
                <p><?= $isRaccordementClients ? 'Validez la zone client, capturez une position précise à 4 mètres maximum, sélectionnez le meilleur OTB disponible et réservez un port avant transmission à l’équipe raccordement.' : 'Décrivez la situation observée sur site, identifiez les éléments impactés et rassemblez les premières preuves visuelles avant toute action corrective.' ?></p>
              </div>
              <div class="step-hero-badge"><i class="fas fa-compass"></i>Étape 1 sur 4</div>
            </div>

            <?php if ($isRaccordementClients): ?>
            <div class="row g-3 mb-4">
              <div class="col-12 col-xl-4">
                <section class="step-feature-card h-100">
                  <div class="step-feature-head">
                    <div class="step-feature-icon"><i class="fas fa-location-crosshairs"></i></div>
                    <div>
                      <strong>Localisation d'étude</strong>
                      <span>La transmission n'est possible qu'avec une précision GPS inférieure ou égale à 4 m.</span>
                    </div>
                  </div>
                  <div class="d-grid gap-2">
                    <button type="button" class="btn btn-outline-primary" id="captureStudyGpsBtn" <?= $raccordementStudyCanEdit ? '' : 'disabled' ?>>
                      <i class="fas fa-location-arrow me-1"></i>Ma position
                    </button>
                    <div class="alert alert-light border mb-0 small" id="studyGpsStatus">
                      <?php if ($raccordementStudyLat !== '' && $raccordementStudyLng !== ''): ?>
                        Position enregistrée, précision <?= htmlspecialchars($raccordementStudyAccuracy !== '' ? $raccordementStudyAccuracy . ' m' : 'non renseignée') ?>.
                      <?php else: ?>
                        Aucune position d'étude enregistrée pour le moment.
                      <?php endif; ?>
                    </div>
                    <div class="small text-muted" id="studyGpsCoords">
                      <?php if ($raccordementStudyLat !== '' && $raccordementStudyLng !== ''): ?>
                        <?= htmlspecialchars($raccordementStudyLat) ?>, <?= htmlspecialchars($raccordementStudyLng) ?>
                      <?php else: ?>
                        Coordonnées en attente.
                      <?php endif; ?>
                    </div>
                  </div>
                </section>
              </div>
              <div class="col-12 col-xl-4">
                <section class="step-feature-card h-100">
                  <div class="step-feature-head">
                    <div class="step-feature-icon"><i class="fas fa-network-wired"></i></div>
                    <div>
                      <strong>Sélection intelligente de l'OTB</strong>
                      <span>Zone client : <?= htmlspecialchars($raccordementZoneLabel) ?>. L'OTB recommandé est proposé automatiquement.</span>
                    </div>
                  </div>
                  <label class="form-label">Boîtier OTB</label>
                  <select name="selected_otb_id" id="selectedOtbIdInput" class="form-select input-soft" <?= $raccordementStudyCanEdit ? '' : 'disabled' ?>>
                    <option value="">Sélectionner un boîtier</option>
                    <?php foreach ($raccordementOtbCandidates as $candidateId => $candidateBox): ?>
                    <?php $candidateDistance = $candidateBox['distance_meters'] ?? null; ?>
                    <option value="<?= (int)$candidateId ?>"
                            data-distance="<?= htmlspecialchars((string)($candidateDistance ?? '')) ?>"
                            <?= $raccordementRecommendedBoxId === (int)$candidateId ? 'data-recommended="1"' : '' ?>
                            <?= $raccordementSelectedBoxId === (int)$candidateId ? 'selected' : '' ?>>
                      <?= htmlspecialchars((string)($candidateBox['box_code'] ?? ('OTB #' . $candidateId))) ?>
                      <?= !empty($candidateBox['box_name']) ? ' - ' . htmlspecialchars((string)$candidateBox['box_name']) : '' ?>
                    </option>
                    <?php endforeach; ?>
                  </select>
                  <div class="form-text" id="otbRecommendationHint">
                    <?php if (!empty($raccordementOtbRecommendation['recommended'])): ?>
                    Recommandation automatique : <?= htmlspecialchars((string)($raccordementOtbRecommendation['recommended']['box_code'] ?? 'OTB')) ?> à <?= htmlspecialchars((string)round((float)($raccordementOtbRecommendation['recommended']['distance_meters'] ?? 0))) ?> m.
                    <?php else: ?>
                    Aucun OTB recommandé automatiquement pour cette zone. Choisissez manuellement un boîtier actif.
                    <?php endif; ?>
                  </div>
                  <label class="form-label mt-3">Port actif à réserver</label>
                  <select name="selected_otb_port_number" id="selectedOtbPortInput" class="form-select input-soft" <?= $raccordementStudyCanEdit ? '' : 'disabled' ?>>
                    <option value="">Sélectionner un port</option>
                    <?php foreach ($raccordementPortOptions as $portOption): ?>
                    <?php
                      $portNumber = is_array($portOption) ? (int)($portOption['number'] ?? 0) : (int)$portOption;
                      if ($portNumber <= 0) {
                        continue;
                      }
                    ?>
                    <option value="<?= $portNumber ?>" <?= $raccordementSelectedPort === $portNumber ? 'selected' : '' ?>>Port <?= $portNumber ?></option>
                    <?php endforeach; ?>
                  </select>
                  <div class="form-text">Le port choisi passera au statut « Réservé » lors de la transmission.</div>
                </section>
              </div>
              <div class="col-12 col-xl-4">
                <section class="step-feature-card h-100">
                  <div class="step-feature-head">
                    <div class="step-feature-icon"><i class="fas fa-people-arrows"></i></div>
                    <div>
                      <strong>Transmission vers l'équipe terrain</strong>
                      <span><?= htmlspecialchars($raccordementTeamLabel) ?> prendra le relais pour les phases 2 à 4.</span>
                    </div>
                  </div>
                  <div class="alert <?= $isRaccordementStudyPhase ? 'alert-info' : 'alert-secondary' ?> mb-3">
                    <strong>Phase actuelle :</strong> <?= $isRaccordementStudyPhase ? 'Étude' : 'Installation / exécution' ?><br>
                    <span class="small">
                      <?php if ($raccordementStudyTechnician): ?>Étude : <?= htmlspecialchars((string)($raccordementStudyTechnician['name'] ?? '')) ?><br><?php endif; ?>
                      <?php if ($raccordementInstallationTechnician): ?>Installation : <?= htmlspecialchars((string)($raccordementInstallationTechnician['name'] ?? '')) ?><br><?php endif; ?>
                      Équipe cible : <?= htmlspecialchars($raccordementTeamLabel) ?>
                    </span>
                  </div>
                  <textarea name="study_dispatch_comment" class="form-control input-soft" rows="4" placeholder="Consignes pour l'équipe raccordement, contraintes d'accès, points de vigilance…" <?= $raccordementStudyCanEdit ? '' : 'readonly' ?>><?= htmlspecialchars($report['planning_comment'] ?? '') ?></textarea>
                  <div class="form-text">Le commentaire d'étude est transmis avec la réservation du port.</div>
                </section>
              </div>
            </div>
            <?php if ($isRaccordementInstallationPhase): ?>
            <div class="alert alert-success d-flex align-items-center gap-2 mb-4">
              <i class="fas fa-circle-check"></i>
              <div>L'étude a déjà été transmise. Le boîtier <?= htmlspecialchars((string)($raccordementSelectedBox['box_code'] ?? 'sélectionné')) ?> et le port <?= $raccordementSelectedPort > 0 ? (int)$raccordementSelectedPort : 'non renseigné' ?> sont réservés pour l'installation.</div>
            </div>
            <?php endif; ?>
            <?php endif; ?>

            <div class="constat-grid">
              <section class="step-feature-card">
                <div class="step-feature-head">
                  <div class="step-feature-icon"><i class="fas fa-clipboard"></i></div>
                  <div>
                    <strong>Constat terrain</strong>
                    <span>Décrivez l’état initial, les symptômes visibles et tout indice utile à l’analyse technique.</span>
                  </div>
                </div>
                <textarea name="constat_comments" class="form-control input-soft" rows="6" placeholder="Décrivez l'état constaté sur site…"><?= htmlspecialchars($report['constat_comments'] ?? '') ?></textarea>
                <div class="step-inline-hint"><i class="fas fa-lightbulb"></i><div>Précisez par exemple la perte de service, l’état du câblage, les alarmes visibles ou les constats côté client.</div></div>
              </section>

              <section class="step-feature-card">
                <div class="step-feature-head">
                  <div class="step-feature-icon"><i class="fas fa-plug"></i></div>
                  <div>
                    <strong>Équipements impactés</strong>
                    <span>Référencez les éléments réseau ou terminaux affectés pour faciliter l’analyse et la validation.</span>
                  </div>
                </div>
                <div id="eqList" class="mb-3"></div>
                <div class="input-group eq-input-shell">
                  <input type="text" id="eqInput" class="form-control input-soft" placeholder="Nom de l'équipement…" list="eqSuggestions">
                  <button type="button" class="btn btn-outline-primary" onclick="addEquipment()"><i class="fas fa-plus"></i></button>
                </div>
                <datalist id="eqSuggestions"></datalist>
              </section>
            </div>

            <section class="photo-stage-card">
              <div class="photo-stage-head">
                <div class="photo-stage-icon"><i class="fas fa-camera"></i></div>
                <div>
                  <strong>Photos de constat</strong>
                  <span>Capturez l’état initial. Les images déjà enregistrées restent consultables pour garder l’historique du diagnostic.</span>
                </div>
              </div>
              <input type="file" name="constat_photos[]" class="form-control input-soft" accept="image/*" multiple capture="environment">
              <div class="form-text mt-2">Sélection multiple autorisée. Les photos déjà enregistrées restent visibles ci-dessous.</div>
              <?php if (!empty($constatPhotos)): ?>
              <div class="existing-photo-grid mt-3">
                <?php foreach ($constatPhotos as $ph): ?>
                <div class="existing-photo-card">
                  <img src="<?= htmlspecialchars(upload_url('ftth/'.$ticket['id'].'/'.$ph['photo_path'])) ?>" onclick="lbShow(this.src)" alt="Photo constat">
                  <?php if (!empty($ph['comment'])): ?><div class="small text-muted"><?= nl2br(htmlspecialchars($ph['comment'])) ?></div><?php endif; ?>
                </div>
                <?php endforeach; ?>
              </div>
              <?php endif; ?>
            </section>
          </div>

          <!-- Étape 2 : Intervention -->
          <div class="tab-pane fade" id="step2">
            <div class="intervention-hero">
              <div class="intervention-hero-copy">
                <h6><i class="fas fa-toolbox text-primary me-2"></i><?= $isRaccordementClients ? 'Installation terrain et exécution du raccordement' : 'Exécution terrain et traçabilité de l’intervention' ?></h6>
                <p><?= $isRaccordementClients ? 'L’équipe raccordement intervient sur le boîtier et le port réservés, documente la réalisation et joint les preuves visuelles du raccordement effectué.' : 'Documentez les pièces utilisées, les actions réalisées et les preuves visuelles associées pour fiabiliser la restitution technique.' ?></p>
              </div>
              <div class="step-hero-badge"><i class="fas fa-screwdriver-wrench"></i>Étape 2 sur 4</div>
            </div>

            <?php if ($isRaccordementClients): ?>
            <div class="alert alert-light border d-flex flex-wrap gap-3 align-items-center mb-4">
              <div><strong>Boîtier réservé :</strong> <?= htmlspecialchars((string)($raccordementSelectedBox['box_code'] ?? 'Non défini')) ?></div>
              <div><strong>Port réservé :</strong> <?= $raccordementSelectedPort > 0 ? 'Port ' . (int)$raccordementSelectedPort : 'Non défini' ?></div>
              <div><strong>Statut :</strong> <?= $raccordementSelectedPortStatus === 'occupied' ? 'Occupé' : ($raccordementSelectedPortStatus === 'reserved' ? 'Réservé' : 'À définir') ?></div>
            </div>
            <?php endif; ?>

            <div class="intervention-grid">
              <section class="step-feature-card">
                <div class="step-feature-head">
                  <div class="step-feature-icon"><i class="fas fa-toolbox"></i></div>
                  <div>
                    <strong><?= $isRaccordementClients ? 'Ressources réservées pour le raccordement' : 'Matériaux et pièces utilisés' ?></strong>
                    <span><?= $isRaccordementClients ? 'Ces informations proviennent de l’étude. Elles restent verrouillées pendant l’installation pour garantir la cohérence de la réservation.' : 'Ajoutez les consommables, équipements ou remplacements effectués pendant l’intervention.' ?></span>
                  </div>
                </div>
                <?php if ($isRaccordementClients): ?>
                <div class="row g-2">
                  <div class="col-12 col-md-6">
                    <label class="form-label">Boîtier OTB</label>
                    <input type="text" class="form-control input-soft bg-light" value="<?= htmlspecialchars((string)($raccordementSelectedBox['box_code'] ?? '')) ?>" readonly>
                  </div>
                  <div class="col-12 col-md-6">
                    <label class="form-label">Port réservé</label>
                    <input type="text" class="form-control input-soft bg-light" value="<?= $raccordementSelectedPort > 0 ? 'Port ' . (int)$raccordementSelectedPort : '' ?>" readonly>
                  </div>
                </div>
                <div class="form-text mt-2">Le boîtier et le port réservés sont figés après transmission de l'étude.</div>
                <?php else: ?>
                <div id="matList" class="mb-3"></div>
                <div class="row g-2 material-input-shell">
                  <div class="col-6"><input type="text" id="matNameInput" class="form-control input-soft" placeholder="Désignation" list="matSuggestions"></div>
                  <div class="col-3"><input type="text" id="matQtyInput" class="form-control input-soft" placeholder="Qté"></div>
                  <div class="col-3"><button type="button" class="btn btn-outline-primary w-100 h-100" onclick="addMaterial()"><i class="fas fa-plus"></i></button></div>
                </div>
                <datalist id="matSuggestions"></datalist>
                <?php endif; ?>
              </section>

              <section class="step-feature-card">
                <div class="step-feature-head">
                  <div class="step-feature-icon"><i class="fas fa-notes-medical"></i></div>
                  <div>
                    <strong><?= $isRaccordementClients ? 'Rapport d\'installation' : 'Compte-rendu d\'intervention' ?></strong>
                    <span><?= $isRaccordementClients ? 'Décrivez le déroulé du raccordement, les vérifications réalisées et le résultat constaté en fin d’installation.' : 'Décrivez les opérations menées, les tests réalisés et le résultat observé après intervention.' ?></span>
                  </div>
                </div>
                <textarea name="general_comments" class="form-control input-soft" rows="7" placeholder="<?= $isRaccordementClients ? 'Déroulement de l\'installation, tests optiques, observations sur le branchement…' : 'Déroulement de l\'intervention…' ?>"><?= htmlspecialchars($report['general_comments'] ?? '') ?></textarea>
                <div class="step-inline-hint"><i class="fas fa-list-check"></i><div><?= $isRaccordementClients ? 'Précisez la méthode de raccordement, les tests de validation, les réserves éventuelles et l’état final du branchement.' : 'Indiquez les manipulations effectuées, les contrôles de continuité, les remplacements opérés et le résultat final obtenu.' ?></div></div>
              </section>
            </div>

            <section class="photo-stage-card">
              <div class="photo-stage-head">
                <div class="photo-stage-icon"><i class="fas fa-images"></i></div>
                <div>
                  <strong><?= $isRaccordementClients ? 'Photos de raccordement commentées' : 'Photos d\'intervention commentées' ?></strong>
                  <span><?= $isRaccordementClients ? 'Joignez les photos du raccordement réalisé. Chaque image peut être accompagnée d’un commentaire décrivant l’étape ou le résultat visible.' : 'Ajoutez les preuves visuelles de l’intervention. Un commentaire facultatif peut être associé à chaque image sélectionnée.' ?></span>
                </div>
              </div>
              <input type="file" name="interv_photos[]" id="intervPhotosInput" class="form-control input-soft" accept="image/*" multiple capture="environment">
              <div id="intervPhotoPreview" class="upload-preview-grid"></div>
              <?php if (!empty($interventionPhotos)): ?>
              <div class="mt-3">
                <div class="small text-muted fw-semibold mb-2 text-uppercase" style="letter-spacing:.06em">Photos déjà enregistrées</div>
                <div class="existing-photo-grid">
                  <?php foreach ($interventionPhotos as $ph): ?>
                  <div class="existing-photo-card">
                    <img src="<?= htmlspecialchars(upload_url('ftth/'.$ticket['id'].'/'.$ph['photo_path'])) ?>" onclick="lbShow(this.src)" alt="Photo intervention">
                    <?php if (!empty($ph['comment'])): ?><div class="small text-muted"><?= nl2br(htmlspecialchars($ph['comment'])) ?></div><?php else: ?><div class="small text-muted">Sans commentaire</div><?php endif; ?>
                  </div>
                  <?php endforeach; ?>
                </div>
              </div>
              <?php endif; ?>
            </section>
          </div>

          <!-- Étape 3 : Appréciation client -->
          <div class="tab-pane fade" id="step3">
            <div class="satisfaction-hero">
              <div class="satisfaction-hero-copy">
                <h6><i class="fas fa-face-smile text-warning me-2"></i>Retour client et restitution de service</h6>
                <p>Qualifiez l’expérience vécue par le client après l’intervention, confirmez l’état du service et conservez les remarques utiles pour la validation ou l’analyse qualité.</p>
              </div>
              <div class="satisfaction-hero-badge"><i class="fas fa-sparkles"></i>Étape 3 sur 4</div>
            </div>
            <?php
            $satGroups = [
              'satisfaction_service'  => ['Qualité du service', 'fa-star'],
              'satisfaction_delay'    => ['Délai d\'intervention', 'fa-clock'],
              'satisfaction_quality'  => ['Qualité du travail', 'fa-tools'],
              'satisfaction_behavior' => ['Comportement de l\'agent', 'fa-smile'],
            ];
            $satOptions = [
              'très_satisfait' => ['Très satisfait', 'success'],
              'satisfait'      => ['Satisfait', 'primary'],
              'peu_satisfait'  => ['Peu satisfait', 'warning'],
              'non_satisfait'  => ['Non satisfait', 'danger'],
            ];
            ?>
            <div class="satisfaction-grid">
              <?php foreach ($satGroups as $field => [$label, $icon]): ?>
              <section class="satisfaction-card">
                <div class="satisfaction-card-head">
                  <div class="satisfaction-card-icon"><i class="fas <?= $icon ?>"></i></div>
                  <div>
                    <strong><?= $label ?></strong>
                    <span>Sélectionnez l’évaluation qui correspond le mieux au ressenti formulé sur site.</span>
                  </div>
                </div>
                <div class="satisfaction-options">
                  <?php foreach ($satOptions as $val => [$opt, $col]): ?>
                  <div class="satisfaction-option">
                    <input type="radio" name="<?= $field ?>" id="<?= $field ?>_<?= $val ?>" value="<?= $val ?>"
                           <?= ($report[$field] ?? '') === $val ? 'checked' : '' ?>>
                    <label for="<?= $field ?>_<?= $val ?>"><?= $opt ?></label>
                  </div>
                  <?php endforeach; ?>
                </div>
              </section>
              <?php endforeach; ?>
            </div>

            <div class="satisfaction-side-grid">
              <section class="service-restore-card">
                <h6><i class="fas fa-signal me-2 text-success"></i><?= $isRaccordementClients ? 'État final de l\'installation' : 'État final du service' ?></h6>
                <p><?= $isRaccordementClients ? 'Indiquez si le client est finalement raccordé ou si l’installation n’a pas pu aboutir.' : 'Confirmez si le service est de nouveau opérationnel après l’intervention terrain.' ?></p>
                <div class="service-restore-toggle">
                  <div>
                    <input type="radio" name="service_restored" value="1" id="srOui" <?= ($report['service_restored'] ?? 0) ? 'checked' : '' ?>>
                    <label for="srOui"><?= $isRaccordementClients ? 'Raccordé' : 'Oui, service rétabli' ?></label>
                  </div>
                  <div>
                    <input type="radio" name="service_restored" value="0" id="srNon" <?= !($report['service_restored'] ?? 0) ? 'checked' : '' ?>>
                    <label for="srNon"><?= $isRaccordementClients ? 'Non raccordé' : 'Non, anomalie persistante' ?></label>
                  </div>
                </div>
              </section>

              <section class="client-remarks-card">
                <div class="client-identity-card">
                  <div class="client-identity-icon"><i class="fas fa-user-clock"></i></div>
                  <div>
                    <strong>Disponibilité du client</strong>
                    <span>Précisez si l'intervention a été réalisée, reportée faute de présence ou reprogrammée à la demande du client.</span>
                  </div>
                </div>
                <div class="satisfaction-options mt-3">
                  <?php foreach ($clientVisitStatusLabels as $value => $label): ?>
                  <div class="satisfaction-option">
                    <input type="radio" name="client_visit_status" id="clientVisitStatus_<?= htmlspecialchars($value) ?>" value="<?= htmlspecialchars($value) ?>" <?= $clientVisitStatus === $value ? 'checked' : '' ?>>
                    <label for="clientVisitStatus_<?= htmlspecialchars($value) ?>"><?= htmlspecialchars($label) ?></label>
                  </div>
                  <?php endforeach; ?>
                </div>
                <div class="row g-2 mt-2">
                  <div class="col-12 col-md-6">
                    <label class="form-label">Date de replanification</label>
                    <input type="date" name="planned_intervention_date" class="form-control input-soft" value="<?= htmlspecialchars((string)($report['planned_intervention_date'] ?? '')) ?>">
                  </div>
                  <div class="col-12 col-md-6">
                    <label class="form-label">Heure de replanification</label>
                    <input type="time" name="planned_intervention_time" class="form-control input-soft" value="<?= htmlspecialchars(!empty($report['planned_intervention_time']) ? substr((string)$report['planned_intervention_time'], 0, 5) : '') ?>">
                  </div>
                </div>
                <label class="form-label mt-3">Motif ou consigne de planification</label>
                <textarea name="planning_comment" class="form-control input-soft" rows="3" placeholder="Ex. client absent, accès au site indisponible, rappel souhaité demain matin…"><?= htmlspecialchars($report['planning_comment'] ?? '') ?></textarea>
              </section>

              <section class="client-remarks-card">
                <div class="client-identity-card">
                  <div class="client-identity-icon"><i class="fas fa-user-check"></i></div>
                  <div>
                    <strong>Client concerné</strong>
                    <span><?= htmlspecialchars($ticket['client_name'] ?? '') ?></span>
                  </div>
                </div>
                <h6><i class="fas fa-comment-dots me-2 text-primary"></i>Retour libre du client</h6>
                <p>Conservez ici les observations, réserves ou validations exprimées au moment de la restitution.</p>
                <input type="hidden" name="client_name_onsite" value="<?= htmlspecialchars($ticket['client_name'] ?? '') ?>">
                <textarea name="client_remarks" class="form-control input-soft" rows="5" placeholder="Ex. Le client confirme le retour du service, signale une amélioration partielle ou demande un suivi complémentaire."><?= htmlspecialchars($report['client_remarks'] ?? '') ?></textarea>
              </section>
            </div>
          </div>

          <!-- Étape 4 : Signatures + GPS -->
          <div class="tab-pane fade" id="step4">
            <div class="signature-hero">
              <div class="signature-hero-copy">
                <h6><i class="fas fa-signature text-primary me-2"></i>Signatures et preuve de présence</h6>
                <p>Finalisez la fiche avec les validations manuscrites et la position GPS de soumission afin de consolider la traçabilité de l’intervention.</p>
              </div>
              <div class="satisfaction-hero-badge"><i class="fas fa-shield-check"></i>Étape finale</div>
            </div>

            <div class="signature-grid">
              <section class="signature-card">
                <div class="signature-card-head">
                  <div class="signature-card-icon"><i class="fas fa-user-pen"></i></div>
                  <div>
                    <strong>Signature client</strong>
                    <span>Le client valide ici la restitution ou l’état constaté en fin d’intervention.</span>
                  </div>
                </div>
                <canvas id="clientSigCanvas" class="sig-canvas d-block"></canvas>
                <div class="signature-card-actions">
                  <button type="button" class="btn btn-outline-secondary btn-sm" onclick="clearSig('clientSigCanvas','clientSigData')"><i class="fas fa-eraser me-1"></i>Effacer</button>
                  <?php if ($report['client_signature_path'] ?? null): ?>
                  <small class="text-success align-self-center"><i class="fas fa-check me-1"></i>Signature existante conservée si non redessinée</small>
                  <?php endif; ?>
                </div>
              </section>

              <section class="signature-card">
                <div class="signature-card-head">
                  <div class="signature-card-icon"><i class="fas fa-user-gear"></i></div>
                  <div>
                    <strong>Signature agent terrain</strong>
                    <span>L’agent confirme l’exécution de l’intervention et la cohérence des informations renseignées.</span>
                  </div>
                </div>
                <canvas id="agentSigCanvas" class="sig-canvas d-block"></canvas>
                <div class="signature-card-actions">
                  <button type="button" class="btn btn-outline-secondary btn-sm" onclick="clearSig('agentSigCanvas','agentSigData')"><i class="fas fa-eraser me-1"></i>Effacer</button>
                </div>
              </section>
            </div>

            <section class="signature-gps-card">
              <div class="signature-gps-meta">
                <div>
                  <h6><i class="fas fa-location-crosshairs me-2 text-success"></i>Position GPS de soumission</h6>
                  <p>La géolocalisation est récupérée automatiquement juste avant l’envoi pour confirmer la présence terrain au moment de la clôture.</p>
                </div>
                <div class="signature-gps-pill"><i class="fas fa-satellite-dish"></i>Capture automatique</div>
              </div>
              <div class="gps-passive-card">
                <i class="fas fa-location-crosshairs"></i>
                <div>
                  <div class="fw-semibold text-dark mb-1">Détection automatique</div>
                  <div id="gpsStatus" class="small text-muted">Aucune action manuelle requise. La plateforme tentera de récupérer la position du technicien juste avant l'envoi.</div>
                </div>
              </div>
              <?php if ($report['submit_gps_lat'] ?? null): ?>
              <div class="small text-success mt-2"><i class="fas fa-check me-1"></i>GPS précédent : <?= round((float)$report['submit_gps_lat'],5) ?>, <?= round((float)$report['submit_gps_lng'],5) ?></div>
              <?php endif; ?>
            </section>
          </div>

        </div><!-- /tab-content -->

        <!-- Actions -->
        <div class="card-footer bg-transparent d-none d-lg-flex gap-2 flex-wrap justify-content-end border-top">
          <div class="me-auto submit-status js-submit-status"><?= $isRaccordementStudyPhase ? 'Le brouillon d’étude reste modifiable. La transmission réserve le port, fixe la phase Installation et réassigne le ticket.' : 'Brouillon possible à tout moment. La soumission ajoute automatiquement le GPS et l\'heure de fin.' ?></div>
          <div class="step-flow-actions me-lg-2">
            <button type="button" class="btn btn-outline-secondary js-step-prev" onclick="navigateFicheStep(-1)" disabled>
              <i class="fas fa-arrow-left me-1"></i>Précédent
            </button>
            <button type="button" class="btn btn-outline-primary js-step-next" onclick="navigateFicheStep(1)">
              Suivant<i class="fas fa-arrow-right ms-1"></i>
            </button>
          </div>
          <button type="button" class="btn btn-outline-secondary" onclick="submitFiche('draft')">
            <i class="fas fa-save me-1"></i>Enregistrer brouillon
          </button>
          <?php if ($isRaccordementStudyPhase): ?>
          <button type="button" class="btn btn-primary" onclick="submitFiche('handoff')" <?= $raccordementStudyCanEdit ? '' : 'disabled' ?>>
            <i class="fas fa-share-from-square me-1"></i>Transmettre à l'équipe raccordement
          </button>
          <?php endif; ?>
          <button type="button" class="btn btn-success js-step-submit" onclick="submitFiche('submit')" hidden>
            <i class="fas fa-paper-plane me-1"></i>Soumettre pour validation
          </button>
        </div>
      </div><!-- /card -->

      <div class="ftth-sticky-actions d-lg-none">
        <div class="d-grid gap-2">
          <div class="submit-status js-submit-status"><?= $isRaccordementStudyPhase ? 'Le brouillon d’étude peut être repris. La transmission réserve le port et passe la mission à l’équipe raccordement.' : 'Le GPS et l\'heure de fin seront ajoutés automatiquement à la soumission.' ?></div>
          <button type="button" class="btn btn-outline-secondary js-step-prev" onclick="navigateFicheStep(-1)" disabled>
            <i class="fas fa-arrow-left me-1"></i>Étape précédente
          </button>
          <button type="button" class="btn btn-outline-primary js-step-next" onclick="navigateFicheStep(1)">
            Étape suivante<i class="fas fa-arrow-right ms-1"></i>
          </button>
          <button type="button" class="btn btn-outline-secondary" onclick="submitFiche('draft')">
            <i class="fas fa-save me-1"></i>Enregistrer brouillon
          </button>
          <?php if ($isRaccordementStudyPhase): ?>
          <button type="button" class="btn btn-primary" onclick="submitFiche('handoff')" <?= $raccordementStudyCanEdit ? '' : 'disabled' ?>>
            <i class="fas fa-share-from-square me-1"></i>Transmettre à l'équipe raccordement
          </button>
          <?php endif; ?>
          <button type="button" class="btn btn-success js-step-submit" onclick="submitFiche('submit')" hidden>
            <i class="fas fa-paper-plane me-1"></i>Soumettre pour validation
          </button>
        </div>
      </div>
    </form>

    <?php elseif ($report): ?>
    <!-- ─────── LECTURE SEULE ─────── -->
    <?php
    $rpColor2 = ['brouillon'=>'secondary','soumis'=>'warning','validé'=>'success','rejeté'=>'danger'][$report['status']] ?? 'secondary';
    ?>
    <?php if ($lastReportSavedAt !== ''): ?>
    <div class="alert alert-light border d-flex align-items-center gap-2 mb-3">
      <i class="fas fa-clock-rotate-left text-info"></i>
      <div>
        <strong>Dernier enregistrement du formulaire</strong><br>
        <small class="text-muted"><?= htmlspecialchars($lastReportSavedAt) ?></small>
      </div>
    </div>
    <?php endif; ?>
    <div class="d-flex align-items-center gap-2 mb-3 flex-wrap">
      <span class="badge bg-<?= $rpColor2 ?> fs-6 py-2 px-3"><i class="fas fa-clipboard-check me-1"></i><?= ucfirst($report['status']) ?></span>
      <?php if ($report['submitted_at']): ?>
      <span class="text-muted small">Soumis le <?= date('d/m/Y H:i', strtotime($report['submitted_at'])) ?></span>
      <?php endif; ?>
      <?php if ($report['technician_name'] ?? null): ?>
      <span class="text-muted small">par <strong><?= htmlspecialchars($report['technician_name']) ?></strong></span>
      <?php endif; ?>
      <?php if ($isSuperv && $report['status'] === 'soumis'): ?>
      <div class="ms-auto d-flex gap-2">
        <form id="ftthValidateForm" method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/validate')) ?>">
          <input type="hidden" name="report_id" value="<?= (int)($report['report_id'] ?? $report['id'] ?? 0) ?>">
          <input type="hidden" name="action" value="validate">
          <button type="button" class="btn btn-success btn-sm" data-bs-toggle="modal" data-bs-target="#modalValidate">
            <i class="fas fa-check-double me-1"></i>Valider
          </button>
        </form>
        <button class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#modalReject">
          <i class="fas fa-times me-1"></i>Rejeter
        </button>
      </div>
      <?php elseif ($report['status'] === 'validé'): ?>
      <span class="ms-auto text-success small">
        <i class="fas fa-check-double me-1"></i>Validé par <?= htmlspecialchars($report['validated_by_name'] ?? '') ?> le <?= $report['validated_at'] ? date('d/m/Y', strtotime($report['validated_at'])) : '' ?>
      </span>
      <?php elseif ($report['status'] === 'rejeté'): ?>
      <div class="ms-auto">
        <span class="text-danger small"><i class="fas fa-times-circle me-1"></i><?= htmlspecialchars($report['rejection_reason'] ?? '') ?></span>
      </div>
      <?php endif; ?>
    </div>

    <!-- Résumé en-tête -->
    <div class="row g-2 mb-3">
      <div class="col-auto"><span class="badge bg-info fs-6"><?= ucfirst($report['operation_type']) ?></span></div>
      <div class="col-auto"><span class="badge bg-<?= $clientVisitStatusColor ?><?= in_array($clientVisitStatusColor, ['warning','info'], true) ? ' text-dark' : '' ?> fs-6 py-2 px-3"><i class="fas fa-user-clock me-1"></i><?= htmlspecialchars($clientVisitStatusLabel) ?></span></div>
      <?php if ($report['intervention_date']): ?>
      <div class="col-auto"><span class="badge bg-light text-dark border"><i class="fas fa-calendar me-1"></i><?= date('d/m/Y', strtotime($report['intervention_date'])) ?></span></div>
      <?php if ($report['intervention_start'] && $report['intervention_end']): ?>
      <div class="col-auto"><span class="badge bg-light text-dark border"><i class="fas fa-clock me-1"></i><?= substr($report['intervention_start'],0,5) ?> → <?= substr($report['intervention_end'],0,5) ?></span></div>
      <?php endif; ?>
      <?php endif; ?>
      <?php if ($plannedInterventionDisplay !== ''): ?>
      <div class="col-auto"><span class="badge bg-light text-dark border"><i class="fas fa-calendar-days me-1"></i><?= htmlspecialchars($plannedInterventionDisplay) ?></span></div>
      <?php endif; ?>
    </div>

    <!-- Onglets lecture -->
    <div class="surface-card">
      <div class="card-header border-0 bg-transparent pt-3 pb-0">
        <ul class="nav step-tabs gap-1 justify-content-center" id="readTabs">
          <li class="nav-item"><button type="button" class="nav-link active" data-bs-toggle="tab" data-bs-target="#rTab1"><span class="step-num">1</span>Constat</button></li>
          <li class="nav-item"><button type="button" class="nav-link"        data-bs-toggle="tab" data-bs-target="#rTab2"><span class="step-num">2</span>Intervention</button></li>
          <li class="nav-item"><button type="button" class="nav-link"        data-bs-toggle="tab" data-bs-target="#rTab3"><span class="step-num">3</span>Appréciation</button></li>
          <li class="nav-item"><button type="button" class="nav-link"        data-bs-toggle="tab" data-bs-target="#rTab4"><span class="step-num">4</span>Signatures & GPS</button></li>
        </ul>
      </div>
      <div class="tab-content card-body">

        <!-- Constat lecture -->
        <div class="tab-pane fade show active" id="rTab1">
          <?php if ($report['constat_comments']): ?>
          <div class="mb-3 p-3 bg-light rounded"><?= nl2br(htmlspecialchars($report['constat_comments'])) ?></div>
          <?php endif; ?>
          <?php if (!empty($equipItems)): ?>
          <div class="mb-3">
            <div class="small text-muted fw-semibold mb-2 text-uppercase" style="letter-spacing:.06em">Équipements</div>
            <div class="d-flex flex-wrap gap-2">
              <?php foreach ($equipItems as $eq): ?>
              <span class="badge bg-light text-dark border py-2 px-3"><i class="fas fa-plug text-warning me-1"></i><?= htmlspecialchars($eq['name'] ?? '') ?></span>
              <?php endforeach; ?>
            </div>
          </div>
          <?php endif; ?>
          <?php $cPhotos = array_values(array_filter($photos, fn($p) => $p['tab_type']==='constat')); ?>
          <?php if (!empty($cPhotos)): ?>
          <div>
            <div class="small text-muted fw-semibold mb-2 text-uppercase" style="letter-spacing:.06em">Photos</div>
            <div class="existing-photo-grid">
              <?php foreach ($cPhotos as $ph): ?>
              <div class="existing-photo-card">
                <img src="<?= htmlspecialchars(upload_url('ftth/'.$ticket['id'].'/'.$ph['photo_path'])) ?>"
                     class="photo-thumb" onclick="lbShow(this.src)" alt="">
                <?php if (!empty($ph['comment'])): ?><div class="small text-muted mt-2"><?= nl2br(htmlspecialchars($ph['comment'])) ?></div><?php endif; ?>
              </div>
              <?php endforeach; ?>
            </div>
          </div>
          <?php endif; ?>
          <?php if (!$report['constat_comments'] && empty($equipItems) && empty($cPhotos)): ?><p class="text-muted small mb-0">Aucun constat renseigné.</p><?php endif; ?>
        </div>

        <!-- Intervention lecture -->
        <div class="tab-pane fade" id="rTab2">
          <?php if (!empty($matItems)): ?>
          <div class="table-responsive mb-3">
            <table class="table table-sm table-hover mb-0">
              <thead class="table-light"><tr><th>Désignation</th><th>Qté</th></tr></thead>
              <tbody>
                <?php foreach ($matItems as $mat): ?>
                <tr><td><?= htmlspecialchars($mat['name'] ?? '') ?></td><td><?= htmlspecialchars($mat['qty'] ?? '—') ?></td></tr>
                <?php endforeach; ?>
              </tbody>
            </table>
          </div>
          <?php endif; ?>
          <?php if ($report['general_comments']): ?>
          <div class="p-3 bg-light rounded"><?= nl2br(htmlspecialchars($report['general_comments'])) ?></div>
          <?php endif; ?>
          <?php $iPhotos = array_values(array_filter($photos, fn($p) => $p['tab_type']==='intervention')); ?>
          <?php if (!empty($iPhotos)): ?>
          <div class="mt-3">
            <div class="small text-muted fw-semibold mb-2 text-uppercase" style="letter-spacing:.06em">Photos</div>
            <div class="existing-photo-grid">
              <?php foreach ($iPhotos as $ph): ?>
              <div class="existing-photo-card">
                <img src="<?= htmlspecialchars(upload_url('ftth/'.$ticket['id'].'/'.$ph['photo_path'])) ?>"
                     class="photo-thumb" onclick="lbShow(this.src)" alt="">
                <?php if (!empty($ph['comment'])): ?><div class="small text-muted mt-2"><?= nl2br(htmlspecialchars($ph['comment'])) ?></div><?php else: ?><div class="small text-muted mt-2">Sans commentaire</div><?php endif; ?>
              </div>
              <?php endforeach; ?>
            </div>
          </div>
          <?php endif; ?>
          <?php if (empty($matItems) && !$report['general_comments'] && empty($iPhotos)): ?><p class="text-muted small mb-0">Aucune intervention renseignée.</p><?php endif; ?>
        </div>

        <!-- Appréciation lecture -->
        <div class="tab-pane fade" id="rTab3">
          <div class="row g-2 mb-3">
            <?php
            $satDefs = ['satisfaction_service'=>'Service','satisfaction_delay'=>'Délai','satisfaction_quality'=>'Qualité','satisfaction_behavior'=>'Comportement'];
            $satColors = ['très_satisfait'=>'success','satisfait'=>'primary','peu_satisfait'=>'warning','non_satisfait'=>'danger'];
            foreach ($satDefs as $field => $label):
              $val = $report[$field] ?? '';
              $col = $satColors[$val] ?? 'secondary';
            ?>
            <div class="col-12 col-sm-6">
              <div class="d-flex justify-content-between align-items-center p-3 border rounded">
                <span class="small text-muted"><?= $label ?></span>
                <span class="badge bg-<?= $col ?>"><?= htmlspecialchars($satLabels[$val] ?? ($val ?: '—')) ?></span>
              </div>
            </div>
            <?php endforeach; ?>
          </div>
          <div class="d-flex gap-3 align-items-center flex-wrap">
            <span class="badge bg-<?= $report['service_restored'] ? 'success' : 'danger' ?> fs-6 py-2 px-3">
              <i class="fas fa-<?= $report['service_restored'] ? 'check' : 'times' ?>-circle me-1"></i>
              Service <?= $report['service_restored'] ? 'rétabli' : 'non rétabli' ?>
            </span>
            <span class="badge bg-<?= $clientVisitStatusColor ?><?= in_array($clientVisitStatusColor, ['warning','info'], true) ? ' text-dark' : '' ?> fs-6 py-2 px-3">
              <i class="fas fa-user-clock me-1"></i><?= htmlspecialchars($clientVisitStatusLabel) ?>
            </span>
            <?php if ($plannedInterventionDisplay !== ''): ?>
            <span class="text-muted small">Créneau proposé : <strong><?= htmlspecialchars($plannedInterventionDisplay) ?></strong></span>
            <?php endif; ?>
            <?php if ($report['client_name_onsite']): ?>
            <span class="text-muted small">Client : <strong><?= htmlspecialchars($report['client_name_onsite']) ?></strong></span>
            <?php endif; ?>
          </div>
          <?php if (!empty($report['planning_comment'])): ?>
          <div class="mt-3 p-3 border rounded bg-white small"><strong>Consigne de planification</strong><br><?= nl2br(htmlspecialchars($report['planning_comment'])) ?></div>
          <?php endif; ?>
          <?php if ($report['client_remarks']): ?>
          <div class="mt-3 p-3 bg-light rounded small"><?= nl2br(htmlspecialchars($report['client_remarks'])) ?></div>
          <?php endif; ?>
        </div>

        <!-- Signatures lecture -->
        <div class="tab-pane fade" id="rTab4">
          <div class="row g-3 mb-3">
            <div class="col-12 col-sm-6 text-center">
              <div class="small text-muted fw-semibold mb-2">Signature client</div>
              <?php if ($report['client_signature_path']): ?>
                  <img src="<?= htmlspecialchars(ftth_upload_url($ticket['id'] ?? 0, $report['client_signature_path'] ?? '')) ?>"
                   class="img-fluid border rounded" style="max-height:140px;background:#fff;cursor:zoom-in"
                   onclick="lbShow(this.src)">
              <?php else: ?><div class="text-muted small py-4 border rounded bg-light">Non fournie</div><?php endif; ?>
            </div>
            <div class="col-12 col-sm-6 text-center">
              <div class="small text-muted fw-semibold mb-2">Signature agent</div>
              <?php if ($report['agent_signature_path']): ?>
                  <img src="<?= htmlspecialchars(ftth_upload_url($ticket['id'] ?? 0, $report['agent_signature_path'] ?? '')) ?>"
                   class="img-fluid border rounded" style="max-height:140px;background:#fff;cursor:zoom-in"
                   onclick="lbShow(this.src)">
              <?php else: ?><div class="text-muted small py-4 border rounded bg-light">Non fournie</div><?php endif; ?>
            </div>
          </div>
          <?php if ($report['submit_gps_lat'] && $report['submit_gps_lng']): ?>
          <div class="small text-muted fw-semibold mb-2"><i class="fas fa-map-marker-alt text-danger me-1"></i>Position GPS de soumission</div>
          <div id="agentMap" style="height:200px;border-radius:8px;overflow:hidden"></div>
          <script>
          document.addEventListener('DOMContentLoaded', () => {
            if (typeof L === 'undefined') return;
            const m = L.map('agentMap').setView([<?= (float)$report['submit_gps_lat'] ?>, <?= (float)$report['submit_gps_lng'] ?>], 16);
            L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{attribution:'© OSM'}).addTo(m);
            L.marker([<?= (float)$report['submit_gps_lat'] ?>, <?= (float)$report['submit_gps_lng'] ?>]).addTo(m)
             .bindPopup('<?= addslashes($report['technician_name'] ?? 'Agent') ?>').openPopup();
          });
          </script>
          <?php endif; ?>
        </div>

      </div>
    </div>

    <?php else: ?>
    <!-- ─────── PAS DE FICHE ─────── -->
    <div class="surface-card border-start border-4 border-secondary">
      <div class="card-body py-5 text-center text-muted">
        <i class="fas fa-clipboard fa-3x mb-3 opacity-20"></i>
        <?php if (empty($assignments)): ?>
        <p class="mb-2 fw-semibold">Aucun technicien assigné.</p>
        <p class="small mb-3">Assignez d'abord un technicien depuis l'onglet Équipe.</p>
        <button class="btn btn-warning btn-sm" onclick="document.querySelector('[data-bs-target=\'#tabEquipe\']').click()">
          <i class="fas fa-user-plus me-1"></i>Aller à l'assignation
        </button>
        <?php else: ?>
        <p class="mb-2 fw-semibold"><?= $isRaccordementClients ? 'Le suivi terrain du raccordement n\'a pas encore été renseigné.' : 'La fiche terrain n\'a pas encore été renseignée.' ?></p>
        <p class="small mb-0"><?= $isRaccordementClients ? 'Le technicien peut saisir ce suivi depuis cette page ou depuis l\'application mobile.' : 'Le technicien peut la saisir depuis cette page (web) ou depuis l\'application mobile.' ?></p>
        <?php endif; ?>
      </div>
    </div>
    <?php endif; ?>

    </div><!-- /tabFiche -->

    <!-- ══════════════════════════════════════ TAB HISTORIQUE -->
    <div class="tab-pane fade" id="tabHistorique">
      <div class="surface-card">
        <div class="card-header border-0 bg-transparent pt-3 pb-0">
          <h6 class="fw-bold text-muted text-uppercase mb-0" style="font-size:.72rem;letter-spacing:.08em">
            <i class="fas fa-clock-rotate-left me-2 text-secondary"></i><?= $isRaccordementClients ? 'Historique du dossier' : 'Historique du ticket' ?>
          </h6>
        </div>
        <div class="card-body mt-2">
          <?php if (!empty($historyEvents)): ?>
          <div class="history-timeline">
            <?php foreach ($historyEvents as $event): ?>
            <div class="history-item tone-<?= htmlspecialchars($event['tone']) ?>">
              <div class="history-icon">
                <i class="fas fa-<?= htmlspecialchars($event['icon']) ?>"></i>
              </div>
              <div>
                <div class="history-date"><?= htmlspecialchars($event['date_label']) ?></div>
                <div class="history-title"><?= htmlspecialchars($event['title']) ?></div>
                <?php if (!empty($event['detail'])): ?>
                <div class="history-detail"><?= nl2br(htmlspecialchars((string)$event['detail'])) ?></div>
                <?php endif; ?>
              </div>
            </div>
            <?php endforeach; ?>
          </div>
          <?php else: ?>
          <div class="text-muted small">Aucun événement horodaté disponible pour ce <?= htmlspecialchars($moduleEntityLabel) ?>.</div>
          <?php endif; ?>
        </div>
      </div>
    </div>

  </div><!-- /tab-content principal -->
</div>
</section>

<?php if ($isAdmin && $isRaccordementClients): ?>
<div class="modal fade ftth-create-modal" id="modalEditRaccordementDetail" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <form method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/update')) ?>">
      <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
      <div class="modal-content">
        <div class="modal-header">
          <div class="modal-header-inner">
            <div>
              <div class="modal-kicker"><i class="fas fa-pen"></i>Modification</div>
              <h5 class="modal-title mt-3 mb-0">Modifier le raccordement</h5>
              <div class="modal-subtitle">Ajustez les champs clés RACCORDES du dossier courant.</div>
            </div>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
          </div>
        </div>
        <div class="modal-body">
          <div class="row g-3">
            <div class="col-12 col-lg-6">
              <div class="section-card"><div class="card-body"><div class="section-title"><i class="fas fa-id-card"></i><span>Entête RACCORDES</span></div><div class="row g-3">
                <div class="col-12 col-md-6"><label class="form-label">Référence dossier</label><input type="text" name="ref_code" class="form-control" value="<?= htmlspecialchars($raccordementEditData['ref_code']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Numéro abonnement</label><input type="text" name="client_code" class="form-control" value="<?= htmlspecialchars($raccordementEditData['client_code']) ?>"></div>
                <div class="col-12"><label class="form-label">Nom du client</label><input type="text" name="client_name" class="form-control" value="<?= htmlspecialchars($raccordementEditData['client_name']) ?>" required></div>
                <div class="col-12 col-md-6"><label class="form-label">Ville</label><input type="text" name="raccordement_city" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_city']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Commune</label><input type="text" name="raccordement_commune" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_commune']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Contact client 1</label><input type="text" name="client_phone" class="form-control" value="<?= htmlspecialchars($raccordementEditData['client_phone']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Contact client 2</label><input type="text" name="client_phone2" class="form-control" value="<?= htmlspecialchars($raccordementEditData['client_phone2']) ?>"></div>
                <div class="col-12"><label class="form-label">Localisation</label><textarea name="client_address" class="form-control" rows="3"><?= htmlspecialchars($raccordementEditData['client_address']) ?></textarea></div>
                <div class="col-12 col-md-6"><label class="form-label">Latitude_Terrain</label><input type="text" name="raccordement_latitude" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_latitude']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Longitude_Terrain</label><input type="text" name="raccordement_longitude" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_longitude']) ?>"></div>
              </div></div></div>
            </div>
            <div class="col-12 col-lg-6">
              <div class="section-card"><div class="card-body"><div class="section-title"><i class="fas fa-network-wired"></i><span>Repères et pilotage</span></div><div class="row g-3">
                <div class="col-12 col-md-4"><label class="form-label">PLAQUE</label><input type="text" name="sro_client" class="form-control" value="<?= htmlspecialchars($raccordementEditData['sro_client']) ?>"></div>
                <div class="col-12 col-md-4"><label class="form-label">JDV</label><input type="text" name="jdv_client" class="form-control" value="<?= htmlspecialchars($raccordementEditData['jdv_client']) ?>"></div>
                <div class="col-12 col-md-4"><label class="form-label">PCO</label><input type="text" name="pco_client" class="form-control" value="<?= htmlspecialchars($raccordementEditData['pco_client']) ?>"></div>
                <div class="col-12"><label class="form-label">EntrepriseFTTH</label><input type="text" name="company_name" class="form-control" value="<?= htmlspecialchars($raccordementEditData['company_name']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">SNONT</label><input type="text" name="raccordement_snont" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_snont']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">ND</label><input type="text" name="raccordement_nd" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_nd']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Date_Enregistrement_Instances</label><input type="date" name="raccordement_date_enregistrement" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_date_enregistrement']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Date_Envoi_Instances_Prestataires</label><input type="date" name="raccordement_date_envoi_prestataires" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_date_envoi_prestataires']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Duree_attente_j</label><input type="text" name="raccordement_duree_attente" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_duree_attente']) ?>"></div>
                <div class="col-12 col-md-6"><label class="form-label">Equipe_raccordement</label><input type="text" name="raccordement_team" class="form-control" value="<?= htmlspecialchars($raccordementEditData['raccordement_team']) ?>"></div>
                <div class="col-12 col-md-4"><label class="form-label">Avancement</label><input type="text" name="avancement" class="form-control" value="<?= htmlspecialchars($raccordementEditData['avancement']) ?>"></div>
                <div class="col-12 col-md-4"><label class="form-label">Priorité</label><select name="priority" class="form-select"><?php foreach (['Moyenne','Haute','Urgent','Basse'] as $priority): ?><option value="<?= htmlspecialchars($priority) ?>" <?= $raccordementEditData['priority'] === $priority ? 'selected' : '' ?>><?= htmlspecialchars($priority) ?></option><?php endforeach; ?></select></div>
                <div class="col-12 col-md-4"><label class="form-label">Statut</label><select name="status" class="form-select"><?php foreach (['nouveau','assigné','en_cours','attente_planification','traité','validé','clôturé'] as $statusOption): ?><option value="<?= htmlspecialchars($statusOption) ?>" <?= $raccordementEditData['status'] === $statusOption ? 'selected' : '' ?>><?= htmlspecialchars($statusOption === 'attente_planification' ? 'En attente de planification' : ucfirst($statusOption)) ?></option><?php endforeach; ?></select></div>
              </div></div></div>
            </div>
            <div class="col-12">
              <div class="section-card"><div class="card-body"><div class="section-title"><i class="fas fa-file-lines"></i><span>Commentaires et étude technique</span></div><div class="row g-3">
                <div class="col-12"><label class="form-label">Etude_Technique</label><textarea name="raccordement_etude_technique" class="form-control" rows="3"><?= htmlspecialchars($raccordementEditData['raccordement_etude_technique']) ?></textarea></div>
                <div class="col-12 col-lg-6"><label class="form-label">Commentaires</label><textarea name="description" class="form-control" rows="4"><?= htmlspecialchars($raccordementEditData['description']) ?></textarea></div>
                <div class="col-12 col-lg-6"><label class="form-label">Problèmes</label><textarea name="cause_comment" class="form-control" rows="4"><?= htmlspecialchars($raccordementEditData['cause_comment']) ?></textarea></div>
              </div></div></div>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <div class="footer-note me-auto">Les modifications sont enregistrées immédiatement et tracées dans l'historique du dossier.</div>
          <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Annuler</button>
          <button type="submit" class="btn btn-primary"><i class="fas fa-save me-1"></i>Enregistrer</button>
        </div>
      </div>
    </form>
  </div>
</div>

<div class="modal fade" id="modalPriorityRaccordementDetail" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-sm modal-dialog-centered">
    <form method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/requalify-priority')) ?>">
      <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
      <div class="modal-content">
        <div class="modal-header py-2">
          <h6 class="modal-title"><i class="fas fa-bolt me-2 text-danger"></i>Requalifier la criticité</h6>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
          <p class="small text-muted mb-3">Dossier : <strong><?= htmlspecialchars($heroClientDisplay) ?></strong></p>
          <label class="form-label small fw-semibold">Nouvelle criticité</label>
          <select name="priority" class="form-select" required>
            <?php foreach (['Basse','Moyenne','Haute','Urgent'] as $priority): ?>
            <option value="<?= htmlspecialchars($priority) ?>" <?= ($ticket['priority'] ?? '') === $priority ? 'selected' : '' ?>><?= htmlspecialchars($priority) ?></option>
            <?php endforeach; ?>
          </select>
        </div>
        <div class="modal-footer py-2">
          <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annuler</button>
          <button type="submit" class="btn btn-danger btn-sm"><i class="fas fa-bolt me-1"></i>Mettre à jour</button>
        </div>
      </div>
    </form>
  </div>
</div>
<?php endif; ?>

<!-- Modal Assign (depuis hero) -->
<?php if ($isAdmin && empty($assignments)): ?>
<div class="modal fade" id="modalAssignHero" tabindex="-1">
  <div class="modal-dialog modal-sm">
    <form method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/assign')) ?>">
      <input type="hidden" name="ticket_id" value="<?= (int)$ticket['id'] ?>">
      <div class="modal-content">
        <div class="modal-header py-2">
          <h6 class="modal-title"><i class="fas fa-user-plus text-warning me-2"></i>Assigner</h6>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
          <select name="technician_ids[]" class="form-select mb-2" multiple size="<?= min(6,max(3,count($technicians))) ?>" required>
            <?php foreach ($technicians as $tech): ?>
            <option value="<?= (int)$tech['id'] ?>"><?= htmlspecialchars($tech['name']) ?></option>
            <?php endforeach; ?>
          </select>
          <small class="text-muted d-block mb-2">Ctrl+clic pour sélection multiple</small>
          <textarea name="notes" class="form-control form-control-sm" rows="2" placeholder="Notes…"></textarea>
        </div>
        <div class="modal-footer py-2">
          <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annuler</button>
          <button type="submit" class="btn btn-warning btn-sm"><i class="fas fa-paper-plane me-1"></i>Assigner</button>
        </div>
      </div>
    </form>
  </div>
</div>
<?php endif; ?>

<!-- Modal Rejet -->
<?php if ($isSuperv && $report && $report['status'] === 'soumis'): ?>
<div class="modal fade" id="modalValidate" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered modal-sm">
    <div class="modal-content">
      <div class="modal-header py-2">
        <h6 class="modal-title text-success"><i class="fas fa-check-double me-1"></i>Valider le rapport</h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
      </div>
      <div class="modal-body">
        <p class="mb-0"><?= $isRaccordementClients ? 'Confirmer la validation de ce rapport de raccordement&nbsp;?' : 'Confirmer la validation de ce rapport FTTH&nbsp;?' ?></p>
      </div>
      <div class="modal-footer py-2">
        <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annuler</button>
        <button type="submit" form="ftthValidateForm" class="btn btn-success btn-sm">
          <i class="fas fa-check-double me-1"></i>Valider
        </button>
      </div>
    </div>
  </div>
</div>

<div class="modal fade" id="modalReject" tabindex="-1">
  <div class="modal-dialog modal-sm">
    <form method="POST" action="<?= htmlspecialchars(route_url($moduleBasePath . '/validate')) ?>">
      <input type="hidden" name="report_id" value="<?= (int)($report['report_id'] ?? $report['id'] ?? 0) ?>">
      <input type="hidden" name="action" value="reject">
      <div class="modal-content">
        <div class="modal-header py-2">
          <h6 class="modal-title text-danger"><i class="fas fa-times me-1"></i>Rejeter le rapport</h6>
          <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
        </div>
        <div class="modal-body">
          <textarea name="reason" class="form-control" rows="3" required placeholder="Motif du rejet…"></textarea>
        </div>
        <div class="modal-footer py-2">
          <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annuler</button>
          <button type="submit" class="btn btn-danger btn-sm"><i class="fas fa-times me-1"></i>Rejeter</button>
        </div>
      </div>
    </form>
  </div>
</div>
<?php endif; ?>

<div class="modal fade" id="modalFtthActionConfirm" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered modal-sm">
    <div class="modal-content">
      <div class="modal-header py-2">
        <h6 class="modal-title" id="modalFtthActionConfirmTitle"><i class="fas fa-circle-question me-1"></i>Confirmer l'action</h6>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
      </div>
      <div class="modal-body">
        <p class="mb-0" id="modalFtthActionConfirmMessage">Confirmer cette action ?</p>
      </div>
      <div class="modal-footer py-2">
        <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Annuler</button>
        <button type="button" class="btn btn-primary btn-sm" id="modalFtthActionConfirmButton">Confirmer</button>
      </div>
    </div>
  </div>
</div>

<!-- Lightbox -->
<div id="lb" onclick="this.style.display='none'">
  <img id="lbSrc" src="" style="max-width:94vw;max-height:94vh;border-radius:10px;box-shadow:0 8px 40px rgba(0,0,0,.6)">
</div>

<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>

<script>
const reportAutosaveUrl = <?= json_encode(route_url($moduleBasePath . '/report/autosave')) ?>;
const reportSuggestionsUrl = <?= json_encode(route_url($moduleBasePath . '/report/suggestions')) ?>;
const isRaccordementClientsView = <?= json_encode($isRaccordementClients) ?>;
const isRaccordementStudyPhaseView = <?= json_encode($isRaccordementStudyPhase) ?>;
const raccordementPortsByBox = <?= json_encode($raccordementPortsByBox, JSON_UNESCAPED_UNICODE) ?>;
const initialRecommendedOtbId = <?= json_encode($raccordementRecommendedBoxId) ?>;
const importedDistanceDisplayFallback = <?= json_encode((string)($importedDistanceField['value'] ?? ''), JSON_UNESCAPED_UNICODE) ?>;
const submitStatusDefaults = Array.from(document.querySelectorAll('.js-submit-status')).map((node) => node.textContent);
let autosaveTimer = null;
let autosaveFeedbackTimer = null;
let autosaveRequestSerial = 0;
let collectionsBootstrapped = false;

/* ── Lightbox ── */
function lbShow(src){ const lb=document.getElementById('lb'); document.getElementById('lbSrc').src=src; lb.style.display='flex'; }

/* ── Métadonnées automatiques ── */
function toLocalDate(date){ return date.toISOString().slice(0,10); }
function toLocalTime(date){ return date.toTimeString().slice(0,5); }

function ensureInterventionStartMeta(){
  const now = new Date();
  const dateInput = document.getElementById('interventionDateInput');
  const startInput = document.getElementById('interventionStartInput');
  if (dateInput && !dateInput.value) dateInput.value = toLocalDate(now);
  if (startInput && !startInput.value) startInput.value = toLocalTime(now);
}

function updateGpsStatus(message, variant='muted'){
  const st = document.getElementById('gpsStatus');
  if (!st) return;
  st.className = 'small';
  if (variant === 'success') st.classList.add('text-success');
  else if (variant === 'warning') st.classList.add('text-warning');
  else if (variant === 'info') st.classList.add('text-primary');
  else st.classList.add('text-muted');
  st.textContent = message;
}

function updateSubmitStatus(message, variant='busy'){
  document.querySelectorAll('.js-submit-status').forEach((node) => {
    node.textContent = message;
    node.classList.remove('is-busy', 'is-success', 'is-warning');
    if (variant === 'busy') node.classList.add('is-busy');
    if (variant === 'success') node.classList.add('is-success');
    if (variant === 'warning') node.classList.add('is-warning');
  });
}

function restoreSubmitStatus(){
  document.querySelectorAll('.js-submit-status').forEach((node, index) => {
    node.textContent = submitStatusDefaults[index] ?? '';
    node.classList.remove('is-busy', 'is-success', 'is-warning');
  });
}

const ficheStepTargets = ['#step1', '#step2', '#step3', '#step4'];

function getActiveFicheStepIndex(){
  const activeButton = document.querySelector('#stepsTab .nav-link.active');
  if (!activeButton) return 0;
  const target = activeButton.getAttribute('data-bs-target');
  const index = ficheStepTargets.indexOf(target);
  return index >= 0 ? index : 0;
}

function showFicheStepByIndex(index){
  const boundedIndex = Math.max(0, Math.min(index, ficheStepTargets.length - 1));
  const selector = ficheStepTargets[boundedIndex];
  const trigger = document.querySelector(`#stepsTab .nav-link[data-bs-target="${selector}"]`);
  if (!trigger) return;
  if (window.bootstrap?.Tab) {
    window.bootstrap.Tab.getOrCreateInstance(trigger).show();
  } else {
    trigger.click();
  }
}

function navigateFicheStep(direction){
  showFicheStepByIndex(getActiveFicheStepIndex() + direction);
}

function updateFicheStepActions(){
  const currentIndex = getActiveFicheStepIndex();
  const isLastStep = currentIndex === ficheStepTargets.length - 1;
  const isFirstStep = currentIndex === 0;

  document.querySelectorAll('.js-step-prev').forEach((button) => {
    button.disabled = isFirstStep;
  });

  document.querySelectorAll('.js-step-next').forEach((button) => {
    button.hidden = isLastStep;
  });

  document.querySelectorAll('.js-step-submit').forEach((button) => {
    button.hidden = !isLastStep || isRaccordementStudyPhaseView;
  });
}

function updateStudyGpsStatus(message, variant='muted'){
  const statusNode = document.getElementById('studyGpsStatus');
  if (!statusNode) return;
  statusNode.className = 'alert border mb-0 small';
  if (variant === 'success') statusNode.classList.add('alert-success');
  else if (variant === 'warning') statusNode.classList.add('alert-warning');
  else if (variant === 'info') statusNode.classList.add('alert-info');
  else statusNode.classList.add('alert-light');
  statusNode.textContent = message;
}

function formatOtbDistance(distance){
  const numericDistance = Number(distance || 0);
  if (!Number.isFinite(numericDistance) || numericDistance <= 0) {
    return 'Distance non disponible';
  }
  if (numericDistance >= 1000) {
    return `${(numericDistance / 1000).toFixed(2).replace('.', ',')} km`;
  }
  return `${Math.round(numericDistance)} m`;
}

function syncOtbDistanceDisplay(){
  const cardNode = document.getElementById('otbDistanceCard');
  const valueNode = document.getElementById('otbDistanceDisplay');
  if (!cardNode || !valueNode) return;

  const hiddenDistanceValue = document.getElementById('otbDistanceInput')?.value || '';
  let nextValue = '';

  if (Number.isFinite(Number(hiddenDistanceValue)) && Number(hiddenDistanceValue) > 0) {
    nextValue = formatOtbDistance(hiddenDistanceValue);
  } else {
    nextValue = String(importedDistanceDisplayFallback || '').trim();
  }

  if (nextValue === '') {
    cardNode.classList.add('d-none');
    valueNode.textContent = '';
    return;
  }

  cardNode.classList.remove('d-none');
  valueNode.textContent = nextValue;
}

function renderRaccordementPortOptions(selectedPort = null){
  const boxInput = document.getElementById('selectedOtbIdInput');
  const portInput = document.getElementById('selectedOtbPortInput');
  const distanceInput = document.getElementById('otbDistanceInput');
  const selectionModeInput = document.getElementById('otbSelectionModeInput');
  if (!boxInput || !portInput) return;

  const boxId = String(boxInput.value || '');
  const ports = Array.isArray(raccordementPortsByBox[boxId]) ? raccordementPortsByBox[boxId] : [];
  const selectedOption = boxInput.options[boxInput.selectedIndex] || null;
  const distance = selectedOption ? selectedOption.getAttribute('data-distance') || '' : '';
  const isRecommended = selectedOption ? selectedOption.hasAttribute('data-recommended') : false;

  portInput.innerHTML = '<option value="">Sélectionner un port</option>' + ports.map((portOption) => {
    const portValue = Number(typeof portOption === 'object' && portOption !== null ? portOption.number : portOption);
    if (!Number.isFinite(portValue) || portValue <= 0) {
      return '';
    }
    const isSelected = String(selectedPort ?? '') === String(portValue);
    return `<option value="${portValue}"${isSelected ? ' selected' : ''}>Port ${portValue}</option>`;
  }).join('');

  if (distanceInput) distanceInput.value = distance;
  if (selectionModeInput) selectionModeInput.value = isRecommended ? 'auto' : 'manual';
  syncOtbDistanceDisplay();
}

function captureStudyGps(){
  return new Promise((resolve) => {
    if (!navigator.geolocation) {
      updateStudyGpsStatus('La géolocalisation n\'est pas disponible sur cet appareil.', 'warning');
      resolve(false);
      return;
    }

    updateStudyGpsStatus('Recherche d\'une position précise en cours…', 'info');
    navigator.geolocation.getCurrentPosition(
      (position) => {
        const latitude = position.coords.latitude;
        const longitude = position.coords.longitude;
        const accuracy = Number(position.coords.accuracy || 0);
        document.getElementById('studyGpsLatInput').value = latitude;
        document.getElementById('studyGpsLngInput').value = longitude;
        document.getElementById('studyGpsAccuracyInput').value = accuracy ? accuracy.toFixed(1) : '';
        const coordsNode = document.getElementById('studyGpsCoords');
        if (coordsNode) {
          coordsNode.textContent = `${latitude.toFixed(6)}, ${longitude.toFixed(6)}`;
        }
        if (accuracy > 0 && accuracy <= 4) {
          updateStudyGpsStatus(`Position enregistrée avec une précision de ${accuracy.toFixed(1)} m.`, 'success');
          resolve(true);
          return;
        }
        updateStudyGpsStatus(`Position trouvée mais précision insuffisante (${accuracy.toFixed(1)} m). Recommencez jusqu'à obtenir 4 m maximum.`, 'warning');
        resolve(false);
      },
      () => {
        updateStudyGpsStatus('Impossible de récupérer la position d\'étude.', 'warning');
        resolve(false);
      },
      { enableHighAccuracy: true, timeout: 15000, maximumAge: 0 }
    );
  });
}

function updateRouteStatus(message, variant='default'){
  const node = document.getElementById('routeStatus');
  if (!node) return;
  node.textContent = message;
  node.classList.remove('is-success', 'is-warning');
  if (variant === 'success') node.classList.add('is-success');
  if (variant === 'warning') node.classList.add('is-warning');
}

function bindFtthConfirmButtons(){
  const modalEl = document.getElementById('modalFtthActionConfirm');
  const titleEl = document.getElementById('modalFtthActionConfirmTitle');
  const messageEl = document.getElementById('modalFtthActionConfirmMessage');
  const confirmBtn = document.getElementById('modalFtthActionConfirmButton');
  if (!modalEl || !titleEl || !messageEl || !confirmBtn) return;

  const modal = window.bootstrap?.Modal
    ? window.bootstrap.Modal.getOrCreateInstance(modalEl)
    : null;

  document.querySelectorAll('.js-ftth-confirm-trigger').forEach((button) => {
    button.addEventListener('click', () => {
      const formId = button.getAttribute('data-ftth-confirm-form') || '';
      const title = button.getAttribute('data-ftth-confirm-title') || 'Confirmer l\'action';
      const message = button.getAttribute('data-ftth-confirm-message') || 'Confirmer cette action ?';
      const actionLabel = button.getAttribute('data-ftth-confirm-button') || 'Confirmer';
      const actionClass = button.getAttribute('data-ftth-confirm-button-class') || 'btn-primary';
      const form = document.getElementById(formId);
      if (!form) return;

      titleEl.innerHTML = '<i class="fas fa-circle-question me-1"></i>' + title;
      messageEl.textContent = message;
      confirmBtn.textContent = actionLabel;
      confirmBtn.className = 'btn btn-sm ' + actionClass;
      confirmBtn.onclick = () => form.submit();

      if (modal) {
        modal.show();
        return;
      }

      form.submit();
    });
  });
}

function formatRouteDistance(meters){
  if (!Number.isFinite(meters)) return '-';
  return meters >= 1000 ? `${(meters / 1000).toFixed(1)} km` : `${Math.round(meters)} m`;
}

function formatRouteDuration(seconds){
  if (!Number.isFinite(seconds)) return '-';
  const totalMinutes = Math.round(seconds / 60);
  const hours = Math.floor(totalMinutes / 60);
  const minutes = totalMinutes % 60;
  if (hours > 0) return `${hours} h ${minutes.toString().padStart(2, '0')} min`;
  return `${minutes} min`;
}

document.addEventListener('DOMContentLoaded', () => {
  bindFtthConfirmButtons();

  document.querySelectorAll('.js-open-map-tab').forEach((trigger) => {
    trigger.addEventListener('click', () => {
      document.querySelector('[data-bs-target="#tabCarte"]')?.click();
    });
  });

  if (typeof L === 'undefined') return;

  const mapTabTrigger = document.querySelector('[data-bs-target="#tabCarte"]');
  const mapContainer = document.getElementById('clientMap');
  const startRouteBtn = document.getElementById('startRouteBtn');
  const centerDestinationBtn = document.getElementById('centerDestinationBtn');
  const routeSummary = document.getElementById('routeSummary');
  const distanceValue = document.getElementById('routeDistanceValue');
  const durationValue = document.getElementById('routeDurationValue');
  if (!mapTabTrigger || !mapContainer) return;

  const destination = [<?= json_encode($gpsMapLat) ?>, <?= json_encode($gpsMapLng) ?>];
  let mapInstance = null;
  let destinationMarker = null;
  let currentMarker = null;
  let routeLine = null;

  const ensureMap = () => {
    if (!mapInstance) {
      mapInstance = L.map('clientMap', { zoomControl: true }).setView(destination, 15);
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '© OSM'
      }).addTo(mapInstance);
      destinationMarker = L.marker(destination).addTo(mapInstance)
        .bindPopup('<strong><?= addslashes(htmlspecialchars($ticket['client_name'])) ?></strong><br><?= addslashes(htmlspecialchars($ticket['client_address'] ?? '')) ?>');
      destinationMarker.openPopup();
    }
    window.setTimeout(() => mapInstance.invalidateSize(), 220);
    return mapInstance;
  };

  const setRouteSummary = (distance, duration) => {
    if (!routeSummary || !distanceValue || !durationValue) return;
    distanceValue.textContent = formatRouteDistance(distance);
    durationValue.textContent = formatRouteDuration(duration);
    routeSummary.hidden = false;
  };

  const clearPreviousRoute = () => {
    if (routeLine && mapInstance) {
      mapInstance.removeLayer(routeLine);
      routeLine = null;
    }
    if (currentMarker && mapInstance) {
      mapInstance.removeLayer(currentMarker);
      currentMarker = null;
    }
  };

  const drawRoute = async (origin) => {
    const map = ensureMap();
    clearPreviousRoute();
    updateRouteStatus('Calcul de l\'itinéraire en cours…');
    try {
      const url = `https://router.project-osrm.org/route/v1/driving/${origin[1]},${origin[0]};${destination[1]},${destination[0]}?overview=full&geometries=geojson`;
      const response = await fetch(url);
      if (!response.ok) throw new Error('route_http');
      const data = await response.json();
      const route = data.routes && data.routes[0] ? data.routes[0] : null;
      if (!route || !route.geometry || !Array.isArray(route.geometry.coordinates)) throw new Error('route_empty');

      const latLngs = route.geometry.coordinates.map(([lng, lat]) => [lat, lng]);
      routeLine = L.polyline(latLngs, {
        color: '#1f7a8c',
        weight: 6,
        opacity: 0.85
      }).addTo(map);

      currentMarker = L.marker(origin).addTo(map)
        .bindPopup('Votre position actuelle');
      destinationMarker?.openPopup();
      map.fitBounds(L.latLngBounds(latLngs), { padding: [32, 32] });
      setRouteSummary(route.distance, route.duration);
      updateRouteStatus('Itinéraire tracé sur la carte. Vous restez dans l\'application pour suivre le chemin.', 'success');
    } catch (error) {
      updateRouteStatus('Impossible de calculer l\'itinéraire pour le moment. Vérifiez la connexion réseau et réessayez.', 'warning');
    }
  };

  mapTabTrigger.addEventListener('shown.bs.tab', ensureMap);

  centerDestinationBtn?.addEventListener('click', () => {
    const map = ensureMap();
    map.setView(destination, 15);
    destinationMarker?.openPopup();
  });

  startRouteBtn?.addEventListener('click', () => {
    if (!navigator.geolocation) {
      updateRouteStatus('La géolocalisation n\'est pas disponible sur cet appareil.', 'warning');
      return;
    }
    updateRouteStatus('Recherche de votre position actuelle…');
    navigator.geolocation.getCurrentPosition(
      (position) => {
        drawRoute([position.coords.latitude, position.coords.longitude]);
      },
      () => {
        updateRouteStatus('Accès à la position refusé ou indisponible. Impossible de démarrer l\'itinéraire.', 'warning');
      },
      { enableHighAccuracy: true, timeout: 12000, maximumAge: 30000 }
    );
  });
});

function detectGpsBeforeSubmit(){
  return new Promise((resolve) => {
    if (!navigator.geolocation) {
      updateGpsStatus('Géolocalisation indisponible. La fiche sera soumise sans position.', 'warning');
      resolve();
      return;
    }
    updateGpsStatus('Localisation en cours avant envoi…', 'info');
    navigator.geolocation.getCurrentPosition(
      (position) => {
        document.getElementById('gpsLatInput').value = position.coords.latitude;
        document.getElementById('gpsLngInput').value = position.coords.longitude;
        updateGpsStatus('Position détectée et jointe à la soumission.', 'success');
        resolve();
      },
      () => {
        updateGpsStatus('Position non récupérée. La fiche sera soumise sans GPS.', 'warning');
        resolve();
      },
      { enableHighAccuracy: true, timeout: 12000, maximumAge: 60000 }
    );
  });
}

/* ── Equipements ── */
let equipItems = <?= json_encode($equipItems, JSON_UNESCAPED_UNICODE) ?>;
function renderEq(shouldAutosave = true){
  const c=document.getElementById('eqList'); if(!c)return;
  c.innerHTML=equipItems.map((e,i)=>`
    <div class="d-flex align-items-center gap-2 mb-1 p-2 border rounded bg-light">
      <i class="fas fa-plug text-warning"></i>
      <span class="flex-fill small">${e.name}</span>
      <button type="button" class="btn btn-xs btn-outline-danger btn-sm py-0 px-1" onclick="equipItems.splice(${i},1);syncEq();renderEq()"><i class="fas fa-times"></i></button>
    </div>`).join('');
  document.getElementById('impactedEqInput').value=JSON.stringify(equipItems);
  if (shouldAutosave && collectionsBootstrapped) scheduleCollectionsAutosave();
}
function syncEq(){ document.getElementById('impactedEqInput').value=JSON.stringify(equipItems); }
function addEquipment(){
  const inp=document.getElementById('eqInput'); if(!inp.value.trim())return;
  equipItems.push({name:inp.value.trim()}); inp.value=''; renderEq();
}
document.getElementById('eqInput')?.addEventListener('keydown',e=>{if(e.key==='Enter'){e.preventDefault();addEquipment();}});
renderEq(false);

/* ── Matériaux ── */
let matItems = <?= json_encode($matItems, JSON_UNESCAPED_UNICODE) ?>;
function renderMat(shouldAutosave = true){
  const c=document.getElementById('matList'); if(!c)return;
  c.innerHTML=matItems.map((m,i)=>`
    <div class="d-flex align-items-center gap-2 mb-1 p-2 border rounded bg-light">
      <i class="fas fa-tools text-primary"></i>
      <span class="flex-fill small"><strong>${m.name}</strong>${m.qty?' × '+m.qty:''}</span>
      <button type="button" class="btn btn-sm btn-outline-danger py-0 px-1" onclick="matItems.splice(${i},1);syncMat();renderMat()"><i class="fas fa-times"></i></button>
    </div>`).join('');
  syncMat();
  if (shouldAutosave && collectionsBootstrapped) scheduleCollectionsAutosave();
}
function syncMat(){ document.getElementById('materialsInput').value=JSON.stringify(matItems); }
function addMaterial(){
  const n=document.getElementById('matNameInput'), q=document.getElementById('matQtyInput');
  if(!n.value.trim())return;
  matItems.push({name:n.value.trim(), qty:q.value.trim()}); n.value=''; q.value=''; renderMat();
}
['matNameInput','matQtyInput'].forEach((id) => {
  document.getElementById(id)?.addEventListener('keydown', (event) => {
    if (event.key === 'Enter') {
      event.preventDefault();
      addMaterial();
    }
  });
});
renderMat(false);

async function autosaveReportCollections(){
  const ticketInput = document.querySelector('#ficheForm input[name="ticket_id"]');
  if (!ticketInput || !reportAutosaveUrl) return;

  const requestSerial = ++autosaveRequestSerial;
  updateSubmitStatus('Enregistrement automatique des équipements et matériaux…', 'busy');

  try {
    const payload = new URLSearchParams();
    payload.set('ticket_id', ticketInput.value);
    payload.set('impacted_equipment', JSON.stringify(equipItems));
    payload.set('materials_used', JSON.stringify(matItems));

    const response = await fetch(reportAutosaveUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'X-Requested-With': 'XMLHttpRequest'
      },
      body: payload.toString()
    });
    const data = await response.json();
    if (!response.ok || !data.ok) {
      throw new Error(data?.error || 'autosave_failed');
    }
    if (requestSerial !== autosaveRequestSerial) return;

    updateSubmitStatus(`Listes auto-enregistrées à ${data.saved_at || ''}`.trim(), 'success');
    window.clearTimeout(autosaveFeedbackTimer);
    autosaveFeedbackTimer = window.setTimeout(restoreSubmitStatus, 2400);
  } catch (error) {
    if (requestSerial !== autosaveRequestSerial) return;
    updateSubmitStatus('Enregistrement automatique indisponible pour le moment.', 'warning');
  }
}

function scheduleCollectionsAutosave(){
  window.clearTimeout(autosaveTimer);
  autosaveTimer = window.setTimeout(autosaveReportCollections, 550);
}

function populateSuggestionList(listId, items){
  const datalist = document.getElementById(listId);
  if (!datalist) return;
  datalist.innerHTML = (items || []).map((item) => `<option value="${String(item).replace(/"/g, '&quot;')}"></option>`).join('');
}

const suggestionTimers = { equipment: null, material: null };
async function fetchSuggestionItems(kind, query, listId){
  const normalizedQuery = String(query || '').trim();
  if (normalizedQuery.length < 2) {
    populateSuggestionList(listId, []);
    return;
  }

  try {
    const response = await fetch(`${reportSuggestionsUrl}?kind=${encodeURIComponent(kind)}&q=${encodeURIComponent(normalizedQuery)}`, {
      headers: { 'X-Requested-With': 'XMLHttpRequest' }
    });
    const data = await response.json();
    if (!response.ok || !data.ok) {
      throw new Error(data?.error || 'suggestions_failed');
    }
    populateSuggestionList(listId, data.items || []);
  } catch (error) {
    populateSuggestionList(listId, []);
  }
}

function bindSuggestionInput(inputId, kind, listId){
  const input = document.getElementById(inputId);
  if (!input) return;
  input.addEventListener('input', () => {
    window.clearTimeout(suggestionTimers[kind]);
    suggestionTimers[kind] = window.setTimeout(() => fetchSuggestionItems(kind, input.value, listId), 220);
  });
}

bindSuggestionInput('eqInput', 'equipment', 'eqSuggestions');
bindSuggestionInput('matNameInput', 'material', 'matSuggestions');
collectionsBootstrapped = true;

document.getElementById('captureStudyGpsBtn')?.addEventListener('click', () => {
  captureStudyGps();
});

document.getElementById('selectedOtbIdInput')?.addEventListener('change', (event) => {
  renderRaccordementPortOptions();
  const recommendedInput = document.getElementById('recommendedOtbIdInput');
  if (recommendedInput && !recommendedInput.value) {
    recommendedInput.value = String(initialRecommendedOtbId || '');
  }
});

renderRaccordementPortOptions(<?= json_encode($raccordementSelectedPort) ?>);

document.querySelectorAll('#stepsTab .nav-link').forEach((button) => {
  button.addEventListener('shown.bs.tab', updateFicheStepActions);
});
updateFicheStepActions();

/* ── Photos d'intervention avec commentaire ── */
function renderInterventionPhotoPreview(){
  const input = document.getElementById('intervPhotosInput');
  const container = document.getElementById('intervPhotoPreview');
  if (!input || !container) return;
  const files = Array.from(input.files || []);
  if (!files.length) {
    container.innerHTML = '';
    return;
  }

  container.innerHTML = files.map((file, index) => {
    const previewUrl = URL.createObjectURL(file);
    const safeName = String(file.name || 'photo');
    return `
      <div class="upload-preview-card">
        <img src="${previewUrl}" alt="${safeName}" class="upload-preview-thumb">
        <div class="small fw-semibold text-dark mb-2">${safeName}</div>
        <input type="hidden" name="interv_photo_item_index[]" value="${index}">
        <label class="form-label mb-2">Commentaire optionnel</label>
        <textarea name="interv_photo_comments[]" class="form-control input-soft" placeholder="Ex. remplacement PTO, soudure validée, mesure conforme…"></textarea>
      </div>`;
  }).join('');
}
document.getElementById('intervPhotosInput')?.addEventListener('change', renderInterventionPhotoPreview);

/* ── Canvas signatures ── */
function initCanvas(id, hiddenId){
  const canvas=document.getElementById(id); if(!canvas)return;
  const ctx=canvas.getContext('2d');
  canvas.width=canvas.offsetWidth; canvas.height=canvas.offsetHeight;
  let drawing=false, last={x:0,y:0};
  function getPos(e){ const r=canvas.getBoundingClientRect(),src=e.touches?e.touches[0]:e; return{x:src.clientX-r.left,y:src.clientY-r.top}; }
  function start(e){ drawing=true; last=getPos(e); }
  function move(e){ if(!drawing)return; e.preventDefault(); const p=getPos(e); ctx.beginPath();ctx.moveTo(last.x,last.y);ctx.lineTo(p.x,p.y);ctx.strokeStyle='#1a3a5c';ctx.lineWidth=2.5;ctx.lineCap='round';ctx.stroke();last=p; canvas.classList.add('has-data'); }
  function stop(){ drawing=false; document.getElementById(hiddenId).value=canvas.toDataURL('image/png'); }
  canvas.addEventListener('mousedown',start); canvas.addEventListener('mousemove',move); canvas.addEventListener('mouseup',stop);
  canvas.addEventListener('touchstart',start,{passive:true}); canvas.addEventListener('touchmove',move,{passive:false}); canvas.addEventListener('touchend',stop);
}
function clearSig(id,hiddenId){ const c=document.getElementById(id); if(!c)return; c.getContext('2d').clearRect(0,0,c.width,c.height); c.classList.remove('has-data'); document.getElementById(hiddenId).value=''; }
initCanvas('clientSigCanvas','clientSigData');
initCanvas('agentSigCanvas','agentSigData');
ensureInterventionStartMeta();

/* ── Soumission ── */
let ficheSubmitLock = false;
async function submitFiche(action){
  if (ficheSubmitLock) return;
  ensureInterventionStartMeta();
  const endInput = document.getElementById('interventionEndInput');
  document.getElementById('formActionType').value=action;
  if ((action === 'submit' || action === 'handoff') && endInput) {
    endInput.value = toLocalTime(new Date());
  }

  if (action === 'handoff') {
    const selectedOtb = document.getElementById('selectedOtbIdInput')?.value || '';
    const selectedPort = document.getElementById('selectedOtbPortInput')?.value || '';
    let accuracy = Number(document.getElementById('studyGpsAccuracyInput')?.value || 0);
    if (!selectedOtb) {
      updateStudyGpsStatus('Sélectionnez un boîtier OTB avant la transmission.', 'warning');
      return;
    }
    if (!selectedPort) {
      updateStudyGpsStatus('Sélectionnez un port actif à réserver avant la transmission.', 'warning');
      return;
    }
    if (!(accuracy > 0 && accuracy <= 4)) {
      const ok = await captureStudyGps();
      accuracy = Number(document.getElementById('studyGpsAccuracyInput')?.value || 0);
      if (!ok || !(accuracy > 0 && accuracy <= 4)) {
        return;
      }
    }
  }

  ficheSubmitLock = true;
  document.querySelectorAll('button[onclick*="submitFiche"]').forEach((button) => { button.disabled = true; });
  updateSubmitStatus(action === 'submit' ? 'Préparation de la soumission terrain…' : (action === 'handoff' ? 'Transmission de l\'étude en cours…' : 'Enregistrement du brouillon en cours…'), 'busy');
  if (action === 'submit') {
    await detectGpsBeforeSubmit();
    updateSubmitStatus('Soumission en cours…', 'success');
  } else if (action === 'handoff') {
    updateSubmitStatus('Réservation du port et réaffectation en cours…', 'success');
  }
  document.getElementById('ficheForm').submit();
}
</script>
