<script setup>
import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
import { useAuthStore } from 'src/stores/auth'
import { useDispatchStore } from 'src/stores/dispatch'
import { fetchTechnicians } from 'src/api/dispatch'
import { createEquipmentInstall } from 'src/api/service-request'

const auth     = useAuthStore()
const store    = useDispatchStore()

// ── UI state ────────────────────────────────────────────────────────────────
const phase         = ref('loading')  // 'loading' | 'login' | 'select-tech' | 'jobs'
const tab           = ref('jobs')     // 'jobs' | 'equipment' | 'map' | 'profile'
const showCompleted = ref(false)
const showToast     = ref(false)
const toastMsg      = ref('')
const detailJob     = ref(null)

// Login form
const loginUser  = ref('')
const loginPass  = ref('')
const showPwd    = ref(false)

// Tech selector
const techList   = ref([])
const selTechId  = ref('')
const selTech    = computed(() => techList.value.find(t => t.name === selTechId.value) || null)
const techName   = computed(() => selTech.value?.fullName || selTech.value?.name || '')

const COLORS     = ['#6366f1','#10b981','#f59e0b','#8b5cf6','#06b6d4','#f43f5e','#f97316','#14b8a6']
const techColor  = computed(() => {
  const idx = techList.value.indexOf(selTech.value)
  return COLORS[idx >= 0 ? idx % COLORS.length : 0]
})
const initials   = computed(() =>
  (techName.value || 'T').split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2)
)
const today      = computed(() =>
  new Date().toLocaleDateString('fr-FR', { weekday: 'long', day: 'numeric', month: 'long' })
)

// ── Job lists ────────────────────────────────────────────────────────────────
const myJobs       = computed(() => store.jobs)
const activeJob    = computed(() => myJobs.value.find(j => j.status === 'in_progress') || null)
const upcomingJobs = computed(() =>
  myJobs.value.filter(j => !j.completed && j.status !== 'in_progress' && j.status !== 'completed')
    .sort((a, b) => (a.routeOrder || 99) - (b.routeOrder || 99))
)
const completedJobs = computed(() => myJobs.value.filter(j => j.status === 'completed'))
const stats = computed(() => [
  { lbl: 'Total',   val: myJobs.value.length },
  { lbl: 'A faire', val: upcomingJobs.value.length + (activeJob.value ? 1 : 0) },
  { lbl: 'Faits',   val: completedJobs.value.length },
])

// ── Auth + boot ──────────────────────────────────────────────────────────────
async function loadTechs () {
  const raw = await fetchTechnicians()
  techList.value = raw.map((t, idx) => ({
    name:     t.name,
    fullName: t.full_name || t.name,
    techId:   t.technician_id || t.name,
    user:     t.user || null,
    colorIdx: idx,
  }))
  const linked = techList.value.find(t => t.user === auth.user)
  selTechId.value = linked ? linked.name : (techList.value[0]?.name || '')
}

async function boot () {
  await auth.checkSession()
  if (auth.user) {
    loginUser.value = auth.user
    await loadTechs()
    phase.value = 'select-tech'
  } else {
    phase.value = 'login'
  }
}

async function doLogin () {
  await auth.doLogin(loginUser.value, loginPass.value)
  if (auth.user) {
    await loadTechs()
    phase.value = 'select-tech'
  }
}

async function doLogout () {
  await auth.doLogout()
  store.jobs = []
  selTechId.value = ''
  phase.value = 'login'
}

async function loadJobs () {
  if (!selTechId.value || !selTech.value) return
  await store.loadJobsForTech(selTech.value.techId)
  phase.value = 'jobs'
}

// ── Actions ──────────────────────────────────────────────────────────────────
async function markComplete (job) {
  if (!job || job.status === 'completed') return
  await store.setJobStatus(job.id, 'completed')
  job.status = 'completed'
  toast(job.id + ' complété !')
}

async function markEnRoute (job) {
  if (!job) return
  myJobs.value.forEach(j => { if (j.status === 'in_progress') j.status = 'assigned' })
  await store.setJobStatus(job.id, 'in_progress')
  job.status = 'in_progress'
  detailJob.value = null
  toast('En route vers ' + job.id)
}

function toast (msg) {
  toastMsg.value = msg
  showToast.value = true
  setTimeout(() => { showToast.value = false }, 2800)
}

function startTime (idx) {
  let m = 8 * 60
  if (activeJob.value) {
    m += (parseInt(activeJob.value.legDur) || 0) + (parseFloat(activeJob.value.duration) || 1) * 60
  }
  for (let i = 0; i < idx; i++) {
    const j = upcomingJobs.value[i]
    m += (parseInt(j.legDur) || 0) + (parseFloat(j.duration) || 1) * 60
  }
  m += parseInt(upcomingJobs.value[idx]?.legDur) || 0
  return String(Math.floor(m / 60)).padStart(2, '0') + 'h' + String(m % 60).padStart(2, '0')
}

function prioLbl  (p) { return { high: 'Urgent', medium: 'Moyen', low: 'Faible' }[p] || p }
function prioStyle (p) {
  return {
    high:   'background:#fef2f2;color:#dc2626',
    medium: 'background:#fffbeb;color:#d97706',
    low:    'background:#f0fdf4;color:#16a34a',
  }[p] || ''
}
function mapsUrl (addr) { return 'https://maps.google.com/?q=' + encodeURIComponent(addr) }

// ── Equipment / Barcode ───────────────────────────────────────────────────────
const EQUIPMENT_TYPES = ['Modem', 'Routeur', 'Décodeur TV', 'Téléphone IP', 'Câble coaxial', 'Amplificateur', 'Splitter', 'ONT/ONU', 'Autre']

const eqRequestName = ref('')           // which service request we're working on
const eqItems       = ref([])           // array of equipment items to submit
const eqSubmitting  = ref(false)
const eqDone        = ref(false)
const scannerActive = ref(false)
let   _scanner      = null

const eqJobs = computed(() =>
  myJobs.value.filter(j => j.status !== 'completed')
)

function newEqItem (barcode = '') {
  return { barcode, equipment_type: 'Modem', brand: '', model: '', notes: '', photo_base64: '', _id: Date.now() + Math.random() }
}

function addEqItem () {
  eqItems.value.push(newEqItem())
}

function removeEqItem (item) {
  eqItems.value = eqItems.value.filter(e => e._id !== item._id)
}

async function startScanner () {
  scannerActive.value = true
  await nextTick()
  try {
    const { Html5Qrcode } = await import('html5-qrcode')
    _scanner = new Html5Qrcode('qr-reader')
    await _scanner.start(
      { facingMode: 'environment' },
      { fps: 10, qrbox: { width: 260, height: 80 } },
      (decoded) => {
        stopScanner()
        const existing = eqItems.value.find(e => e.barcode === decoded)
        if (!existing) {
          eqItems.value.push(newEqItem(decoded))
          toast('Scanné : ' + decoded)
        } else {
          toast('Déjà dans la liste')
        }
      },
      () => {}
    )
  } catch (e) {
    scannerActive.value = false
    toast('Caméra non disponible')
  }
}

async function stopScanner () {
  if (_scanner) {
    await _scanner.stop().catch(() => {})
    _scanner = null
  }
  scannerActive.value = false
}

function onPhotoChange (item, event) {
  const file = event.target.files[0]
  if (!file) return
  const reader = new FileReader()
  reader.onload = e => { item.photo_base64 = e.target.result }
  reader.readAsDataURL(file)
}

async function submitEquipment () {
  if (!eqRequestName.value || eqItems.value.length === 0) return
  eqSubmitting.value = true
  try {
    for (const item of eqItems.value) {
      await createEquipmentInstall({
        request:        eqRequestName.value,
        barcode:        item.barcode,
        equipment_type: item.equipment_type,
        brand:          item.brand,
        model:          item.model,
        notes:          item.notes,
        photo_base64:   item.photo_base64,
      })
    }
    const count = eqItems.value.length
    eqItems.value = []
    eqDone.value = true
    toast(count + ' équipement(s) enregistré(s)')
  } catch {
    toast('Erreur lors de la soumission')
  } finally {
    eqSubmitting.value = false
  }
}

onUnmounted(() => { stopScanner() })

onMounted(boot)
</script>

<template>
<div class="mobile-app">

  <!-- Header -->
  <div class="app-header">
    <div class="app-header-bar">
      <div>
        <div class="app-header-sub">{{ today }}</div>
        <div class="app-header-title">
          <span v-if="phase === 'jobs'">{{ techName }}</span>
          <span v-else-if="phase === 'select-tech'">Choisir un technicien</span>
          <span v-else>Dispatch Mobile</span>
        </div>
      </div>
      <div style="display:flex;align-items:center;gap:0.5rem;">
        <span :class="auth.user ? 'badge badge-online' : 'badge badge-offline'">
          {{ auth.user ? 'En ligne' : 'Hors ligne' }}
        </span>
        <button v-if="phase === 'jobs'" class="btn-icon"
                @click="phase = 'select-tech'" title="Changer de tech">&#8646;</button>
        <div v-if="phase === 'jobs'" class="avatar" :style="'background:' + techColor">
          {{ initials }}
        </div>
      </div>
    </div>
    <div v-if="phase === 'jobs'" class="stats-strip">
      <div v-for="s in stats" :key="s.lbl" class="stat-box">
        <div class="stat-val">{{ s.val }}</div>
        <div class="stat-lbl">{{ s.lbl }}</div>
      </div>
    </div>
  </div>

  <!-- Content -->
  <div class="app-content">

    <!-- Loading -->
    <div v-if="phase === 'loading'" style="display:flex;flex-direction:column;align-items:center;padding:3rem 1rem;gap:1rem;">
      <div class="spinner"></div>
      <div style="color:#94a3b8;font-size:0.88rem;">Chargement...</div>
    </div>

    <!-- Login -->
    <div v-else-if="phase === 'login'" class="login-wrap">
      <div class="login-hero">
        <div class="login-icon">&#9889;</div>
        <div style="font-size:1.2rem;font-weight:700;color:#1e293b;">Connexion ERPNext</div>
        <div style="color:#64748b;font-size:0.82rem;margin-top:0.3rem;">Entrez vos identifiants pour continuer</div>
      </div>
      <div class="login-card">
        <label class="field-label">Utilisateur (email)</label>
        <input v-model="loginUser" type="email" placeholder="admin@example.com"
               class="field-input" :class="{ err: !!auth.error }" @keyup.enter="doLogin" />
        <label class="field-label">Mot de passe</label>
        <input v-model="loginPass" :type="showPwd ? 'text' : 'password'" placeholder="••••••••"
               class="field-input" :class="{ err: !!auth.error }" @keyup.enter="doLogin" />
        <div v-if="auth.error" class="error-msg">{{ auth.error }}</div>
        <label class="show-pwd">
          <input type="checkbox" v-model="showPwd" /> Afficher le mot de passe
        </label>
        <button class="btn-primary"
                :disabled="!loginUser || !loginPass || auth.loading"
                @click="doLogin">
          {{ auth.loading ? 'Connexion...' : 'Se connecter' }}
        </button>
      </div>
    </div>

    <!-- Select tech -->
    <div v-else-if="phase === 'select-tech'" class="login-wrap">
      <div class="login-hero">
        <div class="login-icon" style="font-size:1.6rem;">&#128119;</div>
        <div style="font-size:1.2rem;font-weight:700;color:#1e293b;">Choisir un technicien</div>
        <div style="color:#64748b;font-size:0.82rem;margin-top:0.3rem;">
          Connecté&nbsp;: <strong>{{ auth.user }}</strong>
        </div>
      </div>
      <div class="login-card">
        <label class="field-label">Technicien</label>
        <select v-model="selTechId" class="field-select">
          <option value="" disabled>-- Choisir --</option>
          <option v-for="t in techList" :key="t.name" :value="t.name">{{ t.fullName }}</option>
        </select>
        <button class="btn-primary" :disabled="!selTechId || store.loading" @click="loadJobs">
          {{ store.loading ? 'Chargement...' : 'Voir les jobs &rarr;' }}
        </button>
        <button class="btn-secondary" @click="doLogout">Changer de compte</button>
      </div>
    </div>

    <!-- Jobs -->
    <template v-else-if="phase === 'jobs'">

      <!-- En cours -->
      <div v-if="activeJob">
        <div class="section-label">En cours</div>
        <div class="job-card active-card" :style="'border-left-color:' + techColor"
             @click="detailJob = activeJob">
          <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:0.5rem;">
            <div style="display:flex;align-items:center;gap:0.5rem;">
              <span class="prio-dot" :class="'prio-' + activeJob.priority"></span>
              <span style="font-size:0.72rem;font-weight:700;color:#6366f1;">{{ activeJob.id }}</span>
            </div>
            <span class="badge badge-active">En cours</span>
          </div>
          <div style="font-size:0.97rem;font-weight:700;margin-bottom:0.3rem;">{{ activeJob.subject }}</div>
          <div style="font-size:0.77rem;color:#64748b;margin-bottom:0.6rem;">&#128205; {{ activeJob.address }}</div>
          <div style="display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap;">
            <span class="chip">&#9202; {{ activeJob.duration }}h</span>
            <span v-if="activeJob.legDur" class="chip">&#128664; {{ activeJob.legDur }}min</span>
            <span style="flex:1;"></span>
            <button class="btn-green" style="flex:0;padding:4px 14px;font-size:0.75rem;border-radius:8px;"
                    @click.stop="markComplete(activeJob)">Terminer</button>
          </div>
        </div>
      </div>

      <!-- A venir -->
      <div class="section-label">A venir ({{ upcomingJobs.length }})</div>
      <div v-if="upcomingJobs.length === 0"
           style="text-align:center;padding:1.5rem;color:#94a3b8;font-size:0.85rem;">
        Aucun job à venir
      </div>
      <div v-for="(job, idx) in upcomingJobs" :key="job.id"
           class="job-card" :style="'border-left-color:' + techColor" @click="detailJob = job">
        <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:0.4rem;">
          <div style="display:flex;align-items:center;gap:0.5rem;">
            <div class="num-bubble" :style="'background:' + techColor">
              {{ idx + (activeJob ? 2 : 1) }}
            </div>
            <span style="font-size:0.72rem;font-weight:600;color:#6366f1;">{{ job.id }}</span>
            <span class="prio-dot" :class="'prio-' + job.priority"></span>
          </div>
          <span class="chip">{{ startTime(idx) }}</span>
        </div>
        <div style="font-size:0.92rem;font-weight:600;margin-bottom:0.25rem;">{{ job.subject }}</div>
        <div style="font-size:0.75rem;color:#64748b;margin-bottom:0.5rem;">&#128205; {{ job.address }}</div>
        <div style="display:flex;gap:0.4rem;flex-wrap:wrap;">
          <span class="chip">&#9202; {{ job.duration }}h</span>
          <span v-if="job.legDur" class="chip">&#128664; {{ job.legDur }}m</span>
        </div>
      </div>

      <!-- Complétés -->
      <div v-if="completedJobs.length > 0">
        <div class="section-label" @click="showCompleted = !showCompleted">
          Complétés ({{ completedJobs.length }})
          <span style="font-size:0.9rem;">{{ showCompleted ? '&#8963;' : '&#8964;' }}</span>
        </div>
        <div v-if="showCompleted">
          <div v-for="job in completedJobs" :key="job.id"
               class="job-card done-card" @click="detailJob = job">
            <div style="display:flex;align-items:center;gap:0.6rem;">
              <div class="check-circle">&#10003;</div>
              <div>
                <div style="font-size:0.85rem;font-weight:600;text-decoration:line-through;color:#64748b;">
                  {{ job.subject }}
                </div>
                <div style="font-size:0.71rem;color:#94a3b8;">{{ job.id }}</div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Aucun job -->
      <div v-if="myJobs.length === 0" style="text-align:center;padding:3rem 1rem;">
        <div style="font-size:3rem;margin-bottom:0.75rem;">&#128197;</div>
        <div style="font-size:1rem;font-weight:600;color:#374151;margin-bottom:0.3rem;">Aucun job aujourd'hui</div>
        <div style="color:#94a3b8;font-size:0.83rem;">Votre planning est vide.</div>
      </div>

    </template>

    <!-- ── Equipment tab ──────────────────────────────────────────────────── -->
    <template v-else-if="phase === 'jobs' && tab === 'equipment'">

      <!-- Confirm done banner -->
      <div v-if="eqDone" class="eq-done-banner">
        &#10003; Équipements enregistrés avec succès !
        <button @click="eqDone = false" style="margin-left:0.75rem;background:none;border:none;color:inherit;font-size:1rem;cursor:pointer;">&times;</button>
      </div>

      <!-- Request picker -->
      <div class="section-label">Appel de service</div>
      <select v-model="eqRequestName" class="field-select" style="margin-bottom:0.5rem;">
        <option value="" disabled>-- Choisir un ticket --</option>
        <option v-for="j in eqJobs" :key="j.id" :value="j.id">{{ j.id }} — {{ j.subject }}</option>
      </select>

      <!-- Scanner -->
      <div class="section-label">Scanner un code-barres</div>
      <div v-if="!scannerActive" style="margin-bottom:1rem;">
        <button class="btn-indigo-full" @click="startScanner">
          &#128247; Activer la caméra
        </button>
      </div>
      <div v-else style="margin-bottom:1rem;">
        <div id="qr-reader" class="qr-reader-box"></div>
        <button class="btn-secondary" style="width:100%;margin-top:0.5rem;" @click="stopScanner">
          Arrêter le scanner
        </button>
      </div>

      <!-- Scanned items -->
      <div class="section-label">Équipements ({{ eqItems.length }})</div>
      <div v-if="eqItems.length === 0" style="text-align:center;padding:1.5rem;color:#94a3b8;font-size:0.85rem;">
        Scannez un code-barres ou ajoutez manuellement.
      </div>

      <div v-for="item in eqItems" :key="item._id" class="eq-card">
        <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.75rem;">
          <span style="font-size:0.72rem;font-weight:700;color:#6366f1;flex:1;">CODE-BARRES</span>
          <button @click="removeEqItem(item)" style="background:none;border:none;color:#ef4444;font-size:1.1rem;cursor:pointer;">&times;</button>
        </div>
        <input v-model="item.barcode" placeholder="Code-barres ou numéro de série" class="eq-input" />

        <label class="eq-label">Type d'équipement</label>
        <select v-model="item.equipment_type" class="eq-select">
          <option v-for="t in EQUIPMENT_TYPES" :key="t" :value="t">{{ t }}</option>
        </select>

        <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.5rem;">
          <div>
            <label class="eq-label">Marque</label>
            <input v-model="item.brand" placeholder="ex: Cisco" class="eq-input" />
          </div>
          <div>
            <label class="eq-label">Modèle</label>
            <input v-model="item.model" placeholder="ex: DPC3829" class="eq-input" />
          </div>
        </div>

        <label class="eq-label">Notes</label>
        <input v-model="item.notes" placeholder="Observations, port, emplacement..." class="eq-input" />

        <label class="eq-label">Photo</label>
        <div style="display:flex;align-items:center;gap:0.75rem;">
          <label class="btn-photo">
            &#128247; Prendre une photo
            <input type="file" accept="image/*" capture="environment" style="display:none"
                   @change="onPhotoChange(item, $event)" />
          </label>
          <img v-if="item.photo_base64" :src="item.photo_base64" class="eq-thumb" />
        </div>
      </div>

      <button class="btn-secondary" style="width:100%;margin-top:0.5rem;margin-bottom:0.75rem;" @click="addEqItem">
        + Ajouter manuellement
      </button>

      <button class="btn-green-full"
              :disabled="!eqRequestName || eqItems.length === 0 || eqSubmitting"
              @click="submitEquipment">
        {{ eqSubmitting ? 'Enregistrement...' : 'Enregistrer les équipements (' + eqItems.length + ')' }}
      </button>

    </template>

  </div>

  <!-- Footer tabs -->
  <div class="app-footer">
    <button class="tab-btn" :class="{ active: tab === 'jobs' }" @click="tab = 'jobs'">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
      </svg>
      Jobs
    </button>
    <button class="tab-btn" :class="{ active: tab === 'map' }" @click="tab = 'map'">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/>
        <line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/>
      </svg>
      Carte
    </button>
    <button class="tab-btn" :class="{ active: tab === 'equipment' }"
            @click="tab = 'equipment'; if(scannerActive) stopScanner()">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <rect x="3" y="3" width="18" height="18" rx="2"/><path d="M7 7h.01M12 7h.01M17 7h.01M7 12h.01M12 12h.01M17 12h.01M7 17h.01M12 17h.01M17 17h.01"/>
      </svg>
      Équip.
    </button>
    <button class="tab-btn" :class="{ active: tab === 'profile' }" @click="tab = 'profile'">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
        <path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/>
        <circle cx="12" cy="7" r="4"/>
      </svg>
      Profil
    </button>
  </div>

  <!-- Detail modal -->
  <div v-if="detailJob" class="modal-backdrop" @click.self="detailJob = null">
    <div class="modal-sheet">
      <div class="modal-handle"><div class="modal-handle-bar"></div></div>
      <div style="padding:1rem 1.25rem 0.25rem;display:flex;align-items:flex-start;justify-content:space-between;gap:0.5rem;">
        <div>
          <div style="display:flex;align-items:center;gap:0.5rem;margin-bottom:0.35rem;">
            <span style="font-size:0.75rem;font-weight:700;color:#6366f1;">{{ detailJob.id }}</span>
            <span class="prio-dot" :class="'prio-' + detailJob.priority"></span>
            <span style="font-size:0.68rem;font-weight:600;padding:2px 8px;border-radius:6px;"
                  :style="prioStyle(detailJob.priority)">{{ prioLbl(detailJob.priority) }}</span>
          </div>
          <div style="font-size:1.05rem;font-weight:700;color:#1e293b;">{{ detailJob.subject }}</div>
        </div>
        <button @click="detailJob = null"
                style="background:none;border:none;font-size:1.4rem;color:#94a3b8;cursor:pointer;line-height:1;">&times;</button>
      </div>
      <div class="modal-row">
        <div class="modal-row-icon">&#128205;</div>
        <div style="flex:1;">
          <div class="modal-row-label">Adresse</div>
          <div class="modal-row-value">{{ detailJob.address }}</div>
        </div>
        <a :href="mapsUrl(detailJob.address)" target="_blank"
           style="color:#6366f1;font-size:0.8rem;text-decoration:none;font-weight:600;">Carte</a>
      </div>
      <div class="modal-row">
        <div class="modal-row-icon">&#9202;</div>
        <div>
          <div class="modal-row-label">Durée estimée</div>
          <div class="modal-row-value">{{ detailJob.duration }}h</div>
        </div>
      </div>
      <div v-if="detailJob.legDist" class="modal-row">
        <div class="modal-row-icon">&#128664;</div>
        <div>
          <div class="modal-row-label">Trajet jusqu'au job</div>
          <div class="modal-row-value">{{ detailJob.legDist }} km · {{ detailJob.legDur }} min</div>
        </div>
      </div>
      <div class="modal-actions">
        <button v-if="detailJob.status !== 'completed'" class="btn-indigo"
                @click="markEnRoute(detailJob)">En route</button>
        <button v-if="detailJob.status !== 'completed'" class="btn-green"
                @click="markComplete(detailJob); detailJob = null">Terminer</button>
        <button v-if="detailJob.status === 'completed'" disabled
                style="flex:1;padding:0.7rem;background:#f1f5f9;color:#94a3b8;border:none;border-radius:10px;font-weight:700;font-family:inherit;">
          Ticket complété
        </button>
      </div>
    </div>
  </div>

  <!-- Toast -->
  <div v-if="showToast" class="toast">&#10003; {{ toastMsg }}</div>

</div>
</template>

<style scoped>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
.mobile-app { height: 100vh; display: flex; flex-direction: column; background: #f1f5f9; color: #1e293b; font-family: 'Inter', system-ui, sans-serif; }

/* Layout */
.app-header { background: linear-gradient(135deg, #6366f1, #8b5cf6); color: white; flex-shrink: 0; }
.app-header-bar { display: flex; align-items: center; justify-content: space-between; padding: 0.9rem 1rem; }
.app-header-title { font-size: 1.1rem; font-weight: 700; }
.app-header-sub { font-size: 0.7rem; opacity: 0.75; margin-bottom: 2px; }
.app-content { flex: 1; overflow-y: auto; padding: 1rem; padding-bottom: 5rem; }
.app-footer { position: fixed; bottom: 0; left: 0; right: 0; background: white; border-top: 1px solid #e2e8f0; display: flex; z-index: 100; }
.tab-btn { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px; padding: 0.55rem 0; font-size: 0.65rem; font-weight: 600; color: #94a3b8; border: none; background: none; cursor: pointer; transition: color 0.15s; }
.tab-btn.active { color: #6366f1; }
.tab-btn svg { width: 20px; height: 20px; }

/* Stats */
.stats-strip { background: #4f46e5; display: flex; padding: 0.5rem 1rem; gap: 0.5rem; }
.stat-box { flex: 1; background: rgba(255,255,255,0.12); border-radius: 8px; padding: 0.4rem 0.5rem; text-align: center; }
.stat-val { font-size: 1.1rem; font-weight: 700; color: white; }
.stat-lbl { font-size: 0.6rem; color: rgba(255,255,255,0.75); margin-top: 1px; }

/* Badges */
.badge { display: inline-flex; align-items: center; font-size: 0.65rem; font-weight: 700; padding: 2px 8px; border-radius: 20px; }
.badge-online  { background: rgba(74,222,128,0.25); color: #16a34a; }
.badge-offline { background: rgba(248,113,113,0.25); color: #dc2626; }
.badge-active  { background: #e0e7ff; color: #4338ca; }

/* Login */
.login-wrap { max-width: 400px; margin: 0 auto; padding-top: 0.5rem; }
.login-hero { text-align: center; padding: 1.75rem 0 1.25rem; }
.login-icon { width: 68px; height: 68px; border-radius: 20px; background: linear-gradient(135deg,#6366f1,#8b5cf6); display: flex; align-items: center; justify-content: center; margin: 0 auto 1rem; font-size: 2rem; }
.login-card { background: white; border-radius: 16px; padding: 1.5rem; box-shadow: 0 4px 24px rgba(0,0,0,0.07); }
.field-label { font-size: 0.75rem; font-weight: 600; color: #475569; display: block; margin-bottom: 0.35rem; }
.field-input { width: 100%; padding: 0.7rem 0.9rem; font-size: 0.9rem; font-family: inherit; border: 1.5px solid #e2e8f0; border-radius: 10px; outline: none; transition: border-color 0.15s; margin-bottom: 0.85rem; }
.field-input:focus { border-color: #6366f1; }
.field-input.err { border-color: #ef4444; }
.show-pwd { display: flex; align-items: center; gap: 0.4rem; margin-bottom: 1rem; font-size: 0.78rem; color: #64748b; cursor: pointer; }
.show-pwd input { accent-color: #6366f1; }
.error-msg { font-size: 0.78rem; color: #ef4444; margin: -0.6rem 0 0.75rem; padding-left: 0.1rem; }
.field-select { width: 100%; padding: 0.7rem 0.9rem; font-size: 0.9rem; font-family: inherit; border: 1.5px solid #e2e8f0; border-radius: 10px; outline: none; background: white; margin-bottom: 1rem; cursor: pointer; }
.field-select:focus { border-color: #6366f1; }

/* Buttons */
.btn-primary { width: 100%; padding: 0.75rem; font-size: 0.92rem; font-weight: 700; font-family: inherit; background: #6366f1; color: white; border: none; border-radius: 10px; cursor: pointer; transition: background 0.15s; }
.btn-primary:hover { background: #4f46e5; }
.btn-primary:disabled { background: #c7d2fe; cursor: not-allowed; }
.btn-secondary { width: 100%; padding: 0.65rem; font-size: 0.85rem; font-weight: 600; font-family: inherit; background: transparent; color: #64748b; border: 1.5px solid #e2e8f0; border-radius: 10px; cursor: pointer; margin-top: 0.6rem; transition: all 0.15s; }
.btn-secondary:hover { border-color: #6366f1; color: #6366f1; }
.btn-green  { flex: 1; padding: 0.7rem; font-size: 0.88rem; font-weight: 700; font-family: inherit; background: #22c55e; color: white; border: none; border-radius: 10px; cursor: pointer; }
.btn-indigo { flex: 1; padding: 0.7rem; font-size: 0.88rem; font-weight: 700; font-family: inherit; background: #6366f1; color: white; border: none; border-radius: 10px; cursor: pointer; }
.btn-icon { background: rgba(255,255,255,0.2); border: none; color: white; width: 34px; height: 34px; border-radius: 50%; cursor: pointer; font-size: 1.1rem; display: flex; align-items: center; justify-content: center; }

/* Cards */
.section-label { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #94a3b8; margin: 1.25rem 0 0.5rem; padding: 0 0.1rem; display: flex; align-items: center; gap: 0.4rem; cursor: pointer; }
.job-card { background: white; border-radius: 14px; padding: 0.9rem 1rem; margin-bottom: 0.7rem; box-shadow: 0 2px 8px rgba(0,0,0,0.06); border-left: 4px solid #e2e8f0; cursor: pointer; transition: transform 0.12s, box-shadow 0.12s; }
.job-card:active { transform: scale(0.985); }
.active-card { box-shadow: 0 4px 20px rgba(99,102,241,0.18); }
.done-card { opacity: 0.6; border-left-color: #22c55e !important; background: #f9fafb; }
.prio-dot { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex-shrink: 0; }
.prio-high   { background: #ef4444; }
.prio-medium { background: #f59e0b; }
.prio-low    { background: #10b981; }
.chip { background: #f1f5f9; border-radius: 6px; padding: 2px 8px; font-size: 0.7rem; font-weight: 600; color: #475569; }
.num-bubble { width: 22px; height: 22px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 0.68rem; font-weight: 700; color: white; flex-shrink: 0; }
.avatar { width: 36px; height: 36px; border-radius: 50%; font-weight: 700; font-size: 0.85rem; color: white; display: flex; align-items: center; justify-content: center; }
.check-circle { width: 32px; height: 32px; border-radius: 50%; background: #22c55e; display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: white; font-size: 1rem; }

/* Modal */
.modal-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,0.45); z-index: 200; display: flex; align-items: flex-end; }
.modal-sheet { background: white; border-radius: 18px 18px 0 0; width: 100%; max-width: 600px; margin: 0 auto; padding-bottom: env(safe-area-inset-bottom, 16px); animation: slideUp 0.22s ease; }
@keyframes slideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.modal-handle { display: flex; justify-content: center; padding: 0.75rem 0 0; }
.modal-handle-bar { width: 40px; height: 4px; border-radius: 2px; background: #e2e8f0; }
.modal-row { display: flex; align-items: center; gap: 0.75rem; padding: 0.6rem 1.25rem; }
.modal-row-icon  { color: #94a3b8; font-size: 1.1rem; width: 22px; text-align: center; }
.modal-row-label { font-size: 0.68rem; color: #94a3b8; }
.modal-row-value { font-size: 0.88rem; font-weight: 600; color: #1e293b; }
.modal-actions { display: flex; gap: 0.5rem; padding: 0.75rem 1.25rem 1.25rem; }

/* Toast */
.toast { position: fixed; top: 1rem; left: 50%; transform: translateX(-50%); background: #22c55e; color: white; border-radius: 12px; padding: 0.65rem 1.2rem; font-weight: 700; font-size: 0.88rem; z-index: 300; white-space: nowrap; box-shadow: 0 4px 16px rgba(0,0,0,0.15); animation: fadeIn 0.2s ease; }
@keyframes fadeIn { from { opacity: 0; transform: translateX(-50%) translateY(-8px); } to { opacity: 1; transform: translateX(-50%) translateY(0); } }

/* Spinner */
.spinner { width: 40px; height: 40px; border: 3px solid #e2e8f0; border-top-color: #6366f1; border-radius: 50%; animation: spin 0.7s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* Equipment tab */
.eq-done-banner { background: #dcfce7; color: #16a34a; border-radius: 10px; padding: 0.75rem 1rem; font-size: 0.85rem; font-weight: 600; margin-bottom: 1rem; display: flex; align-items: center; }
.eq-card { background: white; border-radius: 14px; padding: 1rem; margin-bottom: 0.75rem; box-shadow: 0 2px 8px rgba(0,0,0,0.06); }
.eq-label { display: block; font-size: 0.68rem; font-weight: 600; color: #64748b; margin: 0.55rem 0 0.2rem; }
.eq-input { width: 100%; padding: 0.55rem 0.75rem; font-size: 0.85rem; font-family: inherit; border: 1.5px solid #e2e8f0; border-radius: 8px; outline: none; margin-bottom: 0.1rem; }
.eq-input:focus { border-color: #6366f1; }
.eq-select { width: 100%; padding: 0.55rem 0.75rem; font-size: 0.85rem; font-family: inherit; border: 1.5px solid #e2e8f0; border-radius: 8px; outline: none; background: white; }
.eq-select:focus { border-color: #6366f1; }
.qr-reader-box { width: 100%; border-radius: 12px; overflow: hidden; border: 2px solid #6366f1; background: #000; min-height: 200px; }
.btn-photo { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.45rem 0.9rem; font-size: 0.78rem; font-weight: 600; font-family: inherit; background: #ede9fe; color: #6366f1; border: none; border-radius: 8px; cursor: pointer; }
.eq-thumb { width: 52px; height: 52px; object-fit: cover; border-radius: 8px; border: 2px solid #e2e8f0; }
.btn-indigo-full { width: 100%; padding: 0.72rem; font-size: 0.9rem; font-weight: 700; font-family: inherit; background: #6366f1; color: white; border: none; border-radius: 10px; cursor: pointer; }
.btn-green-full { width: 100%; padding: 0.72rem; font-size: 0.9rem; font-weight: 700; font-family: inherit; background: #22c55e; color: white; border: none; border-radius: 10px; cursor: pointer; }
.btn-green-full:disabled { background: #86efac; cursor: not-allowed; }
</style>
