@php
    $statusSteps = [
        'potential'  => ['label' => 'Potansiyel'],
        'offer_sent' => ['label' => 'Teklif Verildi'],
        'revised'    => ['label' => 'Revize Edildi'],
        'confirmed'  => ['label' => 'Satış Tamamlandı'],
        'in_progress'=> ['label' => 'Devam Ediyor'],
        'completed'  => ['label' => 'Kapanan'],
    ];
    $statusKeys = array_keys($statusSteps);
    // Katalog: satılabilir ürünler tipe göre gruplanır. Pasif/taslak ürünler
    // gizlenmez — ayrı bir blokta, sebebiyle birlikte gösterilir (aksi halde
    // "ürünü ekledim ama satışta yok" durumu sessizce yaşanıyordu).
    $sellableProducts = $products->filter(fn($p) => $p->is_active && $p->is_bookable);
    $closedProducts   = $products->reject(fn($p) => $p->is_active && $p->is_bookable);
    $productsByType   = $sellableProducts->groupBy(fn($p) => $p->productType?->name ?? 'Diğer');
    $closedReason     = fn($p) => !$p->is_active ? 'Pasif / taslak' : 'Satışa kapalı';

    // Birleşik mod: mevcut satışa (taslak/gerçek) bağlı ön-dolum
    $sale = $sale ?? null;
    $saleCust = $sale?->customer;
    $saleCustName = $saleCust?->full_name;
    $saleCustSub = $saleCust?->phone ?: (is_array($saleCust?->emails ?? null) ? ($saleCust->emails[0] ?? '') : '');
    // Cari / borçlandırma: müşteri seçiliyse limitin ne kadarı BU SATIŞ HARİÇ
    // kullanılmış? Şerit, satışın kalanını üstüne ekleyerek projeksiyon çizer.
    $saleCredit = $saleCust
        ? app(\App\Services\Customer\CustomerCreditService::class)->summary($saleCust, null, $sale?->id)
        : null;
    // Borç doğuran satış durumları (potansiyel/teklif henüz cari borç değildir)
    $creditDebtStatuses = \App\Services\Customer\CustomerCreditService::DEBT_STATUSES;
    $curStatus = $sale?->status ?: 'potential';
    $curStatusIdx = array_search($curStatus, $statusKeys, true);
    $curStatusIdx = $curStatusIdx === false ? 0 : $curStatusIdx;
    $sv = fn($f, $d = '') => ($sale && $sale->{$f} !== null) ? $sale->{$f} : $d;
    $sd = fn($f) => $sale && $sale->{$f} ? \Carbon\Carbon::parse($sale->{$f})->format('Y-m-d') : '';
    $saleItems = $sale ? $sale->items->map(fn($it) => [
        'name' => $it->name,
        'quantity' => (float) $it->quantity,
        'unit_price' => (float) $it->unit_price,
        'tax_rate' => (float) $it->tax_rate,
        'tax_included' => (bool) $it->tax_included,
        'discount_type' => $it->discount_type ?: 'percent',
        'discount_value' => (float) ($it->discount_value ?? 0),
        'currency' => $it->currency,
        'product_id' => $it->product_id,
        'itemable_type' => $it->itemable_type,
        'itemable_id' => $it->itemable_id,
        'start_date' => $it->start_date?->format('Y-m-d'),
        'end_date' => $it->end_date?->format('Y-m-d'),
        'start_time' => $it->timeStr('start_time'),
        'end_time' => $it->timeStr('end_time'),
        'has_departure' => (bool) $it->departure_id,
    ])->values()->all() : [];

    // Kalem kaydı olmayan mevcut satışlar (eski akışla / tur tarihi seçimiyle oluşturulanlar):
    // tabloyu boş göstermek yerine satırları satışın fiyat kırılımından (yetişkin/çocuk/bebek) türet.
    // Kırılım satış toplamını tutmuyorsa (indirim vb.) tek satıra düşülür; kayıt ilk otomatik
    // kayıtta gerçek SaleItem'lara dönüşür.
    if ($sale && empty($saleItems)) {
        $derivedName = $sale->reservable?->name ?? $sale->product?->name ?? $sale->title;
        if ($derivedName) {
            $rows = [];
            $unitP = (float) ($sale->unit_price ?? 0);
            $childP = (float) ($sale->child_price ?? 0);
            $infP = (float) ($sale->infant_price ?? 0);
            if ($unitP > 0 && $sale->adult_count > 0) {
                $rows[] = ['label' => 'Yetişkin', 'qty' => (int) $sale->adult_count, 'price' => $unitP];
                if ($sale->child_count > 0 && $childP > 0) $rows[] = ['label' => 'Çocuk', 'qty' => (int) $sale->child_count, 'price' => $childP];
                if ($sale->infant_count > 0 && $infP > 0) $rows[] = ['label' => 'Bebek', 'qty' => (int) $sale->infant_count, 'price' => $infP];
            }
            $rowsSum = collect($rows)->sum(fn($r) => $r['qty'] * $r['price']);
            if ((empty($rows) || abs($rowsSum - (float) $sale->total_amount) > 0.01) && (float) $sale->total_amount > 0) {
                $rows = [['label' => null, 'qty' => 1, 'price' => (float) $sale->total_amount]];
            }
            $saleItems = collect($rows)->map(fn($r) => [
                'name' => $derivedName . ($r['label'] ? ' · ' . $r['label'] : ''),
                'quantity' => $r['qty'],
                'unit_price' => $r['price'],
                'tax_rate' => 0, // tur fiyatları kişi başı KDV dahil kabul edilir (çifte vergi olmasın)
                'tax_included' => false, // oran 0 olduğu için mod fark etmez; satırlar tek tip kalsın
                'currency' => $sale->currency ?: 'TRY',
                'product_id' => $sale->product_id,
                'itemable_type' => null,
                'itemable_id' => null,
                'tour_line' => true, // katalogdan yeni kalkış seçilirse bu satırlar değiştirilir
            ])->values()->all();
        }
    }

    // Kayıtlı satış dövizi, kalemlerin (tek tip) dövizinden farklıysa kullanıcı özet
    // panelde bilinçli olarak farklı birim seçmiş demektir → otomatik döviz takibi
    // (qcAutoFollowCurrency) açılışta bu seçimi TRY'ye/kalem dövizine geri çevirmesin.
    // Tur ürünleri: tarih girilince operasyona "kişiye özel kalkış" olarak düşer.
    // (PrivateDepartureService yalnızca tarih modeli olan ürünler için kalkış açar.)
    $tourProductIds = $products
        ->filter(fn($p) => \Illuminate\Support\Str::contains($p->productable_type ?? '', ['Tour', 'DayTrip']))
        ->pluck('id')->map(fn($id) => (int) $id)->values();

    // Satış zaten kişiye özel bir kalkışa bağlıysa "operasyona işlendi" bağlantısı
    // açılışta da görünsün (aksi halde ilk otomatik kayda kadar kayboluyordu).
    // Katalogdan seçilmiş (özel olmayan) kalkışlarda da operasyon kartına çapraz
    // link verilir — satıştan operasyona tek tıkla geçilebilsin.
    $privateDepUrl = null;
    $catalogDepUrl = null;
    if ($sale && $sale->tour_date_type && $sale->tour_date_id) {
        $opsSvc = app(\App\Services\Operation\OperationService::class);
        $dep = app(\App\Services\Operation\DepartureInventoryService::class)
            ->resolve($sale->tour_date_type, (int) $sale->tour_date_id);
        if ($dep) {
            $depUrl = route('agency.operations.quick-view', [$opsSvc->meta($dep)['key'], $dep->id]);
            if ($dep->is_private ?? false) {
                $privateDepUrl = $depUrl;
            } else {
                $catalogDepUrl = $depUrl;
            }
        }
    }

    // Kalem satırlarındaki katalog bağı rozetinden ürün kartına geçiş:
    // product_id → ilgili tur/hizmet quick-view adresi (kartı olmayan tiplerde link çıkmaz).
    $productQvUrls = $products->mapWithKeys(function ($p) {
        $url = $p->productable_id ? match (class_basename((string) $p->productable_type)) {
            'Tour'              => route('agency.products.kultur-turlari.quick-view', $p->productable_id),
            'InternationalTour' => route('agency.products.yurtdisi-turlari.quick-view', $p->productable_id),
            'DayTour'           => route('agency.products.gunubirlik-turlar.quick-view', $p->productable_id),
            'ExtraService'      => route('agency.products.extra-services.quick-view', $p->productable_id),
            default             => null,
        } : null;
        return [$p->id => $url];
    })->filter();
    foreach (($extraServices ?? collect()) as $exSvc) {
        if ($exSvc->product_id) {
            $productQvUrls[$exSvc->product_id] = route('agency.products.extra-services.quick-view', $exSvc->id);
        }
    }

    // Tedarikçi hizmeti kalemlerinden tedarikçi kartına geçiş:
    // SupplierPriceItem id → supplier id
    $supplierByPriceItem = $supplierCatalog
        ->filter(fn ($it) => !empty($it['supplier_id']))
        ->pluck('supplier_id', 'id');

    $itemCurrencies = collect($saleItems)->pluck('currency')->filter()->unique()->values();
    $currencyIsManual = $sale && $itemCurrencies->count() === 1 && $itemCurrencies->first() !== ($sale->currency ?: 'TRY');

    // ── ÇOKLU MÜŞTERİ ──────────────────────────────────────────────────────────
    // Kural: ya TEK şirket ya da bir/birden fazla kişi. Pivot (sale_customers)
    // boşsa (migration öncesi kayıtlar) birincil müşteriden türetilir.
    $custRow = fn($c, $isPrimary) => [
        'id' => $c->id,
        'name' => $c->full_name,
        'sub' => $c->phone ?: (is_array($c->emails ?? null) ? ($c->emails[0] ?? '') : ''),
        'corporate' => $c->customer_type === 'corporate',
        'primary' => (bool) $isPrimary,
    ];
    $saleCustomers = collect();
    if ($sale) {
        try {
            $saleCustomers = $sale->customers->map(fn($c) => $custRow($c, $c->pivot->is_primary))->values();
        } catch (\Throwable $e) {
            // sale_customers tablosu henüz migrate edilmedi → birincil müşteriye düş
            $saleCustomers = collect();
        }
        if ($saleCustomers->isEmpty() && $saleCust) {
            $saleCustomers = collect([$custRow($saleCust, true)]);
        }
    }

    // ── FİYAT TİPLERİ + ODALAMA ────────────────────────────────────────────────
    // Fiyat tipi terimlerinin TEK kaynağı App\Support\TourFareCatalog'dur; etiketler
    // burada da JS'te de elle yazılmaz (bkz. $fareDefs → window.QC_FARES).
    //
    // Konaklamalı turlarda (kültür + yurtdışı) satış ODA TABANLI kurgulanır:
    // her odada kaç yetişkin/çocuk/bebek kalacağı ve ek yatak girilir; tek kişi
    // farkı ile ek yatak fiyatı bu kurgudan OTOMATİK türetilir. Günübirlik
    // turlarda konaklama olmadığı için oda paneli görünmez, eski adet girişi kalır.
    $rt = (string) ($sale?->reservable_type ?? '');
    $saleIsTour = \Illuminate\Support\Str::contains($rt, ['Tour', 'DayTrip']);
    $saleIsOvernight = \Illuminate\Support\Str::contains($rt, 'InternationalTour')
        || (\Illuminate\Support\Str::contains($rt, 'Tour') && !\Illuminate\Support\Str::contains($rt, ['DayTour', 'DayTrip']));
    $saleTd = $saleIsTour ? $sale?->tourDate : null;

    // Fiyat satırı: satışta seçili pazaryeri varsa ONUN satırı kullanılır — böylece
    // kart yeniden açıldığında/yeniden hesaplandığında aynı fiyat gelir.
    $salePricing = (array) data_get($sale?->extra_data, 'pricing', []);
    $saleMarketId = (int) ($salePricing['marketplace_id'] ?? 0) ?: null;
    $fareRow = null;
    $fareMarket = ['id' => null, 'name' => null, 'source' => 'none', 'options' => []];
    if ($saleTd && method_exists($saleTd, 'primaryPriceRow')) {
        try {
            $rows = $saleTd->marketplacePrices;
            $names = $rows->isNotEmpty()
                ? \App\Models\Agency\Marketplace::whereIn('id', $rows->pluck('marketplace_id')->unique())->pluck('name', 'id')
                : collect();
            $primaryId = (int) ($sale?->product?->primary_marketplace_id ?? 0) ?: null;
            $best = fn ($pool) => $pool->firstWhere('tour_class_id', null)
                ?? $pool->sortBy(fn ($r) => (float) $r->adult_price)->first();

            $fareMarket['options'] = $rows->groupBy('marketplace_id')->map(function ($pool, $mid) use ($best, $names, $primaryId) {
                $r = $best($pool);
                return [
                    'id' => (int) $mid,
                    'name' => $names[(int) $mid] ?? ('Pazaryeri #' . $mid),
                    'is_primary' => $primaryId !== null && (int) $mid === $primaryId,
                    'currency' => $r?->currency ?: 'TRY',
                    'adult_price' => (float) ($r?->adult_price ?? 0),
                    'child_price' => (float) ($r?->child_price_1 ?? $r?->child_price ?? 0),
                    'child_price_2' => (float) ($r?->child_price_2 ?? 0),
                    'infant_price' => (float) ($r?->infant_price ?? 0),
                    'single_supplement' => (float) ($r?->single_supplement ?? 0),
                    'extra_bed_price' => (float) ($r?->extra_bed_price ?? 0),
                ];
            })->sortByDesc('is_primary')->values()->all();

            if ($saleMarketId && $rows->where('marketplace_id', $saleMarketId)->isNotEmpty()) {
                $fareRow = $best($rows->where('marketplace_id', $saleMarketId));
                $fareMarket['id'] = $saleMarketId;
                $fareMarket['source'] = $primaryId === $saleMarketId ? 'primary' : 'selected';
            } elseif ($primaryId && $rows->where('marketplace_id', $primaryId)->isNotEmpty()) {
                $fareRow = $best($rows->where('marketplace_id', $primaryId));
                $fareMarket['id'] = $primaryId;
                $fareMarket['source'] = 'primary';
            } elseif ($rows->isNotEmpty()) {
                $fareRow = $saleTd->primaryPriceRow();
                $fareMarket['id'] = (int) ($fareRow?->marketplace_id ?? 0) ?: null;
                $fareMarket['source'] = 'fallback';   // hangi pazarın fiyatı geldiği belirsiz
            }
            $fareMarket['name'] = $fareMarket['id'] ? ($names[$fareMarket['id']] ?? null) : null;
        } catch (\Throwable $e) {
            $fareRow = null;    // fiyat matrisi okunamadı → tarih accessor'larına düşülür
        }
    }

    $farePrice = fn (string $col) => (float) ($fareRow?->{$col} ?? $saleTd?->{$col} ?? 0);
    $fareDefs = \App\Support\TourFareCatalog::forJs((bool) ($saleTd->infant_allowed ?? true));

    $fareCtx = [
        'is_tour' => $saleIsTour,
        'is_overnight' => $saleIsOvernight,
        'currency' => $sale?->currency ?: 'TRY',
        'tour_name' => $sale?->reservable?->name ?: ($sale?->title ?: ''),
        'date_label' => '',
        'room_capacity' => (int) ($saleTd->room_capacity ?? 0) ?: 2,
        'marketplace' => $fareMarket,
        // Anahtarlar TourFareCatalog ile birebir aynı (adult|single|extra_bed|child1|child2|infant)
        'prices' => [
            'adult'     => $farePrice('adult_price'),
            'child1'    => (float) ($fareRow?->child_price_1 ?? $saleTd?->child_price_1 ?? $saleTd?->child_price ?? 0),
            'child2'    => $farePrice('child_price_2'),
            'infant'    => $farePrice('infant_price'),
            'single'    => $farePrice('single_supplement'),
            'extra_bed' => $farePrice('extra_bed_price'),
        ],
    ];

    // Kayıtlı odalar (operasyondaki Odalama sekmesi aynı kayıtları okur/yazar).
    // Okunamadıysa satış kartı oda GÖNDERMEZ — aksi halde boş liste, operasyonda
    // kurulmuş odaları silerdi.
    $saleRoomsBoot = [];
    $saleRoomsReadable = false;
    try {
        $saleRoomsBoot = ($sale?->rooms ?? collect())->map(fn ($r) => [
            'room_type' => $r->room_type,
            'label' => $r->label,
            'capacity' => (int) $r->capacity,
            'adult_count' => (int) $r->adult_count,
            'child_count' => (int) $r->child_count,
            'infant_count' => (int) $r->infant_count,
            'extra_bed' => (bool) $r->extra_bed,
            'notes' => $r->notes,
        ])->values()->all();
        $saleRoomsReadable = true;
    } catch (\Throwable $e) {
        $saleRoomsBoot = [];        // sale_rooms migrate edilmediyse kart yine açılsın
        $saleRoomsReadable = false; // …ama oda yazma akışı kapalı kalsın
    }
@endphp

<x-quick-view.layout class="qv-sales-wrapper qv-wrapper" data-sale-id="{{ $sale?->id }}" data-items-ready="0" data-custs-ready="0">

    {{-- Hidden status input --}}
    <input type="hidden" id="qc-status-value" value="{{ $curStatus }}">

    {{-- ═══ ALANLARIN GERÇEK KARŞILIKLARI ═══
         Künye satırları (defter tasarımı) doğrudan bu alanlara yazar; otomatik
         kayıt da yalnızca buradan okur. Alanların TEK KAYNAK olarak burada
         durması, aynı değerin iki ayrı yazarı (satır PATCH'i + kart kaydı)
         olmasını engelliyor — tarih seçici de gizli kopyaları sarmasın diye
         blok data-dtp-skip taşır. --}}
    <div class="qc-fields" data-dtp-skip hidden>
        <input type="text" id="qc-title" value="{{ $sale?->title }}">
        <input type="date" id="qc-start-date" value="{{ $sd('start_date') ?: date('Y-m-d') }}">
        <input type="date" id="qc-end-date" value="{{ $sd('end_date') }}">
        <select id="qc-product-type">
            <option value="">—</option>
            @foreach($productTypes as $pt)
                <option value="{{ $pt->id }}" @selected($sale?->product_type_id == $pt->id)>{{ $pt->name }}</option>
            @endforeach
        </select>
        <select id="qc-agent">
            <option value="">—</option>
            @foreach($agents as $agent)
                <option value="{{ $agent->id }}" @selected($sale ? ($sale->assigned_to == $agent->id) : (Auth::id() == $agent->id))>{{ $agent->full_name }}</option>
            @endforeach
        </select>
        <input type="text" id="qc-pickup" value="{{ $sale?->pickup_location }}">
        <input type="text" id="qc-flight" value="{{ $sale?->flight_number }}">

        <input type="number" id="qc-adult"  value="{{ $sale?->adult_count ?? 1 }}"  min="1" oninput="qcUpdateMetrics()">
        <input type="number" id="qc-child"  value="{{ $sale?->child_count ?? 0 }}"  min="0" oninput="qcUpdateMetrics()">
        <input type="number" id="qc-infant" value="{{ $sale?->infant_count ?? 0 }}" min="0" oninput="qcUpdateMetrics()">

        <input type="number" id="qc-total-amount" step="any" min="0"
               value="{{ $sale && $sale->total_amount ? number_format($sale->total_amount, 2, '.', '') : '' }}"
               oninput="qcTotalEdited()">
        <select id="qc-currency" onchange="qcOnSaleCurrencyChange(this.value)">
            @foreach($activeCurrencies as $curr)
                <option value="{{ $curr->code }}" @selected($curr->code === ($sale?->currency ?: 'TRY'))>{{ $curr->code }} ({{ $curr->symbol }})</option>
            @endforeach
        </select>
        <input type="number" id="qc-paid-amount" step="any" min="0"
               value="{{ $sale && $sale->paid_amount ? number_format($sale->paid_amount, 2, '.', '') : 0 }}"
               oninput="qcUpdateMetrics()">
        {{-- Hesaplanan alan: qcUpdateMetrics yazar, künyedeki "Kalan Tutar" satırı okur --}}
        <input type="text" id="qc-remaining-display" value="0,00" readonly>
        <select id="qc-payment-status">
            <option value="unpaid"  @selected(($sale?->payment_status ?? 'unpaid') === 'unpaid')>Ödenmedi</option>
            <option value="partial" @selected($sale?->payment_status === 'partial')>Kısmi Ödeme</option>
            <option value="paid"    @selected($sale?->payment_status === 'paid')>Ödendi</option>
        </select>
    </div>

    {{-- ═══ HEADER ═══
         Ortak slim başlık (müşteri / tedarikçi / operasyon kartlarıyla aynı):
         beyaz zemin, başlık + rozetler tek şeritte, metrikler sağda. Kapatma
         düğmesi burada qcClose'a bağlanır — kart kapanmadan bekleyen otomatik
         kaydı göndermek zorunda. --}}
    <x-quick-view.header :slim="true" close="qcClose(this)">
        <x-slot:title>
            @if($sale)
                {{-- Ortak tıkla-düzenle başlık kalıbı. PATCH yerine target kullanılır:
                     değer künyedeki #qc-title alanına yazılır ve kayıt bu kartın kendi
                     otomatik kaydıyla gider — ayrı bir update-field isteği debounce'lu
                     otomatik kaydın üstüne yazardı. --}}
                <x-quick-view.editable-title
                    field="title" target="#qc-title"
                    :value="$sale->title"
                    :auto="'Satış #' . $sale->sale_code"
                    placeholder="Bu satışa bir ad verin…" />
            @else
                {{-- Henüz kaydedilmemiş satışta güncellenecek kayıt yok --}}
                Yeni Satış
            @endif
        </x-slot:title>

        <x-slot:subtitle>
            <span class="sqv-code">{{ $sale?->sale_code ? '#' . $sale->sale_code : 'YENİ' }}</span>
            <span id="qc-customer-label">
                @if($saleCust)
                    {{-- Müşteri kartına çapraz geçiş --}}
                    <a href="javascript:void(0)" class="sqv-customer-link" title="Müşteri kartını aç"
                       onclick="openCustomerDrawer({{ $sale->customer_id }})"><i class="fas fa-user"></i> {{ $saleCustName }}</a>
                @else
                    <i class="fas fa-user"></i> Müşteri seçin
                @endif
            </span>
            <span class="sqv-stat-chip" id="qc-metric-status">{{ $statusSteps[$curStatus]['label'] ?? 'Potansiyel' }}</span>
        </x-slot:subtitle>

        <x-slot:metrics>
            <div class="qv-metric">
                <span class="qv-metric-label">TOPLAM</span>
                <span class="qv-metric-val" id="qc-metric-total">₺0,00</span>
            </div>
            <div class="qv-metric">
                <span class="qv-metric-label">ÖDENEN</span>
                <span class="qv-metric-val text-success" id="qc-metric-paid">₺0,00</span>
            </div>
            <div class="qv-metric">
                <span class="qv-metric-label">KALAN</span>
                <span class="qv-metric-val text-danger" id="qc-metric-remaining">₺0,00</span>
            </div>
            <div class="qv-metric">
                <span class="qv-metric-label">KİŞİ</span>
                <span class="qv-metric-val" id="qc-metric-people">1</span>
            </div>
        </x-slot:metrics>

        <x-slot:actions>
            @if($sale)
                <button type="button" class="sqv-docbtn" onclick="qcDocOpen()" title="Teklif belgesi (teklif mektubu) oluştur — PDF / Word">
                    <i class="fas fa-file-signature"></i><span>Belge Oluştur</span>
                </button>
            @endif
        </x-slot:actions>

        <x-slot:tabs>
            <x-quick-view.tab id="qcgeneral"  label="Genel"   icon="fas fa-th-large" active="true" />
            <x-quick-view.tab id="qcproducts" label="Ürünler" icon="fas fa-box" />
            @if($sale)
                <x-quick-view.tab id="qcinvoices" label="Faturalar" icon="fas fa-file-invoice" :count="$sale->invoices->count()" />
                <x-quick-view.tab id="qcpayments" label="Ödemeler" icon="fas fa-money-bill-transfer" :count="$sale->payments->count()" />
            @endif
        </x-slot:tabs>
    </x-quick-view.header>

    {{-- ═══ PIPELINE (ince stepper) ═══
         Sekmelerin altında durur: aşama satışın tamamına aittir, tek bir
         sekmeye değil — hangi sekmede olursan ol görünür kalması gerekiyor. --}}
    <div class="sqv-pipeline-wrap">
        <div class="sqv-pipeline" id="qc-pipeline">
            @foreach($statusSteps as $key => $step)
                <div class="sqv-seg {{ $loop->index < $curStatusIdx ? 'done' : ($loop->index === $curStatusIdx ? 'current' : 'future') }}"
                     onclick="qcSelectStatus('{{ $key }}', this)"
                     data-key="{{ $key }}"
                     title="{{ $step['label'] }}">
                    <span class="sqv-seg-dot"></span>
                    <span class="sqv-seg-label">{{ $step['label'] }}</span>
                </div>
            @endforeach
        </div>
    </div>

    {{-- ═══ CONTENT ═══ --}}
    <x-quick-view.content>

        {{-- ─────────────────────── TAB: GENEL ─────────────────────── --}}
        <div id="qv-tab-qcgeneral" class="qv-tab-panel active">
            <div class="p-4">
                <div class="qc-autofill-note">
                    <div class="qc-autofill-ico"><i class="fas fa-wand-magic-sparkles"></i></div>
                    <div class="qc-autofill-txt">
                        <b>Otomatik doldurma:</b> Ürünler sekmesinden tur/hizmet ekledikçe <b>başlık, hizmet türü, katılımcı sayısı ve tutar</b> alanları <u>boşsa</u> otomatik doldurulur — bu alanları kendiniz elle de girebilirsiniz, elle girdiğiniz değerler korunur.
                    </div>
                </div>
                <div class="row g-4">

                    {{-- ── LEFT COLUMN (7/12) ── --}}
                    <div class="col-md-7">

                        {{-- MÜŞTERİ — defter kartı kabuğu; içerik zengin bir bileşen
                             olduğu için satır değil .pfx-body kullanılır. --}}
                        <div class="pfx mb-4">
                            <div class="pfx-top">
                                <span class="pfx-top-t"><i class="fas fa-user-tie"></i> Müşteriler <span class="qc-req">*</span></span>
                                <button type="button" class="pfx-chip" onclick="qcToggleCustomerForm(true)">
                                    <i class="fas fa-user-plus"></i> Yeni Müşteri
                                </button>
                            </div>
                            <div class="pfx-body">

                            {{-- Aranabilir müşteri seçici (server-side arama) — çoklu müşteri.
                                 Kural: ya TEK şirket ya da bir/birden fazla kişi seçilebilir. --}}
                            <div class="qc-cust-picker" id="qc-cust-picker">
                                {{-- Birincil müşteri (fatura muhatabı) — mevcut tüm akışlar bunu okur --}}
                                <input type="hidden" id="qc-customer-id" value="{{ $sale?->customer_id }}">

                                {{-- Seçili müşteri listesi (JS çizer) --}}
                                <div class="qc-custchips" id="qc-custchips"></div>

                                <button type="button" class="qc-cust-trigger" id="qc-cust-trigger" onclick="qcCustToggle(event)">
                                    <span class="qc-cust-tr-ico" id="qc-cust-tr-ico"><i class="fas fa-magnifying-glass"></i></span>
                                    <span class="qc-cust-tr-txt" id="qc-cust-tr-txt">Müşteri seçin veya arayın…</span>
                                    <i class="fas fa-chevron-down qc-cust-caret"></i>
                                </button>
                                <div class="qc-cust-dropdown" id="qc-cust-dropdown">
                                    <div class="qc-cust-search">
                                        <i class="fas fa-magnifying-glass"></i>
                                        <input type="text" id="qc-cust-search-input" placeholder="İsim, TC kimlik, telefon veya e-posta ile ara…" autocomplete="off" oninput="qcCustSearch(this)">
                                    </div>
                                    <div class="qc-cust-list" id="qc-cust-list"></div>
                                    <button type="button" class="qc-cust-addnew" onclick="qcCustClose(qcRoot(this)); qcToggleCustomerForm(true)">
                                        <i class="fas fa-user-plus me-1"></i> Bulamadın mı? <b>Yeni müşteri ekle</b>
                                    </button>
                                </div>
                            </div>

                            {{-- Şirket / kişi kuralı ihlalinde görünür uyarı --}}
                            <div class="qc-cust-rule" id="qc-cust-rule" style="display:none;">
                                <i class="fas fa-circle-info"></i><span class="qc-cust-rule-txt"></span>
                            </div>

                            {{-- Yeni müşteri hızlı formu --}}
                            <div id="qc-quick-customer-form" class="qc-newcust-form d-none">
                                <div class="qc-newcust-head"><i class="fas fa-user-plus"></i> Yeni Müşteri Ekle</div>
                                <div class="row g-2">
                                    <div class="col-md-6">
                                        <label class="qc-nc-label">Adı <span class="req">*</span></label>
                                        <input type="text" id="qc_new_first_name" class="qc-nc-input" placeholder="Ahmet" autocomplete="off">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="qc-nc-label">Soyadı <span class="req">*</span></label>
                                        <input type="text" id="qc_new_last_name" class="qc-nc-input" placeholder="Yılmaz" autocomplete="off">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="qc-nc-label">Telefon</label>
                                        <input type="text" id="qc_new_phone" class="qc-nc-input" placeholder="05XX XXX XX XX" autocomplete="off">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="qc-nc-label">E-Posta</label>
                                        <input type="email" id="qc_new_email" class="qc-nc-input" placeholder="ornek@site.com" autocomplete="off">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="qc-nc-label">T.C. / Pasaport</label>
                                        <input type="text" id="qc_new_national_id" class="qc-nc-input" placeholder="Opsiyonel" autocomplete="off" data-digits="off">
                                    </div>
                                    <div class="col-md-6">
                                        <label class="qc-nc-label">Cinsiyet</label>
                                        <select id="qc_new_gender" class="qc-nc-input">
                                            <option value="">Seçiniz</option>
                                            <option value="male">Erkek</option>
                                            <option value="female">Kadın</option>
                                        </select>
                                    </div>
                                    <div class="col-12">
                                        <div id="qc-newcust-error" class="qc-nc-error" style="display:none;"></div>
                                    </div>
                                    <div class="col-12 d-flex justify-content-end gap-2 mt-1">
                                        <button type="button" class="qc-nc-cancel" onclick="qcToggleCustomerForm(false)">İptal</button>
                                        <button type="button" class="qc-nc-save" id="qc-nc-save-btn" onclick="qcSaveQuickCustomer()">
                                            <span class="qc-nc-save-txt"><i class="fas fa-check me-1"></i> Kaydet ve Seç</span>
                                            <span class="qc-nc-save-load d-none"><i class="fas fa-spinner fa-spin me-1"></i> Ekleniyor…</span>
                                        </button>
                                    </div>
                                </div>
                            </div>
                            </div>
                        </div>

                        {{-- ANLAŞMA KÜNYESİ — ortak defter tasarımı (satır satır
                             tıkla-düzenle + kopyala). Alanların gerçek karşılıkları
                             kartın sonundaki gizli blokta; buradaki satırlar oraya
                             yazar, kaydı otomatik kayıt gönderir. --}}
                        <div class="mb-4">
                            @include('agency.sales.partials.qc-deal-ledger')
                        </div>

                        {{-- NOTLAR --}}
                        <div class="pfx qc-notes">
                            <div class="pfx-top">
                                <span class="pfx-top-t"><i class="fas fa-sticky-note"></i> Dahili ve Müşteri Notları</span>
                            </div>
                            <div class="pfx-body">
                                <label class="qc-note-l">Müşteri Notu</label>
                                <div class="rte-wrap">
                                    <div id="qc-customer-note-editor" data-placeholder="Müşteriye iletilecek notlar...">{!! $sale?->customer_note !!}</div>
                                </div>
                                {{-- Quill içeriği bu gizli alana senkronlanır; otomatik kayıt payload'u buradan okur --}}
                                <textarea id="qc-customer-note" class="d-none">{{ $sale?->customer_note }}</textarea>

                                <label class="qc-note-l mt-3">Dahili Not</label>
                                <div class="rte-wrap">
                                    <div id="qc-internal-note-editor" data-placeholder="Sadece çalışanlar görebilir...">{!! $sale?->internal_note !!}</div>
                                </div>
                                <textarea id="qc-internal-note" class="d-none">{{ $sale?->internal_note }}</textarea>
                                <p class="pfx-notes-hint">Dahili not yalnızca acentenize görünür; müşteri notu teklif/voucher belgelerine çıkar.</p>
                            </div>
                        </div>

                    </div>

                    {{-- ── RIGHT COLUMN (5/12) ── --}}
                    <div class="col-md-5">

                        {{-- KATILIMCI VE TUTAR — ortak defter tasarımı --}}
                        <div class="mb-4">
                            @include('agency.sales.partials.qc-money-ledger')
                        </div>

                        {{-- CARİ / BORÇLANDIRMA ŞERİDİ
                             Ödeme alınmadan kalan tutarın müşterinin kredi limitine sığıp
                             sığmadığını KAYDETMEDEN önce gösterir; aşımda kırmızıya döner
                             ve sunucu da aynı kuralla kaydı reddeder. --}}
                        <div class="qc-credit" id="qc-credit" style="display:none;">
                            <div class="qc-credit-h">
                                <i class="fas fa-hand-holding-dollar"></i>
                                <span class="qc-credit-t">Cari limit</span>
                                <span class="qc-credit-state" id="qc-credit-state"></span>
                            </div>
                            <div class="qc-credit-bar"><span id="qc-credit-fill"></span></div>
                            <div class="qc-credit-msg" id="qc-credit-msg"></div>
                        </div>

                        {{-- OTOMATİK KAYIT DURUMU + BİTİR --}}
                        <div class="qc-autosave-strip" id="qc-autosave-strip">
                            <i class="fas fa-bolt"></i>
                            <span>Bu satış <b>otomatik kaydediliyor</b> — her değişiklik anında saklanır.</span>
                            <span class="qc-save-indicator" id="qc-save-indicator" data-state="saved"><i class="fas fa-circle-check"></i> Kaydedildi</span>
                        </div>

                        {{-- Kayıt başarısızsa sessiz kalmaz: sebep + tekrar dene --}}
                        <div class="qc-save-error" id="qc-save-error" style="display:none;">
                            <div class="qc-save-error-head">
                                <i class="fas fa-triangle-exclamation"></i>
                                <b>Değişiklikleriniz kaydedilemedi</b>
                            </div>
                            <div class="qc-save-error-msg">—</div>
                            <button type="button" class="qc-save-error-btn" onclick="qcSaveNow(qcRoot(this))">
                                <i class="fas fa-rotate-right me-1"></i> Tekrar dene
                            </button>
                        </div>

                        <div class="d-grid">
                            <button type="button" onclick="qcClose(this)"
                                class="btn btn-lg fw-bold"
                                style="background:#f1f5f9;color:#334155;border:none;border-radius:14px;font-size:0.95rem;padding:0.85rem;transition:all 0.2s;">
                                <i class="fas fa-xmark me-2"></i>Kapat
                            </button>
                        </div>

                    </div>

                    {{-- ── ODALAMA + FİYAT TİPLERİ (yalnızca tur satışlarında) ──
                         Konaklamalı turlarda oda kurgusu yapılır: her odada kaç
                         yetişkin/çocuk/bebek kalacağı ve ek yatak girilir; tek kişilik
                         oda farkı ile ek yatak fiyatı bu kurgudan OTOMATİK türetilir ve
                         gerekçesiyle gösterilir. Günübirlikte oda paneli görünmez, yalnızca
                         adet girişi kalır. Her iki modda da tek kaynak satış kalemleridir. --}}
                    <div class="col-12" id="qc-fares-wrap" @if(!$saleIsTour) style="display:none;" @endif>
                        <div class="sqv-card qcfp-card">
                            <div class="qcfp-head">
                                <div class="qcfp-head-title">
                                    <h6 class="sqv-card-title mb-0"><i class="fas fa-bed me-2 text-primary"></i><span id="qcfp-title">Odalama ve Fiyatlandırma</span></h6>
                                    <span class="qcfp-hint" id="qcfp-subhint">Odaları kurun — <b>tek kişilik oda farkı</b> ve <b>ek yatak</b> otomatik hesaplanır, satış kalemleri ve toplam anında güncellenir.</span>
                                </div>
                                <div class="qcfp-head-date" id="qcfp-date"></div>
                            </div>

                            {{-- Fiyat hangi pazaryerinden geliyor? Belirsizse kullanıcı uyarılır. --}}
                            <div class="qcmp" id="qcmp" style="display:none;">
                                <div class="qcmp-main">
                                    <i class="fas fa-store qcmp-ico"></i>
                                    <span class="qcmp-lbl">Fiyat kaynağı</span>
                                    <select class="qcmp-select" id="qcmp-select" onchange="qcMarketChanged(this)" aria-label="Fiyatların alınacağı pazaryeri"></select>
                                    <span class="qcmp-badge" id="qcmp-badge"></span>
                                </div>
                                <div class="qcmp-note" id="qcmp-note"></div>
                            </div>

                            {{-- Oda kurgusu (yalnızca konaklamalı turlar) --}}
                            <div class="qcrm" id="qcrm" style="display:none;">
                                <div class="qcrm-bar">
                                    <div class="qcrm-bar-counts" id="qcrm-summary"></div>
                                    <div class="qcrm-bar-actions">
                                        <button type="button" class="qcrm-btn-ghost" onclick="qcRoomsAutoFill(this)" title="Genel sekmesindeki kişi sayısından odaları otomatik dağıt">
                                            <i class="fas fa-wand-magic-sparkles"></i> Otomatik Dağıt
                                        </button>
                                        <button type="button" class="qcrm-btn-add" onclick="qcRoomAdd(this)">
                                            <i class="fas fa-plus"></i> Oda Ekle
                                        </button>
                                    </div>
                                </div>
                                <div class="qcrm-list" id="qcrm-list"></div>
                                <div class="qcrm-empty" id="qcrm-empty" style="display:none;">
                                    <i class="fas fa-door-open"></i>
                                    <div>
                                        <b>Henüz oda eklenmedi.</b>
                                        <span>“Oda Ekle” ile başlayın ya da <b>Otomatik Dağıt</b> ile kişi sayısına göre odaları kurdurun.</span>
                                    </div>
                                </div>
                            </div>

                            {{-- Fiyat tipi kırılımı: oda modunda odalardan türer (salt okunur),
                                 günübirlikte elle adet girilir. --}}
                            <div class="qcfp-cap" id="qcfp-cap" style="display:none;">
                                <i class="fas fa-receipt"></i> Fiyat kırılımı
                                <span>odalardan otomatik hesaplandı</span>
                            </div>

                            <div class="qcfp-table" id="qcfp-table">
                                <div class="qcfp-thead">
                                    <span class="qcfp-c-name">Fiyat Tipi</span>
                                    <span class="qcfp-c-unit">Birim Fiyat</span>
                                    <span class="qcfp-c-qty">Adet</span>
                                    <span class="qcfp-c-sub">Tutar</span>
                                </div>
                                <div class="qcfp-rows" id="qcfp-rows"></div>
                            </div>

                            <div class="qcfp-empty" id="qcfp-empty" style="display:none;">
                                <i class="fas fa-tags"></i>
                                <div>
                                    <b>Bu satışta tarifeli bir tur tarihi yok.</b>
                                    <span>Ürünler sekmesinden katalogdan bir tur ve kalkış tarihi seçtiğinizde fiyat tipleri burada listelenir.</span>
                                </div>
                            </div>

                            <div class="qcfp-foot" id="qcfp-foot">
                                <div class="qcfp-foot-counts">
                                    <span class="qcfp-chip"><i class="fas fa-user"></i> <b id="qcfp-n-adult">0</b> yetişkin</span>
                                    <span class="qcfp-chip"><i class="fas fa-child"></i> <b id="qcfp-n-child">0</b> çocuk</span>
                                    <span class="qcfp-chip"><i class="fas fa-baby"></i> <b id="qcfp-n-infant">0</b> bebek</span>
                                </div>
                                <div class="qcfp-total">
                                    <span class="qcfp-total-lbl">Tur Toplamı</span>
                                    <span class="qcfp-total-val" id="qcfp-total">0</span>
                                </div>
                            </div>
                        </div>
                    </div>

                </div>
            </div>
        </div>

        {{-- ─────────────────────── TAB: ÜRÜNLER ─────────────────────── --}}
        <div id="qv-tab-qcproducts" class="qv-tab-panel">
            {{-- Seçilen tur + kalkış tarihi bağı (satış bu tarihe bağlanır → operasyon & yolcu listesi) --}}
            {{-- Mevcut bağlar açılışta doldurulur: boş gönderilirse otomatik kayıt
                 satışın kalkış/ürün bağını silip operasyondaki yolcu listesini boşaltıyordu. --}}
            <input type="hidden" id="qc-product-id" value="{{ $sale?->product_id }}">
            <input type="hidden" id="qc-tour-date-id" value="{{ $sale?->tour_date_id }}">
            <input type="hidden" id="qc-tour-date-type" value="{{ $sale?->tour_date_type }}">
            {{-- Fiyatların çekildiği pazaryeri: satış yeniden hesaplandığında aynı
                 fiyatın gelmesi için saklanır (sales.extra_data → pricing). --}}
            <input type="hidden" id="qc-marketplace-id" value="{{ $fareMarket['id'] }}">
            <input type="hidden" id="qc-marketplace-name" value="{{ $fareMarket['name'] }}">
            <div class="p-4">
                <div class="d-flex justify-content-between align-items-center mb-3 pb-2 border-bottom">
                    <div>
                        <h6 class="qcx-tabtitle mb-0">
                            <i class="fas fa-box me-2 text-primary"></i>Satış Kalemleri
                        </h6>
                        <p class="qcx-tabhint mb-0">
                            <i class="fas fa-keyboard me-1"></i>Adı direkt yazın
                            <span class="mx-1 text-muted">·</span>
                            <i class="fas fa-layer-group me-1 text-indigo"></i>veya <strong>Katalog</strong>'dan tur, ürün ya da tedarikçi hizmeti seçin
                        </p>
                    </div>
                    <div class="d-flex gap-2 align-items-center">
                        {{-- Fiyatlara KDV dahil mi? (tüm satırlara uygulanır) --}}
                        <div class="qcx-master" title="Girdiğiniz birim fiyatların KDV'yi içerip içermediğini seçin">
                            <span class="qcx-master-lbl"><i class="fas fa-percent"></i> Fiyatlar</span>
                            <div class="qcx-seg qcx-seg-lg" id="qc-tax-master">
                                <button type="button" data-ti="0" onclick="qcSetAllTaxIncluded(0)">KDV Hariç</button>
                                <button type="button" data-ti="1" onclick="qcSetAllTaxIncluded(1)">KDV Dahil</button>
                            </div>
                        </div>
                        <button class="btn btn-sm qcdt-bulk-btn" onclick="qcOpenDateModal(null)" title="Tüm kalemlere tek seferde tarih uygula">
                            <i class="fas fa-calendar-days me-1"></i> Toplu Tarih
                        </button>
                        <button class="btn btn-catalog-open btn-sm" onclick="openProductCatalog(null)">
                            <i class="fas fa-layer-group me-1"></i> Katalog
                        </button>
                        <button class="btn btn-outline-secondary btn-sm" style="border-radius:10px;font-weight:700;" onclick="addBlankQvProductRow()">
                            <i class="fas fa-plus me-1 text-primary"></i> Satır
                        </button>
                        <button class="btn btn-success btn-sm" style="border-radius:10px;font-weight:700;box-shadow:0 4px 10px rgba(16,185,129,0.2);" onclick="qcSyncProductTotals()">
                            <i class="fas fa-sync me-1"></i> Toplamı Güncelle
                        </button>
                    </div>
                </div>

                {{-- Elle girilen kalemler kataloğa alınsın mı? --}}
                <div id="qc-svc-banner" class="qc-svc-banner" style="display:none;">
                    <div class="qc-svc-banner-ico"><i class="fas fa-wand-magic-sparkles"></i></div>
                    <div class="qc-svc-banner-txt">
                        <b><span id="qc-svc-banner-n">0</span> kalemi elle girdiniz</b> — bunlar ürün kataloğunuzda kayıtlı değil.
                        Kataloğa kaydetmek ister misiniz? Bir daha aramadan, tarih ve fiyatıyla birlikte seçebilirsiniz.
                    </div>
                    <button type="button" class="qc-svc-banner-btn" onclick="qcOpenServiceModalForFirst()">
                        <i class="fas fa-plus me-1"></i> Kataloğa Ekle
                    </button>
                    <button type="button" class="qc-svc-banner-x" onclick="qcDismissSvcBanner()" title="Şimdilik gizle"><i class="fas fa-times"></i></button>
                </div>

                {{-- Kalem tarihinden üretilen kişiye özel kalkış --}}
                <div id="qc-ops-link" class="qc-ops-link" @style(['display:none' => !$privateDepUrl])>
                    <div class="qc-ops-link-ico"><i class="fas fa-diagram-project"></i></div>
                    <div class="qc-ops-link-txt">
                        <b>Bu satış operasyona işlendi</b> — girdiğiniz tarihle <b>kişiye özel kalkış</b> açıldı.
                        Acente takviminde ve operasyon listesinde görünür.
                    </div>
                    <button type="button" class="qc-ops-link-btn" data-url="{{ $privateDepUrl }}" onclick="qcOpenOpsDeparture(this)">
                        <i class="fas fa-arrow-up-right-from-square me-1"></i> Operasyonu Aç
                    </button>
                </div>

                {{-- Katalog kalkışına bağlı satış: operasyon kartına çapraz link --}}
                @if($catalogDepUrl)
                <div class="qc-ops-link is-cat">
                    <div class="qc-ops-link-ico"><i class="fas fa-diagram-project"></i></div>
                    <div class="qc-ops-link-txt">
                        <b>Bu satış bir tur kalkışına bağlı</b> — yolcular kalkışın operasyon kartında listelenir;
                        görev ve kaynak atamalarını oradan yönetebilirsiniz.
                    </div>
                    <button type="button" class="qc-ops-link-btn" data-url="{{ $catalogDepUrl }}" onclick="qcOpenOpsDeparture(this)">
                        <i class="fas fa-arrow-up-right-from-square me-1"></i> Operasyonu Aç
                    </button>
                </div>
                @endif
                <div id="qc-ops-skipped" class="qc-ops-skipped" style="display:none;">
                    <i class="fas fa-circle-info"></i>
                    Tarihi girilmiş <b><span class="qc-ops-skipped-n">0</span> tur kalemi</b> daha var; bir satış tek kalkışa
                    bağlanabildiği için yalnızca ilk kalem operasyona işlendi. Diğerleri takvimde satış kalemi olarak görünür.
                </div>

                {{-- Bağlı kalkış rozeti --}}
                <div id="qc-departure-banner" class="qc-dep-banner" style="display:none;">
                    <div class="qc-dep-icon"><i class="fas fa-calendar-check"></i></div>
                    <div class="qc-dep-info">
                        <div class="qc-dep-title" id="qc-dep-title">—</div>
                        <div class="qc-dep-sub" id="qc-dep-sub">—</div>
                    </div>
                    <div class="qc-dep-badge" id="qc-dep-cap"></div>
                    <button type="button" class="qc-dep-clear" onclick="clearTourDeparture()" title="Kalkış bağını kaldır">
                        <i class="fas fa-times"></i>
                    </button>
                </div>

                <div class="table-responsive qcx-table-wrap">
                    <table class="table align-middle qcx-table" style="font-size:0.88rem;min-width:1080px;">
                        <thead>
                            {{-- Başlık dili defter kartının bölüm başlığıyla (pfx-sec-h) aynı --}}
                            <tr class="qcx-head">
                                <th>Ürün / Hizmet Adı</th>
                                <th class="text-center" style="width:100px;">Adet</th>
                                <th class="text-end" style="width:186px;">Birim Fiyat</th>
                                <th class="text-center" style="width:122px;">İndirim</th>
                                <th class="text-center" style="width:136px;">KDV <small class="qcx-th-sub">oran &amp; dahil mi</small></th>
                                <th class="text-end" style="width:118px;">KDV Tutarı</th>
                                <th class="text-end" style="width:150px;">Toplam</th>
                                <th style="width:36px;"></th>
                            </tr>
                        </thead>
                        <tbody id="qv-products-tbody">
                            <tr id="qv-no-products-row">
                                <td colspan="8" class="text-center py-5 text-muted">
                                    <i class="fas fa-box-open mb-2" style="font-size:2rem;opacity:0.3;display:block;"></i>
                                    Henüz kalem eklenmedi.
                                    <div class="mt-3">
                                        <button type="button" class="btn btn-catalog-open btn-sm" onclick="openProductCatalog(null)">
                                            <i class="fas fa-layer-group me-1"></i> Katalogdan Seç
                                        </button>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>

                {{-- Özet --}}
                <div class="d-flex justify-content-between align-items-center mt-4 border-top pt-3">
                    <span class="text-muted small"><i class="fas fa-info-circle me-1"></i> Ürünleri ekledikten sonra <strong>Toplamı Güncelle</strong> ile Genel sekmesine aktarabilirsiniz.</span>
                    {{-- Özet kutusu da defter dilinde: beyaz kart, ince başlık şeridi --}}
                    <div class="qcx-sum">
                        <div class="d-flex justify-content-between align-items-center mb-2 pb-2 border-bottom">
                            <span class="qcx-sum-l"><i class="fas fa-coins me-1"></i>Toplam Para Birimi</span>
                            <select id="qv-summary-currency" class="qcx-input qcx-select" style="width:auto;" onchange="qcOnSummaryCurrencyChange(this.value)">
                                @foreach($activeCurrencies as $curr)
                                    <option value="{{ $curr->code }}" @selected($curr->code === ($sale?->currency ?: 'TRY'))>{{ $curr->code }}</option>
                                @endforeach
                            </select>
                        </div>
                        <div id="qv-summary-mixed" class="mb-2" style="display:none;font-size:0.72rem;color:#b45309;background:#fffbeb;border:1px solid #fde68a;border-radius:8px;padding:5px 9px;">
                            <i class="fas fa-circle-info me-1"></i> Kalemler farklı para birimlerinde — toplam seçtiğiniz birime çevrilir.
                        </div>
                        <div class="d-flex justify-content-between mb-2" style="font-size:0.82rem;">
                            <span class="text-muted fw-semibold">Ara Toplam:</span>
                            <span class="fw-bold text-dark" id="qv-summary-subtotal">₺0,00</span>
                        </div>
                        <div class="d-flex justify-content-between mb-2" style="font-size:0.82rem;">
                            <span class="text-muted fw-semibold">KDV Toplamı:</span>
                            <span class="fw-bold text-muted" id="qv-summary-tax">₺0,00</span>
                        </div>
                        {{-- İndirim: yüzde veya satış para biriminde tutar --}}
                        @php
                            $qcDiscRate = (float) ($sale?->discount_rate ?? 0);
                            $qcDiscAmt  = (float) ($sale?->discount_amount ?? 0);
                            $qcDiscType = $qcDiscRate > 0 ? 'percent' : 'amount';
                            $qcDiscVal  = $qcDiscRate > 0 ? $qcDiscRate : ($qcDiscAmt > 0 ? $qcDiscAmt : '');
                        @endphp
                        <div class="d-flex justify-content-between align-items-center mb-2" style="font-size:0.82rem;">
                            <span class="text-muted fw-semibold"><i class="fas fa-tag me-1" style="color:#059669;"></i>İndirim:</span>
                            <div class="d-flex align-items-center gap-1">
                                <div class="qc-disc-seg">
                                    <button type="button" data-disc-type="percent" class="{{ $qcDiscType === 'percent' ? 'active' : '' }}" onclick="qcSetDiscountType('percent')" title="Yüzde indirim">%</button>
                                    <button type="button" data-disc-type="amount" class="{{ $qcDiscType === 'amount' ? 'active' : '' }}" onclick="qcSetDiscountType('amount')" title="Tutar indirim (satış para biriminde)"><span id="qc-disc-cur-label">{{ $sale?->currency ?: 'TRY' }}</span></button>
                                </div>
                                <input type="number" id="qc-discount-value" min="0" step="0.01" placeholder="0" value="{{ $qcDiscVal }}"
                                       class="qcx-input text-end" style="width:92px;"
                                       oninput="calculateQvProductTotals()">
                            </div>
                        </div>
                        {{-- Toplam indirim: satır indirimleri + genel indirim --}}
                        <div class="d-flex justify-content-between mb-2" style="font-size:0.82rem;" id="qc-disc-line">
                            <span class="text-muted fw-semibold">İndirim Tutarı:</span>
                            <span class="fw-bold" style="color:#059669;" id="qv-summary-discount">−₺0,00</span>
                        </div>
                        <input type="hidden" id="qc-discount-type" value="{{ $qcDiscType }}">
                        <input type="hidden" id="qc-discount-amount" value="{{ $qcDiscAmt > 0 ? $qcDiscAmt : '' }}">
                        <div class="border-top my-2"></div>
                        <div class="d-flex justify-content-between align-items-center">
                            <span class="text-dark fw-bold" style="font-size:0.95rem;">Genel Toplam:</span>
                            <span class="text-primary fw-extrabold" style="font-size:1.25rem;" id="qv-summary-total">₺0,00</span>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        {{-- ─────────────────────── TAB: FATURALAR ─────────────────────── --}}
        @if($sale)
        <div id="qv-tab-qcinvoices" class="qv-tab-panel">
            <div class="p-4">
                @php
                    $qcNextInvoiceNo = app(\App\Services\Sale\InvoiceNumberService::class)->next($sale->agency);
                @endphp
                <div class="d-flex justify-content-between align-items-center mb-3 pb-2 border-bottom flex-wrap gap-2">
                    <div>
                        <h6 class="qcx-tabtitle mb-0">
                            <i class="fas fa-file-invoice me-2 text-primary"></i>Faturalar
                        </h6>
                        <p class="qcx-tabhint mb-0">
                            Fatura numarası kuralınıza göre otomatik verilir; belgeyi (PDF/görsel/XML) ekleyebilirsiniz.
                        </p>
                    </div>
                    <div class="qc-inv-autonum" title="Fatura numarası, acentenizin numara kuralına göre otomatik oluşturulur. Kuralı Ayarlar → Fatura Şablonu ekranından değiştirebilirsiniz.">
                        <i class="fas fa-hashtag"></i>
                        <span>Sıradaki No</span>
                        <b id="qc-inv-next-no">{{ $qcNextInvoiceNo }}</b>
                    </div>
                </div>

                {{-- Yeni fatura formu --}}
                <form id="qc-invoice-form" class="qc-inv-form" onsubmit="qcInvoiceSubmit(event)">
                    <div class="qc-inv-form-grid">
                        <div class="qc-inv-fld">
                            <label>Tür</label>
                            <select name="invoice_type">
                                @foreach(\App\Models\Sale\SaleInvoice::TYPES as $tv => $tl)
                                    <option value="{{ $tv }}">{{ $tl }}</option>
                                @endforeach
                            </select>
                        </div>
                        @php
                            $qcSuggestedBilling = $sale->customer
                                ? \App\Http\Controllers\Agency\InvoiceController::suggestedBillingType($sale->customer)
                                : 'individual';
                        @endphp
                        <div class="qc-inv-fld">
                            <label>Muhatap</label>
                            <select name="billing_type" title="Şirket seçilse bile müşterinin fatura bilgisi eksikse TC kimlik numarasına (şahıs) kesilir.">
                                <option value="individual" @selected($qcSuggestedBilling === 'individual')>Şahıs (TC)</option>
                                <option value="company" @selected($qcSuggestedBilling === 'company')>Şirket</option>
                            </select>
                        </div>
                        <div class="qc-inv-fld">
                            <label>Kesim Tarihi</label>
                            <input type="date" name="issue_date" required value="{{ now()->format('Y-m-d') }}">
                        </div>
                        <div class="qc-inv-fld">
                            <label>Tutar</label>
                            <input type="number" name="amount" required min="0" step="0.01" value="{{ (float) ($sale->total_amount ?? 0) ?: '' }}" placeholder="0,00">
                        </div>
                        <div class="qc-inv-fld">
                            <label>Para Birimi</label>
                            <select name="currency">
                                @foreach($activeCurrencies as $curr)
                                    <option value="{{ $curr->code }}" @selected($curr->code === ($sale->currency ?: 'TRY'))>{{ $curr->code }}</option>
                                @endforeach
                            </select>
                        </div>
                        <div class="qc-inv-fld">
                            <label>Durum</label>
                            <select name="status">
                                @foreach(\App\Models\Sale\SaleInvoice::STATUSES as $sv2 => $sl2)
                                    <option value="{{ $sv2 }}" @selected($sv2 === 'issued')>{{ $sl2 }}</option>
                                @endforeach
                            </select>
                        </div>
                        <div class="qc-inv-fld" style="grid-column:span 2; display:flex; align-items:flex-end;">
                            <label class="d-flex align-items-center gap-2 mb-1" style="cursor:pointer; text-transform:none; letter-spacing:0;">
                                <input type="checkbox" name="from_sale" value="1" checked style="width:1.05rem; height:1.05rem; cursor:pointer;">
                                <span style="font-size:.78rem; font-weight:700; color:#334155;">Ürün satırlarını fatura kalemi olarak ekle</span>
                            </label>
                        </div>
                        <div class="qc-inv-fld" style="grid-column:span 2;">
                            <label>Belge <small>(PDF · görsel · XML — ops.)</small></label>
                            <input type="file" name="file" accept=".pdf,.jpg,.jpeg,.png,.webp,.xml">
                        </div>
                        <div class="qc-inv-fld" style="grid-column:span 2;">
                            <label>Not <small>(ops.)</small></label>
                            <input type="text" name="notes" maxlength="1000" placeholder="Örn: e-Arşiv, GİB no…">
                        </div>
                        <div class="qc-inv-fld qc-inv-submit">
                            <button type="submit" id="qc-inv-submit-btn">
                                <i class="fas fa-plus me-1"></i> Fatura Ekle
                            </button>
                        </div>
                    </div>
                </form>

                {{-- Fatura listesi --}}
                <div id="qc-invoices-list" class="mt-3">
                    @include('agency.sales.partials.invoices-list', ['sale' => $sale])
                </div>
            </div>
        </div>
        @endif

        {{-- ─────────────────────── TAB: ÖDEMELER ─────────────────────── --}}
        @if($sale)
        <div id="qv-tab-qcpayments" class="qv-tab-panel">
            <div class="p-4">
                @include('agency.payments.partials.payment-list', [
                    'payments' => $sale->payments,
                    'createUrl' => route('agency.payments.quick-create', ['sale' => $sale->id, 'direction' => 'in']),
                    'summary' => [
                        ['label' => 'Satış Tutarı', 'value' => number_format((float) $sale->total_amount, 2, ',', '.') . ' ' . $sale->currency, 'tone' => 'neutral'],
                        ['label' => 'Tahsil Edilen', 'value' => number_format((float) $sale->paid_amount, 2, ',', '.') . ' ' . $sale->currency, 'tone' => 'ok'],
                        ['label' => 'Kalan', 'value' => number_format((float) $sale->remaining_amount, 2, ',', '.') . ' ' . $sale->currency, 'tone' => (float) $sale->remaining_amount > 0 ? 'warn' : 'ok'],
                        ['label' => 'Durum', 'value' => $sale->payment_status_label, 'tone' => $sale->payment_status === 'paid' ? 'ok' : 'warn'],
                    ],
                    'emptyText' => 'Bu satış için henüz tahsilat girilmedi.',
                ])
            </div>
        </div>
        @endif

    </x-quick-view.content>

    {{-- ═══ TEKLİF BELGESİ (teklif mektubu) MODALI ═══ --}}
    @if($sale)
    @php
        $qcDocRenderer = app(\App\Services\Sale\SaleDocumentRenderService::class);
        $qcNextDocNo = $qcDocRenderer->nextNumber($sale->agency);
        $qcDocuments = $sale->offerDocuments()->with('creator:id,first_name,last_name')->get();
    @endphp
    <div class="qcdoc-overlay" id="qcdoc-overlay" hidden>
        <div class="qcdoc-modal">
            <div class="qcdoc-head">
                <div class="qcdoc-head-icon"><i class="fas fa-file-signature"></i></div>
                <div>
                    <div class="qcdoc-title">Teklif Belgesi</div>
                    <div class="qcdoc-sub">Teklif mektubu — fiyatlar ve ürünlerle satış özeti. Şablonu Ayarlar → Teklif Belgesi Şablonu ekranından düzenleyebilirsiniz.</div>
                </div>
                <button type="button" class="qcdoc-x" onclick="qcDocClose()"><i class="fas fa-times"></i></button>
            </div>

            <div class="qcdoc-body">
                <div class="qcdoc-form">
                    <div class="qcdoc-fld">
                        <label>Belge No <small>(kuralınıza göre otomatik — isterseniz değiştirin)</small></label>
                        <input type="text" id="qcdoc-number" maxlength="100" value="{{ $qcNextDocNo }}">
                    </div>
                    <div class="qcdoc-fld">
                        <label>Format</label>
                        <div class="qcdoc-seg" id="qcdoc-format">
                            <button type="button" class="active" data-fmt="pdf"><i class="fas fa-file-pdf"></i> PDF</button>
                            <button type="button" data-fmt="word"><i class="fas fa-file-word"></i> Word</button>
                        </div>
                    </div>
                    <button type="button" class="qcdoc-create" id="qcdoc-create-btn" onclick="qcDocCreate()">
                        <i class="fas fa-wand-magic-sparkles"></i> Oluştur ve İndir
                    </button>
                </div>

                <div class="qcdoc-sendrow">
                    <button type="button" class="qcdoc-send" disabled title="Mail modülü hazır olduğunda aktifleşecek">
                        <i class="fas fa-envelope"></i> Mail Gönder <span class="soon">Yakında</span>
                    </button>
                    <button type="button" class="qcdoc-send" disabled title="Mesaj modülü hazır olduğunda aktifleşecek">
                        <i class="fas fa-comment-dots"></i> Mesaj Gönder <span class="soon">Yakında</span>
                    </button>
                </div>

                <div class="qcdoc-list-head">
                    <i class="fas fa-clock-rotate-left"></i> Oluşturulan Belgeler
                    <span class="qcdoc-count" id="qcdoc-count">{{ $qcDocuments->count() }}</span>
                </div>
                <div class="qcdoc-list" id="qcdoc-list">
                    @forelse($qcDocuments as $doc)
                        <div class="qcdoc-row" data-doc-id="{{ $doc->id }}">
                            <div class="qcdoc-row-ico"><i class="fas fa-file-lines"></i></div>
                            <div class="qcdoc-row-main">
                                <b>{{ $doc->document_number }}</b>
                                <small>{{ $doc->created_at?->format('d.m.Y H:i') }}{{ $doc->creator ? ' · ' . $doc->creator->full_name : '' }}</small>
                            </div>
                            <div class="qcdoc-row-acts">
                                <a href="{{ route('agency.sales.offer-documents.preview', [$sale->id, $doc->id]) }}" target="_blank" title="Önizle"><i class="fas fa-eye"></i></a>
                                <a href="{{ route('agency.sales.offer-documents.download', [$sale->id, $doc->id]) }}?format=pdf" title="PDF indir"><i class="fas fa-file-pdf"></i></a>
                                <a href="{{ route('agency.sales.offer-documents.download', [$sale->id, $doc->id]) }}?format=word" title="Word indir"><i class="fas fa-file-word"></i></a>
                                <button type="button" class="danger" onclick="qcDocDelete({{ $doc->id }})" title="Sil"><i class="fas fa-trash-can"></i></button>
                            </div>
                        </div>
                    @empty
                        <div class="qcdoc-empty" id="qcdoc-empty">
                            <i class="fas fa-file-circle-plus"></i>
                            Henüz belge oluşturulmadı.<br><small>Yukarıdan format seçip "Oluştur ve İndir"e basın.</small>
                        </div>
                    @endforelse
                </div>
            </div>
        </div>
    </div>
    @endif

    {{-- ═══ ÜRÜN & HİZMET KATALOĞU MODALI ═══ --}}
    <div class="modal fade qvcat-modal" id="qvProductCatalogModal" tabindex="-1" aria-hidden="true" style="z-index:1065;">
        <div class="modal-dialog qvcat-dialog modal-dialog-centered">
            <div class="modal-content qvcat-content">

                {{-- Header --}}
                <div class="qvcat-header">
                    <div class="qvcat-head-title">
                        <div class="qvcat-head-icon"><i class="fas fa-layer-group"></i></div>
                        <div>
                            <h5>Ürün &amp; Hizmet Kataloğu</h5>
                            <p>Turları tarih &amp; fiyatıyla, ürünleri ve tedarikçi hizmetlerini tek yerden seçin</p>
                        </div>
                    </div>
                    <button type="button" class="qvcat-x" data-bs-dismiss="modal"><i class="fas fa-times"></i></button>
                </div>

                {{-- Tabs --}}
                <div class="qvcat-tabs">
                    <button type="button" class="qvcat-tab active" data-cat-tab="products" onclick="catalogSwitchTab('products', this)">
                        <i class="fas fa-box-open"></i> Ürünler &amp; Turlar
                        <span class="qvcat-tab-count">{{ $products->count() }}</span>
                    </button>
                    <button type="button" class="qvcat-tab" data-cat-tab="suppliers" onclick="catalogSwitchTab('suppliers', this)">
                        <i class="fas fa-handshake"></i> Tedarikçi Hizmetleri
                        <span class="qvcat-tab-count">{{ $supplierCatalog->count() }}</span>
                    </button>
                    <button type="button" class="qvcat-tab" data-cat-tab="extras" onclick="catalogSwitchTab('extras', this)">
                        <i class="fas fa-tags"></i> Ekstra Hizmetler
                        <span class="qvcat-tab-count">{{ ($extraServices ?? collect())->count() }}</span>
                    </button>
                </div>

                {{-- Toolbar --}}
                <div class="qvcat-toolbar">
                    <div class="qvcat-search">
                        <i class="fas fa-search"></i>
                        <input type="text" id="catalogSearchInput" placeholder="Ara: tur veya ürün adı..." oninput="filterCatalog()" autocomplete="off">
                    </div>
                    <select id="catalogTypeFilter" class="qvcat-filter" onchange="filterCatalog()">
                        <option value="">Tüm Ürün Tipleri</option>
                        @foreach($products->pluck('productType')->filter()->unique('id') as $pt)
                            <option value="{{ $pt->id }}">{{ $pt->name }}</option>
                        @endforeach
                    </select>
                    <select id="catalogSupplierFilter" class="qvcat-filter" onchange="filterCatalog()" style="display:none;">
                        <option value="">Tüm Hizmet Tipleri</option>
                        @foreach($supplierCatalog->pluck('type_label', 'type') as $tk => $tl)
                            <option value="{{ $tk }}">{{ $tl }}</option>
                        @endforeach
                    </select>
                    <select id="catalogCurrencyFilter" class="qvcat-filter" onchange="filterCatalog()" style="display:none;">
                        <option value="">Tüm Para Birimleri</option>
                        @foreach($supplierCatalog->pluck('currency')->filter()->unique()->sort()->values() as $cc)
                            <option value="{{ $cc }}">{{ $cc }}</option>
                        @endforeach
                    </select>
                    <select id="catalogExtraFilter" class="qvcat-filter" onchange="filterCatalog()" style="display:none;">
                        <option value="">Tüm Kategoriler</option>
                        @foreach(($extraServices ?? collect())->pluck('category')->filter()->unique('id')->values() as $ec)
                            <option value="{{ $ec->id }}">{{ $ec->name }}</option>
                        @endforeach
                        @if(($extraServices ?? collect())->whereNull('category_id')->isNotEmpty())
                            <option value="0">Kategorisiz</option>
                        @endif
                    </select>
                </div>

                {{-- Body --}}
                <div class="qvcat-body">

                    {{-- ── PANE: ÜRÜNLER & TURLAR ── --}}
                    <div class="qvcat-pane active" id="catPaneProducts">

                        {{-- ürün/tur grid --}}
                        <div id="catalogProductGrid">
                            @forelse($productsByType as $typeName => $typeProducts)
                                <div class="qvcat-group" data-type-name="{{ $typeName }}">
                                    <div class="qvcat-group-head">
                                        <span class="qvcat-group-badge">{{ $typeName }}</span>
                                        <span class="qvcat-group-line"></span>
                                        <span class="qvcat-group-n">{{ $typeProducts->count() }}</span>
                                    </div>
                                    <div class="qvcat-grid">
                                        @foreach($typeProducts as $p)
                                            @php $isTour = \Illuminate\Support\Str::contains($p->productable_type ?? '', ['Tour', 'DayTrip']); @endphp
                                            <div class="qvcat-card catalog-product-item {{ $isTour ? 'is-tour' : '' }}"
                                                 data-name="{{ strtolower($p->name) }}"
                                                 data-type-id="{{ $p->productType?->id }}"
                                                 data-id="{{ $p->id }}"
                                                 data-pname="{{ $p->name }}"
                                                 data-price="{{ $p->base_price }}"
                                                 data-currency="{{ $p->currency }}"
                                                 data-has-dates="{{ $isTour ? 1 : 0 }}"
                                                 onclick="catalogPickProduct(this)">
                                                <div class="qvcat-card-ico"><i class="fas {{ $p->productType?->icon ?? 'fa-box' }}"></i></div>
                                                <div class="qvcat-card-body">
                                                    <div class="qvcat-card-name">{{ $p->name }}</div>
                                                    <div class="qvcat-card-meta">
                                                        @if($isTour)
                                                            <span class="qvcat-chip tour"><i class="fas fa-calendar-days"></i> Tarih &amp; fiyat seç</span>
                                                        @else
                                                            <span class="qvcat-chip"><i class="fas fa-tag"></i> Ürün</span>
                                                        @endif
                                                    </div>
                                                </div>
                                                <div class="qvcat-card-right">
                                                    @if($p->base_price)
                                                        <div class="qvcat-card-price">{{ $isTour ? '~' : '' }}{{ number_format($p->base_price, 0, ',', '.') }} <small>{{ $p->currency }}</small></div>
                                                    @else
                                                        <div class="qvcat-card-price muted">—</div>
                                                    @endif
                                                    <div class="qvcat-card-cta">{{ $isTour ? 'Tarih Seç' : 'Seç' }} <i class="fas fa-chevron-right"></i></div>
                                                </div>
                                            </div>
                                        @endforeach
                                    </div>
                                </div>
                            @empty
                                @if($closedProducts->isEmpty())
                                    <div class="qvcat-empty">
                                        <i class="fas fa-box-open"></i>
                                        <p>Tanımlı ürün bulunamadı.</p>
                                    </div>
                                @endif
                            @endforelse

                            {{-- Satışa kapalı ürünler: gizlemek yerine sebebiyle göster --}}
                            @if($closedProducts->isNotEmpty())
                                <div class="qvcat-group qvcat-closed-group" data-type-name="__closed__">
                                    <div class="qvcat-group-head">
                                        <span class="qvcat-group-badge closed"><i class="fas fa-lock me-1"></i>Satışa kapalı ürünler</span>
                                        <span class="qvcat-group-line"></span>
                                        <span class="qvcat-group-n">{{ $closedProducts->count() }}</span>
                                    </div>
                                    <div class="qvcat-closed-note">
                                        <i class="fas fa-circle-info"></i>
                                        Bu ürünler <b>taslak</b> ya da <b>satışa kapalı</b> durumda olduğu için normalde katalogda çıkmaz.
                                        Ürünün ayarlarından <b>Aktif</b> ve <b>Satılabilir</b> seçeneklerini açtığınızda listenin üstüne taşınır.
                                        Yine de bu satışa ekleyebilirsiniz.
                                    </div>
                                    <div class="qvcat-grid">
                                        @foreach($closedProducts as $p)
                                            @php $isTour = \Illuminate\Support\Str::contains($p->productable_type ?? '', ['Tour', 'DayTrip']); @endphp
                                            <div class="qvcat-card catalog-product-item is-closed {{ $isTour ? 'is-tour' : '' }}"
                                                 data-name="{{ strtolower($p->name) }}"
                                                 data-type-id="{{ $p->productType?->id }}"
                                                 data-id="{{ $p->id }}"
                                                 data-pname="{{ $p->name }}"
                                                 data-price="{{ $p->base_price }}"
                                                 data-currency="{{ $p->currency }}"
                                                 data-has-dates="{{ $isTour ? 1 : 0 }}"
                                                 onclick="catalogPickProduct(this)">
                                                <div class="qvcat-card-ico closed"><i class="fas {{ $p->productType?->icon ?? 'fa-box' }}"></i></div>
                                                <div class="qvcat-card-body">
                                                    <div class="qvcat-card-name">{{ $p->name }}</div>
                                                    <div class="qvcat-card-meta">
                                                        <span class="qvcat-chip warn"><i class="fas fa-triangle-exclamation"></i> {{ $closedReason($p) }}</span>
                                                        <span class="qvcat-chip muted">{{ $p->productType?->name ?? 'Diğer' }}</span>
                                                    </div>
                                                </div>
                                                <div class="qvcat-card-right">
                                                    @if($p->base_price)
                                                        <div class="qvcat-card-price">{{ number_format($p->base_price, 0, ',', '.') }} <small>{{ $p->currency }}</small></div>
                                                    @else
                                                        <div class="qvcat-card-price muted">—</div>
                                                    @endif
                                                    <div class="qvcat-card-cta">{{ $isTour ? 'Tarih Seç' : 'Yine de Seç' }} <i class="fas fa-chevron-right"></i></div>
                                                </div>
                                            </div>
                                        @endforeach
                                    </div>
                                </div>
                            @endif

                            <div id="catalogNoResults" class="qvcat-empty d-none">
                                <i class="fas fa-search"></i>
                                <p>Arama kriterlerine uygun sonuç yok.</p>
                            </div>
                        </div>

                        {{-- tur tarihi drill-down --}}
                        <div id="catalogDateView" style="display:none;">
                            <button type="button" class="qvcat-back" onclick="catalogBackToGrid()"><i class="fas fa-arrow-left"></i> Ürünlere dön</button>
                            <div class="qvcat-date-head">
                                <div class="qvcat-date-head-ico"><i class="fas fa-calendar-star"></i></div>
                                <div>
                                    <div class="qvcat-date-head-name" id="catalogDateTourName">—</div>
                                    <div class="qvcat-date-head-sub">Kalkış tarihi seçip fiyat tipini belirleyin — ya da <b>özel tarih</b> girin.</div>
                                </div>
                            </div>
                            <div id="catalogDateLoading" class="qvcat-date-loading"><i class="fas fa-spinner fa-spin me-2"></i> Tarihler yükleniyor…</div>
                            <div id="catalogDateGrid" class="qvcat-date-grid"></div>
                            <div id="catalogDateNoUpcoming" class="qvcat-date-none d-none">
                                <i class="fas fa-calendar-xmark me-1"></i> Bu tur için yaklaşan kayıtlı kalkış yok. Aşağıdan özel tarih girebilirsiniz.
                            </div>

                            {{-- Fiyat tipi seçici (bir tarih seçilince açılır) --}}
                            <div id="catalogFarePanel" class="qvcat-fare-panel" style="display:none;">
                                <div class="qvcat-fare-head">
                                    <span><i class="fas fa-coins"></i> Fiyat tipleri — <b id="catalogFareDate">—</b></span>
                                    <span class="qvcat-fare-total">Toplam: <b id="catalogFareTotal">0</b></span>
                                </div>
                                {{-- Fiyat hangi pazaryerinden geliyor? Birden fazlaysa seçilebilir. --}}
                                <div id="catalogFareMarket" class="qvcat-fare-mk"></div>
                                <div id="catalogFareRows" class="qvcat-fare-rows"></div>
                                {{-- Konaklamalı turda tek kişi farkı / ek yatak burada girilmez --}}
                                <div id="catalogFareRoomNote" class="qvcat-fare-roomnote" style="display:none;">
                                    <i class="fas fa-bed"></i>
                                    <span><b>Tek kişilik oda farkı</b> ve <b>ek yatak</b> burada girilmez — satış kartındaki
                                    <b>Odalama</b> bölümünde oda kurgusuna göre otomatik hesaplanır ve gerekçesiyle gösterilir.</span>
                                </div>
                                <div class="qvcat-fare-actions">
                                    <button type="button" class="qvcat-fare-cancel" onclick="catalogCloseFares()">Vazgeç</button>
                                    <button type="button" class="qvcat-fare-confirm" onclick="catalogApplyFares()"><i class="fas fa-check me-1"></i> Bu tarihi seç ve ekle</button>
                                </div>
                            </div>

                            {{-- Özel tarih (kayıtlı tarih olmadan sat) --}}
                            <div class="qvcat-customdate">
                                <div class="qvcat-customdate-head" onclick="catalogToggleCustomDate()">
                                    <span><i class="fas fa-calendar-plus"></i> Kayıtlı tarih olmadan sat — <b>özel tarih gir</b></span>
                                    <i class="fas fa-chevron-down" id="catalogCustomChevron"></i>
                                </div>
                                <div id="catalogCustomBody" class="qvcat-customdate-body" style="display:none;">
                                    <div class="qvcat-cd-fields">
                                        <div class="qvcat-cd-fld">
                                            <label>Başlangıç</label>
                                            <input type="date" id="catalogCustomStart" value="{{ date('Y-m-d') }}">
                                        </div>
                                        <div class="qvcat-cd-fld">
                                            <label>Bitiş</label>
                                            <input type="date" id="catalogCustomEnd">
                                        </div>
                                        <div class="qvcat-cd-fld">
                                            <label>Kişi Başı Fiyat</label>
                                            <input type="number" id="catalogCustomPrice" min="0" step="any" placeholder="0">
                                        </div>
                                        <div class="qvcat-cd-fld">
                                            <label>Para Birimi</label>
                                            <select id="catalogCustomCurrency">
                                                @foreach($activeCurrencies as $curr)
                                                    <option value="{{ $curr->code }}">{{ $curr->code }}</option>
                                                @endforeach
                                            </select>
                                        </div>
                                        <button type="button" class="qvcat-cd-apply" onclick="applyCustomTourDate()"><i class="fas fa-check me-1"></i> Uygula</button>
                                    </div>
                                    <div class="qvcat-cd-hint"><i class="fas fa-circle-info"></i> Özel tarihte satış tura bağlanır ama belirli bir kalkışa bağlanmaz. Fiyat ve adetleri kalem tablosunda düzenleyebilirsiniz.</div>
                                </div>
                            </div>
                        </div>

                    </div>

                    {{-- ── PANE: TEDARİKÇİ HİZMETLERİ ── --}}
                    <div class="qvcat-pane" id="catPaneSuppliers">
                        <div id="catalogSupplierGrid">
                            @php $supplierGroups = $supplierCatalog->groupBy('type'); @endphp
                            @forelse($supplierGroups as $typeKey => $items)
                                <div class="qvcat-group" data-sup-type="{{ $typeKey }}">
                                    <div class="qvcat-group-head">
                                        <span class="qvcat-group-badge sup"><i class="fas {{ $items->first()['type_icon'] }} me-1"></i>{{ $items->first()['type_label'] }}</span>
                                        <span class="qvcat-group-line"></span>
                                        <span class="qvcat-group-n">{{ $items->count() }}</span>
                                    </div>
                                    <div class="qvcat-grid">
                                        @foreach($items as $it)
                                            <div class="qvcat-card catalog-supplier-item"
                                                 data-name="{{ strtolower($it['title'].' '.$it['subtitle'].' '.$it['supplier_name']) }}"
                                                 data-sup-type="{{ $it['type'] }}"
                                                 data-id="{{ $it['id'] }}"
                                                 data-title="{{ $it['title'] }}"
                                                 data-price="{{ $it['sale_price'] }}"
                                                 data-currency="{{ $it['currency'] }}"
                                                 data-tax="{{ $it['tax_rate'] }}"
                                                 data-supplier="{{ $it['supplier_name'] }}"
                                                 onclick="catalogPickSupplier(this)">
                                                <div class="qvcat-card-ico sup"><i class="fas {{ $it['type_icon'] }}"></i></div>
                                                <div class="qvcat-card-body">
                                                    <div class="qvcat-card-name">{{ $it['title'] }}</div>
                                                    <div class="qvcat-card-meta">
                                                        @if($it['subtitle'])<span class="qvcat-chip"><i class="fas fa-circle-info"></i> {{ $it['subtitle'] }}</span>@endif
                                                        @if(!empty($it['supplier_id']))
                                                            {{-- Tedarikçi kartına çapraz geçiş (kart tıklaması kalemi seçer) --}}
                                                            <span class="qvcat-chip muted qvcat-chip-link" title="Tedarikçi kartını aç"
                                                                  onclick="event.stopPropagation(); openSupplierDrawer({{ $it['supplier_id'] }})"><i class="fas fa-building"></i> {{ $it['supplier_name'] }}</span>
                                                        @else
                                                            <span class="qvcat-chip muted"><i class="fas fa-building"></i> {{ $it['supplier_name'] }}</span>
                                                        @endif
                                                    </div>
                                                </div>
                                                <div class="qvcat-card-right">
                                                    <div class="qvcat-card-price">{{ number_format($it['sale_price'], 0, ',', '.') }} <small>{{ $it['currency'] }}</small></div>
                                                    <div class="qvcat-card-cta">Ekle <i class="fas fa-chevron-right"></i></div>
                                                </div>
                                            </div>
                                        @endforeach
                                    </div>
                                </div>
                            @empty
                                <div class="qvcat-empty">
                                    <i class="fas fa-handshake-angle"></i>
                                    <p>Aktif tedarikçi fiyat kalemi yok.<br><span style="font-size:0.75rem;">Tedarikçiler modülünden sezon fiyatı girerek buraya ekleyebilirsiniz.</span></p>
                                </div>
                            @endforelse
                            <div id="catalogSupplierNoResults" class="qvcat-empty d-none">
                                <i class="fas fa-search"></i>
                                <p>Arama kriterlerine uygun hizmet yok.</p>
                            </div>
                        </div>
                    </div>

                    {{-- ── PANE: EKSTRA HİZMETLER ── --}}
                    {{-- Acentenin kendi tanımladığı kalemler (Ürünler → Ekstra Hizmetler).
                         Tura bağlı değildir; seçilince satışa ek kalem olarak eklenir. --}}
                    <div class="qvcat-pane" id="catPaneExtras">
                        <div id="catalogExtraGrid">
                            @php
                                $extras = $extraServices ?? collect();
                                // Kategorisizler her zaman en sonda toplansın
                                $extraGroups = $extras->groupBy(fn ($s) => $s->category?->name ?? '__none__')
                                    ->sortBy(fn ($items, $key) => $key === '__none__' ? 'zzzz' : mb_strtolower($key));
                            @endphp
                            @forelse($extraGroups as $groupName => $items)
                                @php $groupCat = $items->first()->category; @endphp
                                <div class="qvcat-group" data-extra-cat="{{ $groupCat?->id ?? 0 }}">
                                    <div class="qvcat-group-head">
                                        <span class="qvcat-group-badge xtra">
                                            <i class="fas fa-folder me-1"></i>{{ $groupCat?->name ?? 'Kategorisiz' }}
                                        </span>
                                        <span class="qvcat-group-line"></span>
                                        <span class="qvcat-group-n">{{ $items->count() }}</span>
                                    </div>
                                    <div class="qvcat-grid">
                                        @foreach($items as $ex)
                                            @php
                                                $exRate = $ex->tax_rate !== null ? (float) $ex->tax_rate : 0;
                                                $exGross = $ex->gross_price;
                                            @endphp
                                            <div class="qvcat-card catalog-extra-item"
                                                 data-name="{{ strtolower($ex->name . ' ' . ($ex->category?->name ?? '') . ' ' . $ex->description) }}"
                                                 data-extra-cat="{{ $ex->category_id ?? 0 }}"
                                                 data-currency="{{ $ex->currency }}"
                                                 data-id="{{ $ex->id }}"
                                                 data-product-id="{{ $ex->product_id }}"
                                                 data-title="{{ $ex->name }}"
                                                 data-price="{{ $ex->price }}"
                                                 data-tax="{{ $exRate }}"
                                                 data-tax-included="{{ $ex->tax_included ? 1 : 0 }}"
                                                 onclick="catalogPickExtra(this)">
                                                <div class="qvcat-card-ico xtra"><i class="fas fa-tags"></i></div>
                                                <div class="qvcat-card-body">
                                                    <div class="qvcat-card-name">{{ $ex->name }}</div>
                                                    <div class="qvcat-card-meta">
                                                        @if($ex->unit_label)
                                                            <span class="qvcat-chip"><i class="fas fa-ruler"></i> {{ $ex->unit_label }}</span>
                                                        @endif
                                                        @if($ex->tax_rate === null)
                                                            <span class="qvcat-chip muted"><i class="fas fa-percent"></i> Vergisiz</span>
                                                        @else
                                                            <span class="qvcat-chip"><i class="fas fa-percent"></i> {{ $ex->tax_label }}{{ $ex->tax_included ? ' · dahil' : '' }}</span>
                                                        @endif
                                                        @if($ex->description)
                                                            <span class="qvcat-chip muted">{{ Str::limit($ex->description, 42) }}</span>
                                                        @endif
                                                    </div>
                                                </div>
                                                <div class="qvcat-card-right">
                                                    <div class="qvcat-card-price">{{ number_format((float) $ex->price, 0, ',', '.') }} <small>{{ $ex->currency }}</small></div>
                                                    @if($ex->tax_rate !== null && !$ex->tax_included)
                                                        <div class="qvcat-card-sub">Brüt {{ number_format($exGross, 0, ',', '.') }}</div>
                                                    @endif
                                                    <div class="qvcat-card-cta">Ekle <i class="fas fa-chevron-right"></i></div>
                                                </div>
                                            </div>
                                        @endforeach
                                    </div>
                                </div>
                            @empty
                                <div class="qvcat-empty">
                                    <i class="fas fa-tags"></i>
                                    <p>Tanımlı ekstra hizmet yok.<br>
                                        <span style="font-size:0.75rem;">
                                            <a href="{{ route('agency.products.extra-services.index') }}" target="_blank" style="color:#4f46e5;font-weight:700;">Ürünler → Ekstra Hizmetler</a>
                                            bölümünden VQ alan vergisi, vize harcı gibi kalemler ekleyebilirsiniz.
                                        </span>
                                    </p>
                                </div>
                            @endforelse
                            <div id="catalogExtraNoResults" class="qvcat-empty d-none">
                                <i class="fas fa-search"></i>
                                <p>Arama kriterlerine uygun ekstra hizmet yok.</p>
                            </div>
                        </div>
                    </div>

                </div>

                {{-- Footer --}}
                <div class="qvcat-footer">
                    <span class="qvcat-foot-hint"><i class="fas fa-circle-info me-1"></i> Tur seçip tarih belirlerseniz yolcular otomatik olarak operasyona ve tur kalkışına işlenir.</span>
                    <button type="button" class="btn btn-light btn-sm" data-bs-dismiss="modal" style="border-radius:10px;font-weight:700;">Kapat</button>
                </div>

            </div>
        </div>
    </div>

    {{-- ═══ KALEM TARİHİ (tekil / toplu) ═══ --}}
    <div class="modal fade qcdt-modal" id="qcDateModal" tabindex="-1" aria-hidden="true" style="z-index:1070;">
        <div class="modal-dialog modal-dialog-centered qcdt-dialog">
            <div class="modal-content qcdt-content">

                <div class="qcdt-header">
                    <div class="qcdt-head-ico"><i class="fas fa-calendar-day"></i></div>
                    <div class="qcdt-head-txt">
                        <h5 id="qcdt-title">Kalem Tarihi</h5>
                        <p id="qcdt-sub">Bu kalemin gerçekleşeceği tarihi girin.</p>
                    </div>
                    <button type="button" class="qcdt-x" data-bs-dismiss="modal"><i class="fas fa-times"></i></button>
                </div>

                <div class="qcdt-body">
                    {{-- Toplu modda kapsam seçimi --}}
                    <div class="qcdt-scope" id="qcdt-scope" style="display:none;">
                        <label class="qcdt-scope-opt">
                            <input type="radio" name="qcdt_scope" value="empty" checked>
                            <span><b>Yalnızca tarihi olmayan kalemler</b><small>Girilmiş tarihlere dokunulmaz</small></span>
                        </label>
                        <label class="qcdt-scope-opt">
                            <input type="radio" name="qcdt_scope" value="all">
                            <span><b>Tüm kalemler</b><small>Mevcut tarihlerin üzerine yazılır</small></span>
                        </label>
                    </div>

                    <div class="qcdt-grid">
                        <div class="qcdt-fld">
                            <label>Başlangıç Tarihi <span class="req">*</span></label>
                            <input type="date" id="qcdt-start-date">
                        </div>
                        <div class="qcdt-fld">
                            <label>Başlangıç Saati</label>
                            <input type="time" id="qcdt-start-time">
                        </div>
                        <div class="qcdt-fld">
                            <label>Bitiş Tarihi</label>
                            <input type="date" id="qcdt-end-date">
                        </div>
                        <div class="qcdt-fld">
                            <label>Bitiş Saati</label>
                            <input type="time" id="qcdt-end-time">
                        </div>
                    </div>

                    <div class="qcdt-note" id="qcdt-ops-note" style="display:none;">
                        <i class="fas fa-diagram-project"></i>
                        <span>Bu kalem bir <b>tur ürününe</b> bağlı. Tarih girildiğinde satış için
                        <b>kişiye özel bir kalkış</b> açılır; operasyon modülünde ve acente takviminde görünür.
                        Kalkış siteye/satış kataloğuna çıkmaz.</span>
                    </div>
                    <div class="qcdt-note qcdt-note-soft" id="qcdt-cal-note">
                        <i class="fas fa-calendar-check"></i>
                        <span>Girilen tarihler <b>acente takviminde</b> "Satış Kalemi" olarak görünür.</span>
                    </div>
                </div>

                <div class="qcdt-footer">
                    <button type="button" class="qcdt-cancel" data-bs-dismiss="modal">Vazgeç</button>
                    <button type="button" class="qcdt-save" id="qcdt-save-btn" onclick="qcDateSubmit()">
                        <i class="fas fa-check me-1"></i> Tarihi Uygula
                    </button>
                </div>

            </div>
        </div>
    </div>

    {{-- ═══ HİZMETE EKLE (elle girilen kalemi kataloğa kaydet) ═══ --}}
    <div class="modal fade qcsvc-modal" id="qcServiceModal" tabindex="-1" aria-hidden="true" style="z-index:1070;">
        <div class="modal-dialog modal-dialog-centered qcsvc-dialog">
            <div class="modal-content qcsvc-content">

                <div class="qcsvc-header">
                    <div class="qcsvc-head-ico"><i class="fas fa-bookmark"></i></div>
                    <div class="qcsvc-head-txt">
                        <h5>Kataloğa Ekle</h5>
                        <p>Bu kalemi ürün kataloğuna kaydedin — bir dahaki satışta hazır olarak seçin.</p>
                    </div>
                    <button type="button" class="qcsvc-x" data-bs-dismiss="modal"><i class="fas fa-times"></i></button>
                </div>

                <div class="qcsvc-body">
                    <input type="hidden" id="qcsvc-row-idx" value="">

                    {{-- 1 · Ürün tipi --}}
                    <div class="qcsvc-step">
                        <div class="qcsvc-step-head">
                            <span class="qcsvc-step-n">1</span> Bu kalem hangi ürün tipi?
                            <span class="qcsvc-step-hint">Yalnızca acentenizde açık olan tipler</span>
                        </div>
                        <div class="qcsvc-types" id="qcsvc-types">
                            @foreach($serviceTypes as $st)
                                <label class="qcsvc-type">
                                    <input type="radio" name="qcsvc_type" value="{{ $st->id }}" data-code="{{ $st->code }}" onchange="qcSvcTypeChanged()">
                                    <span class="qcsvc-type-face">
                                        <i class="fas {{ $st->icon ?: 'fa-box' }}"></i>
                                        <b>{{ $st->name }}</b>
                                    </span>
                                </label>
                            @endforeach
                        </div>
                        <div class="qcsvc-types-note">
                            <i class="fas fa-circle-info"></i>
                            Aradığınız tip yoksa <b>Ürün Yönetimi → Ürün Tipleri</b> ekranından açabilirsiniz.
                        </div>
                    </div>

                    {{-- 2 · Temel bilgiler --}}
                    <div class="qcsvc-step">
                        <div class="qcsvc-step-head"><span class="qcsvc-step-n">2</span> Ürün bilgileri</div>
                        <div class="qcsvc-grid">
                            <div class="qcsvc-fld qcsvc-span2">
                                <label>Ürün / Hizmet Adı <span class="req">*</span></label>
                                <input type="text" id="qcsvc-name" maxlength="255" placeholder="Örn: Havalimanı Transferi (VIP)">
                            </div>
                            <div class="qcsvc-fld">
                                <label>Birim Fiyat</label>
                                <div class="qcsvc-money">
                                    <input type="number" id="qcsvc-price" min="0" step="any" placeholder="0,00">
                                    <select id="qcsvc-currency">
                                        @foreach($activeCurrencies as $curr)
                                            <option value="{{ $curr->code }}">{{ $curr->code }}</option>
                                        @endforeach
                                    </select>
                                </div>
                            </div>
                            <div class="qcsvc-fld">
                                <label>KDV Oranı</label>
                                <select id="qcsvc-tax">
                                    @foreach($taxRates as $tax)
                                        <option value="{{ (float) $tax->rate }}" @selected($tax->is_default)>%{{ rtrim(rtrim(number_format((float) $tax->rate, 2, '.', ''), '0'), '.') }}</option>
                                    @endforeach
                                </select>
                            </div>
                            <div class="qcsvc-fld qcsvc-span2">
                                <label>Fiyat KDV dahil mi?</label>
                                <div class="qcx-seg qcx-seg-lg" id="qcsvc-taxincl-seg">
                                    <button type="button" data-ti="0" class="active" onclick="qcSvcSetTaxIncl(0)">KDV Hariç</button>
                                    <button type="button" data-ti="1" onclick="qcSvcSetTaxIncl(1)">KDV Dahil</button>
                                </div>
                                <input type="hidden" id="qcsvc-taxincl" value="0">
                            </div>
                        </div>
                    </div>

                    {{-- 3 · Tipe göre özel alanlar --}}
                    <div class="qcsvc-step" id="qcsvc-detail-step" style="display:none;">
                        <div class="qcsvc-step-head">
                            <span class="qcsvc-step-n">3</span> <span id="qcsvc-detail-title">Tarih &amp; konum bilgileri</span>
                            <small class="qcsvc-step-hint">Seçtiğiniz ürün tipine göre değişir — boş bırakabilirsiniz</small>
                        </div>
                        <div class="qcsvc-grid" id="qcsvc-detail-grid"></div>
                    </div>

                    {{-- 4 · Not --}}
                    <div class="qcsvc-step">
                        <div class="qcsvc-step-head"><span class="qcsvc-step-n">4</span> Not <small class="qcsvc-step-hint">opsiyonel</small></div>
                        <textarea id="qcsvc-notes" rows="2" maxlength="2000" placeholder="Bu hizmetle ilgili hatırlatma, tedarikçi bilgisi, iptal koşulu…"></textarea>
                    </div>
                </div>

                <div class="qcsvc-footer">
                    <span class="qcsvc-foot-hint"><i class="fas fa-circle-info me-1"></i> Kaydedilen kalem katalogda anında görünür ve bu satır ona bağlanır.</span>
                    <div class="d-flex gap-2">
                        <button type="button" class="qcsvc-cancel" data-bs-dismiss="modal">Vazgeç</button>
                        <button type="button" class="qcsvc-save" id="qcsvc-save-btn" onclick="qcSvcSubmit()"><i class="fas fa-check me-1"></i> Kataloğa Kaydet</button>
                    </div>
                </div>

            </div>
        </div>
    </div>

</x-quick-view.layout>

{{-- Ortak katman: künye satırlarının stili ve tıkla-düzenle davranışı
     components/quick-view/ledger-ui'de. Kart burada JS yazmaz. --}}
@include('components.quick-view.ledger-ui')

{{-- ═══ CSS ═══ --}}
<style>
    /* ═══ HEADER ═══
       Başlık şeridinin kendisi ortak bileşende (quick-view/header → .slim).
       Burada yalnızca satış kartına özgü rozetler kalır. */
    .sqv-code{font-weight:800;color:#94a3b8;font-size:0.6rem;letter-spacing:0.06em;background:#f1f5f9;border:1px solid #e2e8f0;padding:2px 8px;border-radius:6px;}
    .sqv-dot{color:#cbd5e1;font-weight:700;}
    /* Header'daki müşteri adı → müşteri kartı */
    .sqv-customer-link{color:#059669;font-weight:700;font-size:0.76rem;text-decoration:none;transition:color .15s;}
    .sqv-customer-link:hover{color:#047857;text-decoration:underline;}
    #qc-customer-label{font-size:0.76rem;color:#94a3b8;font-weight:600;}
    #qc-customer-label i{color:#cbd5e1;margin-right:2px;}
    /* Aşama rozeti: pipeline ile aynı yeşil dil, header'da tek bakışlık özet */
    .sqv-stat-chip{font-size:0.66rem;font-weight:800;color:#047857;background:#ecfdf5;border:1px solid #d1fae5;border-radius:20px;padding:2px 10px;white-space:nowrap;}
    /* Belge oluştur düğmesi ortak aksiyon şeridinde duruyor; yüksekliği ona uysun */
    .qv-header.slim .sqv-docbtn{height:30px;}
    /* Müşteri seçicisinin yanındaki "kartını aç" ikonu (inline-edit alanı linke çevrilmez) */
    .qc-cust-jump{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;flex-shrink:0;border-radius:8px;color:#94a3b8;font-size:0.72rem;transition:all .15s;}
    .qc-cust-jump:hover{color:#059669;background:#d1fae5;}

    /* ═══ DEFTER (pfx) — satış kartına özgü küçük eklemeler ═══ */
    /* Zorunlu alan işareti kart başlığında */
    .qc-req{color:#dc2626;font-weight:800;}
    /* Notlar: iki Quill editörü tek kartta; etiketler satır etiketleriyle aynı dil */
    .qc-note-l{display:block;font-size:.66rem;font-weight:800;color:#94a3b8;text-transform:uppercase;letter-spacing:.05em;margin-bottom:5px;}
    .qc-notes .rte-wrap{border:1px solid #e6ecf5;border-radius:12px;overflow:hidden;background:#fff;}
    .pfx-notes-hint{margin:.6rem 0 0;font-size:.68rem;font-weight:600;color:#94a3b8;line-height:1.5;}
    /* Cari şeridi künye kartının altında serbest durur */
    .qc-credit{margin-bottom:1rem;}
    /* Alanların gerçek karşılıkları hiçbir koşulda çizilmez (yalnızca değer taşırlar) */
    .qc-fields{display:none !important;}

    /* ═══ PIPELINE (ince stepper) ═══
       Sekme şeridinin hemen altında, içerikten ince bir çizgiyle ayrılmış
       kendi bandında durur: aşama tüm sekmelerde görünür kalmalı. */
    .sqv-pipeline-wrap{flex-shrink:0;padding:0.5rem 1.25rem 0.6rem;background:#fff;border-bottom:1px solid #eef2f7;}
    .sqv-pipeline{display:flex;width:100%;--sqv-arrow:13px;--sqv-seam:3px;}
    /* Her aşamanın sağ kenarı ok ucu, sol kenarı aynı açıda çentik → akış yönü */
    .sqv-seg{flex:1 1 0;min-width:0;display:flex;align-items:center;justify-content:center;gap:6px;padding:0.4rem 0.5rem 0.4rem calc(var(--sqv-arrow) + 0.3rem);cursor:pointer;transition:background .25s cubic-bezier(.4,0,.2,1),filter .2s,color .2s;position:relative;z-index:1;min-height:30px;background:#f1f5f9;margin-left:calc(var(--sqv-seam) - var(--sqv-arrow));clip-path:polygon(0 0,calc(100% - var(--sqv-arrow)) 0,100% 50%,calc(100% - var(--sqv-arrow)) 100%,0 100%,var(--sqv-arrow) 50%);}
    .sqv-seg:first-child{margin-left:0;padding-left:0.6rem;border-radius:8px 0 0 8px;clip-path:polygon(0 0,calc(100% - var(--sqv-arrow)) 0,100% 50%,calc(100% - var(--sqv-arrow)) 100%,0 100%);}
    .sqv-seg:last-child{border-radius:0 8px 8px 0;clip-path:polygon(0 0,100% 0,100% 100%,0 100%,var(--sqv-arrow) 50%);}
    .sqv-seg-dot{width:6px;height:6px;border-radius:50%;background:#cbd5e1;flex-shrink:0;transition:.2s;}
    .sqv-seg-label{font-size:0.66rem;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;letter-spacing:0.01em;}
    .sqv-seg.done{background:#d1fae5;z-index:3;}
    .sqv-seg.done .sqv-seg-dot{background:#10b981;}
    .sqv-seg.done .sqv-seg-label{color:#047857;}
    .sqv-seg.current{background:linear-gradient(135deg,#34d399,#10b981);z-index:4;filter:drop-shadow(0 3px 8px rgba(16,185,129,0.3));}
    .sqv-seg.current .sqv-seg-dot{background:#fff;box-shadow:0 0 0 3px rgba(255,255,255,0.35);}
    .sqv-seg.current .sqv-seg-label{color:#fff;font-weight:800;}
    .sqv-seg.future{background:#f1f5f9;}
    .sqv-seg.future .sqv-seg-label{color:#94a3b8;}
    .sqv-seg.done:hover,.sqv-seg.current:hover{z-index:5;filter:brightness(1.05) drop-shadow(0 4px 10px rgba(16,185,129,0.32));}
    .sqv-seg.future:hover{background:#e2e8f0;z-index:5;}
    .sqv-seg.future:hover .sqv-seg-label{color:#64748b;}
    @media (max-width:767px){.sqv-pipeline{overflow-x:auto;justify-content:flex-start;}.sqv-seg{flex:0 0 auto;padding-right:calc(var(--sqv-arrow) + 0.3rem);}}

    /* ═══ KART KABUKLARI ═══
       Genel sekmesindeki alanlar artık ortak defter kartında (pfx). Aşağıdaki
       .sqv-card yalnızca hâlâ tablo/ızgara barındıran bloklar (odalama,
       ürün özeti) için duruyor. */
    .sqv-card{background:#fff;border:1px solid #e6ecf5;border-radius:16px;padding:1.25rem;box-shadow:0 1px 2px rgba(15,23,42,0.04);}
    /* Başlık dili defter kartının başlık şeridiyle (pfx-top-t) aynı ölçüde */
    .sqv-card-title{font-weight:800;font-size:0.8rem;color:#0f172a;letter-spacing:-0.01em;margin-bottom:0.9rem;display:block;}

    /* ═══ SATIŞ KALEMLERİ TABLOSU — defter (ledger) diliyle ═══
       Künye satırlarındaki kural burada da geçerli: alan boştayken DEĞER gibi
       görünür, çerçevesi yoktur. Kutu ancak üzerine gelince belirir, odakta
       mavi halkayla açılır. Böylece tabloya bakan göz sekiz ayrı input kutusu
       değil, okunabilir bir tutar listesi görüyor.
       Kopyalama düğmesi YOK: bu alanlar zaten doğrudan yazılabiliyor. */
    .qcx-table{border-collapse:separate;border-spacing:0;}
    .qcx-head{border-bottom:1px solid #eef2f7;}
    .qcx-head th{font-size:0.6rem;font-weight:800;letter-spacing:0.11em;text-transform:uppercase;color:#94a3b8;}
    .qcx-table > thead th{padding-bottom:0.5rem;vertical-align:bottom;}
    .qcx-th-sub{display:block;font-size:0.56rem;font-weight:600;letter-spacing:0.02em;text-transform:none;color:#c3cddc;margin-top:1px;}
    .qcx-table > tbody > tr > td{padding:0.2rem 0.35rem;border-bottom:1px solid #f4f7fb;vertical-align:top;}
    /* Tüm hücrelerin ilk satırı aynı hizada: kontroller ~30px bandına oturur */
    .qcx-table > tbody > tr > td .qcx-out{margin-top:6px;}
    .qcx-table > tbody > tr > td .qcx-out-strong{margin-top:4px;}
    .qcx-table > tbody > tr > td .qcx-del{margin-top:3px;}
    .qcx-table > tbody > tr > td:first-child{padding-left:0;}
    .qcx-table > tbody > tr > td:last-child{padding-right:0;}
    .qv-product-row{transition:background .12s;}
    .qv-product-row:hover{background:#f7faff;}

    /* Okuma hâli: değer gibi. Hover: hafif kutu. Odak: pfx-in ile aynı halka. */
    .qcx-input{width:100%;background:transparent;border:1.5px solid transparent;border-radius:7px;
        padding:0.28rem 0.42rem;font-size:0.815rem;font-weight:650;color:#0f172a;line-height:1.35;
        transition:border-color .13s,box-shadow .13s,background .13s;appearance:none;}
    .qcx-input::placeholder{color:#c3cddc;font-weight:500;font-style:italic;}
    .qcx-input:hover{background:#fff;border-color:#dbe6f7;}
    .qcx-input:focus{outline:none;background:#fff;border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.18);}
    /* Fiyatı girilmiş ama adı boş satır: kaydedilmeyeceği için uyarı çerçevesi */
    .qv-product-row.qcx-unnamed .qcx-name{border-color:#f87171;background:#fef2f2;}
    .qv-product-row.qcx-unnamed .qcx-name::placeholder{color:#f87171;font-weight:700;font-style:normal;}
    .qcx-name{font-weight:700;}
    .qcx-num{text-align:center;font-variant-numeric:tabular-nums;}
    .qcx-select{padding-right:1.15rem;text-align:center;cursor:pointer;
        background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='%23c3cddc'%3E%3Cpath d='M4.5 6.5 8 10l3.5-3.5z'/%3E%3C/svg%3E");
        background-repeat:no-repeat;background-position:right 0.25rem center;background-size:13px;}

    /* Birim fiyat: tutar + para birimi TEK alan gibi davranır (ikisi bir değer) */
    .qcx-money{display:flex;align-items:stretch;background:transparent;border:1.5px solid transparent;border-radius:7px;overflow:hidden;transition:border-color .13s,box-shadow .13s,background .13s;}
    .qcx-money:hover{background:#fff;border-color:#dbe6f7;}
    .qcx-money:focus-within{background:#fff;border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.18);}
    .qcx-money .qcx-money-in{flex:1;min-width:0;border:none;border-radius:0;background:transparent;text-align:right;font-weight:700;font-size:0.84rem;color:#0f172a;padding:0.28rem 0.4rem;font-variant-numeric:tabular-nums;}
    .qcx-money .qcx-money-in:hover{background:transparent;border-color:transparent;}
    .qcx-money .qcx-money-in:focus{background:transparent;border-color:transparent;box-shadow:none;}
    .qcx-money-cur{border:none;background:transparent;color:#94a3b8;font-size:0.66rem;font-weight:800;padding:0 0.3rem;cursor:pointer;appearance:none;text-align:center;}
    .qcx-money-cur:focus{outline:none;color:#2563eb;}

    /* KDV hücresi: oran + dahil/hariç */
    .qcx-taxcell{display:flex;flex-direction:column;gap:4px;}

    /* Segmentli anahtar (KDV dahil / hariç) */
    .qcx-seg{display:inline-flex;background:#f1f5f9;border-radius:8px;padding:2px;gap:2px;}
    .qcx-seg button{border:none;background:transparent;color:#94a3b8;font-weight:800;border-radius:6px;cursor:pointer;white-space:nowrap;transition:all .13s;line-height:1.5;}
    .qcx-seg button:hover{color:#475569;}
    .qcx-seg button.active{background:#fff;color:#0f172a;box-shadow:0 1px 2px rgba(15,23,42,0.1);}
    .qcx-seg-sm button{font-size:0.6rem;padding:2px 0;flex:1;}
    .qcx-seg-lg button{font-size:0.7rem;padding:4px 10px;}
    .qcx-seg-sm{width:100%;}
    .qcx-seg button[data-ti="1"].active{color:#1d4ed8;}
    /* Başlıktaki toplu KDV anahtarı defter kartının başlık çipiyle aynı dilde */
    .qcx-master{display:flex;align-items:center;gap:6px;background:#fff;border:1px solid #e2e8f0;border-radius:9px;padding:3px 5px 3px 9px;}
    .qcx-master-lbl{font-size:0.63rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;white-space:nowrap;}
    .qcx-master-lbl i{color:#cbd5e1;margin-right:2px;}
    .qcx-master.is-mixed{border-color:#fde68a;background:#fffdf5;}

    /* Satır çıktıları (KDV tutarı / toplam) — yazılamayan değerler: düz metin */
    .qcx-out{display:inline-block;font-weight:650;font-size:0.815rem;color:#94a3b8;font-variant-numeric:tabular-nums;}
    .qcx-out-strong{font-size:0.86rem;font-weight:800;color:#0f172a;padding:0.28rem 0.1rem;background:none;border:0;}
    .qv-product-row.is-tax-incl .qcx-out-strong{color:#047857;}
    .qcx-del{border:0;background:transparent;color:#c3cddc;width:26px;height:26px;border-radius:6px;cursor:pointer;opacity:0;transition:color .13s,background .13s,opacity .13s;}
    .qv-product-row:hover .qcx-del,.qv-product-row:focus-within .qcx-del{opacity:1;}
    @media (hover:none){.qcx-del{opacity:1;}}
    .qcx-del:hover{color:#dc2626;background:#fef2f2;}

    /* Sekme başlıkları (Ürünler / Faturalar) — künye kartı başlığıyla aynı ölçü */
    .qcx-tabtitle{font-weight:800;font-size:0.86rem;color:#0f172a;letter-spacing:-0.01em;}
    .qcx-tabhint{font-size:0.7rem;color:#94a3b8;font-weight:600;margin-top:2px;}
    .qcx-tabhint i{color:#cbd5e1;}
    .qcx-tabhint strong{color:#64748b;}

    /* Özet kutusu (ara toplam / KDV / indirim / genel toplam) */
    .qcx-sum{width:350px;background:#fff;border:1px solid #e6ecf5;border-radius:16px;padding:0.85rem 0.95rem;box-shadow:0 1px 2px rgba(15,23,42,0.04);}
    .qcx-sum-l{font-size:0.63rem;font-weight:800;letter-spacing:0.06em;text-transform:uppercase;color:#94a3b8;}
    .qcx-sum-l i{color:#cbd5e1;}

    .qv-product-name-cell{display:flex;align-items:center;gap:7px;}
    .qv-product-name-cell .qv-product-name{flex:1;min-width:0;}
    .btn-catalog-pick{display:flex;align-items:center;gap:5px;font-size:0.66rem;font-weight:700;color:#64748b;background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:3px 8px;cursor:pointer;white-space:nowrap;transition:border-color .14s,color .14s,background .14s;flex-shrink:0;opacity:0;}
    .qv-product-row:hover .btn-catalog-pick,.qv-product-row:focus-within .btn-catalog-pick{opacity:1;}
    @media (hover:none){.btn-catalog-pick{opacity:1;}}
    .btn-catalog-pick:hover{border-color:#bfdbfe;color:#1d4ed8;background:#eff6ff;}
    .btn-tosvc{display:flex;align-items:center;gap:5px;font-size:0.7rem;font-weight:800;color:#b45309;background:#fef3c7;border:1px solid #fde68a;border-radius:8px;padding:4px 9px;cursor:pointer;white-space:nowrap;transition:all 0.2s;flex-shrink:0;}
    .btn-tosvc:hover{background:#fde68a;transform:translateY(-1px);}
    .qcx-linked{color:#10b981;font-size:0.7rem;flex-shrink:0;}
    /* Katalog bağı rozeti kartı olan ürünlerde tıklanabilir */
    .qcx-linked.is-openable{cursor:pointer;padding:3px 5px;border-radius:7px;transition:all .15s;}
    .qcx-linked.is-openable:hover{color:#047857;background:#d1fae5;}
    /* Tedarikçi hizmeti kalemi → tedarikçi kartı */
    .qcx-suplink{color:#4f46e5;font-size:0.7rem;flex-shrink:0;cursor:pointer;padding:3px 5px;border-radius:7px;transition:all .15s;}
    .qcx-suplink:hover{color:#3730a3;background:#eef2ff;}

    /* "Bu kalemleri kataloğa ekleyelim mi?" bandı */
    .qc-svc-banner{display:flex;align-items:center;gap:0.8rem;background:linear-gradient(135deg,#fffbeb,#fef9ec);border:1.5px solid #fde68a;border-radius:14px;padding:0.7rem 0.85rem;margin-bottom:0.9rem;}
    .qc-svc-banner-ico{width:34px;height:34px;flex-shrink:0;border-radius:10px;display:grid;place-items:center;background:#fef3c7;color:#d97706;font-size:0.9rem;}
    .qc-svc-banner-txt{flex:1;min-width:0;font-size:0.75rem;line-height:1.5;color:#92400e;}
    .qc-svc-banner-btn{flex-shrink:0;border:none;border-radius:10px;font-weight:800;font-size:0.75rem;color:#fff;background:linear-gradient(135deg,#f59e0b,#d97706);padding:0.45rem 0.9rem;cursor:pointer;box-shadow:0 4px 12px rgba(217,119,6,0.28);transition:transform .15s,box-shadow .15s;}
    .qc-svc-banner-btn:hover{transform:translateY(-1px);box-shadow:0 8px 18px rgba(217,119,6,0.34);}
    .qc-svc-banner-x{flex-shrink:0;border:none;background:transparent;color:#d6b163;font-size:0.8rem;cursor:pointer;padding:4px;}
    .qc-svc-banner-x:hover{color:#92400e;}

    /* ═══ HİZMETE EKLE MODALI ═══ */
    .qcsvc-dialog{max-width:660px;}
    .qcsvc-content{border:none;border-radius:22px;overflow:hidden;box-shadow:0 30px 70px rgba(15,23,42,0.28);}
    .qcsvc-header{display:flex;align-items:center;gap:0.9rem;padding:1.15rem 1.4rem;background:linear-gradient(135deg,#0f172a,#1e293b);}
    .qcsvc-head-ico{width:42px;height:42px;flex-shrink:0;border-radius:13px;display:grid;place-items:center;font-size:1.05rem;color:#fbbf24;background:rgba(251,191,36,0.16);border:1px solid rgba(251,191,36,0.22);}
    .qcsvc-head-txt{flex:1;min-width:0;}
    .qcsvc-head-txt h5{margin:0;color:#fff;font-size:1.02rem;font-weight:800;letter-spacing:-0.01em;}
    .qcsvc-head-txt p{margin:2px 0 0;color:#94a3b8;font-size:0.72rem;}
    .qcsvc-x{border:none;background:rgba(255,255,255,0.08);color:#cbd5e1;width:32px;height:32px;border-radius:10px;cursor:pointer;flex-shrink:0;transition:all .15s;}
    .qcsvc-x:hover{background:rgba(255,255,255,0.16);color:#fff;}

    .qcsvc-body{padding:1.15rem 1.4rem;background:#f8fafc;max-height:62vh;overflow-y:auto;}
    .qcsvc-step{margin-bottom:1.1rem;}
    .qcsvc-step:last-child{margin-bottom:0;}
    .qcsvc-step-head{display:flex;align-items:center;gap:8px;font-size:0.8rem;font-weight:800;color:#1e293b;margin-bottom:0.6rem;}
    .qcsvc-step-n{width:20px;height:20px;flex-shrink:0;border-radius:7px;display:grid;place-items:center;font-size:0.68rem;font-weight:800;color:#fff;background:linear-gradient(135deg,#f59e0b,#d97706);}
    .qcsvc-step-hint{font-weight:600;font-size:0.68rem;color:#94a3b8;}

    .qcsvc-types{display:grid;grid-template-columns:repeat(auto-fill,minmax(148px,1fr));gap:0.5rem;}
    .qcsvc-type input{position:absolute;opacity:0;pointer-events:none;}
    .qcsvc-type-face{display:flex;align-items:center;gap:8px;background:#fff;border:1.5px solid #e3e9f2;border-radius:12px;padding:0.55rem 0.7rem;cursor:pointer;transition:all .15s;min-width:0;}
    .qcsvc-type-face i{color:#94a3b8;font-size:0.85rem;flex-shrink:0;transition:color .15s;}
    .qcsvc-type-face b{font-size:0.76rem;font-weight:700;color:#475569;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qcsvc-type-face:hover{border-color:#cfd9e6;transform:translateY(-1px);}
    .qcsvc-type input:checked + .qcsvc-type-face{border-color:#f59e0b;background:#fffbeb;box-shadow:0 4px 12px rgba(217,119,6,0.16);}
    .qcsvc-type input:checked + .qcsvc-type-face i{color:#d97706;}
    .qcsvc-type input:checked + .qcsvc-type-face b{color:#92400e;}
    .qcsvc-type input:focus-visible + .qcsvc-type-face{box-shadow:0 0 0 3.5px rgba(245,158,11,0.22);}
    /* Kalem tarihinden üretilen kişiye özel kalkış bildirimi */
    .qc-ops-link{display:flex;align-items:center;gap:0.75rem;margin-bottom:0.85rem;padding:0.7rem 0.9rem;border-radius:14px;
        background:linear-gradient(135deg,#fff1f2,#ffe4e6);border:1px solid #fecdd3;}
    .qc-ops-link-ico{width:34px;height:34px;flex-shrink:0;border-radius:11px;display:grid;place-items:center;
        background:linear-gradient(135deg,#f43f5e,#e11d48);color:#fff;font-size:0.85rem;box-shadow:0 5px 13px rgba(225,29,72,0.32);}
    .qc-ops-link-txt{flex:1;min-width:0;font-size:0.74rem;line-height:1.5;color:#881337;font-weight:600;}
    .qc-ops-link-txt b{font-weight:800;color:#9f1239;}
    .qc-ops-link-btn{flex-shrink:0;border:none;background:#e11d48;color:#fff;font-weight:800;font-size:0.74rem;
        border-radius:10px;padding:0.42rem 0.9rem;cursor:pointer;box-shadow:0 4px 12px rgba(225,29,72,0.3);}
    .qc-ops-link-btn:hover{background:#be123c;}
    /* Katalog kalkışına bağlı satış banner'ı: özel kalkıştan farklı, zümrüt dilde */
    .qc-ops-link.is-cat{background:linear-gradient(135deg,#ecfdf5,#d1fae5);border-color:#a7f3d0;}
    .qc-ops-link.is-cat .qc-ops-link-ico{background:linear-gradient(135deg,#10b981,#059669);box-shadow:0 5px 13px rgba(5,150,105,0.32);}
    .qc-ops-link.is-cat .qc-ops-link-txt{color:#065f46;}
    .qc-ops-link.is-cat .qc-ops-link-txt b{color:#047857;}
    .qc-ops-link.is-cat .qc-ops-link-btn{background:#059669;box-shadow:0 4px 12px rgba(5,150,105,0.3);}
    .qc-ops-link.is-cat .qc-ops-link-btn:hover{background:#047857;}
    .qc-ops-skipped{display:flex;align-items:flex-start;gap:7px;margin-bottom:0.85rem;padding:0.55rem 0.8rem;border-radius:12px;
        background:#fffbeb;border:1px solid #fde68a;font-size:0.72rem;line-height:1.5;color:#92400e;font-weight:600;}
    .qc-ops-skipped i{color:#d97706;margin-top:2px;flex-shrink:0;}

    /* ═══ KALEM TARİHİ ═══ */
    /* Satır içi tarih rozeti — boşken sessiz, doluyken belirgin */
    .qcdt-row{display:flex;align-items:center;gap:6px;margin-top:5px;flex-wrap:wrap;}
    .qcdt-btn{display:inline-flex;align-items:center;gap:5px;border:1.5px dashed #d7dfea;background:#fff;color:#94a3b8;
        font-size:0.7rem;font-weight:700;border-radius:8px;padding:0.22rem 0.55rem;cursor:pointer;transition:all .15s;}
    .qcdt-btn:hover{border-color:#bfdbfe;color:#1d4ed8;background:#eff6ff;}
    .qcdt-btn i{font-size:0.68rem;}
    .qcdt-btn.has-date{border-style:solid;border-color:#bbf7d0;background:#f0fdf4;color:#15803d;}
    .qcdt-clear{border:none;background:transparent;color:#cbd5e1;font-size:0.68rem;cursor:pointer;padding:2px 4px;border-radius:6px;}
    .qcdt-clear:hover{color:#ef4444;background:#fef2f2;}
    .qcdt-ops{display:inline-flex;align-items:center;gap:4px;font-size:0.63rem;font-weight:800;letter-spacing:0.02em;
        color:#be123c;background:#fff1f2;border:1px solid #fecdd3;border-radius:999px;padding:0.12rem 0.5rem;}

    .qcdt-bulk-btn{border:1.5px solid #e2e8f0;background:#fff;color:#475569;font-weight:700;border-radius:10px;}
    .qcdt-bulk-btn:hover{border-color:#bfdbfe;color:#1d4ed8;background:#eff6ff;}

    .qcdt-dialog{max-width:520px;width:96%;}
    .qcdt-content{border:none;border-radius:20px;overflow:hidden;box-shadow:0 28px 70px rgba(2,6,23,0.38);background:#f8fafc;}
    .qcdt-header{display:flex;align-items:center;gap:0.85rem;padding:1.1rem 1.35rem;
        background:linear-gradient(135deg,#0f172a 0%,#1e293b 60%,#065f46 150%);position:relative;overflow:hidden;}
    .qcdt-head-ico{width:38px;height:38px;flex-shrink:0;border-radius:12px;display:grid;place-items:center;
        background:linear-gradient(135deg,#10b981,#059669);color:#fff;font-size:0.95rem;box-shadow:0 6px 16px rgba(16,185,129,0.4);}
    .qcdt-head-txt h5{margin:0;font-size:1rem;font-weight:800;color:#fff;letter-spacing:-0.01em;}
    .qcdt-head-txt p{margin:2px 0 0;font-size:0.72rem;color:#94a3b8;font-weight:600;}
    .qcdt-x{margin-left:auto;width:32px;height:32px;border:none;border-radius:10px;background:rgba(255,255,255,0.1);color:#cbd5e1;cursor:pointer;}
    .qcdt-x:hover{background:rgba(255,255,255,0.2);color:#fff;}

    .qcdt-body{padding:1.1rem 1.35rem;background:#f8fafc;}
    .qcdt-scope{display:flex;flex-direction:column;gap:0.45rem;margin-bottom:1rem;}
    .qcdt-scope-opt{display:flex;align-items:flex-start;gap:9px;background:#fff;border:1.5px solid #e3e9f2;border-radius:12px;
        padding:0.6rem 0.75rem;cursor:pointer;transition:all .15s;}
    .qcdt-scope-opt:hover{border-color:#cfd9e6;}
    .qcdt-scope-opt input{margin-top:3px;accent-color:#10b981;}
    .qcdt-scope-opt b{display:block;font-size:0.8rem;font-weight:800;color:#1e293b;}
    .qcdt-scope-opt small{display:block;font-size:0.68rem;color:#94a3b8;font-weight:600;margin-top:1px;}
    .qcdt-scope-opt:has(input:checked){border-color:#10b981;background:#f0fdf4;box-shadow:0 3px 10px rgba(16,185,129,0.12);}

    .qcdt-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:0.65rem;}
    @media (max-width:480px){.qcdt-grid{grid-template-columns:1fr;}}
    .qcdt-fld{display:flex;flex-direction:column;gap:4px;min-width:0;}
    .qcdt-fld label{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;}
    .qcdt-fld label .req{color:#ef4444;}
    .qcdt-fld input{width:100%;background:#fff;border:1.5px solid #e3e9f2;border-radius:10px;padding:0.46rem 0.65rem;
        font-size:0.86rem;font-weight:700;color:#1e293b;box-shadow:0 1px 2px rgba(15,23,42,0.04);transition:border-color .15s,box-shadow .15s;}
    .qcdt-fld input:focus{outline:none;border-color:#10b981;box-shadow:0 0 0 3.5px rgba(16,185,129,0.14);}

    .qcdt-note{display:flex;align-items:flex-start;gap:8px;margin-top:0.9rem;padding:0.65rem 0.8rem;border-radius:12px;
        background:#fff1f2;border:1px solid #fecdd3;font-size:0.72rem;line-height:1.5;color:#9f1239;font-weight:600;}
    .qcdt-note i{color:#e11d48;margin-top:2px;flex-shrink:0;}
    .qcdt-note b{font-weight:800;}
    .qcdt-note-soft{background:#f0fdf4;border-color:#bbf7d0;color:#166534;}
    .qcdt-note-soft i{color:#16a34a;}

    .qcdt-footer{display:flex;align-items:center;justify-content:flex-end;gap:0.6rem;padding:0.85rem 1.35rem;background:#fff;border-top:1px solid #e2e8f0;}
    .qcdt-cancel{border:1.5px solid #e2e8f0;background:#fff;color:#64748b;font-weight:700;font-size:0.8rem;border-radius:10px;padding:0.45rem 1rem;cursor:pointer;}
    .qcdt-cancel:hover{background:#f1f5f9;}
    .qcdt-save{border:none;background:linear-gradient(135deg,#10b981,#059669);color:#fff;font-weight:800;font-size:0.82rem;
        border-radius:10px;padding:0.45rem 1.2rem;cursor:pointer;box-shadow:0 5px 14px rgba(16,185,129,0.32);}
    .qcdt-save:hover{box-shadow:0 7px 18px rgba(16,185,129,0.42);}

    .qcsvc-types-note{margin-top:0.5rem;font-size:0.68rem;font-weight:600;color:#94a3b8;}
    .qcsvc-types-note i{color:#f59e0b;margin-right:4px;}
    .qcsvc-types-note b{color:#64748b;}

    .qcsvc-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:0.65rem;}
    .qcsvc-span2{grid-column:span 2;}
    @media (max-width:560px){.qcsvc-grid{grid-template-columns:1fr;}.qcsvc-span2{grid-column:span 1;}}
    .qcsvc-fld{display:flex;flex-direction:column;gap:4px;min-width:0;}
    .qcsvc-fld label{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;}
    .qcsvc-fld label .req{color:#ef4444;}
    .qcsvc-fld input,.qcsvc-fld select,.qcsvc-body textarea{width:100%;background:#fff;border:1.5px solid #e3e9f2;border-radius:10px;padding:0.46rem 0.65rem;font-size:0.84rem;font-weight:600;color:#1e293b;
        box-shadow:0 1px 2px rgba(15,23,42,0.04);transition:border-color .15s,box-shadow .15s;}
    .qcsvc-fld input::placeholder,.qcsvc-body textarea::placeholder{color:#b6c2d2;font-weight:500;}
    .qcsvc-fld input:focus,.qcsvc-fld select:focus,.qcsvc-body textarea:focus{outline:none;border-color:#f59e0b;box-shadow:0 0 0 3.5px rgba(245,158,11,0.15);}
    .qcsvc-body textarea{resize:vertical;font-size:0.82rem;}
    .qcsvc-money{display:flex;align-items:stretch;background:#fff;border:1.5px solid #e3e9f2;border-radius:10px;overflow:hidden;box-shadow:0 1px 2px rgba(15,23,42,0.04);transition:border-color .15s,box-shadow .15s;}
    .qcsvc-money:focus-within{border-color:#f59e0b;box-shadow:0 0 0 3.5px rgba(245,158,11,0.15);}
    .qcsvc-money input{flex:1;min-width:0;border:none!important;border-radius:0;box-shadow:none!important;text-align:right;font-weight:800;font-size:0.9rem;}
    .qcsvc-money select{width:auto;border:none!important;border-left:1px solid #eef2f7!important;border-radius:0;box-shadow:none!important;background:#f8fafc;color:#64748b;font-size:0.7rem;font-weight:800;padding:0 0.5rem;}

    .qcsvc-footer{display:flex;align-items:center;justify-content:space-between;gap:0.8rem;padding:0.85rem 1.4rem;background:#fff;border-top:1px solid #eef2f7;}
    .qcsvc-foot-hint{font-size:0.7rem;color:#94a3b8;min-width:0;}
    .qcsvc-cancel{border:none;background:#f1f5f9;color:#475569;font-weight:700;font-size:0.8rem;border-radius:10px;padding:0.5rem 0.95rem;cursor:pointer;transition:background .15s;}
    .qcsvc-cancel:hover{background:#e2e8f0;}
    .qcsvc-save{border:none;background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;font-weight:800;font-size:0.8rem;border-radius:10px;padding:0.5rem 1.1rem;cursor:pointer;white-space:nowrap;
        box-shadow:0 5px 14px rgba(217,119,6,0.3);transition:transform .15s,box-shadow .15s;}
    .qcsvc-save:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 9px 22px rgba(217,119,6,0.36);}
    .qcsvc-save:disabled{opacity:0.65;cursor:default;}

    /* ═══ KATALOG AÇMA BUTONU ═══ */
    .btn-catalog-open{display:inline-flex;align-items:center;gap:6px;border:none;border-radius:10px;font-weight:800;font-size:0.78rem;color:#fff;
        background:linear-gradient(135deg,#10b981,#059669);padding:0.42rem 0.9rem;box-shadow:0 4px 12px rgba(79,70,229,0.28);transition:transform .15s,box-shadow .15s;}
    .btn-catalog-open:hover{color:#fff;transform:translateY(-1px);box-shadow:0 8px 20px rgba(79,70,229,0.36);}

    /* ═══ BAĞLI KALKIŞ ROZETİ ═══ */
    /* ── Faturalar sekmesi ── */
    /* ═══ FATURA FORMU — defter (ledger) diliyle ═══
       Alanlar boştayken değer gibi görünür; kutu hover'da belirir, odakta mavi
       halkayla açılır. Etiketler künye satırının etiketiyle aynı ölçüde. */
    .qc-inv-form{background:#fff;border:1px solid #e6ecf5;border-radius:16px;padding:0.9rem 1rem;box-shadow:0 1px 2px rgba(15,23,42,0.04);}
    .qc-inv-form-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:0.55rem 0.7rem;align-items:end;}
    @media(max-width:900px){.qc-inv-form-grid{grid-template-columns:repeat(2,1fr);}}
    .qc-inv-fld label{display:block;font-size:0.6rem;font-weight:800;letter-spacing:0.08em;text-transform:uppercase;color:#9aa7bb;margin-bottom:0.2rem;}
    .qc-inv-fld label small{text-transform:none;letter-spacing:0;color:#c3cddc;font-weight:600;}
    .qc-inv-fld input,.qc-inv-fld select{width:100%;border:1.5px solid transparent;background:transparent;border-radius:7px;padding:0.28rem 0.42rem;font-size:0.815rem;font-weight:650;color:#0f172a;line-height:1.35;transition:border-color .13s,box-shadow .13s,background .13s;}
    .qc-inv-fld input::placeholder{color:#c3cddc;font-weight:500;font-style:italic;}
    .qc-inv-fld input:hover,.qc-inv-fld select:hover{background:#fff;border-color:#dbe6f7;}
    .qc-inv-fld input:focus,.qc-inv-fld select:focus{outline:none;background:#fff;border-color:#2563eb;box-shadow:0 0 0 3px rgba(37,99,235,.18);}
    /* Dosya alanı tıklanabilir olduğunu belli etmeli: kutusu hep görünür */
    .qc-inv-fld input[type=file]{padding:0.24rem 0.4rem;font-size:0.72rem;font-weight:600;border-color:#e6ecf5;background:#fff;}
    .qc-inv-fld input[type=checkbox]{width:auto;border:0;background:none;}
    .qc-inv-submit{grid-column:1 / -1;display:flex;justify-content:flex-end;}
    .qc-inv-autonum{display:inline-flex;align-items:center;gap:0.4rem;background:#f8fbff;border:1px solid #e2e8f0;border-radius:9px;padding:0.3rem 0.7rem;cursor:help;}
    .qc-inv-autonum i{color:#94a3b8;font-size:0.66rem;}
    .qc-inv-autonum span{font-size:0.6rem;font-weight:800;letter-spacing:0.06em;text-transform:uppercase;color:#94a3b8;}
    .qc-inv-autonum b{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:0.78rem;font-weight:700;color:#0f172a;}
    .qc-inv-submit button{border:none;border-radius:9px;padding:0.42rem 1.05rem;font-size:0.74rem;font-weight:800;color:#fff;background:#2563eb;box-shadow:0 6px 14px -8px rgba(37,99,235,0.85);cursor:pointer;transition:.16s;white-space:nowrap;}
    .qc-inv-submit button:hover{transform:translateY(-1px);filter:brightness(1.06);}
    .qc-inv-submit button:disabled{opacity:.6;transform:none;cursor:wait;}

    .qc-inv-row{display:flex;align-items:center;gap:0.8rem;background:#fff;border:1px solid #e6ecf5;border-radius:14px;padding:0.65rem 0.85rem;margin-bottom:0.6rem;transition:border-color .15s,box-shadow .15s;}
    .qc-inv-row:hover{border-color:#dbe6f7;box-shadow:0 8px 20px -14px rgba(37,99,235,0.35);}
    .qc-inv-row.is-cancelled{opacity:.6;}
    .qc-inv-row.is-clickable{cursor:pointer;}
    .qc-inv-row.is-clickable:hover{transform:translateX(2px);}
    .qc-inv-ico{width:38px;height:38px;border-radius:11px;display:grid;place-items:center;font-size:0.95rem;flex-shrink:0;background:#ecfdf5;color:#059669;}
    .qc-inv-ico.is-refund{background:#fff7ed;color:#ea580c;}
    .qc-inv-main{flex:1;min-width:0;}
    .qc-inv-no{font-size:0.85rem;font-weight:800;color:#0f172a;display:flex;align-items:center;gap:0.45rem;flex-wrap:wrap;}
    .qc-inv-type{font-size:0.6rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#047857;background:#d1fae5;border-radius:20px;padding:1px 8px;}
    .qc-inv-type.is-refund{color:#c2410c;background:#ffedd5;}
    .qc-inv-official{display:inline-flex;align-items:center;gap:4px;font-size:0.6rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;border-radius:20px;padding:1px 8px;border:1px solid transparent;}
    .qc-inv-official.pending{color:#92400e;background:#fef3c7;border-color:#fcd34d;animation:qcInvPulse 2.2s ease-in-out infinite;}
    .qc-inv-official.issued{color:#065f46;background:#d1fae5;border-color:#a7f3d0;}
    .qc-inv-official.cancelled{color:#b91c1c;background:#fee2e2;border-color:#fecaca;}
    @keyframes qcInvPulse{0%,100%{box-shadow:0 0 0 0 rgba(217,119,6,.35);}50%{box-shadow:0 0 0 5px rgba(217,119,6,0);}}
    .qc-inv-issue{display:inline-flex;align-items:center;gap:5px;border:none;cursor:pointer;font-family:inherit;font-size:0.68rem;font-weight:800;padding:0 10px;height:32px;border-radius:9px;color:#fff;background:linear-gradient(135deg,#d97706,#b45309);box-shadow:0 6px 14px -6px rgba(217,119,6,0.6);transition:all .16s ease;white-space:nowrap;}
    .qc-inv-issue:hover{transform:translateY(-1px);filter:brightness(1.08);}

    /* ── Teklif belgesi (teklif mektubu) ── */
    .sqv-docbtn{display:inline-flex;align-items:center;gap:6px;border:none;cursor:pointer;font-family:inherit;font-size:0.72rem;font-weight:800;padding:0 12px;height:32px;border-radius:10px;color:#fff;background:linear-gradient(135deg,#4f46e5,#3730a3);box-shadow:0 6px 14px -6px rgba(79,70,229,0.6);transition:all .16s ease;white-space:nowrap;}
    .sqv-docbtn:hover{transform:translateY(-1px);filter:brightness(1.08);}
    .qcdoc-overlay{position:fixed;inset:0;z-index:1090;display:flex;align-items:center;justify-content:center;background:rgba(2,6,23,0.6);backdrop-filter:blur(4px);padding:20px;animation:qcDocFade .18s ease;}
    @keyframes qcDocFade{from{opacity:0;}to{opacity:1;}}
    .qcdoc-modal{width:100%;max-width:560px;max-height:calc(100vh - 40px);display:flex;flex-direction:column;background:#fff;border-radius:20px;overflow:hidden;box-shadow:0 40px 90px -20px rgba(2,6,23,0.5);animation:qcDocPop .22s cubic-bezier(.22,1,.36,1);}
    @keyframes qcDocPop{from{opacity:0;transform:translateY(16px) scale(.98);}to{opacity:1;transform:none;}}
    .qcdoc-head{display:flex;align-items:flex-start;gap:12px;padding:1.1rem 1.3rem .9rem;}
    .qcdoc-head-icon{width:42px;height:42px;border-radius:13px;flex-shrink:0;display:grid;place-items:center;color:#fff;font-size:1rem;background:linear-gradient(135deg,#4f46e5,#3730a3);box-shadow:0 8px 18px -8px rgba(79,70,229,0.6);}
    .qcdoc-title{font-weight:800;font-size:1.05rem;color:#0f172a;}
    .qcdoc-sub{font-size:0.7rem;font-weight:600;color:#94a3b8;line-height:1.5;margin-top:2px;}
    .qcdoc-x{width:34px;height:34px;margin-left:auto;flex-shrink:0;border:none;border-radius:10px;background:#f1f5f9;color:#64748b;cursor:pointer;transition:.15s;}
    .qcdoc-x:hover{background:#fee2e2;color:#b91c1c;}
    .qcdoc-body{flex:1;overflow-y:auto;padding:0 1.3rem 1.2rem;}
    .qcdoc-form{display:flex;align-items:flex-end;gap:0.7rem;flex-wrap:wrap;background:#f5f6fe;border:1px solid #e0e3f8;border-radius:14px;padding:0.9rem 1rem;}
    .qcdoc-fld{flex:1;min-width:150px;}
    .qcdoc-fld label{display:block;font-size:0.62rem;font-weight:800;letter-spacing:0.05em;text-transform:uppercase;color:#6d74b8;margin-bottom:0.3rem;}
    .qcdoc-fld label small{text-transform:none;letter-spacing:0;font-weight:600;color:#9aa2c8;}
    .qcdoc-fld input{width:100%;border:1.5px solid #dfe3f6;background:#fff;border-radius:10px;padding:0.45rem 0.65rem;font-size:0.82rem;font-weight:700;font-family:'JetBrains Mono',ui-monospace,monospace;color:#1e1b4b;transition:.15s;}
    .qcdoc-fld input:focus{outline:none;border-color:#818cf8;box-shadow:0 0 0 3px rgba(129,140,248,0.15);}
    .qcdoc-seg{display:inline-flex;background:#fff;border:1.5px solid #dfe3f6;border-radius:10px;padding:3px;gap:3px;}
    .qcdoc-seg button{border:none;background:transparent;color:#64748b;font-family:inherit;font-size:0.72rem;font-weight:800;padding:0.35rem 0.8rem;border-radius:8px;cursor:pointer;transition:.14s;display:inline-flex;align-items:center;gap:5px;}
    .qcdoc-seg button.active{background:linear-gradient(135deg,#4f46e5,#3730a3);color:#fff;box-shadow:0 4px 10px -4px rgba(79,70,229,0.5);}
    .qcdoc-create{display:inline-flex;align-items:center;gap:7px;border:none;cursor:pointer;font-family:inherit;font-size:0.78rem;font-weight:800;padding:0.55rem 1.1rem;border-radius:11px;color:#fff;background:linear-gradient(135deg,#4f46e5,#3730a3);box-shadow:0 8px 18px -8px rgba(79,70,229,0.55);transition:.16s;white-space:nowrap;}
    .qcdoc-create:hover{transform:translateY(-1px);filter:brightness(1.07);}
    .qcdoc-create:disabled{opacity:.6;cursor:wait;transform:none;}
    .qcdoc-sendrow{display:flex;gap:0.6rem;margin-top:0.7rem;}
    .qcdoc-send{flex:1;display:inline-flex;align-items:center;justify-content:center;gap:7px;border:1.5px dashed #e2e8f0;background:#f8fafc;color:#94a3b8;font-family:inherit;font-size:0.74rem;font-weight:800;padding:0.55rem;border-radius:11px;cursor:not-allowed;}
    .qcdoc-send .soon{font-size:0.56rem;font-weight:800;text-transform:uppercase;letter-spacing:0.05em;color:#b45309;background:#fef3c7;border:1px solid #fcd34d;border-radius:20px;padding:1px 7px;}
    .qcdoc-list-head{display:flex;align-items:center;gap:7px;font-size:0.72rem;font-weight:800;color:#334155;margin:1.1rem 0 0.5rem;}
    .qcdoc-list-head i{color:#818cf8;}
    .qcdoc-count{min-width:20px;height:20px;padding:0 6px;border-radius:7px;display:inline-flex;align-items:center;justify-content:center;font-size:0.66rem;font-weight:800;color:#4f46e5;background:#eef2ff;border:1px solid #c7d2fe;}
    .qcdoc-row{display:flex;align-items:center;gap:0.7rem;background:#fff;border:1.5px solid #eef2f7;border-radius:12px;padding:0.55rem 0.7rem;margin-bottom:0.45rem;transition:border-color .15s;}
    .qcdoc-row:hover{border-color:#c7d2fe;}
    .qcdoc-row-ico{width:32px;height:32px;border-radius:9px;flex-shrink:0;display:grid;place-items:center;font-size:0.8rem;background:#eef2ff;color:#4f46e5;}
    .qcdoc-row-main{flex:1;min-width:0;}
    .qcdoc-row-main b{display:block;font-size:0.78rem;font-family:'JetBrains Mono',ui-monospace,monospace;color:#1e1b4b;}
    .qcdoc-row-main small{font-size:0.64rem;font-weight:600;color:#94a3b8;}
    .qcdoc-row-acts{display:flex;gap:0.3rem;}
    .qcdoc-row-acts a,.qcdoc-row-acts button{width:28px;height:28px;border-radius:8px;border:1px solid #e2e8f0;background:#fff;color:#64748b;display:grid;place-items:center;font-size:0.68rem;cursor:pointer;text-decoration:none;transition:.14s;}
    .qcdoc-row-acts a:hover{border-color:#818cf8;color:#4f46e5;background:#eef2ff;}
    .qcdoc-row-acts button.danger:hover{border-color:#fecaca;color:#ef4444;background:#fff5f5;}
    .qcdoc-empty{text-align:center;padding:1.4rem 1rem;color:#94a3b8;border:1.5px dashed #e2e8f0;border-radius:12px;font-size:0.76rem;font-weight:700;line-height:1.6;}
    .qcdoc-empty i{display:block;font-size:1.3rem;opacity:.4;margin-bottom:0.4rem;}
    .qcdoc-empty small{font-weight:600;color:#cbd5e1;}

    /* ── Fiyat sınıfı bileti (Yetişkin/Çocuk/Bebek…) — fiyatın altında ── */
    .qcx-fare-slot:not(:empty){margin-top:4px;text-align:right;}
    .qcx-fare-ticket{display:inline-flex;align-items:center;gap:5px;font-size:0.6rem;font-weight:800;text-transform:uppercase;letter-spacing:0.05em;padding:2px 8px;border-radius:6px;border:1px solid transparent;white-space:nowrap;cursor:default;}
    .qcx-fare-ticket i{font-size:0.62rem;padding-right:5px;border-right:1px dashed currentColor;opacity:.75;}
    .qcx-fare-ticket.ft-adult{color:#3730a3;background:#eef2ff;border-color:#c7d2fe;}
    .qcx-fare-ticket.ft-child{color:#b45309;background:#fef3c7;border-color:#fcd34d;}
    .qcx-fare-ticket.ft-infant{color:#be185d;background:#fce7f3;border-color:#fbcfe8;}
    .qcx-fare-ticket.ft-single{color:#475569;background:#f1f5f9;border-color:#e2e8f0;}
    .qcx-fare-ticket.ft-bed{color:#0f766e;background:#ccfbf1;border-color:#99f6e4;}
    .qc-inv-sub{display:flex;align-items:center;gap:0.8rem;flex-wrap:wrap;font-size:0.7rem;color:#94a3b8;font-weight:600;margin-top:2px;}
    .qc-inv-amount{font-size:0.92rem;font-weight:800;color:#0f172a;white-space:nowrap;}
    .qc-inv-amount small{font-size:0.68rem;color:#94a3b8;font-weight:700;}
    .qc-inv-status{border:1.5px solid;border-radius:9px;padding:0.3rem 0.5rem;font-size:0.72rem;font-weight:800;cursor:pointer;transition:.15s;}
    .qc-inv-acts{display:flex;gap:0.35rem;flex-shrink:0;}
    .qc-inv-btn{width:32px;height:32px;border-radius:9px;border:1px solid #e2e8f0;background:#fff;color:#64748b;display:grid;place-items:center;font-size:0.76rem;cursor:pointer;transition:.15s;text-decoration:none;}
    .qc-inv-btn:hover{border-color:#bfdbfe;color:#1d4ed8;background:#eff6ff;}
    .qc-inv-btn.danger:hover{border-color:#fecaca;color:#ef4444;background:#fff5f5;}
    .qc-inv-empty{text-align:center;padding:2.2rem 1rem;color:#94a3b8;border:1.5px dashed #e2e8f0;border-radius:14px;}
    .qc-inv-empty i{font-size:1.8rem;opacity:.35;display:block;margin-bottom:0.6rem;}
    .qc-inv-empty p{font-size:0.82rem;font-weight:700;margin:0;line-height:1.5;}
    .qc-inv-empty small{font-weight:600;color:#cbd5e1;}

    .qc-disc-seg{display:inline-flex;background:#e2e8f0;border-radius:9px;padding:2px;}
    .qc-disc-seg button{border:none;background:transparent;color:#64748b;font-size:0.72rem;font-weight:800;padding:0.28rem 0.55rem;border-radius:7px;cursor:pointer;transition:.15s;line-height:1;}
    .qc-disc-seg button.active{background:#fff;color:#047857;box-shadow:0 1px 3px rgba(15,23,42,0.15);}
    .qc-dep-banner{display:flex;align-items:center;gap:0.85rem;margin-bottom:1rem;padding:0.85rem 1rem;border-radius:14px;
        background:linear-gradient(135deg,#ecfdf5,#ecfdf5);border:1.5px solid #a7f3d0;box-shadow:0 4px 14px rgba(16,185,129,0.08);}
    .qc-dep-icon{width:40px;height:40px;border-radius:12px;flex-shrink:0;display:grid;place-items:center;font-size:1.05rem;color:#fff;background:linear-gradient(135deg,#10b981,#047857);}
    .qc-dep-info{flex:1;min-width:0;}
    .qc-dep-title{font-weight:800;font-size:0.9rem;color:#312e81;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qc-dep-sub{font-size:0.74rem;color:#047857;font-weight:600;margin-top:2px;}
    .qc-dep-badge{flex-shrink:0;font-size:0.72rem;font-weight:800;color:#047857;background:#fff;border:1px solid #a7f3d0;border-radius:20px;padding:5px 11px;}
    .qc-dep-clear{flex-shrink:0;width:30px;height:30px;border-radius:9px;border:none;background:rgba(16,185,129,0.12);color:#10b981;cursor:pointer;transition:.15s;}
    .qc-dep-clear:hover{background:#ef4444;color:#fff;}

    /* Genel sekmesi — otomatik doldurma notu */
    .qc-autofill-note{display:flex;align-items:flex-start;gap:0.7rem;margin-bottom:1.1rem;padding:0.8rem 1rem;border-radius:14px;background:linear-gradient(135deg,#ecfdf5,#faf5ff);border:1px solid #d1fae5;}
    .qc-autofill-ico{width:34px;height:34px;border-radius:10px;flex-shrink:0;display:grid;place-items:center;font-size:0.9rem;color:#fff;background:linear-gradient(135deg,#34d399,#10b981);}
    .qc-autofill-txt{font-size:0.78rem;color:#047857;line-height:1.5;font-weight:500;}
    .qc-autofill-txt b{color:#065f46;font-weight:800;}
    .qc-autofill-txt u{text-decoration-color:#6ee7b7;}

    /* ═══ MÜŞTERİ SEÇİCİ (aranabilir) ═══ */
    .qc-cust-picker{position:relative;}
    .qc-cust-trigger{display:flex;align-items:center;gap:0.7rem;width:100%;border:1.5px solid #e2e8f0;background:#fff;border-radius:12px;padding:0.55rem 0.75rem;cursor:pointer;transition:.15s;text-align:left;}
    .qc-cust-trigger:hover{border-color:#a7f3d0;}
    .qc-cust-trigger.open,.qc-cust-trigger.selected{border-color:#10b981;box-shadow:0 0 0 3px rgba(16,185,129,0.1);}
    .qc-cust-tr-ico{width:34px;height:34px;border-radius:10px;flex-shrink:0;display:grid;place-items:center;font-size:0.82rem;font-weight:800;color:#94a3b8;background:#f1f5f9;}
    .qc-cust-tr-ico.has{color:#fff;background:linear-gradient(135deg,#10b981,#047857);}
    .qc-cust-tr-txt{flex:1;min-width:0;font-size:0.86rem;font-weight:600;color:#64748b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qc-cust-tr-txt b{color:#1e293b;font-weight:700;}
    .qc-cust-tr-sub{color:#94a3b8;font-weight:600;font-size:0.78rem;}
    .qc-cust-caret{color:#94a3b8;font-size:0.72rem;flex-shrink:0;transition:transform .2s;}
    .qc-cust-trigger.open .qc-cust-caret{transform:rotate(180deg);}
    .qc-cust-dropdown{display:none;position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:60;background:#fff;border:1px solid #e2e8f0;border-radius:14px;box-shadow:0 18px 44px rgba(15,23,42,0.16);overflow:hidden;}
    .qc-cust-dropdown.open{display:block;animation:qcCustIn .15s ease;}
    @keyframes qcCustIn{from{opacity:0;transform:translateY(-5px);}to{opacity:1;transform:none;}}
    .qc-cust-search{display:flex;align-items:center;gap:8px;padding:0.65rem 0.8rem;border-bottom:1px solid #f1f5f9;}
    .qc-cust-search i{color:#94a3b8;font-size:0.82rem;}
    .qc-cust-search input{flex:1;border:none;outline:none;font-size:0.86rem;font-weight:600;color:#1e293b;background:none;}
    .qc-cust-list{max-height:270px;overflow-y:auto;padding:0.35rem;}
    .qc-cust-row{display:flex;align-items:center;gap:0.7rem;padding:0.5rem 0.55rem;border-radius:10px;cursor:pointer;transition:background .12s;}
    .qc-cust-row:hover{background:#f5f7ff;}
    .qc-cust-av{width:36px;height:36px;border-radius:10px;flex-shrink:0;display:grid;place-items:center;font-size:0.76rem;font-weight:800;color:#059669;background:#ecfdf5;}
    .qc-cust-meta{flex:1;min-width:0;}
    .qc-cust-name{font-weight:700;font-size:0.85rem;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qc-cust-sub{font-size:0.73rem;color:#94a3b8;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qc-cust-pick{color:#cbd5e1;font-size:0.88rem;flex-shrink:0;}
    .qc-cust-row:hover .qc-cust-pick{color:#10b981;}
    .qc-cust-loading,.qc-cust-empty{padding:1.4rem 1rem;text-align:center;color:#94a3b8;font-size:0.83rem;font-weight:600;}
    .qc-cust-addnew{width:100%;border:none;border-top:1px solid #f1f5f9;background:#fafbff;color:#059669;font-size:0.77rem;font-weight:600;padding:0.6rem;cursor:pointer;transition:.15s;}
    .qc-cust-addnew:hover{background:#ecfdf5;}
    .qc-cust-addnew b{font-weight:800;}

    /* ── Çoklu müşteri çipleri ── */
    .qc-custchips{display:flex;flex-direction:column;gap:0.4rem;margin-bottom:0.5rem;}
    .qc-custchips:empty{display:none;}
    .qc-custchip{display:flex;align-items:center;gap:0.6rem;border:1.5px solid #e2e8f0;background:#fff;border-radius:12px;padding:0.45rem 0.55rem 0.45rem 0.6rem;transition:border-color .15s,box-shadow .15s;}
    .qc-custchip:hover{border-color:#a7f3d0;}
    .qc-custchip.is-primary{border-color:#10b981;box-shadow:0 0 0 3px rgba(16,185,129,0.08);}
    .qc-custchip.is-corp{border-color:#c7d2fe;background:#f8faff;}
    .qc-custchip-av{width:32px;height:32px;flex-shrink:0;border-radius:10px;display:grid;place-items:center;font-size:0.72rem;font-weight:800;color:#fff;background:linear-gradient(135deg,#10b981,#047857);}
    .qc-custchip.is-corp .qc-custchip-av{background:linear-gradient(135deg,#6366f1,#4338ca);}
    .qc-custchip-meta{flex:1;min-width:0;line-height:1.25;}
    .qc-custchip-name{display:block;font-size:0.85rem;font-weight:700;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qc-custchip-sub{display:block;font-size:0.72rem;font-weight:600;color:#94a3b8;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qc-custchip-tag{flex-shrink:0;font-size:0.62rem;font-weight:800;letter-spacing:0.02em;text-transform:uppercase;padding:2px 7px;border-radius:6px;background:#d1fae5;color:#047857;}
    .qc-custchip-tag.corp{background:#e0e7ff;color:#4338ca;}
    .qc-custchip-act{width:26px;height:26px;flex-shrink:0;border:none;background:none;border-radius:8px;color:#cbd5e1;font-size:0.72rem;cursor:pointer;transition:all .15s;display:inline-flex;align-items:center;justify-content:center;}
    .qc-custchip-act:hover{background:#f1f5f9;color:#475569;}
    .qc-custchip-act.star:hover{background:#fef3c7;color:#b45309;}
    .qc-custchip-act.del:hover{background:#fee2e2;color:#dc2626;}
    .qc-cust-rule{display:flex;align-items:flex-start;gap:7px;margin-top:0.55rem;background:#fffbeb;border:1px solid #fde68a;color:#92400e;border-radius:10px;padding:0.5rem 0.7rem;font-size:0.76rem;font-weight:600;line-height:1.45;}
    .qc-cust-rule i{margin-top:2px;color:#d97706;}
    .qc-cust-rule.is-error{background:#fef2f2;border-color:#fecaca;color:#b91c1c;}
    .qc-cust-rule.is-error i{color:#dc2626;}
    .qc-cust-rule.is-flash{animation:qcRulePulse .6s ease;}

    /* ═══ CARİ / BORÇLANDIRMA ŞERİDİ ═══
       Ödeme alınmadan kalan tutarın limite sığıp sığmadığını kaydetmeden gösterir.
       Renk durumu anlatır: yeşil sığıyor, sarı limite yaklaşıldı, kırmızı aşıldı. */
    .qc-credit{margin-top:0.15rem;background:#f8fafc;border:1px solid #e2e8f0;border-radius:12px;padding:0.6rem 0.75rem;}
    .qc-credit.is-warn{background:#fffbeb;border-color:#fde68a;}
    .qc-credit.is-error{background:#fef2f2;border-color:#fecaca;}
    .qc-credit.is-ok{background:#ecfdf5;border-color:#d1fae5;}
    .qc-credit-h{display:flex;align-items:center;gap:7px;font-size:0.74rem;font-weight:800;color:#334155;}
    .qc-credit-h i{color:#64748b;}
    .qc-credit.is-ok .qc-credit-h i{color:#059669;}
    .qc-credit.is-warn .qc-credit-h i{color:#d97706;}
    .qc-credit.is-error .qc-credit-h i{color:#dc2626;}
    .qc-credit-t{text-transform:uppercase;letter-spacing:0.04em;font-size:0.62rem;color:#94a3b8;}
    .qc-credit-state{margin-left:auto;font-size:0.76rem;font-weight:800;color:#0f172a;white-space:nowrap;}
    .qc-credit.is-error .qc-credit-state{color:#b91c1c;}
    .qc-credit-bar{height:5px;border-radius:999px;background:#e2e8f0;overflow:hidden;margin:0.45rem 0 0.4rem;}
    .qc-credit-bar > span{display:block;height:100%;width:0;border-radius:999px;background:linear-gradient(90deg,#10b981,#059669);transition:width .25s ease;}
    .qc-credit.is-warn .qc-credit-bar > span{background:linear-gradient(90deg,#f59e0b,#d97706);}
    .qc-credit.is-error .qc-credit-bar > span{background:linear-gradient(90deg,#ef4444,#b91c1c);}
    .qc-credit-msg{font-size:0.74rem;font-weight:600;line-height:1.45;color:#475569;}
    .qc-credit.is-error .qc-credit-msg{color:#b91c1c;}
    .qc-credit.is-warn .qc-credit-msg{color:#92400e;}
    .qc-credit-msg b{font-weight:800;}
    .qc-cust-row.is-disabled{opacity:0.5;cursor:not-allowed;}
    .qc-cust-row.is-disabled:hover{background:transparent;}
    .qc-cust-row.is-disabled .qc-cust-pick,.qc-cust-row.is-disabled:hover .qc-cust-pick{color:#ef4444;}
    .qc-cust-row.is-denied{animation:qcRowDeny .5s ease;}
    .qc-cust-row.is-picked .qc-cust-pick{color:#10b981;}
    /* Açılır listenin başındaki durum/uyarı şeridi */
    .qc-cust-note{display:flex;align-items:flex-start;gap:7px;margin:0.1rem 0.1rem 0.4rem;padding:0.45rem 0.6rem;border-radius:9px;
        background:#eef2ff;border:1px solid #c7d2fe;color:#3730a3;font-size:0.73rem;font-weight:700;line-height:1.45;}
    .qc-cust-note i{margin-top:2px;flex-shrink:0;color:#4f46e5;}
    .qc-cust-note.is-error{background:#fef2f2;border-color:#fecaca;color:#b91c1c;}
    .qc-cust-note.is-error i{color:#dc2626;}
    .qc-cust-note.is-flash{animation:qcRulePulse .6s ease;}
    .qc-cust-tag{flex-shrink:0;font-size:0.6rem;font-weight:800;letter-spacing:0.02em;text-transform:uppercase;padding:2px 6px;border-radius:6px;background:#d1fae5;color:#047857;}
    .qc-cust-tag.corp{background:#e0e7ff;color:#4338ca;}
    @keyframes qcRulePulse{0%{transform:scale(1);}35%{transform:scale(1.015);box-shadow:0 0 0 4px rgba(220,38,38,0.15);}100%{transform:scale(1);box-shadow:none;}}
    @keyframes qcRowDeny{0%,100%{transform:translateX(0);}20%{transform:translateX(-5px);}40%{transform:translateX(5px);}60%{transform:translateX(-3px);}80%{transform:translateX(3px);}}

    /* Yeni müşteri formu */
    .qc-newcust-form{background:linear-gradient(135deg,#f8fafc,#ecfdf5);border:1.5px dashed #a7f3d0;border-radius:14px;padding:1rem;margin-bottom:0.85rem;}
    .qc-newcust-head{font-size:0.8rem;font-weight:800;color:#047857;margin-bottom:0.75rem;display:flex;align-items:center;gap:7px;}
    .qc-newcust-head i{color:#10b981;}
    .qc-nc-label{font-size:0.64rem;font-weight:800;text-transform:uppercase;letter-spacing:0.03em;color:#64748b;margin-bottom:3px;display:block;}
    .qc-nc-label .req{color:#ef4444;}
    .qc-nc-input{width:100%;border:1.5px solid #e2e8f0;background:#fff;border-radius:9px;padding:0.45rem 0.65rem;font-size:0.84rem;font-weight:600;color:#1e293b;transition:.15s;}
    .qc-nc-input:focus{outline:none;border-color:#10b981;box-shadow:0 0 0 3px rgba(16,185,129,0.1);}
    .qc-nc-error{background:#fef2f2;border:1px solid #fecaca;color:#b91c1c;border-radius:9px;padding:0.5rem 0.75rem;font-size:0.78rem;font-weight:600;}
    .qc-nc-cancel{border:1.5px solid #e2e8f0;background:#fff;color:#64748b;font-weight:700;font-size:0.76rem;border-radius:9px;padding:0.4rem 0.9rem;cursor:pointer;}
    .qc-nc-cancel:hover{background:#f1f5f9;}
    .qc-nc-save{border:none;background:linear-gradient(135deg,#10b981,#059669);color:#fff;font-weight:800;font-size:0.78rem;border-radius:9px;padding:0.4rem 1.1rem;cursor:pointer;box-shadow:0 4px 12px rgba(79,70,229,0.28);}
    .qc-nc-save:disabled{opacity:0.7;cursor:not-allowed;}

    /* ═══ FİYAT TİPİ ADETLERİ ═══ */
    .qcfp-card{padding:1rem 1.1rem 0.85rem;}
    .qcfp-head{display:flex;align-items:flex-start;justify-content:space-between;gap:1rem;flex-wrap:wrap;margin-bottom:0.8rem;}
    .qcfp-head-title{min-width:0;}
    .qcfp-hint{display:block;margin-top:3px;font-size:0.72rem;font-weight:600;color:#94a3b8;line-height:1.45;}
    .qcfp-hint b{color:#64748b;font-weight:800;}
    .qcfp-head-date{flex-shrink:0;font-size:0.74rem;font-weight:700;color:#4338ca;background:#eef2ff;border-radius:9px;padding:0.35rem 0.7rem;white-space:nowrap;}
    .qcfp-head-date:empty{display:none;}

    .qcfp-table{border:1.5px solid #e2e8f0;border-radius:13px;overflow:hidden;}
    .qcfp-thead,.qcfp-row{display:grid;grid-template-columns:minmax(150px,1fr) 130px 96px 130px;align-items:center;gap:0.6rem;padding:0.5rem 0.75rem;}
    .qcfp-thead{background:#f8fafc;border-bottom:1.5px solid #e2e8f0;}
    .qcfp-thead span{font-size:0.6rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;}
    .qcfp-row{border-bottom:1px solid #f1f5f9;transition:background .12s;}
    .qcfp-row:last-child{border-bottom:none;}
    .qcfp-row:hover{background:#fafbff;}
    .qcfp-row.is-on{background:#f0fdf4;}
    .qcfp-row.is-on:hover{background:#ecfdf5;}
    .qcfp-c-unit,.qcfp-c-sub{text-align:right;}
    .qcfp-c-qty{text-align:center;}
    .qcfp-name{display:flex;align-items:center;gap:8px;font-size:0.85rem;font-weight:700;color:#1e293b;min-width:0;}
    .qcfp-name i{width:18px;text-align:center;color:#94a3b8;font-size:0.8rem;flex-shrink:0;}
    .qcfp-row.is-on .qcfp-name i{color:#10b981;}
    .qcfp-unit{text-align:right;font-size:0.82rem;font-weight:700;color:#64748b;font-variant-numeric:tabular-nums;}
    .qcfp-qty{width:100%;text-align:center;border:1.5px solid #e2e8f0;background:#fff;border-radius:9px;padding:0.34rem 0.25rem;font-size:0.86rem;font-weight:800;color:#1e293b;transition:.15s;}
    .qcfp-qty:focus{outline:none;border-color:#10b981;box-shadow:0 0 0 3px rgba(16,185,129,0.1);}
    .qcfp-row.is-on .qcfp-qty{border-color:#6ee7b7;}
    .qcfp-sub{text-align:right;font-size:0.86rem;font-weight:800;color:#1e293b;font-variant-numeric:tabular-nums;}
    .qcfp-row:not(.is-on) .qcfp-sub{color:#cbd5e1;}

    .qcfp-empty{display:flex;align-items:center;gap:0.85rem;border:1.5px dashed #cbd5e1;border-radius:13px;padding:0.85rem 1rem;background:#f8fafc;}
    .qcfp-empty > i{font-size:1.1rem;color:#cbd5e1;}
    .qcfp-empty > div{flex:1;min-width:0;line-height:1.4;}
    .qcfp-empty b{display:block;font-size:0.83rem;font-weight:800;color:#475569;}
    .qcfp-empty span{font-size:0.74rem;font-weight:600;color:#94a3b8;}

    .qcfp-foot{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:0.6rem 1rem;margin-top:0.7rem;padding-top:0.65rem;border-top:1px solid #f1f5f9;}
    .qcfp-foot-counts{display:flex;align-items:center;flex-wrap:wrap;gap:0.5rem;}
    .qcfp-chip{display:inline-flex;align-items:center;gap:6px;font-size:0.74rem;font-weight:600;color:#64748b;background:#f1f5f9;border-radius:8px;padding:0.24rem 0.55rem;}
    .qcfp-chip i{color:#94a3b8;font-size:0.72rem;}
    .qcfp-chip b{font-size:0.8rem;font-weight:800;color:#334155;}
    .qcfp-total{display:flex;align-items:baseline;gap:0.6rem;}
    .qcfp-total-lbl{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;}
    .qcfp-total-val{font-size:1.05rem;font-weight:800;color:#047857;font-variant-numeric:tabular-nums;}

    @media (max-width: 767px){
        .qcfp-thead{display:none;}
        .qcfp-row{grid-template-columns:1fr 92px;grid-template-areas:"name qty" "unit sub";row-gap:0.3rem;}
        .qcfp-row .qcfp-name{grid-area:name;}
        .qcfp-row .qcfp-c-qty{grid-area:qty;}
        .qcfp-row .qcfp-c-unit{grid-area:unit;text-align:left;}
        .qcfp-row .qcfp-c-sub{grid-area:sub;}
    }

    /* Oda modunda adet kutusu odalardan türer → salt okunur görünür */
    .qcfp-qty.is-derived{background:#f8fafc;color:#475569;border-style:dashed;cursor:not-allowed;}
    .qcfp-cap{display:flex;align-items:center;gap:0.4rem;margin:0.85rem 0 0.4rem;font-size:0.68rem;font-weight:800;
        text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;}
    .qcfp-cap i{color:#cbd5e1;}
    .qcfp-cap span{text-transform:none;letter-spacing:0;font-weight:700;color:#10b981;}

    /* ═══ PAZARYERİ ŞERİDİ (fiyat hangi pazardan geliyor) ═══ */
    .qcmp{border:1.5px solid #e2e8f0;border-radius:13px;padding:0.55rem 0.75rem;margin-bottom:0.8rem;background:#f8fafc;}
    .qcmp-main{display:flex;align-items:center;gap:0.55rem;flex-wrap:wrap;}
    .qcmp-ico{width:24px;height:24px;border-radius:8px;display:grid;place-items:center;font-size:0.72rem;color:#4338ca;background:#eef2ff;flex-shrink:0;}
    .qcmp-lbl{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;}
    .qcmp-select{border:1.5px solid #e2e8f0;background:#fff;border-radius:9px;padding:0.3rem 0.6rem;font-size:0.8rem;
        font-weight:700;color:#1e293b;min-width:170px;max-width:100%;}
    .qcmp-select:focus{outline:none;border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,0.12);}
    .qcmp-select:disabled{background:#f1f5f9;color:#64748b;}
    .qcmp-badge{font-size:0.68rem;font-weight:800;border-radius:8px;padding:0.2rem 0.5rem;white-space:nowrap;}
    .qcmp-badge.is-primary{color:#047857;background:#ecfdf5;}
    .qcmp-badge.is-selected{color:#4338ca;background:#eef2ff;}
    .qcmp-badge.is-fallback{color:#b45309;background:#fffbeb;}
    .qcmp-note{margin-top:0.4rem;font-size:0.72rem;font-weight:600;color:#94a3b8;line-height:1.45;}
    .qcmp-note:empty{display:none;}
    .qcmp-note b{color:#64748b;font-weight:800;}
    .qcmp.is-warn{border-color:#fcd34d;background:#fffbeb;}
    .qcmp.is-warn .qcmp-note{color:#92400e;}
    .qcmp.is-warn .qcmp-note b{color:#78350f;}

    /* ═══ ODA KURGUSU ═══ */
    .qcrm{margin-bottom:0.9rem;}
    .qcrm-bar{display:flex;align-items:center;justify-content:space-between;gap:0.6rem;flex-wrap:wrap;margin-bottom:0.55rem;}
    .qcrm-bar-counts{display:flex;align-items:center;flex-wrap:wrap;gap:0.4rem;min-width:0;}
    .qcrm-bar-actions{display:flex;align-items:center;gap:0.4rem;flex-shrink:0;}
    .qcrm-btn-add,.qcrm-btn-ghost{border-radius:9px;font-size:0.74rem;font-weight:800;padding:0.34rem 0.7rem;cursor:pointer;transition:.15s;white-space:nowrap;}
    .qcrm-btn-add{border:none;color:#fff;background:linear-gradient(135deg,#4f46e5,#4338ca);box-shadow:0 4px 10px rgba(79,70,229,0.22);}
    .qcrm-btn-add:hover{transform:translateY(-1px);}
    .qcrm-btn-ghost{border:1.5px solid #e2e8f0;background:#fff;color:#64748b;}
    .qcrm-btn-ghost:hover{background:#f8fafc;color:#334155;}

    .qcrm-list{display:flex;flex-direction:column;gap:0.5rem;}
    .qcrm-room{border:1.5px solid #e2e8f0;border-radius:13px;background:#fff;overflow:hidden;transition:border-color .15s;}
    .qcrm-room:focus-within{border-color:#c7d2fe;}
    .qcrm-room.is-over{border-color:#fca5a5;}
    .qcrm-top{display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap;padding:0.5rem 0.7rem;background:#f8fafc;border-bottom:1px solid #eef2f7;}
    .qcrm-no{width:24px;height:24px;border-radius:8px;display:grid;place-items:center;font-size:0.72rem;font-weight:800;color:#4338ca;background:#eef2ff;flex-shrink:0;}
    .qcrm-type{border:1.5px solid #e2e8f0;background:#fff;border-radius:9px;padding:0.26rem 0.5rem;font-size:0.78rem;font-weight:700;color:#1e293b;}
    .qcrm-type:focus{outline:none;border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,0.12);}
    .qcrm-beds{font-size:0.7rem;font-weight:700;color:#94a3b8;white-space:nowrap;}
    .qcrm-room-total{margin-left:auto;font-size:0.85rem;font-weight:800;color:#047857;font-variant-numeric:tabular-nums;white-space:nowrap;}
    .qcrm-x{border:none;background:transparent;color:#cbd5e1;font-size:0.82rem;padding:0.2rem 0.3rem;cursor:pointer;border-radius:7px;transition:.15s;}
    .qcrm-x:hover{background:#fef2f2;color:#dc2626;}

    .qcrm-body{display:flex;align-items:flex-start;gap:0.5rem 0.85rem;flex-wrap:wrap;padding:0.55rem 0.7rem;}
    .qcrm-field{display:flex;align-items:center;gap:0.35rem;}
    .qcrm-field > label{font-size:0.7rem;font-weight:700;color:#64748b;display:inline-flex;align-items:center;gap:5px;white-space:nowrap;}
    .qcrm-field > label i{color:#94a3b8;font-size:0.72rem;width:13px;text-align:center;}
    .qcrm-step{display:inline-flex;align-items:center;border:1.5px solid #e2e8f0;border-radius:9px;overflow:hidden;background:#fff;}
    .qcrm-step button{border:none;background:#f8fafc;color:#64748b;width:24px;height:28px;font-size:0.72rem;cursor:pointer;transition:.12s;}
    .qcrm-step button:hover{background:#eef2ff;color:#4338ca;}
    .qcrm-step input{width:38px;height:28px;border:none;text-align:center;font-size:0.82rem;font-weight:800;color:#1e293b;
        -moz-appearance:textfield;background:#fff;}
    .qcrm-step input::-webkit-outer-spin-button,.qcrm-step input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
    .qcrm-step input:focus{outline:none;background:#f5f3ff;}
    .qcrm-bed{display:inline-flex;align-items:center;gap:6px;font-size:0.74rem;font-weight:700;color:#475569;
        border:1.5px solid #e2e8f0;border-radius:9px;padding:0.25rem 0.55rem;cursor:pointer;background:#fff;transition:.15s;}
    .qcrm-bed:hover{border-color:#c7d2fe;}
    .qcrm-bed input{accent-color:#4f46e5;cursor:pointer;}
    .qcrm-bed.is-on{border-color:#a5b4fc;background:#eef2ff;color:#3730a3;}
    .qcrm-note-in{flex:1;min-width:130px;border:1.5px solid #e2e8f0;border-radius:9px;padding:0.25rem 0.55rem;font-size:0.76rem;font-weight:600;color:#334155;background:#fff;}
    .qcrm-note-in:focus{outline:none;border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,0.1);}

    /* "Bu tutar neden çıktı?" — oda kırılımı ve otomatik eklenen farklar */
    .qcrm-why{display:flex;flex-wrap:wrap;gap:0.3rem;padding:0 0.7rem 0.55rem;}
    .qcrm-tag{display:inline-flex;align-items:center;gap:5px;font-size:0.71rem;font-weight:700;color:#475569;
        background:#f1f5f9;border-radius:8px;padding:0.2rem 0.5rem;font-variant-numeric:tabular-nums;}
    .qcrm-tag i{font-size:0.68rem;color:#94a3b8;}
    .qcrm-tag b{color:#1e293b;font-weight:800;}
    .qcrm-tag.is-auto{color:#3730a3;background:#eef2ff;}
    .qcrm-tag.is-auto i{color:#6366f1;}
    .qcrm-tag.is-auto b{color:#312e81;}
    .qcrm-tag.is-warn{color:#92400e;background:#fffbeb;}
    .qcrm-tag.is-warn i{color:#d97706;}
    .qcrm-tag.is-warn b{color:#78350f;}

    .qcrm-empty{display:flex;align-items:center;gap:0.85rem;border:1.5px dashed #cbd5e1;border-radius:13px;padding:0.85rem 1rem;background:#f8fafc;}
    .qcrm-empty > i{font-size:1.1rem;color:#cbd5e1;}
    .qcrm-empty > div{flex:1;min-width:0;line-height:1.4;}
    .qcrm-empty b{display:block;font-size:0.83rem;font-weight:800;color:#475569;}
    .qcrm-empty span{font-size:0.74rem;font-weight:600;color:#94a3b8;}

    @media (max-width: 575px){
        .qcrm-room-total{margin-left:0;width:100%;text-align:right;}
        .qcrm-note-in{width:100%;flex:1 1 100%;}
    }

    /* ═══ OTOMATİK KAYIT ŞERİDİ ═══ */
    .qc-autosave-strip{display:flex;align-items:center;gap:0.5rem;font-size:0.75rem;color:#475569;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:0.5rem 0.8rem;margin-bottom:0.6rem;}
    .qc-autosave-strip > i{color:#16a34a;}
    .qc-autosave-strip b{color:#15803d;}
    .qc-save-indicator{margin-left:auto;font-weight:800;font-size:0.72rem;white-space:nowrap;}
    .qc-save-indicator[data-state="saved"]{color:#16a34a;}
    .qc-save-indicator[data-state="saving"]{color:#d97706;}
    .qc-save-indicator[data-state="error"]{color:#dc2626;}
    /* Kayıt düşerse şerit de kırmızıya döner — küçük etiket gözden kaçıyordu */
    .qc-autosave-strip.is-error{background:#fef2f2;border-color:#fecaca;color:#7f1d1d;}
    .qc-autosave-strip.is-error > i,.qc-autosave-strip.is-error b{color:#b91c1c;}

    .qc-save-error{background:#fff;border:1.5px solid #fecaca;border-left:4px solid #dc2626;border-radius:12px;
        padding:0.7rem 0.85rem;margin-bottom:0.7rem;box-shadow:0 6px 18px rgba(220,38,38,0.10);}
    .qc-save-error-head{display:flex;align-items:center;gap:0.45rem;font-size:0.8rem;color:#b91c1c;}
    .qc-save-error-head i{font-size:0.9rem;}
    .qc-save-error-msg{font-size:0.72rem;color:#7f1d1d;line-height:1.45;margin:0.35rem 0 0.55rem;word-break:break-word;max-height:6.5rem;overflow:auto;}
    .qc-save-error-btn{border:none;background:#dc2626;color:#fff;font-weight:800;font-size:0.74rem;border-radius:9px;
        padding:0.38rem 0.9rem;cursor:pointer;box-shadow:0 4px 12px rgba(220,38,38,0.28);}
    .qc-save-error-btn:hover{background:#b91c1c;}

    /* ═══ KATALOG MODALI ═══ */
    .qvcat-dialog{max-width:1240px;width:97%;}
    .qvcat-content{border:none;border-radius:22px;overflow:hidden;box-shadow:0 32px 80px rgba(2,6,23,0.4);max-height:90vh;display:flex;flex-direction:column;background:#f8fafc;}
    .qvcat-header{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1.35rem 1.75rem;flex-shrink:0;
        background:linear-gradient(135deg,#0f172a 0%,#1e293b 55%,#312e81 140%);position:relative;overflow:hidden;}
    .qvcat-header::before{content:'';position:absolute;top:-60%;right:-8%;width:340px;height:340px;background:radial-gradient(circle,rgba(16,185,129,0.28),transparent 70%);pointer-events:none;}
    .qvcat-head-title{display:flex;align-items:center;gap:0.9rem;position:relative;z-index:1;min-width:0;}
    .qvcat-head-icon{width:46px;height:46px;border-radius:14px;display:grid;place-items:center;font-size:1.25rem;color:#a7f3d0;background:rgba(16,185,129,0.18);border:1px solid rgba(199,210,254,0.2);flex-shrink:0;}
    .qvcat-head-title h5{margin:0;color:#fff;font-weight:800;font-size:1.12rem;letter-spacing:-0.02em;}
    .qvcat-head-title p{margin:2px 0 0;color:#94a3b8;font-size:0.74rem;}
    .qvcat-x{width:38px;height:38px;border-radius:11px;border:1px solid rgba(255,255,255,0.12);background:rgba(255,255,255,0.06);color:rgba(255,255,255,0.6);cursor:pointer;transition:.15s;position:relative;z-index:1;flex-shrink:0;}
    .qvcat-x:hover{background:rgba(239,68,68,0.2);color:#fca5a5;border-color:rgba(239,68,68,0.3);}

    .qvcat-tabs{display:flex;gap:4px;padding:0 1.25rem;background:#0f172a;flex-shrink:0;}
    .qvcat-tab{display:inline-flex;align-items:center;gap:8px;border:none;background:none;cursor:pointer;padding:0.85rem 1.1rem;font-size:0.84rem;font-weight:700;
        color:#64748b;border-bottom:2.5px solid transparent;transition:.15s;}
    .qvcat-tab:hover{color:#cbd5e1;}
    .qvcat-tab.active{color:#fff;border-bottom-color:#34d399;}
    .qvcat-tab i{font-size:0.9rem;}
    .qvcat-tab-count{font-size:0.66rem;font-weight:800;background:rgba(255,255,255,0.1);color:#cbd5e1;padding:2px 8px;border-radius:20px;}
    .qvcat-tab.active .qvcat-tab-count{background:#10b981;color:#fff;}

    .qvcat-toolbar{display:flex;gap:0.6rem;padding:0.85rem 1.25rem;background:#fff;border-bottom:1px solid #e2e8f0;flex-shrink:0;}
    .qvcat-search{position:relative;flex:1;display:flex;align-items:center;}
    .qvcat-search i{position:absolute;left:14px;color:#94a3b8;font-size:0.85rem;pointer-events:none;}
    .qvcat-search input{width:100%;border:1.5px solid #e2e8f0;background:#f8fafc;border-radius:11px;padding:0.55rem 0.9rem 0.55rem 38px;font-size:0.86rem;font-weight:600;color:#1e293b;transition:.15s;}
    .qvcat-search input:focus{outline:none;border-color:#10b981;background:#fff;box-shadow:0 0 0 3px rgba(16,185,129,0.1);}
    .qvcat-filter{max-width:210px;border:1.5px solid #e2e8f0;background:#f8fafc;border-radius:11px;padding:0.55rem 0.8rem;font-size:0.82rem;font-weight:700;color:#334155;cursor:pointer;}
    .qvcat-filter:focus{outline:none;border-color:#10b981;}

    .qvcat-body{flex:1;overflow-y:auto;overflow-x:hidden;padding:1.15rem 1.25rem;min-height:340px;min-width:0;}
    .qvcat-pane{display:none;}
    .qvcat-pane.active{display:block;animation:qvcatFade .25s ease;}
    @keyframes qvcatFade{from{opacity:0;transform:translateY(6px);}to{opacity:1;transform:none;}}

    .qvcat-group{margin-bottom:1.4rem;min-width:0;}
    .qvcat-group-head{display:flex;align-items:center;gap:0.65rem;margin-bottom:0.7rem;min-width:0;}
    .qvcat-group-badge{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.05em;color:#059669;background:#d1fae5;padding:4px 11px;border-radius:20px;display:inline-flex;align-items:center;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex-shrink:1;}
    .qvcat-group-badge.sup{color:#0e7490;background:#cffafe;}
    .qvcat-group-line{flex:1;height:1px;background:linear-gradient(90deg,#e2e8f0,transparent);}
    .qvcat-group-n{font-size:0.7rem;font-weight:800;color:#94a3b8;}
    .qvcat-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:0.65rem;}
    @media (max-width:820px){.qvcat-grid{grid-template-columns:1fr;}}

    .qvcat-card{display:flex;align-items:center;gap:0.85rem;background:#fff;border:1.5px solid #e8edf3;border-radius:15px;padding:0.85rem 0.95rem;cursor:pointer;transition:transform .15s,box-shadow .15s,border-color .15s;min-width:0;overflow:hidden;}
    .qvcat-card:hover{border-color:#a7f3d0;box-shadow:0 10px 26px rgba(79,70,229,0.12);transform:translateY(-2px);}
    .qvcat-card.is-tour{border-left:3px solid #34d399;}
    .qvcat-card-ico{width:44px;height:44px;border-radius:13px;flex-shrink:0;display:grid;place-items:center;font-size:1.05rem;color:#059669;background:linear-gradient(135deg,#ecfdf5,#d1fae5);}
    .qvcat-card-ico.sup{color:#0e7490;background:linear-gradient(135deg,#ecfeff,#cffafe);}
    .qvcat-card-body{flex:1;min-width:0;}
    .qvcat-card-name{font-weight:700;font-size:0.88rem;color:#1e293b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
    .qvcat-card-meta{display:flex;flex-wrap:wrap;gap:5px;margin-top:5px;}
    .qvcat-chip{display:inline-flex;align-items:center;gap:4px;font-size:0.66rem;font-weight:700;color:#475569;background:#f1f5f9;border-radius:7px;padding:2px 7px;white-space:nowrap;max-width:100%;overflow:hidden;text-overflow:ellipsis;}
    .qvcat-chip i{font-size:0.6rem;color:#94a3b8;}
    .qvcat-chip.tour{color:#047857;background:#ecfdf5;}
    .qvcat-chip.tour i{color:#10b981;}
    .qvcat-chip.muted{color:#94a3b8;background:#f8fafc;}
    /* Tedarikçi chip'i tıklanabilir: kart tıklamasından bağımsız tedarikçi kartını açar */
    .qvcat-chip-link{cursor:pointer;transition:all .15s;}
    .qvcat-chip-link:hover{color:#4f46e5;background:#eef2ff;}
    .qvcat-chip.warn{color:#b45309;background:#fffbeb;}
    .qvcat-chip.warn i{color:#f59e0b;}

    /* Satışa kapalı / taslak ürünler — gizlenmez, sebebiyle gösterilir */
    .qvcat-group-badge.closed{color:#b45309;background:#fef3c7;}
    .qvcat-closed-note{display:flex;gap:8px;align-items:flex-start;font-size:0.72rem;line-height:1.5;color:#92400e;background:#fffbeb;border:1px solid #fde68a;border-radius:11px;padding:8px 11px;margin-bottom:0.7rem;}
    .qvcat-closed-note i{color:#f59e0b;margin-top:2px;flex-shrink:0;}
    .qvcat-card.is-closed{background:#fcfcfd;border-color:#e8edf3;border-left:3px solid #fbbf24;}
    .qvcat-card.is-closed .qvcat-card-name{color:#64748b;}
    .qvcat-card.is-closed:hover{border-color:#fcd34d;box-shadow:0 10px 26px rgba(245,158,11,0.14);}
    .qvcat-card.is-closed .qvcat-card-cta{color:#d97706;}
    .qvcat-card-ico.closed{color:#b45309;background:linear-gradient(135deg,#fffbeb,#fef3c7);}
    .qvcat-card-right{text-align:right;flex-shrink:0;display:flex;flex-direction:column;align-items:flex-end;gap:3px;}
    .qvcat-card-price{font-weight:800;font-size:0.95rem;color:#0f172a;white-space:nowrap;font-variant-numeric:tabular-nums;}
    .qvcat-card-price small{font-size:0.66rem;color:#94a3b8;font-weight:700;}
    .qvcat-card-price.muted{color:#cbd5e1;}

    /* Ekstra hizmetler sekmesi — mor aile, tedarikçi (camgöbeği) ve ürün (yeşil) ile karışmasın */
    .qvcat-group-badge.xtra{color:#6d28d9;background:#ede9fe;}
    .qvcat-card-ico.xtra{color:#6d28d9;background:linear-gradient(135deg,#f5f3ff,#ede9fe);}
    .qvcat-card-sub{font-size:0.68rem;font-weight:700;color:#a3adc0;white-space:nowrap;margin-top:1px;font-variant-numeric:tabular-nums;}
    .qvcat-card-cta{font-size:0.68rem;font-weight:800;color:#10b981;display:inline-flex;align-items:center;gap:4px;}
    .qvcat-card-cta i{font-size:0.6rem;transition:transform .15s;}
    .qvcat-card:hover .qvcat-card-cta i{transform:translateX(3px);}

    .qvcat-empty{text-align:center;padding:2.6rem 1rem;color:#94a3b8;}
    .qvcat-empty i{font-size:2.2rem;opacity:0.35;display:block;margin-bottom:0.7rem;}
    .qvcat-empty p{font-weight:600;font-size:0.86rem;margin:0;}

    /* Tur tarihi drill-down */
    .qvcat-back{display:inline-flex;align-items:center;gap:7px;border:none;background:#ecfdf5;color:#059669;font-weight:800;font-size:0.76rem;border-radius:10px;padding:0.5rem 0.95rem;cursor:pointer;transition:.15s;margin-bottom:1rem;}
    .qvcat-back:hover{background:#059669;color:#fff;}
    .qvcat-date-head{display:flex;align-items:center;gap:0.85rem;background:linear-gradient(135deg,#fffbeb,#fef3c7);border:1.5px solid #fde68a;border-radius:15px;padding:0.9rem 1.1rem;margin-bottom:1.1rem;}
    .qvcat-date-head-ico{width:44px;height:44px;border-radius:13px;flex-shrink:0;display:grid;place-items:center;font-size:1.15rem;color:#fff;background:linear-gradient(135deg,#f59e0b,#d97706);}
    .qvcat-date-head-name{font-weight:800;font-size:0.98rem;color:#78350f;}
    .qvcat-date-head-sub{font-size:0.74rem;color:#b45309;font-weight:600;margin-top:2px;}
    .qvcat-date-loading{text-align:center;padding:2rem;color:#94a3b8;font-size:0.85rem;font-weight:600;}
    .qvcat-date-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:0.7rem;}
    @media (max-width:820px){.qvcat-date-grid{grid-template-columns:1fr;}}
    .qvcat-date-card{background:#fff;border:1.5px solid #e8edf3;border-radius:15px;padding:0.9rem 1rem;cursor:pointer;transition:transform .15s,box-shadow .15s,border-color .15s;}
    .qvcat-date-card:hover{border-color:#fbbf24;box-shadow:0 10px 26px rgba(245,158,11,0.15);transform:translateY(-2px);}
    .qvcat-date-top{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;margin-bottom:0.6rem;}
    .qvcat-date-when{font-weight:800;font-size:0.86rem;color:#1e293b;display:inline-flex;align-items:center;gap:6px;}
    .qvcat-date-when i{color:#f59e0b;font-size:0.78rem;}
    .qvcat-date-guar{font-size:0.64rem;font-weight:800;color:#16a34a;background:#dcfce7;border-radius:20px;padding:2px 8px;display:inline-flex;align-items:center;gap:4px;white-space:nowrap;}
    .qvcat-date-prices{display:flex;flex-wrap:wrap;gap:0.4rem;margin-bottom:0.65rem;}
    .qvcat-date-prices span{font-size:0.72rem;font-weight:600;color:#64748b;background:#f8fafc;border:1px solid #eef2f7;border-radius:8px;padding:3px 8px;}
    .qvcat-date-prices span.adult{color:#065f46;background:#ecfdf5;border-color:#a7f3d0;}
    .qvcat-date-prices b{font-weight:800;color:#0f172a;}
    .qvcat-date-prices span.adult b{color:#047857;}
    .qvcat-date-foot{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;border-top:1px dashed #eef2f7;padding-top:0.6rem;}
    .qvcat-date-cap{font-size:0.72rem;font-weight:700;color:#64748b;display:inline-flex;align-items:center;gap:5px;}
    .qvcat-date-cap i{color:#94a3b8;}
    .qvcat-date-pick{font-size:0.7rem;font-weight:800;color:#f59e0b;display:inline-flex;align-items:center;gap:5px;}
    .qvcat-date-card:hover .qvcat-date-pick{color:#d97706;}

    .qvcat-date-card.sel{border-color:#f59e0b;box-shadow:0 0 0 3px rgba(245,158,11,0.18);background:#fffdf7;}
    .qvcat-date-none{font-size:0.8rem;font-weight:600;color:#b45309;background:#fffbeb;border:1px solid #fde68a;border-radius:12px;padding:0.7rem 0.9rem;margin-bottom:1rem;}

    /* Fiyat tipi paneli */
    .qvcat-fare-panel{margin-top:1.1rem;background:#fff;border:1.5px solid #e2e8f0;border-radius:16px;overflow:hidden;box-shadow:0 8px 24px rgba(15,23,42,0.06);}
    .qvcat-fare-head{display:flex;align-items:center;justify-content:space-between;gap:0.75rem;flex-wrap:wrap;padding:0.75rem 1rem;background:linear-gradient(135deg,#f8fafc,#ecfdf5);border-bottom:1px solid #e2e8f0;font-size:0.8rem;font-weight:800;color:#334155;}
    .qvcat-fare-head i{color:#10b981;margin-right:5px;}
    .qvcat-fare-total{color:#047857;}
    .qvcat-fare-total b{font-size:0.95rem;}
    .qvcat-fare-rows{padding:0.5rem 1rem;display:flex;flex-direction:column;gap:0.35rem;}
    .qvcat-fare-row{display:flex;align-items:center;gap:0.75rem;flex-wrap:wrap;padding:0.5rem 0;border-bottom:1px dashed #f1f5f9;}
    .qvcat-fare-row:last-child{border-bottom:none;}
    .qvcat-fare-label{font-weight:700;font-size:0.83rem;color:#1e293b;flex:1;min-width:120px;display:flex;align-items:center;gap:7px;}
    .qvcat-fare-label i{width:24px;height:24px;border-radius:7px;display:grid;place-items:center;font-size:0.7rem;color:#059669;background:#ecfdf5;flex-shrink:0;}
    .qvcat-fare-unit{font-size:0.78rem;font-weight:700;color:#64748b;white-space:nowrap;min-width:96px;text-align:right;}
    .qvcat-fare-qty{width:76px;flex-shrink:0;}
    .qvcat-fare-qty input{width:100%;border:1.5px solid #e2e8f0;border-radius:9px;padding:0.35rem 0.4rem;font-size:0.85rem;font-weight:700;text-align:center;color:#0f172a;}
    .qvcat-fare-qty input:focus{outline:none;border-color:#10b981;box-shadow:0 0 0 3px rgba(16,185,129,0.1);}
    .qvcat-fare-sub{font-size:0.82rem;font-weight:800;color:#047857;white-space:nowrap;min-width:110px;text-align:right;}
    .qvcat-fare-mk{display:flex;align-items:center;gap:0.5rem;flex-wrap:wrap;padding:0.6rem 1rem 0;}
    .qvcat-fare-mk:empty{display:none;}
    .qvcat-fare-mk-lbl{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;display:inline-flex;align-items:center;gap:5px;}
    .qvcat-fare-mk-lbl i{color:#4338ca;}
    .qvcat-fare-mk-sel{border:1.5px solid #e2e8f0;background:#fff;border-radius:9px;padding:0.28rem 0.55rem;font-size:0.79rem;font-weight:700;color:#1e293b;min-width:165px;}
    .qvcat-fare-mk-sel:focus{outline:none;border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,0.12);}
    .qvcat-fare-mk-sel:disabled{background:#f1f5f9;color:#64748b;}
    .qvcat-fare-mk-warn{font-size:0.72rem;font-weight:700;color:#92400e;background:#fffbeb;border-radius:8px;padding:0.22rem 0.55rem;}
    .qvcat-fare-mk-warn i{color:#d97706;margin-right:4px;}
    .qvcat-fare-mk-warn a{color:#b45309;text-decoration:underline;font-weight:800;}
    .qvcat-fare-roomnote{display:flex;align-items:flex-start;gap:0.55rem;margin:0 1rem 0.75rem;padding:0.55rem 0.7rem;
        border:1.5px dashed #c7d2fe;border-radius:11px;background:#f5f3ff;font-size:0.74rem;font-weight:600;color:#4338ca;line-height:1.45;}
    .qvcat-fare-roomnote i{color:#6366f1;margin-top:2px;}
    .qvcat-fare-roomnote b{color:#312e81;font-weight:800;}
    .qvcat-date-mk{display:inline-flex;align-items:center;gap:4px;margin-left:0.4rem;font-size:0.68rem;font-weight:700;
        color:#4338ca;background:#eef2ff;border-radius:7px;padding:0.1rem 0.4rem;}
    .qvcat-date-mk.is-warn{color:#92400e;background:#fffbeb;}
    .qvcat-fare-actions{display:flex;align-items:center;justify-content:flex-end;gap:0.6rem;padding:0.75rem 1rem;background:#f8fafc;border-top:1px solid #eef2f7;}
    .qvcat-fare-cancel{border:1.5px solid #e2e8f0;background:#fff;color:#64748b;font-weight:700;font-size:0.8rem;border-radius:10px;padding:0.45rem 1rem;cursor:pointer;transition:.15s;}
    .qvcat-fare-cancel:hover{background:#f1f5f9;color:#334155;}
    .qvcat-fare-confirm{border:none;background:linear-gradient(135deg,#16a34a,#15803d);color:#fff;font-weight:800;font-size:0.8rem;border-radius:10px;padding:0.45rem 1.1rem;cursor:pointer;box-shadow:0 4px 12px rgba(22,163,74,0.28);transition:transform .15s;}
    .qvcat-fare-confirm:hover{transform:translateY(-1px);}

    /* Özel tarih */
    .qvcat-customdate{margin-top:1.1rem;border:1.5px dashed #cbd5e1;border-radius:14px;overflow:hidden;}
    .qvcat-customdate-head{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;padding:0.7rem 1rem;cursor:pointer;font-size:0.8rem;font-weight:700;color:#475569;background:#f8fafc;transition:background .15s;}
    .qvcat-customdate-head:hover{background:#f1f5f9;}
    .qvcat-customdate-head i.fa-calendar-plus{color:#10b981;margin-right:6px;}
    .qvcat-customdate-body{padding:0.9rem 1rem;border-top:1px solid #eef2f7;}
    .qvcat-cd-fields{display:flex;align-items:flex-end;gap:0.6rem;flex-wrap:wrap;}
    .qvcat-cd-fld{display:flex;flex-direction:column;gap:4px;min-width:120px;flex:1;}
    .qvcat-cd-fld label{font-size:0.68rem;font-weight:800;text-transform:uppercase;letter-spacing:0.03em;color:#94a3b8;}
    .qvcat-cd-fld input,.qvcat-cd-fld select{border:1.5px solid #e2e8f0;border-radius:10px;padding:0.45rem 0.6rem;font-size:0.84rem;font-weight:600;color:#1e293b;}
    .qvcat-cd-fld input:focus,.qvcat-cd-fld select:focus{outline:none;border-color:#10b981;box-shadow:0 0 0 3px rgba(16,185,129,0.1);}
    .qvcat-cd-apply{border:none;background:linear-gradient(135deg,#10b981,#059669);color:#fff;font-weight:800;font-size:0.8rem;border-radius:10px;padding:0.5rem 1.1rem;cursor:pointer;white-space:nowrap;box-shadow:0 4px 12px rgba(79,70,229,0.28);}
    .qvcat-cd-hint{font-size:0.7rem;color:#94a3b8;margin-top:0.7rem;}
    .qvcat-cd-hint i{color:#10b981;margin-right:4px;}

    .qvcat-footer{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:0.8rem 1.25rem;background:#fff;border-top:1px solid #e2e8f0;flex-shrink:0;}
    .qvcat-foot-hint{font-size:0.72rem;color:#94a3b8;font-weight:600;}
</style>

<script>
    window.exchangeRates = {
        @foreach($activeCurrencies as $curr)
            "{{ $curr->code }}": {{ (float)$curr->exchange_rate }},
        @endforeach
    };
    window.currencySymbols = {
        @foreach($activeCurrencies as $curr)
            "{{ $curr->code }}": "{{ $curr->symbol }}",
        @endforeach
    };
    // Tur kalkış tarihlerini (yetişkin/çocuk/bebek fiyatlı) getiren endpoint
    var URL_DATES = '{{ route("agency.sales.api.product-dates") }}';
    // Müşteri arama (server-side; binlerce müşteride hızlı bulma)
    var URL_CUSTOMER_SEARCH = '{{ route("agency.customers.search") }}';

    // ─── CARİ / BORÇLANDIRMA ───
    // Satış kartı, müşterinin limitini sunucudan okur; şerit bu satışın kalanını
    // üstüne ekleyip projeksiyon çizer. Kur haritası tutarları limit birimine çevirir.
    var QC_CREDIT_BOOT = @json($saleCredit);
    var QC_DEBT_STATUSES = @json($creditDebtStatuses);
    var QC_CURRENCY_RATES = {
        "TRY": 1,
        @foreach($activeCurrencies as $curr)
            "{{ $curr->code }}": {{ (float) ($curr->exchange_rate ?: 1) ?: 1 }},
        @endforeach
    };

    // Satışa bağlı müşteriler — ilk eleman birincil (fatura muhatabı).
    // Kural: ya TEK şirket ya da bir/birden fazla kişi.
    // NOT: quick-view yığınında aynı anda birden fazla satış kartı açık olabilir;
    // bu yüzden durum global değil, kartın kendi kökünde (root.__qcCustomers /
    // root.__qcFareCtx) tutulur. Aşağıdaki değişkenler yalnızca AÇILIŞ verisidir.
    var _qcCustomersBoot = @json($saleCustomers->all());
    // Fiyat tipi paneli: tur tarihinden gelen birim fiyatlar + tur adı/döviz + pazaryeri
    var _qcFareCtxBoot = @json($fareCtx);
    // Fiyat tiplerinin TEK kaynağı: App\Support\TourFareCatalog (etiketler burada
    // ELLE YAZILMAZ; ürün yönetimi de aynı listeden okur).
    var QC_FARES = @json($fareDefs);
    // Oda tipi → TR etiket / varsayılan yatak sayısı (App\Models\Sale\SaleRoom)
    var QC_ROOM_TYPES = @json(\App\Models\Sale\SaleRoom::ROOM_TYPES);
    var QC_ROOM_CAPS  = @json(\App\Models\Sale\SaleRoom::ROOM_TYPE_CAPACITY);
    // Satışta kayıtlı odalar (operasyondaki Odalama sekmesi aynı kayıtları okur)
    var _qcRoomsBoot = @json($saleRoomsBoot);

    // ─── OTOMATİK KAYIT (submit yerine; her değişiklikte debounce'lu quick-update) ──
    // Kart kapsamlı çalışır: quick-view yığınında aynı anda birden fazla satış kartı
    // açık olabildiği için satış id'si ve alanlar global değil, değişikliğin geldiği
    // .qv-sales-wrapper üzerinden çözülür. Aksi halde ikinci kart hiç bağlanmıyor,
    // bağlansa bile ilk kartın satışına yazıyordu.
    // Not: satış id'si artık global değişkende değil, kartın kendi
    // data-sale-id özniteliğinde tutulur (bkz. qcSaleId/qcRoot).

    /** Aktif satış kartının satış id'si (global değişken kartlar arasında çakışıyordu). */
    function qcSaleId(node) {
        const r = qcRoot(node);
        return (r && r.dataset.saleId) ? r.dataset.saleId : null;
    }
    window.qcSaleId = qcSaleId;

    /** Değişikliğin ait olduğu satış kartı (yoksa aktif/son kart). */
    function qcRoot(node) {
        if (node && node.closest) {
            const own = node.closest('.qv-sales-wrapper');
            if (own) return own;
        }
        const active = document.querySelectorAll('.qv-card-wrapper:not(.inactive) .qv-sales-wrapper');
        if (active.length) return active[active.length - 1];
        const all = document.querySelectorAll('.qv-sales-wrapper');
        return all.length ? all[all.length - 1] : null;
    }

    /**
     * Kart kapsamlı eleman erişimi.
     * Drawer, arka plandaki kartların id'lerini söküp data-original-id'ye taşır
     * (deactivateCard) — bu yüzden id bulunamazsa oradan da bakılır.
     */
    function qcEl(id, root) {
        const r = root || qcRoot();
        if (!r) return document.getElementById(id);
        return r.querySelector('#' + id) || r.querySelector('[data-original-id="' + id + '"]');
    }

    /** Kayıt durumu her kartın kendi üstünde tutulur. */
    function qcState(root) {
        if (!root) return null;
        if (!root.__qcSave) root.__qcSave = { timer: null, inflight: false, dirty: false, seq: 0, done: 0 };
        return root.__qcSave;
    }

    function qcSetSaveState(state, message, root) {
        const r = root || qcRoot();
        const el = qcEl('qc-save-indicator', r);
        if (!el) return;
        el.dataset.state = state || '';
        if (state === 'saving') el.innerHTML = '<i class="fas fa-circle-notch fa-spin"></i> Kaydediliyor…';
        else if (state === 'saved') el.innerHTML = '<i class="fas fa-circle-check"></i> Kaydedildi';
        else if (state === 'error') el.innerHTML = '<i class="fas fa-triangle-exclamation"></i> Kaydedilemedi';
        else el.innerHTML = '';

        // Hata sessiz kalmamalı: şerit kırmızıya döner, sebebi ve "Tekrar dene" görünür.
        const bar = qcEl('qc-save-error', r);
        const strip = qcEl('qc-autosave-strip', r);
        if (bar) {
            bar.style.display = state === 'error' ? '' : 'none';
            const txt = bar.querySelector('.qc-save-error-msg');
            if (txt && state === 'error') txt.textContent = message || 'Sunucuya ulaşılamadı.';
        }
        if (strip) strip.classList.toggle('is-error', state === 'error');
    }

    /**
     * Kalem tarihinden kişiye özel kalkış üretildiyse operasyon bağlantısını gösterir.
     * Kullanıcı satışın operasyona düştüğünü kartı terk etmeden görür.
     */
    function qcPaintOpsLink(d, root) {
        const box = qcEl('qc-ops-link', root);
        if (!box) return;
        const dep = d.private_departure;
        box.style.display = dep ? '' : 'none';
        if (dep) {
            const a = box.querySelector('.qc-ops-link-btn');
            if (a) a.dataset.url = dep.url;
        }
        const warn = qcEl('qc-ops-skipped', root);
        if (warn) {
            warn.style.display = (d.private_skipped > 0) ? '' : 'none';
            const n = warn.querySelector('.qc-ops-skipped-n');
            if (n) n.textContent = d.private_skipped;
        }
    }

    function qcOpenOpsDeparture(btn) {
        const url = btn?.dataset.url;
        if (url && typeof openQuickView === 'function') openQuickView(url);
    }

    function qcBuildPayload(root) {
        const r = root || qcRoot();
        const v = (id, d = null) => { const el = qcEl(id, r); return el ? el.value : d; };

        const items = [];
        qcEl('qv-products-tbody', r)?.querySelectorAll('.qv-product-row').forEach(row => {
            const name = row.querySelector('.qv-product-name').value.trim();
            if (!name) return;
            items.push({
                product_id    : row.querySelector('.row-product-id').value || null,
                itemable_type : row.querySelector('.row-itemable-type')?.value || null,
                itemable_id   : row.querySelector('.row-itemable-id')?.value || null,
                name          : name,
                quantity      : parseFloat(row.querySelector('.qv-product-qty').value) || 1,
                unit_price    : parseFloat(row.querySelector('.qv-product-price').value) || 0,
                tax_rate      : parseFloat(row.querySelector('.qv-product-tax').value) || 0,
                tax_included  : row.querySelector('.qv-product-tax-included')?.value === '1',
                discount_type : row.querySelector('.qv-product-discount-type')?.value || 'percent',
                discount_value: parseFloat(row.querySelector('.qv-product-discount')?.value) || 0,
                currency      : row.querySelector('.qv-product-currency').value,
                start_date    : row.querySelector('.qv-item-start-date')?.value || null,
                end_date      : row.querySelector('.qv-item-end-date')?.value || null,
                start_time    : row.querySelector('.qv-item-start-time')?.value || null,
                end_time      : row.querySelector('.qv-item-end-time')?.value || null
            });
        });

        const payload = {
            customer_id     : v('qc-customer-id') || null,
            title           : v('qc-title') || null,
            start_date      : v('qc-start-date') || null,
            end_date        : v('qc-end-date') || null,
            product_type_id : v('qc-product-type') || null,
            product_id      : v('qc-product-id') || null,
            tour_date_id    : v('qc-tour-date-id') || null,
            assigned_to     : v('qc-agent') || null,
            adult_count     : v('qc-adult') || 1,
            child_count     : v('qc-child') || 0,
            infant_count    : v('qc-infant') || 0,
            total_amount    : v('qc-total-amount') || 0,
            paid_amount     : v('qc-paid-amount') || 0,
            currency        : v('qc-currency'),
            payment_status  : v('qc-payment-status'),
            status          : v('qc-status-value'),
            pickup_location : v('qc-pickup') || null,
            flight_number   : v('qc-flight') || null,
            customer_note   : v('qc-customer-note') || null,
            internal_note   : v('qc-internal-note') || null,
            discount_rate   : (v('qc-discount-type') === 'percent' ? (parseFloat(v('qc-discount-value')) || 0) : 0),
            discount_amount : parseFloat(v('qc-discount-amount')) || 0
        };

        // Kalemler tabloya yüklenmeden gönderilirse sunucu "kalem kalmadı" sanıp
        // kayıtlı kalemleri siler. Yükleme bitene kadar anahtar hiç gönderilmez.
        if (r && r.dataset.itemsReady === '1') payload.items = items;

        // Çoklu müşteri: sıra korunur, ilk eleman birincil (fatura muhatabı).
        // Kalemlerdeki gibi hazırlık bayrağı beklenir — çipler çizilmeden gönderilen
        // boş liste sunucuda kayıtlı müşterileri siliyor olurdu.
        if (r && r.dataset.custsReady === '1') payload.customer_ids = qcCusts(r).map(c => c.id);

        // Odalar: kalemlerdeki gibi hazırlık bayrağı beklenir. Panel çizilmeden
        // gönderilen boş liste, operasyonda kurulmuş odaları silerdi.
        if (r && r.dataset.roomsReady === '1' && qcRoomMode(r)) {
            payload.rooms = qcRoomsPayload(r);
        }

        // Fiyatın çekildiği pazaryeri (sales.extra_data → pricing.marketplace_id).
        // Boş gönderilmez: seçim yoksa sunucudaki kayıtlı değere dokunulmaz.
        const mkId = v('qc-marketplace-id');
        if (mkId) {
            payload.pricing_marketplace_id = mkId;
            payload.pricing_marketplace_name = v('qc-marketplace-name') || '';
        }

        return payload;
    }

    /** Debounce'suz, anında gönderim (kapanış/sekme kapatma gibi son anlarda). */
    function qcSaveNow(root, opts) {
        const r = root || qcRoot();
        const st = qcState(r);
        const saleId = r?.dataset.saleId;
        if (!r || !st || !saleId) return Promise.resolve(false);

        clearTimeout(st.timer);
        st.timer = null;
        st.inflight = true;
        st.dirty = false;
        const seq = ++st.seq;
        qcSetSaveState('saving', null, r);

        return fetch(`/agency/sales/${saleId}/quick-update`, {
            method: 'POST',
            headers: { 'Content-Type':'application/json', 'Accept':'application/json', 'X-CSRF-TOKEN':'{{ csrf_token() }}' },
            body: JSON.stringify(qcBuildPayload(r)),
            keepalive: !!(opts && opts.keepalive) // kart kapanırken istek iptal olmasın
        })
        .then(r2 => r2.json().catch(() => ({ success: false, message: 'Oturum zaman aşımına uğramış olabilir (sayfayı yenileyin).' })))
        .then(d => {
            st.inflight = false;
            if (seq < st.done) return d.success; // eski yanıt taze durumu ezmesin
            st.done = seq;
            qcSetSaveState(d.success ? 'saved' : 'error', d.message, r);
            if (d.success) qcPaintOpsLink(d, r);
            if (d.success && st.dirty) qcAutoSave(r); // uçuş sırasında değişen alanlar
            return !!d.success;
        })
        .catch(() => {
            st.inflight = false;
            qcSetSaveState('error', 'Sunucuya ulaşılamadı — bağlantınızı kontrol edin.', r);
            return false;
        });
    }

    function qcAutoSave(node) {
        const r = qcRoot(node);
        // Künye satırları gizli alanların aynasıdır: kaydedilen ne ise ekranda
        // da o dursun (yeni satışta da geçerli, o yüzden erken çıkıştan önce).
        if (typeof qcPfxSyncAll === 'function') qcPfxSyncAll(r);
        const st = qcState(r);
        if (!r || !st || !r.dataset.saleId) return; // yeni satış: "Satışı Oluştur" ile kaydedilir
        st.dirty = true;
        clearTimeout(st.timer);
        qcSetSaveState('saving', null, r);
        st.timer = setTimeout(() => {
            st.timer = null;
            if (!r.isConnected) return;           // kart kapandı → qcFlushSaves gönderdi
            if (st.inflight) return;              // uçuşta; yanıt gelince tekrar tetiklenir
            qcSaveNow(r);
        }, 650);
    }
    window.qcAutoSave = qcAutoSave;
    window.qcSaveNow = qcSaveNow;

    /** Bekleyen kayıtları (debounce dolmadan) hemen gönder. */
    function qcFlushSaves(root) {
        const roots = root ? [root] : [...document.querySelectorAll('.qv-sales-wrapper')];
        roots.forEach(r => {
            const st = r.__qcSave;
            if (!st) return;
            // Sadece gönderilmemiş değişiklik varsa; aksi halde kapanışta aynı
            // istek iki kez gitmiş oluyordu (qcClose + drawer kancası).
            if (st.timer || st.dirty) qcSaveNow(r, { keepalive: true });
        });
    }
    window.qcFlushSaves = qcFlushSaves;

    // "Kapat": kapatmadan önce bekleyen değişikliği gönderir. 650 ms'lik debounce
    // dolmadan kapatıldığında son yazılan alan kayboluyordu.
    function qcClose(btn) {
        const r = qcRoot(btn);
        qcFlushSaves(r);
        closeQuickView();
    }
    window.qcClose = qcClose;

    // Sekme/pencere kapanırken bekleyen kayıt varsa gönder
    if (!window.__qcUnloadBound) {
        window.__qcUnloadBound = true;
        window.addEventListener('pagehide', () => qcFlushSaves());
        document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'hidden') qcFlushSaves(); });
    }

    // Drawer içindeki alan değişimlerinde otomatik kaydet (katalog modalı ve müşteri arama hariç).
    // Yığında birden fazla satış kartı olabileceği için TÜM bağlanmamış kartlar bağlanır.
    (function () {
        const bind = () => {
            document.querySelectorAll('.qv-sales-wrapper').forEach(wrap => {
                if (wrap.__qcAutoBound) return;
                wrap.__qcAutoBound = true;
                const handler = (e) => {
                    const t = e.target;
                    if (!t.matches || !t.matches('input, textarea, select')) return;
                    if (t.closest('#qvProductCatalogModal') || t.closest('#qcServiceModal') || t.closest('#qcDateModal') || t.closest('#qc-cust-dropdown') || t.closest('#qv-tab-qcinvoices')) return;
                    // Künye satırının kendi düzenleme kutusu geçici: değer henüz
                    // gerçek alana yazılmadı. Kayıt, satır kesinleşince gizli
                    // alandan tetiklenir — her tuş vuruşunda kaydetmeye gerek yok.
                    if (t.closest('.pfx-row')) return;
                    qcAutoSave(t);
                };
                wrap.addEventListener('input', handler);
                wrap.addEventListener('change', handler);
            });
        };
        bind();
        setTimeout(bind, 300);
    })();

    // ─── ZENGİN METİN (QUILL) NOT EDİTÖRLERİ ─────────────────────────────────────
    // Müşteri Notu ve Dahili Not alanları Quill ile zengin metin. İçerik gizli
    // textarea'ya senkronlanır (qcBuildPayload buradan okur) ve her değişimde
    // otomatik kayıt tetiklenir.
    (function initQcNoteEditors() {
        if (typeof Quill === 'undefined') return;
        function makeNoteQuill(editorId, hiddenId) {
            const el = document.getElementById(editorId);
            const hidden = document.getElementById(hiddenId);
            if (!el || !hidden || el.__quillInit) return null;
            el.__quillInit = true;
            const q = new Quill(el, {
                theme: 'snow',
                placeholder: el.dataset.placeholder || 'Buraya yazın...',
                modules: {
                    toolbar: [
                        ['bold', 'italic', 'underline'],
                        [{ 'list': 'ordered' }, { 'list': 'bullet' }],
                        [{ 'header': [3, 4, false] }],
                        ['link', 'clean']
                    ]
                }
            });
            const sync = () => { hidden.value = q.getText().trim().length ? q.root.innerHTML : ''; };
            sync();
            q.on('text-change', () => { sync(); if (typeof qcAutoSave === 'function') qcAutoSave(); });
            return q;
        }
        window.qcCustomerNoteQuill = makeNoteQuill('qc-customer-note-editor', 'qc-customer-note');
        window.qcInternalNoteQuill = makeNoteQuill('qc-internal-note-editor', 'qc-internal-note');
    })();

    // ─── STATUS PIPELINE ────────────────────────────────────────────────────────
    var qcStatusLabels = @json(collect($statusSteps)->map(fn($v,$k)=>$v['label'])->toArray());

    function qcSelectStatus(key, el) {
        document.getElementById('qc-status-value').value = key;
        document.getElementById('qc-metric-status').textContent = qcStatusLabels[key] || key;

        const segs = document.querySelectorAll('#qc-pipeline .sqv-seg');
        const keys = Object.keys(qcStatusLabels);
        const selectedIdx = keys.indexOf(key);

        segs.forEach((seg, i) => {
            seg.classList.remove('done', 'current', 'future');
            if (i < selectedIdx)       seg.classList.add('done');
            else if (i === selectedIdx) seg.classList.add('current');
            else                        seg.classList.add('future');
        });
        // Potansiyel → satış tamamlandı geçişi cari borcu doğurur; şerit tazelenir
        if (typeof qcCreditPaint === 'function') qcCreditPaint();
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    /**
     * Künye satırlarını gizli alanlardan tazeler.
     *
     * Kart alanlarının çoğu katalogdan programla doldurulabiliyor (tur tarihi
     * seçilince tarihler, kişi sayıları ve para birimi; "Toplamı Güncelle"
     * deyince tutar). Programla yazılan `.value` olay üretmediği için satırlar
     * kendiliğinden haberdar olmuyor — her metrik/kayıt turunda toplu okunur.
     */
    function qcPfxSyncAll(root) {
        if (!window.PFX) return;
        const r = root || qcRoot();
        if (!r) return;
        r.querySelectorAll('.pfx-row[data-target]').forEach(row => {
            if (row.classList.contains('editing')) return;
            const el = r.querySelector(row.dataset.target);
            if (!el) return;
            const raw = el.value == null ? '' : String(el.value);
            if (row.dataset.value === raw) return;
            row.dataset.value = raw;
            window.PFX.repaint(row);
        });
    }

    /** Hesaplanan bir künye satırının ham değerini yazıp metnini tazeler. */
    function qcPfxSet(targetSel, raw) {
        if (!window.PFX) return;
        document.querySelectorAll('.pfx-row[data-target="' + targetSel + '"]').forEach(row => {
            if (row.dataset.value === raw) return;
            row.dataset.value = raw;
            window.PFX.repaint(row);
        });
    }

    // ─── METRICS UPDATE ──────────────────────────────────────────────────────────
    function qcUpdateMetrics() {
        const total  = parseFloat(document.getElementById('qc-total-amount').value) || 0;
        const paid   = parseFloat(document.getElementById('qc-paid-amount').value) || 0;
        const remaining = Math.max(0, total - paid);

        const adults   = parseInt(document.getElementById('qc-adult').value) || 0;
        const children = parseInt(document.getElementById('qc-child').value) || 0;
        const infants  = parseInt(document.getElementById('qc-infant').value) || 0;
        const people   = adults + children + infants;

        const saleCurrency = document.getElementById('qc-currency').value || 'TRY';
        const saleSymbol = (window.currencySymbols || {})[saleCurrency] || saleCurrency;

        const fmt = v => saleSymbol + v.toLocaleString('tr-TR', {minimumFractionDigits:2, maximumFractionDigits:2});
        document.getElementById('qc-metric-total').textContent     = fmt(total);
        document.getElementById('qc-metric-paid').textContent      = fmt(paid);
        document.getElementById('qc-metric-remaining').textContent  = fmt(remaining);
        document.getElementById('qc-metric-people').textContent    = people;
        document.getElementById('qc-remaining-display').value      = remaining.toLocaleString('tr-TR', {minimumFractionDigits:2, maximumFractionDigits:2});

        // Auto payment status
        const ps = document.getElementById('qc-payment-status');
        if (paid === 0)       ps.value = 'unpaid';
        else if (paid >= total) ps.value = 'paid';
        else                    ps.value = 'partial';

        // ─ Künye satırları ─
        // Kalan ve ödeme durumu KULLANICIDAN değil bu hesaptan gelir; gizli
        // alanlara programla yazıldıkları için olay tetiklenmez. Satırlar
        // doğrudan tazelenir (olay tetiklemek gereksiz bir kayıt turu açardı).
        qcPfxSet('#qc-remaining-display', String(remaining));
        qcPfxSet('#qc-payment-status', ps.value);
        // Para birimi değişince tutar satırlarının birim eki de değişir; ham
        // değer aynı kaldığı için tazeleme burada elle yapılır.
        document.querySelectorAll('.pfx-row[data-qc-money]').forEach(row => {
            if (row.dataset.suffix === saleSymbol) return;
            row.dataset.suffix = saleSymbol;
            if (window.PFX) window.PFX.repaint(row);
        });

        // Programla doldurulan alanlar (tarih, para birimi, kişi sayısı) satırlara yansısın
        qcPfxSyncAll();

        // Tutar değiştikçe cari şeridi de tazelenir (kaydetmeye gerek yok)
        qcCreditPaint();
    }

    // ─── CARİ / BORÇLANDIRMA ─────────────────────────────────────────────────────
    // Kural sunucuda da uygulanır (SalesController::creditBlockMessage); buradaki
    // şerit yalnızca aynı hesabı kullanıcıya ANINDA gösterir ki satış kaydedilmeye
    // çalışıldığında sürpriz olmasın.

    /** Tutarı kaynak biriminden hedef birime çevirir (ayarlardaki kurlarla, TL üzerinden). */
    function qcCreditConvert(amount, from, to) {
        const fr = QC_CURRENCY_RATES[(from || 'TRY').toUpperCase()] || 1;
        const tr = QC_CURRENCY_RATES[(to || 'TRY').toUpperCase()] || 1;
        return tr > 0 ? (amount * fr) / tr : amount * fr;
    }

    function qcCreditMoney(v, symbol) {
        return (symbol || '') + (Number(v) || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
    }

    /** Müşterinin cari durumunu sunucudan okur (müşteri değiştiğinde bir kez). */
    function qcCreditFetch(root) {
        const r = root || qcRoot();
        const id = qcEl('qc-customer-id', r)?.value || '';
        if (!r) return;

        if (!id) { r.__qcCredit = null; r.__qcCreditId = ''; qcCreditPaint(r); return; }
        if (r.__qcCreditId === String(id) && r.__qcCredit) { qcCreditPaint(r); return; }

        r.__qcCreditId = String(id);
        const sid = qcSaleId(r);
        fetch('/agency/customers/' + encodeURIComponent(id) + '/credit' + (sid ? '?sale_id=' + encodeURIComponent(sid) : ''), {
            headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
        })
        .then(res => res.json())
        .then(d => {
            if (!d || !d.success || r.__qcCreditId !== String(id)) return;
            r.__qcCredit = d.credit;
            r.__qcCreditName = d.customer_name || '';
            qcCreditPaint(r);
        })
        .catch(() => {});
    }

    /** Şeridi çizer: limit ne kadar dolu, bu satışla birlikte ne olacak. */
    function qcCreditPaint(root) {
        const r = root || qcRoot();
        const box = qcEl('qc-credit', r);
        if (!box) return;

        const cr = r ? r.__qcCredit : null;
        if (!cr) { box.style.display = 'none'; return; }

        const total = parseFloat(qcEl('qc-total-amount', r)?.value) || 0;
        const paid  = parseFloat(qcEl('qc-paid-amount', r)?.value) || 0;
        const remaining = Math.max(0, total - paid);
        const status = qcEl('qc-status-value', r)?.value || 'potential';
        const isDebt = QC_DEBT_STATUSES.indexOf(status) > -1;
        const saleCurrency = qcEl('qc-currency', r)?.value || 'TRY';

        // Potansiyel / teklif aşamasındaki satış henüz cari borç doğurmaz
        const debt  = isDebt ? qcCreditConvert(remaining, saleCurrency, cr.currency) : 0;
        const after = (Number(cr.used) || 0) + debt;
        const limit = Number(cr.limit) || 0;
        const money = v => qcCreditMoney(v, cr.symbol);

        let tone = 'is-ok', state = '', msg = '';

        if (!cr.allowed) {
            tone = debt > 0 ? 'is-error' : '';
            state = 'Borçlandırma kapalı';
            msg = debt > 0
                ? 'Bu müşteriye <b>ödeme alınmadan</b> satış yapılamaz. ' + money(debt) + ' tahsilat girin ya da müşteri kartından borçlandırmayı açın.'
                : 'Bu müşteri ödeme alınmadan borçlandırılamaz — satış tutarının tamamı tahsil edilmelidir.';
        } else if (limit <= 0) {
            tone = debt > 0 ? 'is-error' : 'is-warn';
            state = 'Limit girilmemiş';
            msg = 'Borçlandırma açık ama kredi limiti <b>0</b>. Müşteri kartındaki "Cari / Borçlandırma" bölümünden limit girin.';
        } else if (after > limit) {
            tone = 'is-error';
            state = 'Limit aşılıyor';
            msg = 'Limit <b>' + money(limit) + '</b>, mevcut açık bakiye <b>' + money(cr.used) + '</b>. '
                + 'Bu satışın kalanı (' + money(debt) + ') eklendiğinde <b>' + money(after) + '</b> olur — bu haliyle kaydedilemez.';
        } else {
            tone = (limit > 0 && after / limit >= 0.75) ? 'is-warn' : 'is-ok';
            state = 'Kalan limit ' + money(limit - after);
            msg = debt > 0
                ? money(debt) + ' ödeme alınmadan borçlandırılıyor. Limit ' + money(limit) + ', bu satışla birlikte kullanılan ' + money(after) + '.'
                + (cr.term_days > 0 ? ' Vade: <b>' + cr.term_days + ' gün</b>.' : '')
                : 'Ödeme alınmadan <b>' + money(limit - after) + '</b> tutarında satış yapılabilir.';
        }

        box.style.display = '';
        box.classList.remove('is-ok', 'is-warn', 'is-error');
        if (tone) box.classList.add(tone);

        const fill = qcEl('qc-credit-fill', r);
        if (fill) fill.style.width = (limit > 0 ? Math.min(100, Math.round(after / limit * 100)) : (after > 0 ? 100 : 0)) + '%';

        const st = qcEl('qc-credit-state', r);
        if (st) st.textContent = state;

        const mm = qcEl('qc-credit-msg', r);
        if (mm) mm.innerHTML = msg;
    }

    // ─── FATURALAR ───────────────────────────────────────────────────────────────
    function qcInvApply(d) {
        const list = document.getElementById('qc-invoices-list');
        if (list && d.html !== undefined) list.innerHTML = d.html;
        const cnt = document.querySelector('.qv-tab[onclick*="qcinvoices"] .qv-tab-count');
        if (cnt && d.count !== undefined) cnt.textContent = d.count;
    }

    function qcInvoiceSubmit(e) {
        e.preventDefault();
        if (!qcSaleId()) return;
        const form = document.getElementById('qc-invoice-form');
        const btn = document.getElementById('qc-inv-submit-btn');
        btn.disabled = true;
        const fd = new FormData(form);
        fetch(`/agency/sales/${qcSaleId()}/invoices`, {
            method: 'POST',
            headers: { 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
            body: fd
        })
        .then(r => r.json())
        .then(d => {
            btn.disabled = false;
            if (d.success) {
                qcInvApply(d);
                // Sıradaki fatura numarası rozeti güncellenir (numara otomatik üretilir)
                const nn = document.getElementById('qc-inv-next-no');
                if (nn && d.next_number) nn.textContent = d.next_number;
                form.reset();
                // Varsayılanları geri koy (tarih bugün, tutar satış toplamı, para birimi satış dövizi)
                form.querySelector('[name=issue_date]').value = new Date().toISOString().slice(0, 10);
                const ta = document.getElementById('qc-total-amount');
                if (ta && ta.value) form.querySelector('[name=amount]').value = ta.value;
                const cs = document.getElementById('qc-currency');
                if (cs) { const sel = form.querySelector('[name=currency]'); if ([...sel.options].some(o => o.value === cs.value)) sel.value = cs.value; }
                if (typeof Swal !== 'undefined') Swal.fire({ toast:true, position:'top-end', timer:1800, showConfirmButton:false, icon:'success', title:d.message });
            } else {
                let msg = d.message || 'Fatura eklenemedi.';
                if (d.errors) msg = Object.values(d.errors).flat().join('\n');
                Swal.fire({ icon:'error', title:'Hata', text: msg });
            }
        })
        .catch(() => { btn.disabled = false; Swal.fire({ icon:'error', title:'Hata', text:'Fatura eklenemedi.' }); });
    }
    window.qcInvoiceSubmit = qcInvoiceSubmit;

    function qcInvoiceStatus(id, status, sel) {
        if (!qcSaleId()) return;
        sel.disabled = true;
        fetch(`/agency/sales/${qcSaleId()}/invoices/${id}/status`, {
            method: 'PATCH',
            headers: { 'Accept':'application/json', 'Content-Type':'application/json', 'X-CSRF-TOKEN':'{{ csrf_token() }}' },
            body: JSON.stringify({ status })
        })
        .then(r => r.json())
        .then(d => { if (d.success) qcInvApply(d); })
        .finally(() => { sel.disabled = false; });
    }
    window.qcInvoiceStatus = qcInvoiceStatus;

    function qcInvoiceDelete(id) {
        if (!qcSaleId()) return;
        const run = () => fetch(`/agency/sales/${qcSaleId()}/invoices/${id}`, {
            method: 'DELETE',
            headers: { 'Accept':'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
        })
        .then(r => r.json())
        .then(d => {
            if (d.success) {
                qcInvApply(d);
                if (typeof Swal !== 'undefined') Swal.fire({ toast:true, position:'top-end', timer:1600, showConfirmButton:false, icon:'success', title:d.message });
            }
        });
        if (typeof Swal !== 'undefined') {
            Swal.fire({ title:'Fatura silinsin mi?', text:'Fatura kaydı ve ekli belgesi kaldırılacak.', icon:'warning', showCancelButton:true, confirmButtonColor:'#ef4444', confirmButtonText:'Evet, sil', cancelButtonText:'Vazgeç' })
                .then(r => r.isConfirmed && run());
        } else if (confirm('Fatura silinsin mi?')) run();
    }
    window.qcInvoiceDelete = qcInvoiceDelete;

    // Resmi faturayı kes — faturalar modülündeki official-status ucunu kullanır,
    // başarıda satırdaki rozeti yerinde günceller (liste yeniden yüklenmez).
    function qcInvoiceIssue(id, number) {
        const run = () => fetch(`{{ url('agency/invoices') }}/${id}/official-status`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
            body: JSON.stringify({ official_status: 'issued' })
        })
        .then(r => r.json())
        .then(d => {
            if (!d.success) {
                Swal.fire({ icon: 'error', title: 'Hata', text: d.message || 'Resmi fatura durumu güncellenemedi.' });
                return;
            }
            const badge = document.querySelector(`[data-inv-official="${id}"]`);
            if (badge) {
                badge.classList.remove('pending');
                badge.classList.add('issued');
                badge.title = 'Resmi fatura kesildi';
                badge.innerHTML = '<i class="fas fa-stamp"></i> Resmi: Kesildi';
            }
            document.querySelectorAll(`[data-inv-issue="${id}"]`).forEach(b => b.remove());
            if (typeof Swal !== 'undefined') Swal.fire({ toast:true, position:'top-end', timer:1800, showConfirmButton:false, icon:'success', title:d.message });
        })
        .catch(() => Swal.fire({ icon: 'error', title: 'Hata', text: 'Bağlantı hatası oluştu.' }));

        if (typeof Swal !== 'undefined') {
            Swal.fire({
                title: 'Resmi fatura kesildi mi?',
                html: `<b>${number}</b> için resmi fatura durumu <b>"Kesildi"</b> olarak işaretlenecek.<br><small class="text-muted">Entegrasyon bağlandığında bu işlem resmi faturayı otomatik kesecek.</small>`,
                icon: 'question', showCancelButton: true,
                confirmButtonText: 'Evet, kesildi olarak işaretle', cancelButtonText: 'Vazgeç', confirmButtonColor: '#d97706'
            }).then(r => r.isConfirmed && run());
        } else if (confirm('Resmi fatura "Kesildi" olarak işaretlensin mi?')) run();
    }
    window.qcInvoiceIssue = qcInvoiceIssue;

    // ─── TEKLİF BELGESİ (teklif mektubu) ────────────────────────────────────────
    function qcDocOpen() {
        const o = document.getElementById('qcdoc-overlay');
        if (o) o.hidden = false;
    }
    function qcDocClose() {
        const o = document.getElementById('qcdoc-overlay');
        if (o) o.hidden = true;
    }
    window.qcDocOpen = qcDocOpen;
    window.qcDocClose = qcDocClose;

    document.addEventListener('click', function (e) {
        const o = document.getElementById('qcdoc-overlay');
        if (o && !o.hidden && e.target === o) qcDocClose();
    });

    document.getElementById('qcdoc-format')?.addEventListener('click', function (e) {
        const b = e.target.closest('button[data-fmt]');
        if (!b) return;
        this.querySelectorAll('button').forEach(x => x.classList.toggle('active', x === b));
    });

    function qcDocSelectedFormat() {
        return document.querySelector('#qcdoc-format button.active')?.dataset.fmt || 'pdf';
    }

    function qcDocRenderList(docs) {
        const list = document.getElementById('qcdoc-list');
        const cnt = document.getElementById('qcdoc-count');
        if (cnt) cnt.textContent = docs.length;
        if (!list) return;
        if (!docs.length) {
            list.innerHTML = '<div class="qcdoc-empty"><i class="fas fa-file-circle-plus"></i>Henüz belge oluşturulmadı.<br><small>Yukarıdan format seçip "Oluştur ve İndir"e basın.</small></div>';
            return;
        }
        list.innerHTML = docs.map(d => `
            <div class="qcdoc-row" data-doc-id="${d.id}">
                <div class="qcdoc-row-ico"><i class="fas fa-file-lines"></i></div>
                <div class="qcdoc-row-main">
                    <b>${qcEsc(d.number)}</b>
                    <small>${qcEsc(d.date || '')}${d.creator ? ' · ' + qcEsc(d.creator) : ''}</small>
                </div>
                <div class="qcdoc-row-acts">
                    <a href="${d.preview_url}" target="_blank" title="Önizle"><i class="fas fa-eye"></i></a>
                    <a href="${d.pdf_url}" title="PDF indir"><i class="fas fa-file-pdf"></i></a>
                    <a href="${d.word_url}" title="Word indir"><i class="fas fa-file-word"></i></a>
                    <button type="button" class="danger" onclick="qcDocDelete(${d.id})" title="Sil"><i class="fas fa-trash-can"></i></button>
                </div>
            </div>`).join('');
    }

    function qcDocCreate() {
        if (!qcSaleId()) return;
        const btn = document.getElementById('qcdoc-create-btn');
        const numberInput = document.getElementById('qcdoc-number');
        btn.disabled = true;
        fetch(`/agency/sales/${qcSaleId()}/offer-documents`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
            body: JSON.stringify({ document_number: numberInput ? numberInput.value.trim() : '' })
        })
        .then(r => r.json())
        .then(d => {
            btn.disabled = false;
            if (!d.success) {
                let msg = d.message || 'Belge oluşturulamadı.';
                if (d.errors) msg = Object.values(d.errors).flat().join('\n');
                Swal.fire({ icon: 'error', title: 'Hata', text: msg });
                return;
            }
            if (d.documents) qcDocRenderList(d.documents);
            if (numberInput && d.next_number) numberInput.value = d.next_number;
            // Seçili formatta indir
            const fmt = qcDocSelectedFormat();
            const url = fmt === 'word' ? d.document.word_url : d.document.pdf_url;
            window.open(url, '_blank');
            if (typeof Swal !== 'undefined') Swal.fire({ toast:true, position:'top-end', timer:1800, showConfirmButton:false, icon:'success', title:d.message });
        })
        .catch(() => { btn.disabled = false; Swal.fire({ icon: 'error', title: 'Hata', text: 'Belge oluşturulamadı.' }); });
    }
    window.qcDocCreate = qcDocCreate;

    function qcDocDelete(id) {
        if (!qcSaleId()) return;
        const run = () => fetch(`/agency/sales/${qcSaleId()}/offer-documents/${id}`, {
            method: 'DELETE',
            headers: { 'Accept': 'application/json', 'X-CSRF-TOKEN': '{{ csrf_token() }}' }
        })
        .then(r => r.json())
        .then(d => {
            if (d.success) {
                if (d.documents) qcDocRenderList(d.documents);
                const numberInput = document.getElementById('qcdoc-number');
                if (numberInput && d.next_number) numberInput.value = d.next_number;
                if (typeof Swal !== 'undefined') Swal.fire({ toast:true, position:'top-end', timer:1600, showConfirmButton:false, icon:'success', title:d.message });
            }
        });
        if (typeof Swal !== 'undefined') {
            Swal.fire({ title: 'Belge silinsin mi?', text: 'Belge kaydı kaldırılacak.', icon: 'warning', showCancelButton: true, confirmButtonColor: '#ef4444', confirmButtonText: 'Evet, sil', cancelButtonText: 'Vazgeç' })
                .then(r => r.isConfirmed && run());
        } else if (confirm('Belge silinsin mi?')) run();
    }
    window.qcDocDelete = qcDocDelete;

    // İndirim tipi (yüzde / tutar) geçişi
    function qcSetDiscountType(t) {
        const h = document.getElementById('qc-discount-type');
        if (h) h.value = t;
        document.querySelectorAll('.qc-disc-seg button').forEach(b => b.classList.toggle('active', b.dataset.discType === t));
        calculateQvProductTotals();
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }
    window.qcSetDiscountType = qcSetDiscountType;

    // Sync product grand total to the total amount field
    // Kullanıcı toplam tutarı elle girdiyse otomatik senkron onu ezmez
    var _qcTotalManual = false;
    function qcTotalEdited() { _qcTotalManual = true; qcUpdateMetrics(); }

    function qcSyncProductTotals(silent, auto) {
        // auto=true → ürün eklendikçe otomatik senkron; kullanıcı tutarı elle girmişse dokunma
        if (auto === true && _qcTotalManual) { qcUpdateMetrics(); return; }
        const totalEl = document.getElementById('qv-summary-total');
        if (!totalEl) return;
        const text = totalEl.textContent.replace(/[^0-9,-]/g, '').replace(',', '.');
        const val  = parseFloat(text) || 0;
        document.getElementById('qc-total-amount').value = val.toFixed(2);
        if (auto !== true) _qcTotalManual = false; // elle "Toplamı Güncelle" → manuel bayrağı sıfırla
        qcUpdateMetrics();
        // Buton tıklaması input/change üretmediği için otomatik kayıt tetiklenmiyordu:
        // "Toplamı Güncelle" sonrası tutar kaydedilmeden kalıyordu.
        if (typeof qcAutoSave === 'function') qcAutoSave();
        if (silent !== true && typeof Swal !== 'undefined') {
            Swal.fire({ icon:'success', title:'Toplam Güncellendi', text:'Ürün toplamı "Genel" sekmesine aktarıldı.', timer:1500, showConfirmButton:false });
        }
    }

    // Genel sekmesi alanlarını (yalnızca boşsa) ürün seçiminden doldur
    function qcAutofillGeneral(name, typeId) {
        const t = document.getElementById('qc-title');
        if (t && !t.value.trim() && name) {
            t.value = name;
            if (typeof qcUpdateHeaderSubtitle === 'function') qcUpdateHeaderSubtitle();
        }
        const pt = document.getElementById('qc-product-type');
        if (pt && !pt.value && typeId && [...pt.options].some(o => o.value == typeId)) {
            pt.value = String(typeId);
        }
    }

    // Kalem adını elle yazıp çıkınca, satış başlığı boşsa otomatik doldur
    // ─── FİYAT SINIFI BİLETİ ─────────────────────────────────────────────────────
    // Satır adındaki fiyat sınıfı (Yetişkin/Çocuk/Bebek…) yalnızca başlıkta gizli
    // kalmasın: fiyatın yanında bilet (ticket) rozeti olarak da gösterilir.
    var QC_FARE_TICKETS = {
        'Yetişkin':          { cls: 'ft-adult',  icon: 'fa-user' },
        'Çocuk':             { cls: 'ft-child',  icon: 'fa-child' },
        'Bebek':             { cls: 'ft-infant', icon: 'fa-baby' },
        'Tek Kişilik Farkı': { cls: 'ft-single', icon: 'fa-bed' },
        'Ek Yatak':          { cls: 'ft-bed',    icon: 'fa-bed-pulse' },
    };

    function qcPaintFareTicket(row) {
        const slot = row.querySelector('.qcx-fare-slot');
        if (!slot) return;
        const name = (row.querySelector('.qv-product-name')?.value || '').trim();
        const m = name.match(/·\s*(Yetişkin|Çocuk|Bebek|Tek Kişilik Farkı|Ek Yatak)(?:\s*\(özel tarih\))?\s*$/);
        const def = m ? QC_FARE_TICKETS[m[1]] : null;
        slot.innerHTML = def
            ? `<span class="qcx-fare-ticket ${def.cls}" title="Bu satır ${m[1].toLocaleLowerCase('tr')} fiyatıdır"><i class="fas ${def.icon}"></i>${m[1]}</span>`
            : '';
    }
    window.qcPaintFareTicket = qcPaintFareTicket;

    function qcRowNameChanged(input) {
        const name = (input.value || '').trim();
        // Ad elle değiştiyse satır artık katalogdaki ürünle aynı değildir → bağı bırak
        const row = input.closest('.qv-product-row');
        if (row && row.dataset.catalogName && row.dataset.catalogName !== name) {
            row.querySelector('.row-product-id').value = '';
            delete row.dataset.catalogName;
        }
        if (row) qcPaintFareTicket(row);
        if (typeof qcRefreshRowStates === 'function') qcRefreshRowStates();
        if (!name) return;
        const t = document.getElementById('qc-title');
        if (t && !t.value.trim()) { t.value = name; if (typeof qcUpdateHeaderSubtitle === 'function') qcUpdateHeaderSubtitle(); }
    }

    // ─── CUSTOMER (aranabilir seçici + hızlı ekleme) ─────────────────────────────
    function qcEsc(s){ return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
    function qcInitials(name){ return (name||'?').split(/\s+/).map(w=>w[0]||'').slice(0,2).join('').toUpperCase() || '?'; }
    /**
     * "#qc-title programla değişti" duyurusu.
     *
     * Başlık üç yerde birden görünür: header'daki tıkla-düzenle alanı, künyedeki
     * "Satış Başlığı" satırı ve kaydedilen değer. Üçü de #qc-title'ın input
     * olayını dinlediği için burada tek bir olay yayınlamak yetiyor — alan
     * katalogdan otomatik doldurulduğunda (t.value = name) olay kendiliğinden
     * doğmaz, bu yüzden elle tetikleniyor.
     */
    function qcUpdateHeaderSubtitle() {
        const t = qcEl('qc-title');
        if (!t) return;
        t.dispatchEvent(new Event('input', { bubbles: true }));
        t.dispatchEvent(new Event('change', { bubbles: true }));
    }

    function qcToggleCustomerForm(forceOpen) {
        const f = document.getElementById('qc-quick-customer-form');
        const willOpen = (forceOpen === true) ? true : (forceOpen === false ? false : f.classList.contains('d-none'));
        f.classList.toggle('d-none', !willOpen);
        const err = document.getElementById('qc-newcust-error'); if (err) err.style.display = 'none';
        if (willOpen) {
            qcCustClose();
            const fn = document.getElementById('qc_new_first_name');
            // Arama kutusundaki metni ada/soyada ön-doldur
            const q = (document.getElementById('qc-cust-search-input')?.value || '').trim();
            if (q && fn && !fn.value) { const p = q.split(' '); fn.value = p[0]; if (p.length > 1) document.getElementById('qc_new_last_name').value = p.slice(1).join(' '); }
            setTimeout(() => fn && fn.focus(), 60);
        }
    }

    // ── Aranabilir ÇOKLU müşteri seçici (server-side) ──
    // İş kuralı: bir satışta ya TEK şirket (corporate) ya da bir/birden fazla kişi
    // (individual) bulunabilir. Kural hem burada hem sunucuda uygulanır.
    var _qcCustT = null;

    /** Kartın müşteri listesi (kart kapsamlı — açık kartlar birbirini ezmesin). */
    function qcCusts(root) {
        const r = root || qcRoot();
        if (!r) return [];
        if (!r.__qcCustomers) r.__qcCustomers = [];
        return r.__qcCustomers;
    }
    function qcCustsSet(root, list) {
        const r = root || qcRoot();
        if (r) r.__qcCustomers = list;
    }

    function qcCustHasCorporate(r) { return qcCusts(r).some(c => c.corporate); }
    function qcCustPicked(r, id) { return qcCusts(r).some(c => String(c.id) === String(id)); }

    /**
     * Bir müşteri kaydının şirket olup olmadığı. Açılış verisi `corporate`,
     * arama uç noktası `is_corporate` + `type` gönderiyor; hangi anahtar gelirse
     * gelsin doğru okunsun diye üçü de kabul edilir. (Bayrak okunamadığında kural
     * hiç tetiklenmiyor ve hata ancak kayıtta sunucudan dönüyordu.)
     */
    function qcCustIsCorp(c) {
        if (!c) return false;
        if (c.is_corporate || c.corporate || c.isCorporate) return true;
        return String(c.customer_type || c.type || '').toLowerCase() === 'corporate';
    }

    /** Seçilen müşteri kurala takılıyorsa Türkçe sebebi, takılmıyorsa null döner. */
    function qcCustBlockReason(r, isCorporate) {
        const list = qcCusts(r);
        if (!list.length) return null;
        if (isCorporate) {
            return qcCustHasCorporate(r)
                ? 'Bir satışa yalnızca <b>tek bir şirket</b> müşteri eklenebilir.'
                : 'Kişi müşteri seçiliyken şirket eklenemez. Önce kişileri kaldırın.';
        }
        return qcCustHasCorporate(r)
            ? 'Şirket müşteri seçiliyken başka müşteri eklenemez. Önce şirketi kaldırın.'
            : null; // kişi + kişi serbest
    }

    /**
     * Seçici altındaki kural kutusu. html boşsa söner (liste her değiştiğinde
     * tazelenir), doluysa görünür. tone='error' kırmızıya çevirir, flash=true ise
     * kutu görünür alana kaydırılıp kısa bir vurgu animasyonu oynatılır — kullanıcı
     * "hiçbir şey olmadı" sanmasın diye.
     */
    function qcCustShowRule(r, html, tone, flash) {
        const box = qcEl('qc-cust-rule', r);
        if (!box) return;
        box.style.display = html ? '' : 'none';
        box.classList.toggle('is-error', !!html && tone === 'error');
        if (!html) { box.classList.remove('is-flash'); return; }
        box.querySelector('.qc-cust-rule-txt').innerHTML = html;
        if (!flash) return;
        box.classList.remove('is-flash');
        void box.offsetWidth; // animasyonu yeniden tetikle
        box.classList.add('is-flash');
        try { box.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } catch (e) {}
        clearTimeout(box.__qcFlashT);
        box.__qcFlashT = setTimeout(() => box.classList.remove('is-flash'), 1400);
    }

    /** Açılır listede bazı satırların neden kapalı olduğunu anlatan kısa açıklama. */
    function qcCustStateHint(r) {
        const list = qcCusts(r);
        if (!list.length) return '';
        return qcCustHasCorporate(r)
            ? 'Şirket müşteri seçili — bu satışa başka müşteri eklenemez.'
            : 'Kişi müşteri seçili — yalnızca kişi eklenebilir, şirket müşteri seçilemez.';
    }

    /** Açılır listenin başındaki durum/uyarı şeridi (html boşsa kaldırılır). */
    function qcCustNote(root, html, isError) {
        const r = root || qcRoot();
        const list = qcEl('qc-cust-list', r);
        if (!list) return;
        let el = list.querySelector('.qc-cust-note');
        if (!html) { if (el) el.remove(); return; }
        if (!el) {
            el = document.createElement('div');
            el.className = 'qc-cust-note';
            list.insertBefore(el, list.firstChild);
        }
        el.classList.toggle('is-error', !!isError);
        el.innerHTML = '<i class="fas ' + (isError ? 'fa-triangle-exclamation' : 'fa-circle-info') + '"></i><span>' + html + '</span>';
        el.classList.remove('is-flash');
        void el.offsetWidth;
        el.classList.add('is-flash');
        try { el.scrollIntoView({ block: 'nearest' }); } catch (e) {}
    }

    function qcCustToggle(e) {
        if (e) e.stopPropagation();
        const r = qcRoot(e && e.target);
        const dd = qcEl('qc-cust-dropdown', r);
        if (!dd) return;
        const open = !dd.classList.contains('open');
        dd.classList.toggle('open', open);
        qcEl('qc-cust-trigger', r)?.classList.toggle('open', open);
        if (open) {
            const si = qcEl('qc-cust-search-input', r);
            if (si) si.value = '';
            qcCustDoSearch(r, '');
            setTimeout(() => si && si.focus(), 50);
        }
    }
    function qcCustClose(root) {
        const r = root || qcRoot();
        qcEl('qc-cust-dropdown', r)?.classList.remove('open');
        qcEl('qc-cust-trigger', r)?.classList.remove('open');
    }
    function qcCustSearch(el, q) {
        const r = qcRoot(el);
        const term = (q !== undefined) ? q : (el && el.value) || '';
        clearTimeout(_qcCustT);
        _qcCustT = setTimeout(() => qcCustDoSearch(r, term), 220);
    }
    function qcCustDoSearch(root, q) {
        const r = root || qcRoot();
        const list = qcEl('qc-cust-list', r);
        if (!list) return;
        list.innerHTML = '<div class="qc-cust-loading"><i class="fas fa-spinner fa-spin me-1"></i> Aranıyor…</div>';
        fetch(URL_CUSTOMER_SEARCH + '?q=' + encodeURIComponent(q), { headers: { 'Accept': 'application/json' } })
            .then(res => res.json())
            // Endpoint (agency.customers.search) {results:[{id,text,type,is_corporate}]}
            // döner; alternatif anahtarlar (items/data, label/name) da desteklenir.
            .then(d => qcCustRender(r, Array.isArray(d) ? d : (d.results || d.items || d.data || [])))
            .catch(() => { list.innerHTML = '<div class="qc-cust-empty">Arama başarısız oldu.</div>'; });
    }
    function qcCustRender(root, items) {
        const r = root || qcRoot();
        const list = qcEl('qc-cust-list', r);
        if (!list) return;
        if (!items || !items.length) {
            list.innerHTML = '<div class="qc-cust-empty"><i class="fas fa-user-slash me-1"></i> Eşleşen müşteri yok.</div>';
            qcCustNote(r, qcCustStateHint(r), false);
            return;
        }
        list.innerHTML = items.map(c => {
            const raw = c.label || c.text || c.name || '';
            const parts = raw.split(' — ');
            const name = parts[0];
            const sub = (c.sub != null) ? c.sub : parts.slice(1).join(' — ');
            const corp = qcCustIsCorp(c);
            const picked = qcCustPicked(r, c.id);
            const blocked = !picked && qcCustBlockReason(r, corp);
            const payload = qcEsc(JSON.stringify({ id: c.id, name: name, sub: sub, corporate: corp }));
            const cls = 'qc-cust-row' + (picked ? ' is-picked' : (blocked ? ' is-disabled' : ''));
            const title = picked ? 'Zaten seçili' : (blocked ? blocked.replace(/<[^>]+>/g, '') : 'Satışa ekle');
            const ico = picked ? 'fa-circle-check' : (blocked ? 'fa-ban' : 'fa-circle-plus');
            return `<div class="${cls}" data-c="${payload}" title="${qcEsc(title)}" onclick="qcCustSelectEl(this)">
                <div class="qc-cust-av">${qcEsc(qcInitials(name))}</div>
                <div class="qc-cust-meta"><div class="qc-cust-name">${qcEsc(name)}</div>${sub ? '<div class="qc-cust-sub">'+qcEsc(sub)+'</div>' : ''}</div>
                ${corp ? '<span class="qc-cust-tag corp">Şirket</span>' : ''}
                <i class="fas ${ico} qc-cust-pick"></i>
            </div>`;
        }).join('');
        // Liste çizildikten sonra durum açıklaması başa eklenir: kullanıcı tıklamadan
        // da hangi tip müşterinin neden eklenemediğini görür.
        qcCustNote(r, qcCustStateHint(r), false);
    }
    function qcCustSelectEl(el) {
        let d = {};
        try { d = JSON.parse(el.getAttribute('data-c')); } catch (e) {}
        const r = qcRoot(el);
        // Engellenen satıra tıklamada sessiz kalma: satırı titret, sebebi göster.
        if (d.id && !qcCustPicked(r, d.id) && qcCustBlockReason(r, !!d.corporate)) {
            el.classList.remove('is-denied');
            void el.offsetWidth;
            el.classList.add('is-denied');
            clearTimeout(el.__qcDenyT);
            el.__qcDenyT = setTimeout(() => el.classList.remove('is-denied'), 600);
        }
        qcCustAdd(r, d.id, d.name, d.sub, !!d.corporate);
    }

    /** Satışa müşteri ekler (kural ihlalinde eklemez, sebebini gösterir). */
    function qcCustAdd(root, id, name, sub, corporate) {
        const r = root || qcRoot();
        if (!id) return;
        if (qcCustPicked(r, id)) { qcCustClose(r); return; }
        const reason = qcCustBlockReason(r, !!corporate);
        if (reason) {
            // Uyarı seçim anında, seçimin yapıldığı yerde verilir: açılır listenin
            // başındaki şerit + seçicinin altındaki kural kutusu birlikte yanar.
            qcCustNote(r, reason, true);
            qcCustShowRule(r, reason, 'error', true);
            const dd = qcEl('qc-cust-dropdown', r);
            // Liste kapalıyken (ör. yeni müşteri formundan gelen çağrı) şerit
            // görünmeyeceği için modal uyarıya düşülür.
            if (!(dd && dd.classList.contains('open')) && typeof Swal !== 'undefined') {
                Swal.fire({ icon: 'warning', title: 'Eklenemedi', html: reason });
            }
            return;
        }
        const list = qcCusts(r);
        list.push({ id: id, name: name || '', sub: sub || '', corporate: !!corporate, primary: list.length === 0 });
        qcCustPaint(r);
        qcCustClose(r);
        if (typeof qcAutoSave === 'function') qcAutoSave(r);
    }

    function qcCustRemove(el, id) {
        const r = qcRoot(el);
        const list = qcCusts(r).filter(c => String(c.id) !== String(id));
        if (list.length && !list.some(c => c.primary)) list[0].primary = true;
        qcCustsSet(r, list);
        qcCustPaint(r);
        if (typeof qcAutoSave === 'function') qcAutoSave(r);
    }

    /** Birincil müşteri = fatura muhatabı; listenin başına alınır. */
    function qcCustMakePrimary(el, id) {
        const r = qcRoot(el);
        const list = qcCusts(r);
        const i = list.findIndex(c => String(c.id) === String(id));
        if (i < 0) return;
        list.forEach(c => c.primary = false);
        list[i].primary = true;
        list.unshift(list.splice(i, 1)[0]);
        qcCustPaint(r);
        if (typeof qcAutoSave === 'function') qcAutoSave(r);
    }

    /** Çipleri, gizli birincil id'yi, başlık linkini ve kural uyarısını yeniden çizer. */
    function qcCustPaint(root) {
        const r = root || qcRoot();
        const list = qcCusts(r);
        // Bayrak hangi anahtarla gelirse gelsin tek biçime indirgenir (corporate).
        list.forEach(c => { c.corporate = qcCustIsCorp(c); });
        if (list.length && !list.some(c => c.primary)) list[0].primary = true;
        const primary = list.find(c => c.primary) || list[0] || null;

        const hidden = qcEl('qc-customer-id', r);
        if (hidden) hidden.value = primary ? primary.id : '';

        const wrap = qcEl('qc-custchips', r);
        if (wrap) {
            wrap.innerHTML = list.map(c => {
                const isP = !!c.primary;
                const cid = parseInt(c.id, 10);
                // Müşteri kartına geçiş her müşteri için korunur (qc-cust-jump)
                return `<div class="qc-custchip ${isP ? 'is-primary' : ''} ${c.corporate ? 'is-corp' : ''}" data-cid="${cid}">
                    <span class="qc-custchip-av">${qcEsc(qcInitials(c.name))}</span>
                    <span class="qc-custchip-meta">
                        <span class="qc-custchip-name">${qcEsc(c.name)}</span>
                        ${c.sub ? '<span class="qc-custchip-sub">' + qcEsc(c.sub) + '</span>' : ''}
                    </span>
                    ${c.corporate ? '<span class="qc-custchip-tag corp">Şirket</span>' : ''}
                    ${isP ? '<span class="qc-custchip-tag">Birincil</span>' : `<button type="button" class="qc-custchip-act star" title="Birincil (fatura muhatabı) yap" onclick="qcCustMakePrimary(this, ${cid})"><i class="fas fa-star"></i></button>`}
                    <button type="button" class="qc-custchip-act qc-cust-jump" title="Müşteri kartını aç" onclick="openCustomerDrawer(${cid})"><i class="fas fa-arrow-up-right-from-square"></i></button>
                    <button type="button" class="qc-custchip-act del" title="Satıştan çıkar" onclick="qcCustRemove(this, ${cid})"><i class="fas fa-times"></i></button>
                </div>`;
            }).join('');
        }

        // Tetikleyici: seçim yokken "arayın", varken "müşteri ekle"
        const ico = qcEl('qc-cust-tr-ico', r);
        const txt = qcEl('qc-cust-tr-txt', r);
        const trg = qcEl('qc-cust-trigger', r);
        const corpLocked = qcCustHasCorporate(r);
        if (ico && txt && trg) {
            if (list.length) {
                ico.innerHTML = '<i class="fas fa-user-plus"></i>';
                txt.textContent = corpLocked ? 'Şirket seçili — başka müşteri eklenemez' : 'Başka müşteri ekle…';
            } else {
                ico.innerHTML = '<i class="fas fa-magnifying-glass"></i>';
                txt.textContent = 'Müşteri seçin veya arayın…';
            }
            trg.classList.toggle('selected', list.length > 0);
            trg.disabled = corpLocked;
            trg.style.opacity = corpLocked ? '0.55' : '';
            trg.style.cursor = corpLocked ? 'not-allowed' : '';
        }

        // Kart başlığındaki müşteri linki birincil müşteriyi gösterir
        const lbl = qcEl('qc-customer-label', r);
        if (lbl) {
            const extra = list.length > 1 ? ` <span class="sqv-dot">+${list.length - 1}</span>` : '';
            lbl.innerHTML = primary
                ? `<a href="javascript:void(0)" class="sqv-customer-link" title="Müşteri kartını aç" onclick="openCustomerDrawer(${parseInt(primary.id, 10)})"><i class="fas fa-user"></i> ${qcEsc(primary.name)}</a>${extra}`
                : `<i class="fas fa-user"></i> Müşteri seçin`;
        }

        // Kural kutusu liste her değiştiğinde tazelenir. İhlal (eski/kaydedilmemiş
        // durum da dahil) kırmızı yanar ve ne yapılacağını söyler; tek şirket
        // seçiliyken bilgi verir; kişi seçimlerinde söner.
        const corpCount = list.filter(c => c.corporate).length;
        let ruleHtml = '', ruleTone = 'info';
        if (corpCount > 1) {
            ruleHtml = 'Bu satışta <b>' + corpCount + ' şirket müşteri</b> var — bu haliyle kaydedilemez. Yalnızca birini bırakıp diğerlerini <b>×</b> ile çıkarın.';
            ruleTone = 'error';
        } else if (corpCount === 1 && list.length > 1) {
            ruleHtml = 'Şirket müşteri ile kişi müşteriler aynı satışta birleştirilemez — bu haliyle kaydedilemez. Ya şirketi ya da kişileri <b>×</b> ile listeden çıkarın.';
            ruleTone = 'error';
        } else if (corpCount === 1) {
            ruleHtml = 'Şirket müşterili satışlara ikinci bir müşteri eklenemez. Birden fazla müşteri için <b>kişi</b> tipinde müşteriler kullanın.';
        }
        const changed = r && r.__qcCustRuleLast !== ruleHtml;
        if (r) r.__qcCustRuleLast = ruleHtml;
        qcCustShowRule(r, ruleHtml, ruleTone, ruleTone === 'error' && changed);

        // Birincil müşteri değiştiyse cari limiti yeniden okunur (şerit onu gösterir)
        if (typeof qcCreditFetch === 'function') qcCreditFetch(r);

        // Açılır liste açıksa durum açıklaması da tazelensin.
        if (qcEl('qc-cust-dropdown', r)?.classList.contains('open')) {
            qcCustNote(r, qcCustStateHint(r), false);
        }
    }

    /** Geriye dönük uyum: tek müşteri seçen eski çağrılar (yeni müşteri formu vb.). */
    function qcCustSelect(id, name, sub, corporate) {
        const r = qcRoot();
        if (!id) { qcCustsSet(r, []); qcCustPaint(r); if (typeof qcAutoSave === 'function') qcAutoSave(r); return; }
        qcCustAdd(r, id, name, sub, corporate);
    }

    // Dropdown dışına tıklayınca kapat (bir kez bağla)
    if (!window.__qcCustOutsideBound) {
        window.__qcCustOutsideBound = true;
        document.addEventListener('click', function (e) {
            // Açık her kartın seçicisi ayrı ayrı kapatılır (arka plandaki kartların
            // id'leri data-original-id'ye taşındığı için sınıfla seçilir).
            document.querySelectorAll('.qc-cust-picker').forEach(picker => {
                if (!picker.contains(e.target)) {
                    picker.querySelector('.qc-cust-dropdown')?.classList.remove('open');
                    picker.querySelector('.qc-cust-trigger')?.classList.remove('open');
                }
            });
        });
    }

    function qcSaveQuickCustomer() {
        const first = document.getElementById('qc_new_first_name').value.trim();
        const last  = document.getElementById('qc_new_last_name').value.trim();
        const phone = document.getElementById('qc_new_phone').value.trim();
        const email = document.getElementById('qc_new_email').value.trim();
        const national_id = document.getElementById('qc_new_national_id').value.trim();
        const gender = document.getElementById('qc_new_gender').value;
        const errBox = document.getElementById('qc-newcust-error');
        const showErr = (msg) => { errBox.innerHTML = msg; errBox.style.display = ''; };
        errBox.style.display = 'none';

        if (!first || !last) { showErr('<i class="fas fa-circle-exclamation me-1"></i> Ad ve soyad zorunludur.'); return; }
        if (email && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) { showErr('<i class="fas fa-circle-exclamation me-1"></i> Geçerli bir e-posta girin ya da boş bırakın.'); return; }

        const btn = document.getElementById('qc-nc-save-btn');
        const reset = () => { btn.disabled = false; btn.querySelector('.qc-nc-save-txt').classList.remove('d-none'); btn.querySelector('.qc-nc-save-load').classList.add('d-none'); };
        btn.disabled = true; btn.querySelector('.qc-nc-save-txt').classList.add('d-none'); btn.querySelector('.qc-nc-save-load').classList.remove('d-none');

        fetch('{{ route("agency.sales.api.quick-customer") }}', {
            method: 'POST',
            headers: {'Content-Type':'application/json','Accept':'application/json','X-CSRF-TOKEN':'{{ csrf_token() }}'},
            body: JSON.stringify({ first_name:first, last_name:last, phone, email, national_id, gender })
        })
        .then(r => r.json())
        .then(d => {
            reset();
            if (d.success && d.customer) {
                qcCustSelect(d.customer.id, d.customer.full_name, d.customer.phone || d.customer.email || '');
                ['qc_new_first_name','qc_new_last_name','qc_new_phone','qc_new_email','qc_new_national_id'].forEach(id => document.getElementById(id).value = '');
                document.getElementById('qc_new_gender').value = '';
                qcToggleCustomerForm(false);
                if (typeof Swal !== 'undefined') Swal.fire({icon:'success', title:'Müşteri eklendi', text:d.customer.full_name + ' seçildi.', timer:1600, showConfirmButton:false});
            } else if (d.errors) {
                showErr('<i class="fas fa-circle-exclamation me-1"></i> ' + Object.values(d.errors).flat().map(qcEsc).join('<br>'));
            } else {
                showErr('<i class="fas fa-circle-exclamation me-1"></i> ' + qcEsc(d.message || 'Müşteri eklenemedi.'));
            }
        })
        .catch(() => { reset(); showErr('<i class="fas fa-triangle-exclamation me-1"></i> Sunucuya ulaşılamadı.'); });
    }

    // ─── ODALAMA + FİYAT TİPLERİ ────────────────────────────────────────────────
    // Konaklamalı turlarda (kültür + yurtdışı) satış ODA TABANLIDIR: kullanıcı oda
    // ekler, her odaya kaç yetişkin/çocuk/bebek gireceğini ve ek yatak olup
    // olmadığını söyler. Fiyat kuralları odalardan OTOMATİK türer:
    //   · Çift kişilik odada tek başına kalan kişiye  → tek kişilik oda farkı
    //   · Kapasitenin üstünde kalan kişiye            → ek yatak fiyatı
    //   · Oda başına 1. çocuk bir tane, kalanlar 2. çocuk tarifesinden
    // Bu eklemeler sessizce toplama girmez; her odanın altında gerekçesiyle
    // rozet olarak gösterilir ("neden bu tutar çıktı" görünür olsun).
    //
    // TEK KAYNAK: panel kendi adedini saklamaz. Adetler satış kalemlerindeki tur
    // satırlarında (`data-tour-line="1"`, adı "… · <fiyat tipi>" ile biten) tutulur.
    // Günübirlik turlarda oda paneli görünmez; eski elle adet girişi çalışır.

    /** Fiyat tipi anahtarı → kalem adında eşleşecek etiketler.
     *  İlk eleman YENİ kalem adıdır; sonrakiler eski adlandırmalarla uyum içindir.
     *  Görünen etiketler TourFareCatalog'dan (QC_FARES) gelir, burada tekrarlanmaz. */
    var QC_FARE_ALIASES = {
        adult:     ['Yetişkin'],
        single:    ['Tek Kişilik Farkı', 'Tek Kişilik Oda Farkı'],
        extra_bed: [],
        child1:    ['1. Çocuk', 'Çocuk'],
        child2:    [],
        infant:    [],
    };

    /** Fiyat tipi tanımları — TourFareCatalog sırası ve etiketleriyle. */
    var QC_FARE_DEFS = (QC_FARES || []).map(f => ({
        key: f.key,
        label: f.short || f.label,
        long: f.label,
        hint: f.hint || '',
        icon: f.icon || 'fa-tag',
        per: f.per || 'person',
        always: f.key === 'adult',
        labels: [f.short || f.label, f.label].concat(QC_FARE_ALIASES[f.key] || []),
    }));

    function qcFareDef(key) { return QC_FARE_DEFS.find(d => d.key === key) || null; }

    /** Kartın fiyat tipi bağlamı (kart kapsamlı — açık kartlar birbirini ezmesin). */
    function qcFareCtx(root) {
        const r = root || qcRoot();
        const blank = { is_tour: false, is_overnight: false, currency: 'TRY', tour_name: '', date_label: '',
                        room_capacity: 2, marketplace: { id: null, name: null, source: 'none', options: [] },
                        prices: { adult: 0, child1: 0, child2: 0, infant: 0, single: 0, extra_bed: 0 } };
        if (!r) return blank;
        if (!r.__qcFareCtx) r.__qcFareCtx = blank;
        return r.__qcFareCtx;
    }

    /** Oda modu: yalnızca konaklamalı tur satışlarında oda kurgusu paneli görünür. */
    function qcRoomMode(root) {
        const c = qcFareCtx(root || qcRoot());
        return !!(c.is_tour && c.is_overnight);
    }

    /** Adetler odalardan türüyor mu? (Oda yoksa kullanıcı fiyat tipinden elle girebilir.) */
    function qcRoomDerived(root) {
        const r = root || qcRoot();
        return qcRoomMode(r) && qcRooms(r).length > 0;
    }

    /** Paneli tur/tur-dışı satışa göre göster-gizle. */
    function qcFareSetVisible(on, root) {
        const r = root || qcRoot();
        qcFareCtx(r).is_tour = !!on;
        const wrap = qcEl('qc-fares-wrap', r);
        if (wrap) wrap.style.display = on ? '' : 'none';
    }

    /** "Kapadokya Turu · 1. Çocuk (özel tarih)" → "1. çocuk" */
    function qcFareTail(name) {
        if (!name || name.indexOf(' · ') < 0) return '';
        return name.split(' · ').pop().replace(/\s*\(özel tarih\)\s*$/i, '').trim().toLowerCase();
    }

    /** Bu fiyat tipine karşılık gelen tur kalemi (yoksa null). */
    function qcFareItemRow(root, def) {
        const tbody = qcEl('qv-products-tbody', root || qcRoot());
        let found = null;
        (tbody ? tbody.querySelectorAll('.qv-product-row') : []).forEach(tr => {
            if (tr.dataset.tourLine !== '1') return;
            const tail = qcFareTail(tr.querySelector('.qv-product-name')?.value || '');
            if (tail && def.labels.some(l => l.toLowerCase() === tail)) found = tr;
        });
        return found;
    }

    /** Yeni kalem açarken kullanılacak ad: 2. Çocuk tarifesi yoksa sadece "Çocuk". */
    function qcFarePrimaryLabel(ctx, def) {
        if (def.key === 'child1' && !(parseFloat(ctx.prices.child2) > 0)) return 'Çocuk';
        return def.labels[0];
    }

    /** Panelde gösterilecek tipler: her zaman yetişkin + fiyatı tanımlı olanlar + kalemi olanlar. */
    function qcFareVisibleDefs(root) {
        const r = root || qcRoot();
        const ctx = qcFareCtx(r);
        return QC_FARE_DEFS.filter(def => {
            if (def.always) return true;
            if (parseFloat(ctx.prices[def.key]) > 0) return true;
            return !!qcFareItemRow(r, def);
        });
    }

    /** Paneli baştan çizer (yapı değiştiğinde: açılış, tarih seçimi, kalem yükleme). */
    function qcFareRender(root) {
        const r = root || qcRoot();
        const box = qcEl('qcfp-rows', r);
        if (!box) return;
        const ctx = qcFareCtx(r);
        const defs = qcFareVisibleDefs(r);

        const table = qcEl('qcfp-table', r);
        const empty = qcEl('qcfp-empty', r);
        const foot = qcEl('qcfp-foot', r);
        // Tur tarifesi de kalemi de yoksa panel yerine açıklama gösterilir
        const hasAny = defs.some(d => parseFloat(ctx.prices[d.key]) > 0 || qcFareItemRow(r, d));
        if (table) table.style.display = hasAny ? '' : 'none';
        if (foot) foot.style.display = hasAny ? '' : 'none';
        if (empty) empty.style.display = hasAny ? 'none' : '';

        const dateEl = qcEl('qcfp-date', r);
        if (dateEl) dateEl.textContent = ctx.date_label || '';

        // Oda kurgusu varsa adetler odalardan türer → kutular salt okunur, elle girilmez.
        const derived = qcRoomDerived(r);
        const cap = qcEl('qcfp-cap', r);
        if (cap) cap.style.display = (derived && hasAny) ? '' : 'none';

        box.innerHTML = defs.map(def => {
            const row = qcFareItemRow(r, def);
            // Birim fiyat: kalem varsa onunki (kullanıcı Ürünler sekmesinde değiştirmiş
            // olabilir), yoksa tur tarihindeki tarife.
            const price = row ? (parseFloat(row.querySelector('.qv-product-price')?.value) || 0)
                              : (parseFloat(ctx.prices[def.key]) || 0);
            const qty = row ? (parseFloat(row.querySelector('.qv-product-qty')?.value) || 0) : 0;
            const name = qcFarePrimaryLabel(ctx, def);
            const attrs = derived
                ? `readonly tabindex="-1" title="Adet oda kurgusundan hesaplanır — odaları düzenleyin."`
                : `oninput="qcFareQtyChanged(this)"`;
            return `<div class="qcfp-row ${qty > 0 ? 'is-on' : ''}" data-fare-key="${def.key}" data-fare-price="${price}">
                <span class="qcfp-name" title="${qcEsc(def.hint || '')}"><i class="fas ${def.icon}"></i> ${qcEsc(name)}</span>
                <span class="qcfp-c-unit qcfp-unit">${qcFareMoney(price, ctx.currency)}</span>
                <span class="qcfp-c-qty"><input type="number" class="qcfp-qty ${derived ? 'is-derived' : ''}" min="0" step="1" value="${qty}"
                        ${attrs} aria-label="${qcEsc(name)} adedi"></span>
                <span class="qcfp-c-sub qcfp-sub">${qcFareMoney(price * qty, ctx.currency)}</span>
            </div>`;
        }).join('');

        qcMarketRender(r);
        qcFareRecalc(r);
    }

    function qcFareMoney(v, cur) {
        return (parseFloat(v) || 0).toLocaleString('tr-TR', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' ' + (cur || 'TRY');
    }

    /** Satır tutarları + genel toplam + kişi sayacı (DOM'u yeniden kurmaz). */
    function qcFareRecalc(root) {
        const r = root || qcRoot();
        const box = qcEl('qcfp-rows', r);
        if (!box) return;
        const ctx = qcFareCtx(r);
        let total = 0, adult = 0, child = 0, infant = 0;

        box.querySelectorAll('.qcfp-row').forEach(row => {
            const price = parseFloat(row.dataset.farePrice) || 0;
            const qty = Math.max(0, parseInt(row.querySelector('.qcfp-qty').value) || 0);
            const key = row.dataset.fareKey;
            total += price * qty;
            // Tek kişi farkı ve ek yatak "kelle" değildir: biri fark, diğeri zaten
            // sayılmış bir kişinin yatak fiyatıdır — kişi sayacına eklenmezler.
            if (key === 'adult') adult += qty;
            else if (key === 'child1' || key === 'child2') child += qty;
            else if (key === 'infant') infant += qty;
            row.classList.toggle('is-on', qty > 0);
            row.querySelector('.qcfp-sub').textContent = qcFareMoney(price * qty, ctx.currency);
        });

        // Oda modunda kelle sayısı odalardan gelir: ek yatakta kalan kişi fiyat
        // tipinde "ek yatak" satırında görünür ama yine bir yetişkin/çocuktur.
        if (qcRoomDerived(r)) {
            const heads = qcRoomsHeads(r);
            adult = heads.adult; child = heads.child; infant = heads.infant;
        }

        const set = (id, v) => { const el = qcEl(id, r); if (el) el.textContent = v; };
        set('qcfp-n-adult', adult); set('qcfp-n-child', child); set('qcfp-n-infant', infant);
        const t = qcEl('qcfp-total', r);
        if (t) t.textContent = qcFareMoney(total, ctx.currency);
        return { adult, child, infant, total };
    }

    /** Adet değişti → ilgili tur kalemini yaz, toplamları ve katılımcı sayılarını güncelle. */
    function qcFareQtyChanged(input) {
        const r = qcRoot(input);
        const ctx = qcFareCtx(r);
        const rowEl = input.closest('.qcfp-row');
        const def = QC_FARE_DEFS.find(d => d.key === rowEl?.dataset.fareKey);
        if (!def) return;

        const qty = Math.max(0, parseInt(input.value) || 0);
        if (String(qty) !== input.value) input.value = qty; // negatif/boş girişi düzelt

        let item = qcFareItemRow(r, def);
        if (qty <= 0) {
            if (item) item.remove();
        } else if (item) {
            item.querySelector('.qv-product-qty').value = qty;
        } else {
            const price = parseFloat(rowEl.dataset.farePrice) || parseFloat(ctx.prices[def.key]) || 0;
            // Tur fiyatları kişi başı ve KDV dahil kabul edilir → satır KDV'si 0
            if (typeof addBlankQvProductRow === 'function') {
                addBlankQvProductRow({
                    name: (ctx.tour_name || 'Tur') + ' · ' + qcFarePrimaryLabel(ctx, def),
                    qty: qty, price: price, currency: ctx.currency || 'TRY',
                    tax: 0, tourLine: true,
                    productId: qcEl('qc-product-id', r)?.value || null,
                });
            }
        }

        if (typeof calculateQvProductTotals === 'function') calculateQvProductTotals();
        if (typeof qcSyncProductTotals === 'function') qcSyncProductTotals(true, true);
        qcFareSyncParticipants(r);
        qcFareRecalc(r);
        if (typeof qcAutoSave === 'function') qcAutoSave(r);
    }

    /** Panel adetleri → Genel sekmesindeki katılımcı kutuları (çocuk = 1. + 2. çocuk). */
    function qcFareSyncParticipants(root) {
        const r = root || qcRoot();
        const n = qcFareRecalc(r);
        if (!n) return;
        const a = qcEl('qc-adult', r), c = qcEl('qc-child', r), i = qcEl('qc-infant', r);
        if (a) a.value = Math.max(1, n.adult);
        if (c) c.value = n.child;
        if (i) i.value = n.infant;
        if (typeof qcUpdateMetrics === 'function') qcUpdateMetrics();
    }

    /**
     * Kalemler tarafında yapılan değişiklikleri panele yansıtır (ters yön).
     * Kullanıcının o an yazdığı kutuya dokunmaz.
     */
    function qcFareSyncFromItems(root) {
        const r = root || qcRoot();
        const box = qcEl('qcfp-rows', r);
        if (!box) return;
        box.querySelectorAll('.qcfp-row').forEach(row => {
            const def = QC_FARE_DEFS.find(d => d.key === row.dataset.fareKey);
            if (!def) return;
            const item = qcFareItemRow(r, def);
            const qty = item ? (parseFloat(item.querySelector('.qv-product-qty')?.value) || 0) : 0;
            const price = item ? (parseFloat(item.querySelector('.qv-product-price')?.value) || 0)
                               : (parseFloat(qcFareCtx(r).prices[def.key]) || 0);
            if (parseFloat(row.dataset.farePrice) !== price) {
                row.dataset.farePrice = price;
                row.querySelector('.qcfp-unit').textContent = qcFareMoney(price, qcFareCtx(r).currency);
            }
            const input = row.querySelector('.qcfp-qty');
            if (input !== document.activeElement) input.value = qty;
        });
        // Kalemlerde panelde olmayan bir fiyat tipi belirdiyse panel yeniden kurulur
        const shown = new Set([...box.querySelectorAll('.qcfp-row')].map(x => x.dataset.fareKey));
        const structural = qcFareVisibleDefs(r).some(d => !shown.has(d.key));
        if (structural) qcFareRender(r); else qcFareRecalc(r);
    }

    /** Kartın fiyat tipi bağlamını + oda kurgusunu açılışta köke bağlar ve çizer. */
    function qcFareBoot(root) {
        const r = root || qcRoot();
        if (!r) return;
        const boot = JSON.parse(JSON.stringify(_qcFareCtxBoot || {}));
        boot.date_label = '';
        r.__qcFareCtx = boot;
        r.__qcRooms = (_qcRoomsBoot || []).map(x => qcRoomNormalize(x));
        qcRoomsRender(r);
        qcFareRender(r);
    }

    // ─── PAZARYERİ (fiyat hangi pazardan geliyor) ────────────────────────────────
    // Kullanıcı "hangi pazar yerine göre fiyat gelecek" sorusunu kartta görebilsin
    // ve birden fazla pazarın fiyatı varsa seçebilsin diye tarife şeridi çizilir.
    // Seçim satışta saklanır (sales.extra_data → pricing.marketplace_id), böylece
    // kart yeniden açıldığında aynı fiyat gelir.

    function qcMarketRender(root) {
        const r = root || qcRoot();
        const bar = qcEl('qcmp', r);
        if (!bar) return;
        const ctx = qcFareCtx(r);
        const mk = ctx.marketplace || { id: null, name: null, source: 'none', options: [] };
        const opts = mk.options || [];

        // Tur satışı değilse ya da hiç pazaryeri fiyatı yoksa şerit gizlenir
        if (!ctx.is_tour || (!opts.length && !mk.id)) { bar.style.display = 'none'; return; }
        bar.style.display = '';

        const sel = qcEl('qcmp-select', r);
        if (sel) {
            sel.innerHTML = (opts.length ? opts : [{ id: mk.id, name: mk.name || '—', is_primary: false }])
                .map(o => `<option value="${o.id}" ${String(o.id) === String(mk.id) ? 'selected' : ''}>${qcEsc(o.name)}${o.is_primary ? ' (ana pazar)' : ''}</option>`).join('');
            sel.disabled = opts.length < 2;
            sel.title = opts.length < 2 ? 'Bu tarihte yalnızca bir pazaryerinin fiyatı tanımlı.' : 'Fiyatların alınacağı pazaryerini seçin.';
        }

        const badge = qcEl('qcmp-badge', r);
        const note = qcEl('qcmp-note', r);
        const warn = mk.source === 'fallback' || mk.source === 'none';
        bar.classList.toggle('is-warn', warn);

        if (badge) {
            const map = {
                primary:  ['is-primary',  '<i class="fas fa-star"></i> Ana pazar'],
                selected: ['is-selected', '<i class="fas fa-hand-pointer"></i> Elle seçildi'],
                fallback: ['is-fallback', '<i class="fas fa-triangle-exclamation"></i> Belirsiz'],
                none:     ['is-fallback', '<i class="fas fa-triangle-exclamation"></i> Fiyat yok'],
            };
            const [cls, html] = map[mk.source] || map.none;
            badge.className = 'qcmp-badge ' + cls;
            badge.innerHTML = html;
        }

        if (note) {
            if (mk.source === 'fallback') {
                note.innerHTML = 'Bu ürün için <b>ana pazaryeri seçilmemiş</b>; fiyat rastgele bir pazardan alındı. '
                    + 'Kalıcı çözüm için ürün kartındaki <b>Fiyatlandırma → Ana Pazaryeri</b> alanını doldurun. '
                    + 'Bu satışta doğru pazarı yukarıdan seçebilirsiniz.';
            } else if (mk.source === 'none') {
                note.innerHTML = 'Seçili tur tarihinde <b>hiçbir pazaryeri fiyatı tanımlı değil</b>. '
                    + 'Ürün kartındaki tarih & fiyat matrisinden fiyat girilmeli.';
            } else if (mk.source === 'selected') {
                note.innerHTML = 'Fiyatlar bu satış için seçtiğiniz pazaryerinden alınıyor; seçim satışla birlikte saklanır.';
            } else {
                note.innerHTML = 'Fiyatlar ürünün ana pazaryerinden alınıyor.';
            }
        }
    }

    /** Pazaryeri değişti → tarifeler yeni pazarın satırından okunur, her şey yeniden hesaplanır. */
    function qcMarketChanged(sel) {
        const r = qcRoot(sel);
        const ctx = qcFareCtx(r);
        const mk = ctx.marketplace || {};
        const opt = (mk.options || []).find(o => String(o.id) === String(sel.value));
        if (!opt) return;

        mk.id = opt.id;
        mk.name = opt.name;
        mk.source = opt.is_primary ? 'primary' : 'selected';
        ctx.prices = qcPricesFrom(opt);
        if (opt.currency) ctx.currency = opt.currency;

        const idEl = qcEl('qc-marketplace-id', r);   if (idEl) idEl.value = opt.id || '';
        const nmEl = qcEl('qc-marketplace-name', r); if (nmEl) nmEl.value = opt.name || '';

        // Kalemlerdeki birim fiyatlar da yeni pazarın tarifesine çekilir
        qcFareRepriceItems(r);
        if (qcRoomMode(r)) qcRoomsApply(r, { silent: true });
        qcFareRender(r);
        if (typeof qcAutoSave === 'function') qcAutoSave(r);
    }

    /** Tarih/pazaryeri nesnesinden fiyat sözlüğü (TourFareCatalog anahtarlarıyla). */
    function qcPricesFrom(src) {
        return {
            adult:     parseFloat(src.adult_price) || 0,
            child1:    parseFloat(src.child_price) || 0,
            child2:    parseFloat(src.child_price_2) || 0,
            infant:    parseFloat(src.infant_price) || 0,
            single:    parseFloat(src.single_supplement) || 0,
            extra_bed: parseFloat(src.extra_bed_price) || 0,
        };
    }

    /** Mevcut tur kalemlerinin birim fiyatını güncel tarifeye çeker. */
    function qcFareRepriceItems(root) {
        const r = root || qcRoot();
        const ctx = qcFareCtx(r);
        QC_FARE_DEFS.forEach(def => {
            const item = qcFareItemRow(r, def);
            if (!item) return;
            const inp = item.querySelector('.qv-product-price');
            if (inp) inp.value = parseFloat(ctx.prices[def.key]) || 0;
        });
        if (typeof calculateQvProductTotals === 'function') calculateQvProductTotals();
        if (typeof qcSyncProductTotals === 'function') qcSyncProductTotals(true, true);
    }

    // ─── ODA KURGUSU ─────────────────────────────────────────────────────────────
    // Odalar kart kapsamlıdır (r.__qcRooms) ve sunucuya `rooms` olarak gider;
    // sale_rooms'a konum eşlemeli yazılır. Operasyondaki Odalama sekmesi AYNI
    // kayıtları okuyup yolcuları bu odalara yerleştirir — bu yüzden alan adları
    // ve anlamları (adult_count/child_count/infant_count/capacity) birebir korunur.

    function qcRooms(root) {
        const r = root || qcRoot();
        if (!r) return [];
        if (!Array.isArray(r.__qcRooms)) r.__qcRooms = [];
        return r.__qcRooms;
    }

    function qcRoomNormalize(x) {
        const t = QC_ROOM_TYPES[x?.room_type] ? x.room_type : 'double';
        return {
            room_type: t,
            label: x?.label || '',
            capacity: Math.max(1, parseInt(x?.capacity) || (QC_ROOM_CAPS[t] || 2)),
            adult_count: Math.max(0, parseInt(x?.adult_count) || 0),
            child_count: Math.max(0, parseInt(x?.child_count) || 0),
            infant_count: Math.max(0, parseInt(x?.infant_count) || 0),
            extra_bed: !!x?.extra_bed,
            notes: x?.notes || '',
        };
    }

    /** Odalardaki toplam kelle (ek yatakta kalan da bir yetişkin/çocuktur). */
    function qcRoomsHeads(root) {
        return qcRooms(root).reduce((a, x) => ({
            adult: a.adult + (x.adult_count | 0),
            child: a.child + (x.child_count | 0),
            infant: a.infant + (x.infant_count | 0),
        }), { adult: 0, child: 0, infant: 0 });
    }

    /**
     * Bir odanın fiyat kırılımı — otomatik kuralların TEK yeri.
     *
     *  · Odada tek başına kalan yetişkin (yanında yatak işgal eden yok)
     *    → kişi başı fiyatın ÜSTÜNE tek kişilik oda farkı OTOMATİK eklenir.
     *  · Yatak kapasitesinin üstündeki YETİŞKİN → ek yatak fiyatından hesaplanır
     *    (çocuklar hariç: 1./2. çocuk tarifeleri zaten "iki yetişkin yanında
     *    kalan çocuk" varsayımıyla tanımlıdır, ikinci kez fiyatlanmazlar).
     *  · Oda başına 1. çocuk bir tane; kalan çocuklar 2. çocuk tarifesinden
     *    (2. çocuk tarifesi tanımlı değilse hepsi 1. çocuk tarifesinden).
     *  · Bebekler yatak işgal etmez; kapasite hesabına girmezler.
     *
     * Dönen `lines` doğrudan kullanıcıya rozet olarak gösterilir; `auto: true`
     * olanlar "otomatik uygulandı" vurgusuyla ve gerekçesiyle çizilir —
     * hiçbir fark toplama sessizce eklenmez.
     */
    function qcRoomPricing(room, ctx) {
        const p = k => parseFloat((ctx.prices || {})[k]) || 0;
        const A = Math.max(0, room.adult_count | 0);
        const C = Math.max(0, room.child_count | 0);
        const I = Math.max(0, room.infant_count | 0);
        const cap = Math.max(1, room.capacity | 0);
        const bedCap = cap + (room.extra_bed ? 1 : 0);
        const beds = A + C;                       // bebekler yatak işgal etmez
        const overflow = Math.max(0, beds - bedCap);

        const lines = [], warnings = [], notes = [];

        // Ek yatak fiyatı yalnızca kapasitenin üstündeki YETİŞKİN için uygulanır.
        const bedAdult = (room.extra_bed && p('extra_bed') > 0) ? Math.min(1, Math.max(0, A - cap)) : 0;
        if (room.extra_bed && bedAdult === 0) {
            notes.push(C > 0
                ? 'Ek yatak odaya kayıtlı; çocuk tarifeleri zaten ek yatak varsayımıyla tanımlı olduğu için ayrıca ek yatak fiyatı uygulanmadı.'
                : 'Ek yatak odaya kayıtlı ama kapasitenin üstünde yetişkin yok — ek yatak fiyatı uygulanmadı.');
        }
        if (overflow > 0) {
            warnings.push(`Yatak kapasitesi ${overflow} kişi aşıldı — ek yatak açın ya da yeni oda ekleyin.`);
        }

        const adultsFull = Math.max(0, A - bedAdult);
        const hasC2 = p('child2') > 0;
        const c1 = hasC2 ? Math.min(C, 1) : C;
        const c2 = hasC2 ? Math.max(0, C - 1) : 0;
        // Tek kişilik kullanım: odada yalnız bir yetişkin, yanında yatak işgal eden yok
        const singleN = (A === 1 && C === 0 && p('single') > 0) ? 1 : 0;

        const push = (key, qty, auto, reason) => {
            if (qty <= 0) return;
            const def = qcFareDef(key);
            if (!def) return;
            lines.push({ key, qty, unit: p(key), total: qty * p(key),
                         label: qcFarePrimaryLabel(ctx, def), icon: def.icon, auto: !!auto, reason: reason || '' });
        };

        push('adult', adultsFull);
        push('single', singleN, true, 'Odada tek başına kalındığı için tek kişilik oda farkı otomatik eklendi.');
        push('extra_bed', bedAdult, true, `Oda kapasitesi ${cap} yatak; üstündeki yetişkin ek yatak fiyatından hesaplandı.`);
        push('child1', c1);
        push('child2', c2);
        push('infant', I);

        return {
            lines, warnings, notes, beds, overflow, bed_capacity: bedCap,
            total: lines.reduce((s, l) => s + l.total, 0),
        };
    }

    /** Tüm odaların fiyat tipi başına toplam adedi (satış kalemlerini bu besler). */
    function qcRoomsFareTotals(root) {
        const r = root || qcRoot();
        const ctx = qcFareCtx(r);
        const out = {};
        qcRooms(r).forEach(room => {
            qcRoomPricing(room, ctx).lines.forEach(l => { out[l.key] = (out[l.key] || 0) + l.qty; });
        });
        return out;
    }

    function qcRoomsRender(root) {
        const r = root || qcRoot();
        const wrap = qcEl('qcrm', r);
        if (!wrap) return;
        if (!qcRoomMode(r)) { wrap.style.display = 'none'; return; }
        wrap.style.display = '';

        const ctx = qcFareCtx(r);
        const rooms = qcRooms(r);
        const list = qcEl('qcrm-list', r);
        const empty = qcEl('qcrm-empty', r);
        if (empty) empty.style.display = rooms.length ? 'none' : '';
        if (!list) return;

        // Liste her hesapta yeniden kurulduğu için odak kaybolmasın: hangi odanın
        // hangi alanındaysak render sonrası oraya geri dönülür (hızlı klavye girişi).
        const act = document.activeElement;
        const keep = (act && list.contains(act) && act.dataset.roomField)
            ? { idx: act.closest('.qcrm-room')?.dataset.roomIdx, field: act.dataset.roomField }
            : null;

        const typeOpts = Object.keys(QC_ROOM_TYPES).map(k =>
            `<option value="${k}">${qcEsc(QC_ROOM_TYPES[k])}${QC_ROOM_CAPS[k] ? ' · ' + QC_ROOM_CAPS[k] + ' yatak' : ''}</option>`).join('');

        list.innerHTML = rooms.map((room, i) => {
            const pr = qcRoomPricing(room, ctx);
            const step = (field, val, icon, label, max) => `
                <div class="qcrm-field">
                    <label title="${qcEsc(label)}"><i class="fas ${icon}"></i>${qcEsc(label)}</label>
                    <span class="qcrm-step">
                        <button type="button" onclick="qcRoomBump(this,-1)" tabindex="-1" aria-label="${qcEsc(label)} azalt">&minus;</button>
                        <input type="number" min="0" max="${max}" step="1" value="${val}" data-room-field="${field}"
                               oninput="qcRoomEdit(this)" aria-label="${qcEsc(label)} sayısı">
                        <button type="button" onclick="qcRoomBump(this,1)" tabindex="-1" aria-label="${qcEsc(label)} artır">+</button>
                    </span>
                </div>`;

            const tags = pr.lines.map(l => `
                <span class="qcrm-tag ${l.auto ? 'is-auto' : ''}" title="${qcEsc(l.reason || l.label)}">
                    <i class="fas ${l.auto ? 'fa-wand-magic-sparkles' : l.icon}"></i>
                    ${l.qty} × ${qcEsc(l.label)} <b>${qcFareMoney(l.total, ctx.currency)}</b>
                </span>`).join('')
                + (pr.notes || []).map(n => `<span class="qcrm-tag"><i class="fas fa-circle-info"></i> ${qcEsc(n)}</span>`).join('')
                + pr.warnings.map(w => `<span class="qcrm-tag is-warn"><i class="fas fa-triangle-exclamation"></i> ${qcEsc(w)}</span>`).join('');

            return `<div class="qcrm-room ${pr.overflow > 0 && !room.extra_bed ? 'is-over' : ''}" data-room-idx="${i}">
                <div class="qcrm-top">
                    <span class="qcrm-no">${i + 1}</span>
                    <select class="qcrm-type" data-room-field="room_type" onchange="qcRoomEdit(this)" aria-label="Oda ${i + 1} tipi">${typeOpts}</select>
                    <span class="qcrm-beds"><i class="fas fa-bed me-1"></i>${pr.bed_capacity} yatak${room.extra_bed ? ' (1 ek yatak)' : ''}</span>
                    <span class="qcrm-room-total">${qcFareMoney(pr.total, ctx.currency)}</span>
                    <button type="button" class="qcrm-x" onclick="qcRoomRemove(this)" title="Odayı sil" aria-label="Oda ${i + 1} sil"><i class="fas fa-trash"></i></button>
                </div>
                <div class="qcrm-body">
                    ${step('adult_count', room.adult_count, 'fa-user', 'Yetişkin', 9)}
                    ${step('child_count', room.child_count, 'fa-child', 'Çocuk', 9)}
                    ${step('infant_count', room.infant_count, 'fa-baby', 'Bebek', 9)}
                    <label class="qcrm-bed ${room.extra_bed ? 'is-on' : ''}" title="Odaya ilave yatak konulacaksa işaretleyin — ek yatak fiyatı otomatik uygulanır.">
                        <input type="checkbox" data-room-field="extra_bed" ${room.extra_bed ? 'checked' : ''} onchange="qcRoomEdit(this)"> Ek yatak
                    </label>
                    <input type="text" class="qcrm-note-in" data-room-field="notes" value="${qcEsc(room.notes || '')}"
                           placeholder="Oda notu (örn. yan yana odalar)" oninput="qcRoomEdit(this)" aria-label="Oda ${i + 1} notu">
                </div>
                <div class="qcrm-why">${tags}</div>
            </div>`;
        }).join('');

        // select'lerin değerini innerHTML sonrası ayarla (option string'inde selected tutmayalım)
        list.querySelectorAll('.qcrm-room').forEach((el, i) => {
            const s = el.querySelector('.qcrm-type');
            if (s) s.value = rooms[i].room_type;
        });

        if (keep) {
            const back = list.querySelector(`.qcrm-room[data-room-idx="${keep.idx}"] [data-room-field="${keep.field}"]`);
            if (back) {
                back.focus();
                if (back.select && back.type === 'number') back.select();
                else if (back.setSelectionRange && back.type === 'text') { const n = back.value.length; back.setSelectionRange(n, n); }
            }
        }

        const sum = qcEl('qcrm-summary', r);
        if (sum) {
            const h = qcRoomsHeads(r);
            const totals = qcRoomsFareTotals(r);
            const chip = (icon, val, lbl) => `<span class="qcfp-chip"><i class="fas ${icon}"></i> <b>${val}</b> ${lbl}</span>`;
            sum.innerHTML = chip('fa-door-closed', rooms.length, 'oda')
                + chip('fa-user', h.adult, 'yetişkin')
                + chip('fa-child', h.child, 'çocuk')
                + chip('fa-baby', h.infant, 'bebek')
                + ((totals.single || 0) > 0 ? chip('fa-bed', totals.single, 'tek kişi farkı') : '')
                + ((totals.extra_bed || 0) > 0 ? chip('fa-bed-pulse', totals.extra_bed, 'ek yatak') : '');
        }
    }

    /** Oda alanı değişti (adet/tip/ek yatak/not) → kurguyu güncelle, fiyatları yeniden üret. */
    function qcRoomEdit(el) {
        const r = qcRoot(el);
        const card = el.closest('.qcrm-room');
        const i = parseInt(card?.dataset.roomIdx);
        const room = qcRooms(r)[i];
        if (!room) return;
        const f = el.dataset.roomField;

        if (f === 'extra_bed') {
            room.extra_bed = el.checked;
        } else if (f === 'room_type') {
            room.room_type = QC_ROOM_TYPES[el.value] ? el.value : 'double';
            room.capacity = QC_ROOM_CAPS[room.room_type] || 2;
        } else if (f === 'notes') {
            room.notes = el.value;
            qcRoomsApply(r, { skipRender: true });   // not fiyatı etkilemez, DOM'u yeniden kurma
            return;
        } else {
            const v = Math.max(0, Math.min(9, parseInt(el.value) || 0));
            room[f] = v;
            // Kapasite aşıldıysa ek yatak kendiliğinden önerilir (kullanıcı kapatabilir)
            if (!room.extra_bed && (room.adult_count + room.child_count) === room.capacity + 1) room.extra_bed = true;
        }
        qcRoomsApply(r);
    }

    /** +/- düğmeleri: yanındaki adet kutusunu değiştirip aynı akışı tetikler. */
    function qcRoomBump(btn, delta) {
        const input = btn.parentElement.querySelector('input');
        if (!input) return;
        input.value = Math.max(0, (parseInt(input.value) || 0) + delta);
        qcRoomEdit(input);
    }

    function qcRoomAdd(btn) {
        const r = qcRoot(btn);
        // En sık kullanılan kurgu: çift kişilik oda, 2 yetişkin. Kullanıcı tipi değiştirebilir.
        qcRooms(r).push(qcRoomNormalize({ room_type: 'double', capacity: 2, adult_count: 2 }));
        qcRoomsApply(r);
        // Yeni odanın ilk kutusuna odaklan — klavyeyle hızlı giriş
        const last = qcEl('qcrm-list', r)?.querySelector('.qcrm-room:last-child input[data-room-field="adult_count"]');
        if (last) { last.focus(); last.select(); }
    }

    function qcRoomRemove(btn) {
        const r = qcRoot(btn);
        const i = parseInt(btn.closest('.qcrm-room')?.dataset.roomIdx);
        if (isNaN(i)) return;
        qcRooms(r).splice(i, 1);
        qcRoomsApply(r);
    }

    /** Genel sekmesindeki kişi sayılarından odaları otomatik kurar (2'şer yetişkin). */
    function qcRoomsAutoFill(btn) {
        const r = qcRoot(btn);
        const heads = {
            adult: Math.max(1, parseInt(qcEl('qc-adult', r)?.value) || 1),
            child: Math.max(0, parseInt(qcEl('qc-child', r)?.value) || 0),
            infant: Math.max(0, parseInt(qcEl('qc-infant', r)?.value) || 0),
        };
        qcRoomsSeed(r, heads);
        qcRoomsApply(r);
    }

    /**
     * Kelle sayılarından oda kurgusu üretir: yetişkinler ikişerli odalara dağılır,
     * artan yetişkin kendi odasında kalır (tek kişi farkı otomatik uygulanır);
     * çocuklar ve bebekler odalara sırayla dağıtılır.
     */
    function qcRoomsSeed(root, heads) {
        const r = root || qcRoot();
        const ctx = qcFareCtx(r);
        const cap = Math.max(2, parseInt(ctx.room_capacity) || 2);
        const A = Math.max(0, heads.adult | 0), C = Math.max(0, heads.child | 0), I = Math.max(0, heads.infant | 0);
        const n = Math.max(1, Math.ceil(A / 2) || 1);

        const rooms = [];
        let left = A;
        for (let i = 0; i < n; i++) {
            const a = Math.min(2, left); left -= a;
            const type = a <= 1 ? 'single' : 'double';
            rooms.push(qcRoomNormalize({ room_type: type, capacity: a <= 1 ? 1 : 2, adult_count: a }));
        }
        for (let i = 0; i < C; i++) rooms[i % rooms.length].child_count++;
        for (let i = 0; i < I; i++) rooms[i % rooms.length].infant_count++;
        // Çocuk eklenen odalarda yatak sayısı yetmiyorsa ek yatak önerilir
        rooms.forEach(x => {
            if (x.adult_count + x.child_count > x.capacity) {
                const bigger = Object.keys(QC_ROOM_CAPS).find(k => QC_ROOM_CAPS[k] >= x.adult_count + x.child_count && QC_ROOM_CAPS[k] <= cap);
                if (bigger) { x.room_type = bigger; x.capacity = QC_ROOM_CAPS[bigger]; }
                else x.extra_bed = true;
            }
        });
        r.__qcRooms = rooms;
    }

    /**
     * Oda kurgusu → satış kalemleri → toplamlar → panel.
     * Kalemler fiyat tipi başına TEK satırda toplanır (adlar TourFareCatalog'dan);
     * böylece hem eski akışla hem operasyondaki manifesto ile uyum korunur.
     */
    function qcRoomsApply(root, opts) {
        const r = root || qcRoot();
        const o = opts || {};
        if (!qcRoomMode(r)) return;
        const ctx = qcFareCtx(r);
        const totals = qcRoomsFareTotals(r);

        QC_FARE_DEFS.forEach(def => {
            const qty = Math.max(0, parseInt(totals[def.key]) || 0);
            const price = parseFloat(ctx.prices[def.key]) || 0;
            let item = qcFareItemRow(r, def);
            if (qty <= 0) {
                if (item) item.remove();
                return;
            }
            if (item) {
                item.querySelector('.qv-product-qty').value = qty;
                const pi = item.querySelector('.qv-product-price');
                if (pi && !(parseFloat(pi.value) > 0) && price > 0) pi.value = price;
            } else if (typeof addBlankQvProductRow === 'function') {
                // Tur fiyatları kişi başı ve KDV dahil kabul edilir → satır KDV'si 0
                addBlankQvProductRow({
                    name: (ctx.tour_name || 'Tur') + ' · ' + qcFarePrimaryLabel(ctx, def),
                    qty: qty, price: price, currency: ctx.currency || 'TRY',
                    tax: 0, tourLine: true,
                    productId: qcEl('qc-product-id', r)?.value || null,
                });
            }
        });

        if (typeof calculateQvProductTotals === 'function') calculateQvProductTotals();
        if (typeof qcSyncProductTotals === 'function') qcSyncProductTotals(true, true);

        // Katılımcı kutuları odalardan gelir (ek yatakta kalan da bir kelledir)
        const h = qcRoomsHeads(r);
        const a = qcEl('qc-adult', r), c = qcEl('qc-child', r), inf = qcEl('qc-infant', r);
        if (a) a.value = Math.max(1, h.adult);
        if (c) c.value = h.child;
        if (inf) inf.value = h.infant;
        if (typeof qcUpdateMetrics === 'function') qcUpdateMetrics();

        if (!o.skipRender) qcRoomsRender(r);
        qcFareRender(r);
        if (!o.silent && typeof qcAutoSave === 'function') qcAutoSave(r);
    }

    /** Otomatik kayıt payload'u için oda listesi (sale_rooms kolonlarıyla birebir). */
    function qcRoomsPayload(root) {
        const r = root || qcRoot();
        const ctx = qcFareCtx(r);
        return qcRooms(r).map((room, i) => ({
            room_type: room.room_type,
            label: room.label || ('Oda ' + (i + 1)),
            capacity: room.capacity,
            adult_count: room.adult_count,
            child_count: room.child_count,
            infant_count: room.infant_count,
            extra_bed: !!room.extra_bed,
            unit_price: qcRoomPricing(room, ctx).total,
            notes: room.notes || null,
            sort_order: i,
        }));
    }

    // ─── KATALOG (ürün / tur tarihi / tedarikçi hizmeti) ─────────────────────────
    var _catalogTargetRow = null;
    var _catalogCurrentTour = null; // { id, name, currency, price } — tur tarihi drill sırasında
    var _catalogDates = [];          // getProductDates sonucu
    var _catalogSelectedDate = null; // fiyat tipi seçiciyi besleyen seçili tarih
    // Ürünün ana pazaryeri bilgisi — fiyatın hangi pazardan geldiğini göstermek için
    var _catalogMarket = { primary_id: null, primary_name: null, product_url: null };
    // Fiyat tipi panelinde kullanılan pazaryeri (kullanıcı değiştirebilir)
    var _catalogMarketId = null;

    function fmtNum(v) { return (parseFloat(v) || 0).toLocaleString('tr-TR', { maximumFractionDigits: 0 }); }

    function openProductCatalog(row) {
        _catalogTargetRow = row || null;
        catalogSwitchTab('products', document.querySelector('.qvcat-tab[data-cat-tab="products"]'));
        catalogBackToGrid();
        const si = document.getElementById('catalogSearchInput'); if (si) si.value = '';
        const tf = document.getElementById('catalogTypeFilter'); if (tf) tf.value = '';
        const sf = document.getElementById('catalogSupplierFilter'); if (sf) sf.value = '';
        const ef = document.getElementById('catalogExtraFilter'); if (ef) ef.value = '';
        filterCatalog();
        new bootstrap.Modal(document.getElementById('qvProductCatalogModal'), { backdrop: true }).show();
    }

    function catalogSwitchTab(tab, el) {
        document.querySelectorAll('.qvcat-tab').forEach(t => t.classList.remove('active'));
        if (el) el.classList.add('active');
        const isProducts = tab === 'products';
        const isSuppliers = tab === 'suppliers';
        const isExtras = tab === 'extras';

        document.getElementById('catPaneProducts').classList.toggle('active', isProducts);
        document.getElementById('catPaneSuppliers').classList.toggle('active', isSuppliers);
        document.getElementById('catPaneExtras')?.classList.toggle('active', isExtras);

        document.getElementById('catalogTypeFilter').style.display = isProducts ? '' : 'none';
        document.getElementById('catalogSupplierFilter').style.display = isSuppliers ? '' : 'none';
        const ccf = document.getElementById('catalogCurrencyFilter');
        if (ccf) ccf.style.display = isSuppliers ? '' : 'none';
        const cef = document.getElementById('catalogExtraFilter');
        if (cef) cef.style.display = isExtras ? '' : 'none';

        const si = document.getElementById('catalogSearchInput');
        if (si) {
            si.placeholder = isProducts ? 'Ara: tur veya ürün adı...'
                : (isSuppliers ? 'Ara: hizmet, oda tipi veya tedarikçi...' : 'Ara: ekstra hizmet adı veya kategori...');
        }
        if (!isProducts) catalogBackToGrid();
        filterCatalog();
    }

    function filterCatalog() {
        const q = (document.getElementById('catalogSearchInput')?.value || '').toLowerCase().trim();
        const extrasActive = document.getElementById('catPaneExtras')?.classList.contains('active');
        const suppliersActive = document.getElementById('catPaneSuppliers').classList.contains('active');

        if (extrasActive) {
            const cf = document.getElementById('catalogExtraFilter')?.value || '';
            let vis = 0;
            document.querySelectorAll('#catalogExtraGrid .catalog-extra-item').forEach(it => {
                const show = (!q || (it.dataset.name || '').includes(q)) && (!cf || it.dataset.extraCat === cf);
                it.style.display = show ? '' : 'none';
                if (show) vis++;
            });
            document.querySelectorAll('#catalogExtraGrid .qvcat-group').forEach(g => {
                g.style.display = g.querySelectorAll('.catalog-extra-item:not([style*="none"])').length ? '' : 'none';
            });
            document.getElementById('catalogExtraNoResults')?.classList.toggle('d-none', vis > 0);
            return;
        }

        if (suppliersActive) {
            const tf = document.getElementById('catalogSupplierFilter')?.value || '';
            const cf = document.getElementById('catalogCurrencyFilter')?.value || '';
            let vis = 0;
            document.querySelectorAll('#catalogSupplierGrid .catalog-supplier-item').forEach(it => {
                const show = (!q || (it.dataset.name || '').includes(q)) && (!tf || it.dataset.supType === tf) && (!cf || it.dataset.currency === cf);
                it.style.display = show ? '' : 'none';
                if (show) vis++;
            });
            document.querySelectorAll('#catalogSupplierGrid .qvcat-group').forEach(g => {
                g.style.display = g.querySelectorAll('.catalog-supplier-item:not([style*="none"])').length ? '' : 'none';
            });
            document.getElementById('catalogSupplierNoResults')?.classList.toggle('d-none', vis > 0);
        } else {
            const tf = document.getElementById('catalogTypeFilter')?.value || '';
            let vis = 0;
            document.querySelectorAll('#catalogProductGrid .catalog-product-item').forEach(it => {
                const show = (!q || (it.dataset.name || '').includes(q)) && (!tf || it.dataset.typeId === tf);
                it.style.display = show ? '' : 'none';
                if (show) vis++;
            });
            document.querySelectorAll('#catalogProductGrid .qvcat-group').forEach(g => {
                g.style.display = g.querySelectorAll('.catalog-product-item:not([style*="none"])').length ? '' : 'none';
            });
            document.getElementById('catalogNoResults')?.classList.toggle('d-none', vis > 0);
        }
    }

    function catalogBackToGrid() {
        const grid = document.getElementById('catalogProductGrid');
        const dv = document.getElementById('catalogDateView');
        if (grid) grid.style.display = '';
        if (dv) dv.style.display = 'none';
        catalogCloseFares();
    }

    // Ürün karta tıklama: tur ise tarih drill-down, değilse doğrudan seç
    function catalogPickProduct(el) {
        const hasDates = el.dataset.hasDates === '1';
        const id = el.dataset.id, name = el.dataset.pname, typeId = el.dataset.typeId || '';
        const price = parseFloat(el.dataset.price) || 0, currency = el.dataset.currency || 'TRY';
        if (hasDates) catalogShowDates(id, name, currency, price, typeId);
        else selectFromCatalog(id, name, price, currency, typeId);
    }

    // Tur tarihi drill-down: getProductDates ile fiyatlı tarihleri getir
    function catalogShowDates(productId, name, currency, basePrice, typeId) {
        _catalogCurrentTour = { id: productId, name: name, currency: currency, price: basePrice || 0, typeId: typeId || '' };
        document.getElementById('catalogProductGrid').style.display = 'none';
        document.getElementById('catalogDateView').style.display = '';
        document.getElementById('catalogDateTourName').textContent = name;
        catalogCloseFares();
        // Özel tarih bölümünü kapat + varsayılan fiyat/döviz doldur
        const cbody = document.getElementById('catalogCustomBody'); if (cbody) cbody.style.display = 'none';
        const cchev = document.getElementById('catalogCustomChevron'); if (cchev) cchev.style.transform = '';
        const cprice = document.getElementById('catalogCustomPrice'); if (cprice) cprice.value = basePrice ? basePrice : '';
        const ccur = document.getElementById('catalogCustomCurrency'); if (ccur && [...ccur.options].some(o => o.value === currency)) ccur.value = currency;

        const grid = document.getElementById('catalogDateGrid');
        const loading = document.getElementById('catalogDateLoading');
        const none = document.getElementById('catalogDateNoUpcoming');
        grid.innerHTML = ''; grid.style.display = 'none';
        none.classList.add('d-none');
        loading.style.display = '';
        _catalogDates = [];
        _catalogMarket = { primary_id: null, primary_name: null, product_url: null };
        // Bu satışta daha önce bir pazaryeri seçildiyse fiyatlar ondan gelsin —
        // aynı satış yeniden fiyatlandığında tutar değişmemeli.
        const chosen = qcEl('qc-marketplace-id')?.value || '';
        fetch(URL_DATES + '?product_id=' + encodeURIComponent(productId) + (chosen ? '&marketplace_id=' + encodeURIComponent(chosen) : ''))
            .then(r => r.json())
            .then(d => {
                loading.style.display = 'none';
                _catalogMarket = {
                    primary_id: d.primary_marketplace_id || null,
                    primary_name: d.primary_marketplace_name || null,
                    product_url: d.product_edit_url || null,
                };
                if (!d.has_dates || !d.dates || !d.dates.length) {
                    none.classList.remove('d-none');
                    if (cbody) cbody.style.display = '';        // kayıtlı tarih yoksa özel tarihi otomatik aç
                    if (cchev) cchev.style.transform = 'rotate(180deg)';
                    return;
                }
                _catalogDates = d.dates;
                grid.style.display = '';
                grid.innerHTML = d.dates.map((dt, i) => catalogDateCardHTML(dt, i)).join('');
            })
            .catch(() => { loading.style.display = 'none'; none.classList.remove('d-none'); });
    }

    /** Tarih kartındaki fiyat rozetleri — etiketler TourFareCatalog'dan (elle yazılmaz). */
    function catalogFareChips(src, cur) {
        const hasC2 = parseFloat(src.child_price_2) > 0;
        return QC_FARE_DEFS.map(def => {
            const price = qcPricesFrom(src)[def.key] || 0;
            if (!(price > 0)) return '';
            const lbl = (def.key === 'child1' && !hasC2) ? 'Çocuk' : def.label;
            const pre = def.per === 'supplement' ? '+' : '';
            const cls = def.key === 'adult' ? ' class="adult"' : '';
            return `<span${cls} title="${qcEsc(def.hint || '')}">${qcEsc(lbl)} <b>${pre}${fmtNum(price)}${def.key === 'adult' ? ' ' + cur : ''}</b></span>`;
        }).join('');
    }

    function catalogDateCardHTML(dt, i) {
        const cur = dt.currency || 'TRY';
        const cap = (dt.remaining_capacity === null || dt.remaining_capacity === undefined) ? '∞' : dt.remaining_capacity;
        const range = dt.start_date_display + ((dt.end_date_display && dt.end_date !== dt.start_date) ? ' – ' + dt.end_date_display : '');
        const guar = dt.guarantee_departure ? '<span class="qvcat-date-guar"><i class="fas fa-shield-halved"></i> Garantili</span>' : '';
        // Fiyatın hangi pazaryerinden geldiği kartta görünür (belirsizse uyarı rengiyle)
        const mk = dt.marketplace_name
            ? `<span class="qvcat-date-mk ${dt.marketplace_source === 'fallback' ? 'is-warn' : ''}" title="${dt.marketplace_source === 'fallback' ? 'Ürünün ana pazaryeri seçilmemiş — fiyat rastgele bir pazardan alındı.' : 'Fiyatlar bu pazaryerinden alınıyor.'}"><i class="fas fa-store"></i> ${qcEsc(dt.marketplace_name)}</span>`
            : '';
        return `<div class="qvcat-date-card" data-date-idx="${i}" onclick="catalogSelectDate(${i})">
            <div class="qvcat-date-top">
                <div class="qvcat-date-when"><i class="fas fa-calendar-day"></i> ${range}</div>
                ${guar}
            </div>
            <div class="qvcat-date-prices">${catalogFareChips(dt, cur)}</div>
            <div class="qvcat-date-foot">
                <span class="qvcat-date-cap"><i class="fas fa-users"></i> ${cap} kişilik yer ${mk}</span>
                <span class="qvcat-date-pick">Fiyat tipi seç <i class="fas fa-arrow-right"></i></span>
            </div>
        </div>`;
    }

    // Bir tarih seçilince fiyat tipi panelini aç
    function catalogSelectDate(i) {
        const dt = _catalogDates[i];
        if (!dt) return;
        _catalogSelectedDate = dt;
        _catalogMarketId = dt.marketplace_id || null;
        document.querySelectorAll('#catalogDateGrid .qvcat-date-card').forEach(c => c.classList.toggle('sel', c.dataset.dateIdx == i));
        catalogRenderFares(dt);
        const panel = document.getElementById('catalogFarePanel');
        panel.style.display = '';
        panel.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
    }

    /** Fiyat tipi panelinde kullanılacak tarife kaynağı: seçili pazaryerinin satırı. */
    function catalogFareSource(dt) {
        const opt = (dt.marketplaces || []).find(o => String(o.id) === String(_catalogMarketId));
        return opt || dt;
    }

    /**
     * Seçili tarihte gösterilecek fiyat tipleri. Etiketler TourFareCatalog'dan gelir.
     * Adetler Genel sekmesindeki kelle sayılarıyla ön dolu; 2. çocuk tarifesi varsa
     * oda başına 1. çocuk bir tane kabul edilir, kalanı 2. çocuğa düşer.
     *
     * KONAKLAMALI turlarda tek kişilik oda farkı ve ek yatak BURADA GİRİLMEZ —
     * ikisi de satış kartındaki oda kurgusundan otomatik hesaplanır; burada
     * gösterilseydi aynı fark iki kez toplanabilirdi.
     */
    function catalogFareDefs(dt) {
        const src = catalogFareSource(dt);
        const prices = qcPricesFrom(src);
        const a = parseInt(document.getElementById('qc-adult').value) || 1;
        const c = parseInt(document.getElementById('qc-child').value) || 0;
        const inf = parseInt(document.getElementById('qc-infant').value) || 0;
        const hasC2 = prices.child2 > 0;
        const overnight = !!dt.is_overnight;
        const qtyOf = { adult: a, child1: hasC2 ? Math.min(c, 1) : c, child2: Math.max(0, c - 1), infant: inf, single: 0, extra_bed: 0 };

        return QC_FARE_DEFS.filter(def => {
            if (overnight && (def.key === 'single' || def.key === 'extra_bed')) return false;
            return def.key === 'adult' || prices[def.key] > 0;
        }).map(def => ({
            key: def.key,
            label: (def.key === 'child1' && !hasC2) ? 'Çocuk' : def.label,
            hint: def.hint,
            icon: def.icon,
            price: prices[def.key] || 0,
            qty: qtyOf[def.key] || 0,
        }));
    }

    function catalogRenderFares(dt) {
        const src = catalogFareSource(dt);
        const cur = src.currency || dt.currency || (_catalogCurrentTour && _catalogCurrentTour.currency) || 'TRY';
        document.getElementById('catalogFareDate').textContent = dt.start_date_display + ((dt.end_date_display && dt.end_date !== dt.start_date) ? ' – ' + dt.end_date_display : '');

        // Fiyat kaynağı: hangi pazaryeri? Birden fazlaysa buradan seçilir.
        const mkBox = document.getElementById('catalogFareMarket');
        if (mkBox) {
            const opts = dt.marketplaces || [];
            if (!opts.length) {
                mkBox.innerHTML = _catalogMarket.primary_name
                    ? `<span class="qvcat-fare-mk-warn"><i class="fas fa-triangle-exclamation"></i> Bu tarihte pazaryeri fiyatı tanımlı değil.</span>` : '';
            } else {
                const warn = dt.marketplace_source === 'fallback'
                    ? `<span class="qvcat-fare-mk-warn"><i class="fas fa-triangle-exclamation"></i> Ürünün <b>ana pazaryeri seçilmemiş</b>${_catalogMarket.product_url ? ' — <a href="#" onclick="catalogOpenProductCard(event)">ürün kartından seçin</a>' : ''}.</span>` : '';
                mkBox.innerHTML = `<span class="qvcat-fare-mk-lbl"><i class="fas fa-store"></i> Fiyat kaynağı</span>
                    <select class="qvcat-fare-mk-sel" onchange="catalogMarketChanged(this)" aria-label="Fiyatların alınacağı pazaryeri" ${opts.length < 2 ? 'disabled' : ''}>
                        ${opts.map(o => `<option value="${o.id}" ${String(o.id) === String(_catalogMarketId) ? 'selected' : ''}>${qcEsc(o.name)}${o.is_primary ? ' (ana pazar)' : ''}</option>`).join('')}
                    </select>${warn}`;
            }
        }

        document.getElementById('catalogFareRows').innerHTML = catalogFareDefs(dt).map(f => `
            <div class="qvcat-fare-row" data-fare-key="${f.key}" data-fare-label="${qcEsc(f.label)}" data-fare-price="${f.price}">
                <span class="qvcat-fare-label" title="${qcEsc(f.hint || '')}"><i class="fas ${f.icon}"></i> ${qcEsc(f.label)}</span>
                <span class="qvcat-fare-unit">${fmtNum(f.price)} ${cur}</span>
                <span class="qvcat-fare-qty"><input type="number" min="0" step="1" value="${f.qty}" oninput="catalogRecalcFares()" aria-label="${qcEsc(f.label)} adedi"></span>
                <span class="qvcat-fare-sub">0 ${cur}</span>
            </div>`).join('');

        const rn = document.getElementById('catalogFareRoomNote');
        if (rn) rn.style.display = dt.is_overnight ? '' : 'none';

        catalogRecalcFares();
    }

    /** Katalogda pazaryeri değişti → tarifeler o pazarın satırından yeniden çizilir. */
    function catalogMarketChanged(sel) {
        _catalogMarketId = sel.value || null;
        if (_catalogSelectedDate) catalogRenderFares(_catalogSelectedDate);
    }

    function catalogOpenProductCard(ev) {
        ev.preventDefault();
        const url = _catalogMarket.product_url;
        if (!url) return;
        bootstrap.Modal.getInstance(document.getElementById('qvProductCatalogModal'))?.hide();
        if (typeof openQuickView === 'function') openQuickView(url);
    }

    function catalogRecalcFares() {
        const cur = (_catalogSelectedDate && _catalogSelectedDate.currency) || (_catalogCurrentTour && _catalogCurrentTour.currency) || 'TRY';
        let total = 0;
        document.querySelectorAll('#catalogFareRows .qvcat-fare-row').forEach(r => {
            const price = parseFloat(r.dataset.farePrice) || 0;
            const qty = parseInt(r.querySelector('input').value) || 0;
            const sub = price * qty;
            total += sub;
            r.querySelector('.qvcat-fare-sub').textContent = fmtNum(sub) + ' ' + cur;
        });
        document.getElementById('catalogFareTotal').textContent = fmtNum(total) + ' ' + cur;
    }

    function catalogApplyFares() {
        const dt = _catalogSelectedDate;
        if (!dt) return;
        const fares = [];
        document.querySelectorAll('#catalogFareRows .qvcat-fare-row').forEach(r => {
            fares.push({ key: r.dataset.fareKey, label: r.dataset.fareLabel, qty: parseInt(r.querySelector('input').value) || 0, price: parseFloat(r.dataset.farePrice) || 0 });
        });
        if (!fares.some(f => f.qty > 0)) { if (typeof Swal !== 'undefined') Swal.fire({ icon: 'warning', title: 'Adet girin', text: 'En az bir fiyat tipi için adet girmelisiniz.' }); return; }
        applyTourDate(dt, fares);
    }

    function catalogCloseFares() {
        const p = document.getElementById('catalogFarePanel');
        if (p) p.style.display = 'none';
        _catalogSelectedDate = null;
        document.querySelectorAll('#catalogDateGrid .qvcat-date-card.sel').forEach(c => c.classList.remove('sel'));
    }

    // Tur + tarih + seçili fiyat tipleri uygula: satışı kalkışa bağla + kalemleri üret
    function applyTourDate(dt, fares) {
        const tour = _catalogCurrentTour;
        if (!tour) return;

        document.getElementById('qc-product-id').value = tour.id;
        document.getElementById('qc-tour-date-id').value = dt.id;
        document.getElementById('qc-tour-date-type').value = dt.date_type || '';
        if (dt.start_date) document.getElementById('qc-start-date').value = dt.start_date;
        if (dt.end_date) document.getElementById('qc-end-date').value = dt.end_date;

        const src = catalogFareSource(dt);
        const cur = src.currency || dt.currency || tour.currency || 'TRY';
        const curSel = document.getElementById('qc-currency');
        if (curSel && [...curSel.options].some(o => o.value === cur)) curSel.value = cur;

        // Katılımcı sayılarını seçilen fiyat tiplerinden Genel sekmesine yansıt.
        // Çocuk = 1. Çocuk + 2. Çocuk (ikisi de "çocuk kellesi" sayılır).
        const byKey = {}; fares.forEach(f => { if (f.key) byKey[f.key] = f.qty; });
        const heads = {
            adult: byKey.adult != null ? (byKey.adult || 1) : (parseInt(document.getElementById('qc-adult').value) || 1),
            child: (byKey.child1 || 0) + (byKey.child2 || 0),
            infant: byKey.infant || 0,
        };
        document.getElementById('qc-adult').value = heads.adult;
        if (byKey.child1 != null || byKey.child2 != null) document.getElementById('qc-child').value = heads.child;
        if (byKey.infant != null) document.getElementById('qc-infant').value = heads.infant;

        // Fiyat tipi paneli: birim fiyatlar seçilen tur tarihinin SEÇİLİ PAZARYERİ satırından gelir
        const _r = qcRoot();
        const _fctx = qcFareCtx(_r);
        _fctx.prices = qcPricesFrom(src);
        _fctx.currency = cur;
        _fctx.tour_name = tour.name;
        _fctx.is_overnight = !!dt.is_overnight;
        _fctx.room_capacity = parseInt(dt.room_capacity) || 2;
        _fctx.date_label = dt.start_date_display + ((dt.end_date_display && dt.end_date !== dt.start_date) ? ' – ' + dt.end_date_display : '');
        _fctx.marketplace = {
            id: _catalogMarketId || dt.marketplace_id || null,
            name: (dt.marketplaces || []).find(o => String(o.id) === String(_catalogMarketId))?.name || dt.marketplace_name || null,
            source: (_catalogMarketId && String(_catalogMarketId) !== String(dt.marketplace_id)) ? 'selected' : (dt.marketplace_source || 'none'),
            options: dt.marketplaces || [],
        };
        const mkId = qcEl('qc-marketplace-id', _r);   if (mkId) mkId.value = _fctx.marketplace.id || '';
        const mkNm = qcEl('qc-marketplace-name', _r); if (mkNm) mkNm.value = _fctx.marketplace.name || '';
        qcFareSetVisible(true, _r);

        // Yalnızca önceki tur satırlarını + boş satırları temizle; elle eklenenler kalsın.
        // Tur fiyatları kişi-başı ve KDV-dahil kabul edilir → satır KDV'si 0 (çifte vergi olmasın).
        removeTourRows();

        if (dt.is_overnight) {
            // Konaklamalı tur → oda kurgusu üretilir; tek kişi farkı ve ek yatak
            // odalardan OTOMATİK hesaplanır (kalemleri qcRoomsApply yazar).
            qcRoomsSeed(_r, heads);
            qcRoomsApply(_r, { silent: true });
        } else {
            fares.filter(f => f.qty > 0).forEach(f => addBlankQvProductRow({ name: tour.name + ' · ' + f.label, qty: f.qty, price: f.price, currency: cur, productId: tour.id, tax: 0, tourLine: true }));
        }

        calculateQvProductTotals();
        qcSyncProductTotals(true, true);
        qcAutofillGeneral(tour.name, tour.typeId);
        showDepartureBanner(tour.name, Object.assign({}, dt, { adult_price: _fctx.prices.adult }), cur, false);
        qcRoomsRender(_r);
        qcFareRender(_r);   // panel yeni tarifelerle + yeni kalem adetleriyle çizilir

        bootstrap.Modal.getInstance(document.getElementById('qvProductCatalogModal'))?.hide();
        const tabEl = document.querySelector('.qv-tab[onclick*="qcproducts"]');
        if (tabEl && typeof switchQvTab === 'function') switchQvTab('qcproducts', tabEl);
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    // Özel tarih: turu seç, kayıtlı kalkışa bağlanmadan özel tarih + fiyatla sat
    function applyCustomTourDate() {
        const tour = _catalogCurrentTour;
        if (!tour) return;
        const start = document.getElementById('catalogCustomStart').value;
        const end = document.getElementById('catalogCustomEnd').value;
        const price = parseFloat(document.getElementById('catalogCustomPrice').value) || 0;
        const cur = document.getElementById('catalogCustomCurrency').value || 'TRY';
        if (!start) { if (typeof Swal !== 'undefined') Swal.fire({ icon: 'warning', title: 'Tarih gerekli', text: 'Başlangıç tarihi girin.' }); return; }

        document.getElementById('qc-product-id').value = tour.id;   // ürüne bağla (reservable)
        document.getElementById('qc-tour-date-id').value = '';      // belirli bir kalkışa bağlama
        document.getElementById('qc-tour-date-type').value = '';
        document.getElementById('qc-start-date').value = start;
        if (end) document.getElementById('qc-end-date').value = end;
        const curSel = document.getElementById('qc-currency');
        if (curSel && [...curSel.options].some(o => o.value === cur)) curSel.value = cur;

        const adults = parseInt(document.getElementById('qc-adult').value) || 1;
        const children = parseInt(document.getElementById('qc-child').value) || 0;
        const infants = parseInt(document.getElementById('qc-infant').value) || 0;

        removeTourRows();
        // Tarih kalemlere de yazılır: sunucu bundan kişiye özel kalkış üretip
        // satışı operasyona ve acente takvimine düşürür. Üç satır aynı tur +
        // aynı tarih olduğu için tek kalkışta birleşir.
        const dt = { startDate: start, endDate: end || '' };
        addBlankQvProductRow({ name: tour.name + ' · Yetişkin (özel tarih)', qty: adults, price: price, currency: cur, productId: tour.id, tax: 0, tourLine: true, ...dt });
        if (children > 0) addBlankQvProductRow({ name: tour.name + ' · Çocuk (özel tarih)', qty: children, price: 0, currency: cur, productId: tour.id, tax: 0, tourLine: true, ...dt });
        if (infants > 0) addBlankQvProductRow({ name: tour.name + ' · Bebek (özel tarih)', qty: infants, price: 0, currency: cur, productId: tour.id, tax: 0, tourLine: true, ...dt });

        // Özel tarihte kayıtlı kalkış yok → tarife matrisi ve pazaryeri yok.
        // Panel yine de çalışır: birim fiyatlar oluşan kalemlerden okunur.
        // Oda kurgusu da devre dışıdır (tarife olmadan otomatik fark hesaplanamaz).
        const _r = qcRoot();
        const _fctx = qcFareCtx(_r);
        _fctx.prices = { adult: price, child1: 0, child2: 0, infant: 0, single: 0, extra_bed: 0 };
        _fctx.currency = cur;
        _fctx.tour_name = tour.name;
        _fctx.is_overnight = false;
        _fctx.marketplace = { id: null, name: null, source: 'none', options: [] };
        _fctx.date_label = catalogFmtDate(start) + (end ? ' – ' + catalogFmtDate(end) : '') + ' · özel tarih';
        const mkId0 = qcEl('qc-marketplace-id', _r);   if (mkId0) mkId0.value = '';
        const mkNm0 = qcEl('qc-marketplace-name', _r); if (mkNm0) mkNm0.value = '';
        if (_r) _r.__qcRooms = [];
        qcRoomsRender(_r);
        qcFareSetVisible(true, _r);

        calculateQvProductTotals();
        qcSyncProductTotals(true, true);
        qcAutofillGeneral(tour.name, tour.typeId);
        showDepartureBanner(tour.name, { start_date_display: catalogFmtDate(start), end_date_display: end ? catalogFmtDate(end) : null, end_date: end, start_date: start, adult_price: price, remaining_capacity: null }, cur, true);
        qcFareRender();

        bootstrap.Modal.getInstance(document.getElementById('qvProductCatalogModal'))?.hide();
        const tabEl = document.querySelector('.qv-tab[onclick*="qcproducts"]');
        if (tabEl && typeof switchQvTab === 'function') switchQvTab('qcproducts', tabEl);
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    function catalogToggleCustomDate() {
        const body = document.getElementById('catalogCustomBody');
        const chev = document.getElementById('catalogCustomChevron');
        if (!body) return;
        const open = body.style.display !== 'none';
        body.style.display = open ? 'none' : '';
        if (chev) chev.style.transform = open ? '' : 'rotate(180deg)';
    }

    function catalogFmtDate(s) {
        if (!s) return '';
        const d = new Date(s + 'T00:00:00');
        if (isNaN(d.getTime())) return s;
        return d.toLocaleDateString('tr-TR', { day: '2-digit', month: 'short', year: 'numeric' });
    }

    function showDepartureBanner(name, dt, cur, custom) {
        const b = document.getElementById('qc-departure-banner');
        if (!b) return;
        document.getElementById('qc-dep-title').textContent = name;
        const range = dt.start_date_display + ((dt.end_date_display && dt.end_date !== dt.start_date) ? ' – ' + dt.end_date_display : '');
        document.getElementById('qc-dep-sub').innerHTML = `<i class="fas fa-calendar-day me-1"></i>${range}` + (parseFloat(dt.adult_price) > 0 ? ` · Yetişkin ${fmtNum(dt.adult_price)} ${cur}` : '');
        document.getElementById('qc-dep-cap').innerHTML = custom
            ? '<i class="fas fa-pen me-1"></i>Özel tarih'
            : `<i class="fas fa-users me-1"></i>${(dt.remaining_capacity === null || dt.remaining_capacity === undefined) ? '∞' : dt.remaining_capacity} yer`;
        b.style.display = '';
    }

    function clearTourDeparture() {
        // "0" = bilinçli kaldırma. Boş string sunucuda "dokunma" anlamına gelir;
        // aksi halde eski/boş kartlardan gelen kayıtlar bağı yanlışlıkla siliyordu.
        document.getElementById('qc-product-id').value = '0';
        document.getElementById('qc-tour-date-id').value = '0';
        document.getElementById('qc-tour-date-type').value = '';
        const b = document.getElementById('qc-departure-banner');
        if (b) b.style.display = 'none';
        _catalogCurrentTour = null;
        // Tur bağı koptu → fiyat tipi paneli gizlenir (kalemler olduğu gibi kalır)
        qcFareSetVisible(false);
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    function clearProductRows() {
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(r => r.remove());
        const empty = document.getElementById('qv-no-products-row');
        if (empty) empty.remove();
    }

    // Yalnızca otomatik üretilen tur satırlarını ve tamamen boş satırları kaldır (elle eklenenler kalsın)
    function removeTourRows() {
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(r => {
            const isTourLine = r.dataset.tourLine === '1';
            const nameEmpty = !r.querySelector('.qv-product-name').value.trim();
            if (isTourLine || nameEmpty) r.remove();
        });
        const empty = document.getElementById('qv-no-products-row');
        if (empty) empty.remove();
    }

    // Katalog seçimi için doldurulacak satır: hedef satır → mevcut boş satır → yeni satır
    function catGetFillableRow() {
        if (_catalogTargetRow) return _catalogTargetRow;
        const rows = document.querySelectorAll('#qv-products-tbody .qv-product-row');
        for (const r of rows) { if (!r.querySelector('.qv-product-name').value.trim()) return r; }
        return addBlankQvProductRow();
    }

    // Basit ürün seçimi (tur değil) — hedef satır yoksa yeni satır aç
    function selectFromCatalog(id, name, price, currency, typeId) {
        const row = catGetFillableRow();
        if (!row) return;
        row.querySelector('.row-product-id').value = id || '';
        row.querySelector('.row-itemable-type').value = '';
        row.querySelector('.row-itemable-id').value = '';
        row.querySelector('.qv-product-name').value = name;
        row.dataset.catalogName = name;
        row.querySelector('.qv-product-price').value = price;
        const ce = row.querySelector('.qv-product-currency');
        if (ce && [...ce.options].some(o => o.value === currency)) ce.value = currency;
        qcPaintFareTicket(row);
        calculateQvProductTotals();
        qcSyncProductTotals(true, true);
        qcAutofillGeneral(name, typeId);
        bootstrap.Modal.getInstance(document.getElementById('qvProductCatalogModal'))?.hide();
        _catalogTargetRow = null;
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    // Tedarikçi hizmeti seçimi — itemable (SupplierPriceItem) bağı + satış fiyatı + KDV
    function catalogPickSupplier(el) {
        const row = catGetFillableRow();
        if (!row) return;
        const title = el.dataset.title || '';
        const supplier = el.dataset.supplier || '';
        const price = parseFloat(el.dataset.price) || 0;
        const currency = el.dataset.currency || 'TRY';
        const tax = parseFloat(el.dataset.tax) || 0;
        row.querySelector('.row-product-id').value = '';
        row.querySelector('.row-itemable-type').value = 'App\\Models\\Supplier\\SupplierPriceItem';
        row.querySelector('.row-itemable-id').value = el.dataset.id || '';
        row.querySelector('.qv-product-name').value = (supplier && supplier !== '—') ? (title + ' — ' + supplier) : title;
        row.querySelector('.qv-product-price').value = price;
        const ce = row.querySelector('.qv-product-currency');
        if (ce && [...ce.options].some(o => o.value === currency)) ce.value = currency;
        const te = row.querySelector('.qv-product-tax');
        if (te) { let opt = [...te.options].find(o => parseFloat(o.value) === tax); if (!opt) { opt = new Option('%' + tax, tax); te.add(opt); } te.value = opt.value; }
        qcPaintFareTicket(row);
        calculateQvProductTotals();
        qcSyncProductTotals(true, true);
        qcAutofillGeneral(title, null);
        bootstrap.Modal.getInstance(document.getElementById('qvProductCatalogModal'))?.hide();
        _catalogTargetRow = null;
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    // Ekstra hizmet seçimi — satışa ek kalem olarak eklenir.
    // Hem products sarmalayıcısı (product_id) hem de kaynağı (itemable → ExtraService)
    // yazılır; böylece kalem hem raporlarda ürün olarak görünür hem izlenebilir kalır.
    // Satışın genel ürün/tarih alanları DEĞİŞTİRİLMEZ: ekstra hizmet satışın konusu
    // değil, üzerine eklenen bir kalemdir (qcAutofillGeneral çağrılmaz).
    function catalogPickExtra(el) {
        const row = catGetFillableRow();
        if (!row) return;

        const title = el.dataset.title || '';
        const price = parseFloat(el.dataset.price) || 0;
        const currency = el.dataset.currency || 'TRY';
        const tax = parseFloat(el.dataset.tax) || 0;
        const taxIncluded = el.dataset.taxIncluded === '1';

        row.querySelector('.row-product-id').value = el.dataset.productId || '';
        row.querySelector('.row-itemable-type').value = 'App\\Models\\Product\\ExtraService';
        row.querySelector('.row-itemable-id').value = el.dataset.id || '';
        row.querySelector('.qv-product-name').value = title;
        row.dataset.catalogName = title;
        row.querySelector('.qv-product-price').value = price;

        const ce = row.querySelector('.qv-product-currency');
        if (ce && [...ce.options].some(o => o.value === currency)) ce.value = currency;

        // Vergi oranı listede yoksa seçenek olarak eklenir (ör. acenteye özel oran)
        const te = row.querySelector('.qv-product-tax');
        if (te) {
            let opt = [...te.options].find(o => parseFloat(o.value) === tax);
            if (!opt) { opt = new Option('%' + tax, tax); te.add(opt); }
            te.value = opt.value;
        }

        // "Fiyata vergi dahil" bilgisi hizmet tanımından gelir — satırdaki
        // dahil/hariç anahtarı da bu değere göre yeniden boyanır
        const ti = row.querySelector('.qv-product-tax-included');
        if (ti) {
            ti.value = taxIncluded ? 1 : 0;
            if (typeof qcPaintRowTaxSeg === 'function') qcPaintRowTaxSeg(row);
            if (typeof qcPaintTaxMaster === 'function') qcPaintTaxMaster();
        }

        qcPaintFareTicket(row);
        calculateQvProductTotals();
        qcSyncProductTotals(true, true);
        bootstrap.Modal.getInstance(document.getElementById('qvProductCatalogModal'))?.hide();
        _catalogTargetRow = null;
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    function addBlankQvProductRow(prefill) {
        const tbody = document.getElementById('qv-products-tbody');
        if (!tbody) return null;
        const emptyRow = document.getElementById('qv-no-products-row');
        if (emptyRow) emptyRow.remove();
        // Yeni satır dövizi: bir önceki satırın dövizi, hiç satır yoksa TRY
        const _prevRows = tbody.querySelectorAll('.qv-product-row');
        const prevCurrency = _prevRows.length ? (_prevRows[_prevRows.length - 1].querySelector('.qv-product-currency')?.value || 'TRY') : 'TRY';
        const tr = document.createElement('tr');
        tr.className = 'qv-product-row';
        tr.innerHTML = `
            <td>
                <input type="hidden" class="row-id" value="">
                <input type="hidden" class="row-product-id" value="">
                <input type="hidden" class="row-itemable-type" value="">
                <input type="hidden" class="row-itemable-id" value="">
                <input type="hidden" class="qv-product-tax-included" value="${_qcDefaultTaxIncluded ? 1 : 0}">
                <input type="hidden" class="qv-item-start-date" value="">
                <input type="hidden" class="qv-item-end-date" value="">
                <input type="hidden" class="qv-item-start-time" value="">
                <input type="hidden" class="qv-item-end-time" value="">
                <div class="qv-product-name-cell">
                    <input type="text" class="qcx-input qcx-name qv-product-name" value="" placeholder="Ürün / hizmet adını yazın..." autocomplete="off" onchange="qcRowNameChanged(this)">
                    <button type="button" class="btn-catalog-pick" onclick="openProductCatalog(this.closest('.qv-product-row'))" title="Katalogdan seç">
                        <i class="fas fa-layer-group"></i><span>Katalog</span>
                    </button>
                    <button type="button" class="btn-tosvc" style="display:none;" onclick="qcOpenServiceModal(this.closest('.qv-product-row'))" title="Bu kalemi ürün kataloğuna kaydet">
                        <i class="fas fa-bookmark"></i><span>Kataloğa Ekle</span>
                    </button>
                    <span class="qcx-linked" style="display:none;" title="Katalogdaki bir ürüne bağlı"><i class="fas fa-link"></i></span>
                    <span class="qcx-suplink" style="display:none;" title="Tedarikçi kartını aç"><i class="fas fa-truck-field"></i></span>
                </div>
                <div class="qcdt-row">
                    <button type="button" class="qcdt-btn" onclick="qcOpenDateModal(this.closest('.qv-product-row'))" title="Bu kalem için tarih tanımla">
                        <i class="fas fa-calendar-day"></i><span class="qcdt-txt">Tarih ekle</span>
                    </button>
                    <button type="button" class="qcdt-clear" style="display:none;" onclick="qcClearRowDate(this.closest('.qv-product-row'))" title="Tarihi kaldır"><i class="fas fa-times"></i></button>
                    <span class="qcdt-ops" style="display:none;" title="Tur ürünü + tarih → operasyona kişiye özel kalkış olarak düşer"><i class="fas fa-diagram-project"></i> Operasyon</span>
                </div>
            </td>
            <td>
                <input type="number" class="qcx-input qcx-num qv-product-qty" value="1" min="0.01" step="any" oninput="calculateQvProductTotals()">
            </td>
            <td>
                <div class="qcx-money">
                    <input type="number" class="qcx-input qcx-money-in qv-product-price" value="0" min="0" step="any" oninput="calculateQvProductTotals()">
                    <select class="qcx-money-cur qv-product-currency" onchange="calculateQvProductTotals()">
                        @foreach($activeCurrencies as $curr)
                            <option value="{{ $curr->code }}">{{ $curr->code }}</option>
                        @endforeach
                    </select>
                </div>
                <div class="qcx-fare-slot"></div>
            </td>
            <td>
                <div class="qcx-money">
                    <input type="number" class="qcx-input qcx-money-in qv-product-discount" value="" min="0" step="any" placeholder="0" oninput="calculateQvProductTotals()">
                    <select class="qcx-money-cur qv-product-discount-type" onchange="calculateQvProductTotals()">
                        <option value="percent">%</option>
                        <option value="amount">₺</option>
                    </select>
                </div>
            </td>
            <td>
                <div class="qcx-taxcell">
                    <select class="qcx-input qcx-select qv-product-tax" onchange="calculateQvProductTotals()">
                        @foreach($taxRates as $tax)
                            <option value="{{ (float) $tax->rate }}" @selected($tax->is_default)>%{{ rtrim(rtrim(number_format((float) $tax->rate, 2, '.', ''), '0'), '.') }}</option>
                        @endforeach
                    </select>
                    <div class="qcx-seg qcx-seg-sm qcx-rowseg">
                        <button type="button" data-ti="0" onclick="qcSetRowTaxIncluded(this,0)" title="Birim fiyat KDV hariç — vergi üstüne eklenir">Hariç</button>
                        <button type="button" data-ti="1" onclick="qcSetRowTaxIncluded(this,1)" title="Birim fiyat KDV dahil — vergi tutarın içinden ayrıştırılır">Dahil</button>
                    </div>
                </div>
            </td>
            <td class="text-end"><span class="qcx-out qv-row-tax-amount">₺0,00</span></td>
            <td class="text-end"><span class="qcx-out qcx-out-strong qv-row-total-price">₺0,00</span></td>
            <td class="text-end">
                <button type="button" class="qcx-del" onclick="removeQvProductRow(this)" title="Satırı sil">
                    <i class="fas fa-trash"></i>
                </button>
            </td>`;
        tbody.appendChild(tr);
        // Döviz varsayılanı: prefill.currency öncelikli, yoksa önceki satırın dövizi / TRY
        const _ce = tr.querySelector('.qv-product-currency');
        if (_ce) { const want = (prefill && prefill.currency) ? prefill.currency : prevCurrency; if ([..._ce.options].some(o => o.value === want)) _ce.value = want; }
        if (prefill) {
            if (prefill.tourLine) tr.dataset.tourLine = '1';
            if (prefill.name != null) tr.querySelector('.qv-product-name').value = prefill.name;
            if (prefill.qty != null) tr.querySelector('.qv-product-qty').value = prefill.qty;
            if (prefill.price != null) tr.querySelector('.qv-product-price').value = prefill.price;
            if (prefill.productId != null) tr.querySelector('.row-product-id').value = prefill.productId;
            if (prefill.tax != null) { const te = tr.querySelector('.qv-product-tax'); if (te) { let opt = [...te.options].find(o => parseFloat(o.value) === parseFloat(prefill.tax)); if (!opt) { opt = new Option('%' + prefill.tax, prefill.tax); te.add(opt); } te.value = opt.value; } }
            if (prefill.taxIncluded != null) tr.querySelector('.qv-product-tax-included').value = prefill.taxIncluded ? 1 : 0;
            if (prefill.discountType != null) tr.querySelector('.qv-product-discount-type').value = prefill.discountType;
            if (prefill.discountValue != null && parseFloat(prefill.discountValue) > 0) tr.querySelector('.qv-product-discount').value = prefill.discountValue;
            if (prefill.startDate != null) tr.querySelector('.qv-item-start-date').value = prefill.startDate || '';
            if (prefill.endDate != null)   tr.querySelector('.qv-item-end-date').value   = prefill.endDate || '';
            if (prefill.startTime != null) tr.querySelector('.qv-item-start-time').value = prefill.startTime || '';
            if (prefill.endTime != null)   tr.querySelector('.qv-item-end-time').value   = prefill.endTime || '';
            qcPaintRowTaxSeg(tr);
            qcPaintRowDate(tr);
            calculateQvProductTotals();
        } else {
            qcPaintRowTaxSeg(tr);
            qcPaintRowDate(tr);
            qcRefreshRowStates();
            tr.querySelector('.qv-product-name').focus();
        }
        qcPaintFareTicket(tr);
        return tr;
    }

    // ─── KALEM TARİHLERİ (tekil / toplu) ─────────────────────────────────────────
    // Kişiye özel satışlarda katalogda kayıtlı kalkış olmayabilir; kullanıcı tarihi
    // doğrudan satırda girer. Tur ürünlerinde bu tarih sunucuda özel kalkışa
    // dönüşür (PrivateDepartureService) → operasyon + takvim.
    var QC_TOUR_PRODUCT_IDS = new Set(@json($tourProductIds ?? []));
    var _qcDateRow = null;   // null → toplu mod

    /** Satır bir tur ürününe bağlı mı? (tarih girilirse operasyona düşer) */
    function qcRowIsTour(row) {
        const pid = parseInt(row?.querySelector('.row-product-id')?.value || '', 10);
        return !!pid && QC_TOUR_PRODUCT_IDS.has(pid);
    }

    function qcRowDate(row, field) {
        return row.querySelector('.qv-item-' + field)?.value || '';
    }

    /** Satırdaki tarih rozetini/butonunu tazeler. */
    function qcPaintRowDate(row) {
        const sd = qcRowDate(row, 'start-date');
        const ed = qcRowDate(row, 'end-date');
        const st = qcRowDate(row, 'start-time');
        const et = qcRowDate(row, 'end-time');

        const btn = row.querySelector('.qcdt-btn');
        const txt = row.querySelector('.qcdt-txt');
        const clr = row.querySelector('.qcdt-clear');
        const ops = row.querySelector('.qcdt-ops');
        if (!btn || !txt) return;

        const fmt = d => { const p = (d || '').split('-'); return p.length === 3 ? `${p[2]}.${p[1]}.${p[0]}` : ''; };

        if (sd) {
            let label = fmt(sd);
            if (st) label += ' ' + st;
            if (ed && ed !== sd) { label += ' → ' + fmt(ed); if (et) label += ' ' + et; }
            else if (et) { label += '–' + et; }
            txt.textContent = label;
            btn.classList.add('has-date');
            if (clr) clr.style.display = '';
        } else {
            txt.textContent = 'Tarih ekle';
            btn.classList.remove('has-date');
            if (clr) clr.style.display = 'none';
        }
        if (ops) ops.style.display = (sd && qcRowIsTour(row)) ? '' : 'none';
    }

    function qcPaintAllRowDates() {
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(qcPaintRowDate);
    }

    function qcSetRowDate(row, d) {
        row.querySelector('.qv-item-start-date').value = d.start_date || '';
        row.querySelector('.qv-item-end-date').value   = d.end_date || '';
        row.querySelector('.qv-item-start-time').value = d.start_time || '';
        row.querySelector('.qv-item-end-time').value   = d.end_time || '';
        qcPaintRowDate(row);
    }

    function qcClearRowDate(row) {
        qcSetRowDate(row, {});
        if (typeof qcAutoSave === 'function') qcAutoSave(row);
    }

    /** row = satır (tekil) | null (toplu) */
    function qcOpenDateModal(row) {
        const rows = [...document.querySelectorAll('#qv-products-tbody .qv-product-row')]
            .filter(r => r.querySelector('.qv-product-name').value.trim());

        if (!row && !rows.length) {
            if (typeof Swal !== 'undefined') Swal.fire({ icon:'info', title:'Kalem yok', text:'Önce en az bir ürün/hizmet satırı ekleyin.' });
            return;
        }

        _qcDateRow = row || null;

        const title = document.getElementById('qcdt-title');
        const sub   = document.getElementById('qcdt-sub');
        const scope = document.getElementById('qcdt-scope');
        const opsNote = document.getElementById('qcdt-ops-note');

        if (row) {
            const name = row.querySelector('.qv-product-name').value.trim() || 'Kalem';
            title.textContent = 'Kalem Tarihi';
            sub.textContent = name;
            scope.style.display = 'none';
            opsNote.style.display = qcRowIsTour(row) ? '' : 'none';
            document.getElementById('qcdt-start-date').value = qcRowDate(row, 'start-date');
            document.getElementById('qcdt-end-date').value   = qcRowDate(row, 'end-date');
            document.getElementById('qcdt-start-time').value = qcRowDate(row, 'start-time');
            document.getElementById('qcdt-end-time').value   = qcRowDate(row, 'end-time');
        } else {
            title.textContent = 'Toplu Tarih';
            sub.textContent = rows.length + ' kaleme aynı tarih uygulanacak.';
            scope.style.display = '';
            opsNote.style.display = rows.some(qcRowIsTour) ? '' : 'none';
            // Toplu modda satış başlangıç/bitiş tarihi ön-dolum olarak gelir
            document.getElementById('qcdt-start-date').value = document.getElementById('qc-start-date')?.value || '';
            document.getElementById('qcdt-end-date').value   = document.getElementById('qc-end-date')?.value || '';
            document.getElementById('qcdt-start-time').value = '';
            document.getElementById('qcdt-end-time').value   = '';
        }

        new bootstrap.Modal(document.getElementById('qcDateModal')).show();
    }

    function qcDateSubmit() {
        const sd = document.getElementById('qcdt-start-date').value;
        const ed = document.getElementById('qcdt-end-date').value;
        const st = document.getElementById('qcdt-start-time').value;
        const et = document.getElementById('qcdt-end-time').value;

        if (!sd) {
            if (typeof Swal !== 'undefined') Swal.fire({ icon:'warning', title:'Tarih gerekli', text:'Başlangıç tarihini girin.' });
            return;
        }
        if (ed && ed < sd) {
            if (typeof Swal !== 'undefined') Swal.fire({ icon:'warning', title:'Tarih aralığı hatalı', text:'Bitiş tarihi başlangıçtan önce olamaz.' });
            return;
        }

        const payload = { start_date: sd, end_date: ed, start_time: st, end_time: et };
        let applied = 0;

        if (_qcDateRow) {
            qcSetRowDate(_qcDateRow, payload);
            applied = 1;
        } else {
            const onlyEmpty = document.querySelector('input[name="qcdt_scope"]:checked')?.value !== 'all';
            document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(r => {
                if (!r.querySelector('.qv-product-name').value.trim()) return;
                if (onlyEmpty && qcRowDate(r, 'start-date')) return;
                qcSetRowDate(r, payload);
                applied++;
            });
        }

        bootstrap.Modal.getInstance(document.getElementById('qcDateModal'))?.hide();
        _qcDateRow = null;

        if (typeof qcAutoSave === 'function') qcAutoSave();
        if (typeof Swal !== 'undefined') {
            Swal.fire({ toast:true, position:'top-end', timer:1900, showConfirmButton:false, icon:'success',
                title: applied + ' kaleme tarih uygulandı' });
        }
    }

    // ─── KDV DAHİL / HARİÇ ───────────────────────────────────────────────────────
    // Yeni satırların varsayılanı: son kullanılan seçim (üstteki ana anahtar).
    var _qcDefaultTaxIncluded = 0;

    function qcPaintRowTaxSeg(row) {
        const ti = row.querySelector('.qv-product-tax-included')?.value === '1';
        row.querySelectorAll('.qcx-rowseg button').forEach(b => b.classList.toggle('active', (b.dataset.ti === '1') === ti));
        row.classList.toggle('is-tax-incl', ti);
    }

    function qcSetRowTaxIncluded(btn, val) {
        const row = btn.closest('.qv-product-row');
        row.querySelector('.qv-product-tax-included').value = val ? 1 : 0;
        _qcDefaultTaxIncluded = val ? 1 : 0;
        qcPaintRowTaxSeg(row);
        calculateQvProductTotals();
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    function qcSetAllTaxIncluded(val) {
        _qcDefaultTaxIncluded = val ? 1 : 0;
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(row => {
            row.querySelector('.qv-product-tax-included').value = val ? 1 : 0;
            qcPaintRowTaxSeg(row);
        });
        calculateQvProductTotals();
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    /** Ana anahtar: tüm satırlar aynıysa o seçim, karışıksa hiçbiri aktif değil. */
    function qcPaintTaxMaster() {
        const master = document.getElementById('qc-tax-master');
        if (!master) return;
        const vals = [...document.querySelectorAll('#qv-products-tbody .qv-product-tax-included')].map(i => i.value);
        const uniform = vals.length && vals.every(v => v === vals[0]);
        master.querySelectorAll('button').forEach(b => b.classList.toggle('active', uniform && b.dataset.ti === vals[0]));
        master.classList.toggle('is-mixed', vals.length > 1 && !uniform);
    }

    function removeQvProductRow(btn) {
        btn.closest('.qv-product-row').remove();
        calculateQvProductTotals();
        if (typeof qcAutoSave === 'function') qcAutoSave();
    }

    // Acentede tanımlı TÜM para birimleriyle çalışır (kurlar currencies tablosundan;
    // exchange_rate = 1 birimin TRY karşılığı, TRY baz = 1).
    function convertAmount(amount, fromCurr, toCurr) {
        if (fromCurr === toCurr) return amount;
        const rates = window.exchangeRates || {};
        const fromRate = fromCurr === 'TRY' ? 1 : (parseFloat(rates[fromCurr]) || 1);
        const toRate   = toCurr   === 'TRY' ? 1 : (parseFloat(rates[toCurr])   || 1);
        return amount * fromRate / toRate;
    }

    // ─── TOPLAM PARA BİRİMİ (tek birim → otomatik, karışık → kullanıcı seçer) ────
    // Kayıtlı seçim kalem dövizinden farklıysa "manuel" olarak başlar (bkz. @php başlığı)
    var _qcCurrencyManual = @json((bool) ($currencyIsManual ?? false));

    function qcOnSaleCurrencyChange(code) {
        _qcCurrencyManual = true;
        const ss = document.getElementById('qv-summary-currency');
        if (ss && [...ss.options].some(o => o.value === code)) ss.value = code;
        calculateQvProductTotals();
        qcUpdateMetrics();
        if (typeof qcAutoSave === 'function') qcAutoSave(); // seçim kalıcı olsun (currency + çevrilen toplam)
    }
    function qcOnSummaryCurrencyChange(code) {
        _qcCurrencyManual = true;
        const cs = document.getElementById('qc-currency');
        if (cs && [...cs.options].some(o => o.value === code)) cs.value = code;
        calculateQvProductTotals();
        qcUpdateMetrics();
        if (typeof qcAutoSave === 'function') qcAutoSave(); // seçim kalıcı olsun (currency + çevrilen toplam)
    }

    // Kalem para birimlerine göre satış dövizini yönet
    function qcAutoFollowCurrency() {
        const curs = new Set();
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(r => {
            const c = r.querySelector('.qv-product-currency')?.value; if (c) curs.add(c);
        });
        const saleSel = document.getElementById('qc-currency');
        const sumSel = document.getElementById('qv-summary-currency');
        // Tek para birimi + kullanıcı elle seçmediyse → o birime geç
        if (curs.size === 1 && !_qcCurrencyManual && saleSel) {
            const only = [...curs][0];
            if (saleSel.value !== only && [...saleSel.options].some(o => o.value === only)) saleSel.value = only;
        }
        // Karışık uyarısı
        const warn = document.getElementById('qv-summary-mixed');
        if (warn) warn.style.display = curs.size > 1 ? '' : 'none';
        // Özet select'i satış dövizi ile eşitle
        if (sumSel && saleSel && sumSel.value !== saleSel.value && [...sumSel.options].some(o => o.value === saleSel.value)) sumSel.value = saleSel.value;
    }

    function calculateQvProductTotals() {
        qcAutoFollowCurrency();
        let subtotal = 0, taxTotal = 0, grand = 0, itemsDiscount = 0;
        const saleCurrency = document.getElementById('qc-currency').value || 'TRY';
        const currencySymbols = window.currencySymbols || {};

        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(row => {
            const qty  = parseFloat(row.querySelector('.qv-product-qty').value) || 0;
            const price= parseFloat(row.querySelector('.qv-product-price').value) || 0;
            const tax  = parseFloat(row.querySelector('.qv-product-tax').value) || 0;
            const rowCurrency = row.querySelector('.qv-product-currency').value || 'TRY';
            const taxIncl = row.querySelector('.qv-product-tax-included')?.value === '1';
            // Adı boş satırlar sunucuya kaydedilmez → toplamlara da katılmaz
            // (aksi halde Genel sekmesindeki tutar güncellenir ama yenileyince satır kaybolurdu)
            const rowNamed = !!row.querySelector('.qv-product-name').value.trim();

            // Satır indirimi: yüzde veya tutar — brütten, vergiden ÖNCE düşülür
            const dVal = parseFloat(row.querySelector('.qv-product-discount')?.value) || 0;
            const dTyp = row.querySelector('.qv-product-discount-type')?.value || 'percent';
            const gross = qty * price;
            let rowDisc = dTyp === 'amount' ? Math.min(dVal, gross) : gross * (Math.min(dVal, 100) / 100);
            rowDisc = Math.max(0, rowDisc);
            const base = gross - rowDisc;

            // KDV dahil: vergi (indirimli) tutarın içinden ayrıştırılır (iç yüzde).
            // KDV hariç: vergi ara toplamın üstüne eklenir.
            let rs, rt, rt2;
            if (taxIncl) {
                rt  = tax > 0 ? base - (base / (1 + tax / 100)) : 0;
                rs  = base - rt;
                rt2 = base;
            } else {
                rs  = base;
                rt  = base * (tax / 100);
                rt2 = base + rt;
            }

            // Tutar tipi indirim seçeneğinin etiketi satır dövizini izlesin
            const dOpt = row.querySelector('.qv-product-discount-type option[value="amount"]');
            if (dOpt) dOpt.textContent = currencySymbols[rowCurrency] || rowCurrency;

            if (rowNamed) {
                subtotal += convertAmount(rs, rowCurrency, saleCurrency);
                taxTotal += convertAmount(rt, rowCurrency, saleCurrency);
                grand += convertAmount(rt2, rowCurrency, saleCurrency);
                itemsDiscount += convertAmount(rowDisc, rowCurrency, saleCurrency);
            }
            // Fiyat girilmiş ama adı boş satır: kaydedilmeyeceği konusunda uyar
            row.classList.toggle('qcx-unnamed', !rowNamed && (gross > 0 || dVal > 0));
            const nameInp = row.querySelector('.qv-product-name');
            if (nameInp) nameInp.title = (!rowNamed && (gross > 0 || dVal > 0)) ? 'Satır adı girilmedi — bu satır kaydedilmez ve toplama katılmaz!' : '';

            const rowSymbol = currencySymbols[rowCurrency] || rowCurrency;
            row.querySelector('.qv-row-tax-amount').textContent = rowSymbol + rt.toLocaleString('tr-TR',{minimumFractionDigits:2,maximumFractionDigits:2});
            row.querySelector('.qv-row-total-price').textContent= rowSymbol + rt2.toLocaleString('tr-TR',{minimumFractionDigits:2,maximumFractionDigits:2});
        });

        qcPaintTaxMaster();
        qcRefreshRowStates();

        // İndirim: yüzde veya satış para biriminde tutar (genel toplamdan düşülür)
        const dType = document.getElementById('qc-discount-type')?.value || 'amount';
        const dVal  = parseFloat(document.getElementById('qc-discount-value')?.value) || 0;
        let disc = dType === 'percent' ? grand * Math.min(dVal, 100) / 100 : dVal;
        disc = Math.max(0, Math.min(disc, grand));
        grand -= disc;
        const dAmtEl = document.getElementById('qc-discount-amount');
        if (dAmtEl) dAmtEl.value = disc > 0 ? disc.toFixed(2) : '';
        const dCurLbl = document.getElementById('qc-disc-cur-label');
        if (dCurLbl) dCurLbl.textContent = saleCurrency;

        const saleSymbol = currencySymbols[saleCurrency] || saleCurrency;
        const fmt = v => saleSymbol + v.toLocaleString('tr-TR',{minimumFractionDigits:2,maximumFractionDigits:2});
        document.getElementById('qv-summary-subtotal').textContent = fmt(subtotal);
        document.getElementById('qv-summary-tax').textContent      = fmt(taxTotal);
        // İndirim Tutarı = tüm satır indirimleri + genel indirim (tek satırda)
        const dSum = document.getElementById('qv-summary-discount');
        if (dSum) dSum.textContent = '−' + fmt(itemsDiscount + disc);
        document.getElementById('qv-summary-total').textContent    = fmt(grand);

        // "Toplamı Güncelle"ye basmadan Genel toplam + üst metrikler canlı güncellensin
        // (kullanıcı toplamı elle girdiyse korunur — auto=true)
        qcSyncProductTotals(true, true);

        // Ürünler sekmesinde tur kaleminin adedi/fiyatı elle değiştirildiyse
        // fiyat tipi paneli de aynı değeri göstersin (tek kaynak, çift yön).
        if (typeof qcFareSyncFromItems === 'function') qcFareSyncFromItems();
    }

    // ═══ ELLE GİRİLEN KALEMİ HİZMETE (KATALOĞA) EKLE ═════════════════════════════
    // Kolonlar ortak (start_date, end_date, …); etiketler ürün tipine göre değişir.
    var QCSVC_SCHEMAS = @json($serviceFieldSchemas ?? []);
    var QCSVC_URL     = '{{ route("agency.sales.catalog-services.store") }}';
    var _qcSvcRow     = null;
    var _qcSvcDismissed = false;

    // Çapraz linkler: kalem → ürün kartı / tedarikçi kartı
    var QC_PRODUCT_QV = @json($productQvUrls);
    var QC_SUPPLIER_BY_ITEM = @json($supplierByPriceItem);

    /** Satırın katalog bağı var mı → "Kataloğa Ekle" butonu / bağlı rozeti ve üst uyarı. */
    function qcRefreshRowStates() {
        let orphan = 0;
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(row => {
            const pid    = row.querySelector('.row-product-id')?.value || '';
            const linked = !!pid;
            const named  = !!row.querySelector('.qv-product-name')?.value.trim();
            const btn    = row.querySelector('.btn-tosvc');
            const badge  = row.querySelector('.qcx-linked');
            if (btn)   btn.style.display   = (!linked && named) ? '' : 'none';
            if (badge) {
                badge.style.display = linked ? '' : 'none';
                // Kartı olan ürünlerde rozet tıklanabilir: ürün quick-view kartını açar
                const url = linked ? (QC_PRODUCT_QV[pid] || null) : null;
                badge.classList.toggle('is-openable', !!url);
                badge.title = url ? 'Ürün kartını aç' : 'Katalogdaki bir ürüne bağlı';
                badge.onclick = url
                    ? function (e) { e.stopPropagation(); if (typeof openQuickView === 'function') openQuickView(url); }
                    : null;
            }
            // Tedarikçi hizmeti kalemi → tedarikçi kartı
            const supBadge = row.querySelector('.qcx-suplink');
            if (supBadge) {
                const itType = row.querySelector('.row-itemable-type')?.value || '';
                const itId   = row.querySelector('.row-itemable-id')?.value || '';
                const supId  = itType.indexOf('SupplierPriceItem') !== -1 ? (QC_SUPPLIER_BY_ITEM[itId] || null) : null;
                supBadge.style.display = supId ? '' : 'none';
                supBadge.onclick = supId
                    ? function (e) { e.stopPropagation(); if (typeof openSupplierDrawer === 'function') openSupplierDrawer(supId); }
                    : null;
            }
            if (!linked && named) orphan++;
            qcPaintRowDate(row); // ürün bağı değiştiyse "Operasyon" rozeti de değişir
        });

        const banner = document.getElementById('qc-svc-banner');
        if (banner) {
            const show = orphan > 0 && !_qcSvcDismissed;
            banner.style.display = show ? '' : 'none';
            const n = document.getElementById('qc-svc-banner-n');
            if (n) n.textContent = orphan;
        }
    }

    function qcDismissSvcBanner() {
        _qcSvcDismissed = true;
        qcRefreshRowStates();
    }

    /** Bağlı olmayan ilk kalem için modalı aç (üst bantdaki buton). */
    function qcOpenServiceModalForFirst() {
        const row = [...document.querySelectorAll('#qv-products-tbody .qv-product-row')]
            .find(r => !r.querySelector('.row-product-id').value && r.querySelector('.qv-product-name').value.trim());
        if (row) qcOpenServiceModal(row);
    }

    function qcOpenServiceModal(row) {
        _qcSvcRow = row;

        // Satırdaki değerlerle ön-doldur
        document.getElementById('qcsvc-name').value = row.querySelector('.qv-product-name').value.trim();
        document.getElementById('qcsvc-price').value = row.querySelector('.qv-product-price').value || '';
        const cur = row.querySelector('.qv-product-currency').value || 'TRY';
        const curSel = document.getElementById('qcsvc-currency');
        if ([...curSel.options].some(o => o.value === cur)) curSel.value = cur;
        const tax = row.querySelector('.qv-product-tax').value;
        const taxSel = document.getElementById('qcsvc-tax');
        if ([...taxSel.options].some(o => o.value === tax)) taxSel.value = tax;
        qcSvcSetTaxIncl(row.querySelector('.qv-product-tax-included')?.value === '1' ? 1 : 0);

        // Ürün tipi: satışın genel ürün tipi seçiliyse onu öner
        const wantType = document.getElementById('qc-product-type')?.value || '';
        document.querySelectorAll('#qcsvc-types input[name="qcsvc_type"]').forEach(r => { r.checked = (r.value === wantType); });
        document.getElementById('qcsvc-notes').value = '';
        qcSvcTypeChanged();

        new bootstrap.Modal(document.getElementById('qcServiceModal')).show();
    }

    function qcSvcSetTaxIncl(val) {
        document.getElementById('qcsvc-taxincl').value = val ? 1 : 0;
        document.querySelectorAll('#qcsvc-taxincl-seg button')
            .forEach(b => b.classList.toggle('active', (b.dataset.ti === '1') === !!val));
    }

    /** Seçilen ürün tipine göre tarih/saat/konum alanlarını yeniden çiz. */
    function qcSvcTypeChanged() {
        const picked = document.querySelector('#qcsvc-types input[name="qcsvc_type"]:checked');
        const step = document.getElementById('qcsvc-detail-step');
        const grid = document.getElementById('qcsvc-detail-grid');
        if (!picked) { step.style.display = 'none'; grid.innerHTML = ''; return; }

        const schema = QCSVC_SCHEMAS[picked.value] || {};
        const kinds = {
            start_date: 'date', end_date: 'date',
            start_time: 'time', end_time: 'time',
            start_location: 'text', end_location: 'text',
            duration_days: 'number', capacity: 'number',
        };

        let html = '';
        Object.keys(kinds).forEach(key => {
            const label = schema[key];
            if (!label) return; // bu tipte sorulmuyor
            const wide = (key === 'start_location' || key === 'end_location');
            html += `<div class="qcsvc-fld${wide ? ' qcsvc-span2' : ''}">
                <label>${qcEsc(label)}</label>
                <input type="${kinds[key]}" id="qcsvc-${key.replace(/_/g,'-')}" data-svc-field="${key}"${kinds[key]==='number'?' min="0" step="1"':''} placeholder="${wide ? qcEsc(label) : ''}">
            </div>`;
        });

        grid.innerHTML = html;
        step.style.display = html ? '' : 'none';
        const title = document.getElementById('qcsvc-detail-title');
        if (title) title.textContent = picked.closest('.qcsvc-type').querySelector('b').textContent + ' — tarih & konum bilgileri';
    }

    function qcSvcSubmit() {
        const typeEl = document.querySelector('#qcsvc-types input[name="qcsvc_type"]:checked');
        const name = document.getElementById('qcsvc-name').value.trim();

        if (!typeEl) { Swal.fire({icon:'warning', title:'Ürün tipi seçin', text:'Bu kalemin hangi ürün tipine ait olduğunu seçin.'}); return; }
        if (!name)   { Swal.fire({icon:'warning', title:'Ad gerekli', text:'Ürün / hizmet adını yazın.'}); return; }

        const payload = {
            product_type_id : typeEl.value,
            name            : name,
            unit_price      : parseFloat(document.getElementById('qcsvc-price').value) || 0,
            currency        : document.getElementById('qcsvc-currency').value,
            tax_rate        : parseFloat(document.getElementById('qcsvc-tax').value) || 0,
            tax_included    : document.getElementById('qcsvc-taxincl').value === '1',
            notes           : document.getElementById('qcsvc-notes').value || null,
            sale_id         : qcSaleId() || null,
        };
        document.querySelectorAll('#qcsvc-detail-grid [data-svc-field]').forEach(el => {
            if (el.value !== '') payload[el.dataset.svcField] = el.value;
        });

        const btn = document.getElementById('qcsvc-save-btn');
        btn.disabled = true;
        btn.innerHTML = '<span class="spinner-border spinner-border-sm me-1"></span>Kaydediliyor…';

        fetch(QCSVC_URL, {
            method : 'POST',
            headers: { 'Content-Type':'application/json', 'Accept':'application/json', 'X-CSRF-TOKEN':'{{ csrf_token() }}' },
            body   : JSON.stringify(payload)
        })
        .then(r => r.json())
        .then(d => {
            btn.disabled = false;
            btn.innerHTML = '<i class="fas fa-check me-1"></i> Kataloğa Kaydet';
            if (!d.success) {
                let msg = d.message || 'Kataloğa eklenemedi.';
                if (d.errors) msg = Object.values(d.errors).flat().join('<br>');
                Swal.fire({icon:'error', title:'Hata', html: msg});
                return;
            }

            // Satırı yeni ürüne bağla + katalog listesine ekle
            if (_qcSvcRow) {
                _qcSvcRow.querySelector('.row-product-id').value = d.product.id;
                _qcSvcRow.querySelector('.qv-product-name').value = d.product.name;
            }
            qcAddProductToCatalogGrid(d.product);
            bootstrap.Modal.getInstance(document.getElementById('qcServiceModal'))?.hide();
            calculateQvProductTotals();
            if (typeof qcAutoSave === 'function') qcAutoSave();
            Swal.fire({icon:'success', title:'Kataloğa eklendi', text:d.message, timer:1900, showConfirmButton:false});
            _qcSvcRow = null;
        })
        .catch(() => {
            btn.disabled = false;
            btn.innerHTML = '<i class="fas fa-check me-1"></i> Kataloğa Kaydet';
            Swal.fire({icon:'error', title:'Hata', text:'Sunucu ile bağlantı kurulamadı.'});
        });
    }

    /** Yeni kalemi sayfayı yenilemeden katalog modalına ekler. */
    function qcAddProductToCatalogGrid(p) {
        const gridWrap = document.getElementById('catalogProductGrid');
        if (!gridWrap) return;

        let group = [...gridWrap.querySelectorAll('.qvcat-group')]
            .find(g => g.dataset.typeName === p.product_type_name);

        if (!group) {
            group = document.createElement('div');
            group.className = 'qvcat-group';
            group.dataset.typeName = p.product_type_name;
            group.innerHTML = `<div class="qvcat-group-head">
                    <span class="qvcat-group-badge">${qcEsc(p.product_type_name)}</span>
                    <span class="qvcat-group-line"></span>
                    <span class="qvcat-group-n">0</span>
                </div><div class="qvcat-grid"></div>`;
            gridWrap.insertBefore(group, gridWrap.firstChild);
        }

        const card = document.createElement('div');
        card.className = 'qvcat-card catalog-product-item';
        card.dataset.name = (p.name || '').toLowerCase();
        card.dataset.typeId = p.product_type_id;
        card.dataset.id = p.id;
        card.dataset.pname = p.name;
        card.dataset.price = p.base_price || 0;
        card.dataset.currency = p.currency || 'TRY';
        card.dataset.hasDates = '0';
        card.setAttribute('onclick', 'catalogPickProduct(this)');
        card.innerHTML = `<div class="qvcat-card-ico"><i class="fas ${qcEsc(p.product_type_icon || 'fa-box')}"></i></div>
            <div class="qvcat-card-body">
                <div class="qvcat-card-name">${qcEsc(p.name)}</div>
                <div class="qvcat-card-meta">
                    <span class="qvcat-chip"><i class="fas fa-tag"></i> Hizmet</span>
                    ${p.date_summary ? `<span class="qvcat-chip"><i class="fas fa-calendar-days"></i> ${qcEsc(p.date_summary)}</span>` : ''}
                </div>
            </div>
            <div class="qvcat-card-right">
                <div class="qvcat-card-price${p.base_price ? '' : ' muted'}">${p.base_price ? Number(p.base_price).toLocaleString('tr-TR') + ' <small>' + qcEsc(p.currency) + '</small>' : '—'}</div>
                <div class="qvcat-card-cta">Seç <i class="fas fa-chevron-right"></i></div>
            </div>`;

        group.querySelector('.qvcat-grid').appendChild(card);
        const n = group.querySelector('.qvcat-group-n');
        if (n) n.textContent = group.querySelectorAll('.catalog-product-item').length;

        // Tip filtresinde yoksa ekle
        const tf = document.getElementById('catalogTypeFilter');
        if (tf && ![...tf.options].some(o => o.value === String(p.product_type_id))) {
            tf.add(new Option(p.product_type_name, p.product_type_id));
        }
    }

    // ─── SUBMIT ──────────────────────────────────────────────────────────────────
    function submitQuickCreate() {
        const customerId = document.getElementById('qc-customer-id').value;
        const startDate  = document.getElementById('qc-start-date').value;
        const totalAmt   = document.getElementById('qc-total-amount').value;
        const adults     = document.getElementById('qc-adult').value;

        if (!customerId) {
            Swal.fire({icon:'warning', title:'Uyarı', text:'Lütfen bir müşteri seçin.'}); return;
        }
        if (!startDate) {
            Swal.fire({icon:'warning', title:'Uyarı', text:'Başlangıç tarihi zorunludur.'}); return;
        }

        // Collect products
        const items = [];
        document.querySelectorAll('#qv-products-tbody .qv-product-row').forEach(row => {
            const name = row.querySelector('.qv-product-name').value.trim();
            if (!name) return;
            items.push({
                product_id    : row.querySelector('.row-product-id').value || null,
                itemable_type : row.querySelector('.row-itemable-type')?.value || null,
                itemable_id   : row.querySelector('.row-itemable-id')?.value || null,
                name          : name,
                quantity      : parseFloat(row.querySelector('.qv-product-qty').value) || 1,
                unit_price    : parseFloat(row.querySelector('.qv-product-price').value) || 0,
                tax_rate      : parseFloat(row.querySelector('.qv-product-tax').value) || 0,
                tax_included  : row.querySelector('.qv-product-tax-included')?.value === '1',
                discount_type : row.querySelector('.qv-product-discount-type')?.value || 'percent',
                discount_value: parseFloat(row.querySelector('.qv-product-discount')?.value) || 0,
                currency      : row.querySelector('.qv-product-currency').value,
                start_date    : row.querySelector('.qv-item-start-date')?.value || null,
                end_date      : row.querySelector('.qv-item-end-date')?.value || null,
                start_time    : row.querySelector('.qv-item-start-time')?.value || null,
                end_time      : row.querySelector('.qv-item-end-time')?.value || null
            });
        });

        const payload = {
            _token          : '{{ csrf_token() }}',
            customer_id     : customerId,
            title           : document.getElementById('qc-title').value || null,
            start_date      : startDate,
            end_date        : document.getElementById('qc-end-date').value || null,
            product_type_id : document.getElementById('qc-product-type').value || null,
            product_id      : document.getElementById('qc-product-id').value || null,
            tour_date_id    : document.getElementById('qc-tour-date-id').value || null,
            assigned_to     : document.getElementById('qc-agent').value || null,
            adult_count     : adults || 1,
            child_count     : document.getElementById('qc-child').value || 0,
            infant_count    : document.getElementById('qc-infant').value || 0,
            total_amount    : totalAmt || 0,
            paid_amount     : document.getElementById('qc-paid-amount').value || 0,
            currency        : document.getElementById('qc-currency').value,
            payment_status  : document.getElementById('qc-payment-status').value,
            status          : document.getElementById('qc-status-value').value,
            pickup_location : document.getElementById('qc-pickup').value || null,
            flight_number   : document.getElementById('qc-flight').value || null,
            customer_note   : document.getElementById('qc-customer-note').value || null,
            internal_note   : document.getElementById('qc-internal-note').value || null,
            discount_rate   : (document.getElementById('qc-discount-type')?.value === 'percent' ? (parseFloat(document.getElementById('qc-discount-value')?.value) || 0) : 0),
            discount_amount : parseFloat(document.getElementById('qc-discount-amount')?.value) || 0,
            // Çoklu müşteri yeni satışta da kaydedilir (odalama gönderilmez —
            // sale_rooms'un tek sahibi operasyon modülüdür)
            customer_ids    : qcCusts().map(c => c.id),
            items           : items
        };

        const btn = document.getElementById('qc-submit-btn');
        btn.disabled = true;
        btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Kaydediliyor...';

        fetch('{{ route("agency.sales.store") }}', {
            method : 'POST',
            headers: { 'Content-Type':'application/json', 'Accept':'application/json', 'X-CSRF-TOKEN':'{{ csrf_token() }}' },
            body   : JSON.stringify(payload)
        })
        .then(r => r.json())
        .then(d => {
            btn.disabled = false;
            btn.innerHTML = '<i class="fas fa-save me-2"></i>Satışı Oluştur';

            if (d.success && d.sale_id) {
                // Close create drawer and open the new sale's quick-view
                closeQuickView();
                if (typeof openSaleDrawer === 'function') {
                    openSaleDrawer(d.sale_id);
                } else if (typeof openQuickView === 'function') {
                    openQuickView(`/agency/sales/${d.sale_id}/quick-view`);
                }
                Swal.fire({
                    icon: 'success',
                    title: 'Satış Oluşturuldu!',
                    text: `Rezervasyon başarıyla kaydedildi.`,
                    timer: 2000,
                    showConfirmButton: false
                });
            } else {
                let msg = 'Satış kaydedilirken bir hata oluştu.';
                if (d.errors) msg = Object.values(d.errors).flat().join('<br>');
                else if (d.message) msg = d.message;
                Swal.fire({icon:'error', title:'Hata', html: msg});
            }
        })
        .catch(err => {
            btn.disabled = false;
            btn.innerHTML = '<i class="fas fa-save me-2"></i>Satışı Oluştur';
            console.error(err);
            Swal.fire({icon:'error', title:'Hata', text:'Sunucu ile bağlantı kurulamadı.'});
        });
    }

    // Müşteri çipleri + fiyat tipi paneli açılışta bu kartın köküne bağlanır.
    // (Aynı anda birden fazla satış kartı açık olabildiği için durum kart bazlı.)
    (function qcBootScopedState() {
        const r = qcRoot();
        if (!r) return;
        // Cari özeti sunucudan hazır gelir; şerit ilk çizimde boş kalmasın diye
        // önce bu değer kullanılır, sonra qcCustPaint tazelemesini yapar.
        if (QC_CREDIT_BOOT) {
            r.__qcCredit = QC_CREDIT_BOOT;
            r.__qcCreditId = String(qcEl('qc-customer-id', r)?.value || '');
        }
        qcCustsSet(r, (_qcCustomersBoot || []).map(c => Object.assign({}, c)));
        qcCustPaint(r);
        r.dataset.custsReady = '1';   // artık otomatik kayıt customer_ids gönderebilir
        qcFareBoot(r);                // fiyat tipi + oda paneli (kalemler gelince tekrar çizilir)
        // Odalar okunabildiyse otomatik kayıt artık `rooms` gönderebilir.
        if (@json($saleRoomsReadable)) r.dataset.roomsReady = '1';
    })();

    // Mevcut satışın kalemlerini yükle + metrikleri/toplamları hesapla
    var _qcInitItems = @json($saleItems);
    setTimeout(() => {
        const tbody = document.getElementById('qv-products-tbody');
        if (tbody && _qcInitItems.length) {
            _qcInitItems.forEach(it => {
                const row = addBlankQvProductRow({ name: it.name, qty: it.quantity, price: it.unit_price, currency: it.currency, productId: it.product_id, tax: it.tax_rate, taxIncluded: !!it.tax_included, tourLine: !!it.tour_line,
                    discountType: it.discount_type || 'percent', discountValue: it.discount_value || 0,
                    startDate: it.start_date || '', endDate: it.end_date || '', startTime: it.start_time || '', endTime: it.end_time || '' });
                if (row) {
                    if (it.itemable_type) row.querySelector('.row-itemable-type').value = it.itemable_type;
                    if (it.itemable_id) row.querySelector('.row-itemable-id').value = it.itemable_id;
                    // Katalog bağı varsa adı hatırla: ad elle değişirse bağ bırakılır
                    if (it.product_id) row.dataset.catalogName = it.name;
                }
            });
            calculateQvProductTotals();
        } else if (tbody && tbody.querySelectorAll('.qv-product-row').length === 0) {
            addBlankQvProductRow();
        }
        if (typeof qcUpdateMetrics === 'function') qcUpdateMetrics();
        if (typeof qcPaintAllRowDates === 'function') qcPaintAllRowDates();
        // Kalemler geldikten sonra fiyat tipi paneli gerçek adetlerle çizilir
        // (kayıt tetiklenmez — panel kalemleri okur, yazmaz).
        const _rr = tbody ? tbody.closest('.qv-sales-wrapper') : qcRoot();
        if (typeof qcRoomsRender === 'function') qcRoomsRender(_rr);
        if (typeof qcFareRender === 'function') qcFareRender(_rr);

        // Kalemler tabloya yüklendi → artık otomatik kayıt "items" gönderebilir.
        // Bu bayrak olmadan, yükleme tamamlanmadan tetiklenen bir kayıt sunucuya
        // boş kalem listesi gönderip kayıtlı kalemleri siliyordu.
        const _root = tbody ? tbody.closest('.qv-sales-wrapper') : qcRoot();
        if (_root) {
            _root.dataset.itemsReady = '1';
            // Kalemsiz eski satışlarda tablo satışın fiyat kırılımından türetilir;
            // bu satırlar ilk kayıtta gerçek SaleItem'lara dönüşsün.
            if (_qcInitItems.some(it => it.tour_line)) qcAutoSave(_root);
        }
    }, 300);
</script>
