
// ─── STRIPE ──────────────────────────────────────────────────────────────────
// Lazy-load Stripe.js — only when card payment is selected
let _stripePromise = null;
function getStripe(){
  if(_stripePromise) return _stripePromise;
  _stripePromise = new Promise((resolve)=>{
    if(window.Stripe){ resolve(window.Stripe); return; }
    const s=document.createElement("script");
    s.src="https://js.stripe.com/v3/";
    s.onload=()=>resolve(window.Stripe);
    s.onerror=()=>resolve(null);
    document.head.appendChild(s);
  });
  return _stripePromise;
}
// Create a Stripe Checkout session and redirect
function startStripeCheckout(bidderEmail, bidderNum, purpose){
  return fetch("/api/stripe/create-checkout-session",{
    method:"POST",
    headers:{"Content-Type":"application/json"},
    body:JSON.stringify({email:bidderEmail, bidderNum:bidderNum, purpose:purpose||"deposit"})
  })
  .then(function(res){ return res.json(); })
  .then(function(data){
    if(data.url){ window.location.href = data.url; return {ok:true}; }
    if(data.error) return {error:data.error};
    return {error:"Could not create checkout session"};
  })
  .catch(function(){ return {error:"Payment service unavailable. Try Zelle or Cash."}; });
}

// ─── CONSTANTS ────────────────────────────────────────────────────────────────
const COMPANIES = [
  { id:"abc",   label:"ABC Towing",   color:"#3b82f6", dispatchUrl:"https://dispatch.abctowingvegas.com" },
  { id:"kings", label:"Kings Towing", color:"#8b5cf6", dispatchUrl:"https://dispatch.kingstowing.com" },
  { id:"tg",    label:"Tow Guys",     color:"#22c55e", dispatchUrl:"https://dispatch.towguys.com" },
  { id:"titan", label:"Titan Towing", color:"#F5A623", dispatchUrl:"https://dispatch.titantowinglv.com" },
];
const COMPANY_MAP = Object.fromEntries(COMPANIES.map(c=>[c.id,c]));

const AUCTION_EVENTS = {
  tuesday:{ label:"Tuesday Auction", day:2, closeHour:14, address:"250 W Warm Springs Rd, Henderson, NV 89011", viewing:"Monday & Tuesday 8AM–2PM" },
  friday: { label:"Friday Auction",  day:5, closeHour:14, address:"3823 Losee Rd, North Las Vegas, NV 89030", viewing:"Thursday & Friday 8AM–2PM" },
};

const BID_INCREMENTS = [50, 100, 200, 500];
const STAGGER_SECONDS = 30;
const DEFAULT_ADMIN_FEE = 35.47;
const DEFAULT_TAX_RATE  = 8.375; // percent

// ─── ADMIN USERS ──────────────────────────────────────────────────────────────
// Passwords stored here — change in Admin → Settings → Staff Accounts
const INIT_ADMIN_USERS = [
  { id:"admin-1", name:"Idan Etzyoni",   username:"idan",      password:"MaiNiv2026!",   role:"owner",    active:true  },
  { id:"admin-2", name:"Dispatcher 1",   username:"dispatch1", password:"Dispatch#01",   role:"dispatch", active:true  },
  { id:"admin-3", name:"Dispatcher 2",   username:"dispatch2", password:"Dispatch#02",   role:"dispatch", active:true  },
  { id:"admin-4", name:"Office Manager", username:"office1",   password:"Office#2026",   role:"office",   active:true  },
  { id:"admin-5", name:"Office Staff",   username:"office2",   password:"Staff#2026",    role:"office",   active:false },
];

const ADMIN_ROLES = [
  { id:"owner",    label:"Owner",          color:"#003087" },
  { id:"dispatch", label:"Dispatcher",     color:"#8b5cf6" },
  { id:"office",   label:"Office Staff",   color:"#22c55e" },
];

const CC_FEE_RATE = 3.5; // percent — applied to all credit card transactions
const PAY_METHODS = [
  { id:"card",        label:"Credit Card (Online)",    icon:"💳", note:"Processed securely via Stripe · 3.5% fee · Automatically approved to bid", hasFee:true },
  { id:"card-office", label:"Credit Card (In Office)", icon:"🏢", note:"Card swiped in person at our office · 3.5% fee · Requires staff approval", hasFee:true },
  { id:"zelle",       label:"Zelle",                   icon:"💸", note:"Send to (702) 677-0792 · No fee · Requires staff approval", hasFee:false },
  { id:"cash",        label:"Cash",                    icon:"💵", note:"Drop off at our office · No fee · Requires staff approval", hasFee:false },
  { id:"arrange",     label:"Make Arrangements with Staff", icon:"🤝", note:"Contact our staff to discuss deposit options · Call (702) 677-0792", hasFee:false },
];

// ─── TRANSLATIONS ─────────────────────────────────────────────────────────────
const TRANSLATIONS = {
  en: {
    // Nav
    nav_auction:"Auction", nav_signin:"Sign In", nav_register:"Register & Deposit", nav_contact:"Contact", nav_faq:"FAQ", nav_terms:"Terms", nav_howto:"How to Bid",
    terms_title:"Terms & Conditions", terms_sub:"Tow Guys Auto Auction — Nevada Lien Sale · NRS Chapter 108",
    terms_cta_title:"Ready to Bid?", terms_cta_sub:"Register your account and pay your deposit to start bidding.",
    reg_title:"Registration & Bidding Process", reg_sub:"How to get started at Tow Guys Auto Auction",
    reg_new_users:"New Users", reg_returning:"Returning Users",
    reg_location:"Location", reg_phone:"Phone", reg_zelle:"Zelle", reg_hours:"Hours",
    reg_pickup:"Pickup Deadline", reg_deposit:"Deposit",
    reg_zelle_val:"Send to: ", reg_hours_val:"Lot open {open} · Viewing from {start}",
    reg_deposit_val:"$300 refundable deposit required",
    reg_cta_title:"Ready to Register?", reg_cta_sub:"Pay your $300 deposit to activate your bidder account.",
    reg_cta_btn:"Register & Pay Deposit →", terms_cta_btn:"Register & Deposit →",
    nav_myaccount:"My Account", nav_approved:"Approved Bidder", nav_pending:"Pending",
    // Banner
    banner_eyebrow:"Nevada Lien Sale · Closes 2:00 PM",
    banner_title_1:"Live Vehicle", banner_title_2:"Auction",
    banner_sub:"Government-regulated lien sale vehicles. All sales final, as-is. Registration and $300 deposit required to bid.",
    banner_total_lots:"Total Lots", banner_active:"Active Now",
    banner_live:"● LIVE NOW", banner_closes:"Closes",
    // Toolbar
    filter_all:"All", filter_runs:"Runs", filter_no_start:"No Start", filter_label:"Filter:",
    search_placeholder:"Search by make, model, or VIN…",
    terms_link:"Terms & Conditions",
    // Auction card
    card_current_bid:"Current Bid", card_bids:"bids", card_bid:"bid",
    card_min:"Min", card_closed:"Auction Closed",
    card_register:"Register to Bid", card_place_bid:"Place Bid →", card_awaiting:"Awaiting Approval",
    card_mileage:"Mileage", card_increment:"Increment", card_extended:"⚡ Extended",
    card_active_bids:"✓ Active bids", card_buy_now:"💰 Buy Now", card_make_offer:"✉ Make an Offer",
    card_proxy_leading:"You're leading — your max bid", card_proxy_outbid:"Outbid by a max bid", card_proxy_active:"Your max bid is active — max",
    card_runs:"✓ Runs", card_no_start:"✗ No Start",
    card_key_fee:"Key Fee", card_no_key:"No key fee",
    // Bid modal
    bid_title:"Place Bid", bid_your_bid:"Your Bid", bid_quick:"Quick Bid",
    bid_min:"Minimum", bid_increment:"Increment",
    bid_confirm:"Confirm", bid_cancel:"Cancel",
    bid_auto_title:"🤖 Auto-Bid (Proxy)",
    bid_auto_sub:"Set a max and the system bids for you automatically up to that amount.",
    bid_auto_enable:"Enable", bid_auto_min_error:"Max bid must be at least your current bid of",
    bid_auto_ok:"✓ System will auto-bid up to",
    bid_key_fee:"Key Fee: {{amount}} added at invoice.",
    bid_deposit_applied:"Deposit Applied: Your $300 deposit goes toward the balance if you win.",
    bid_max:"max",
    // Bid done
    bid_done_title:"Bid Placed!", bid_done_body:"Your bid of {{amount}} on the {{vehicle}} is live. You'll be notified if outbid or if you win.",
    bid_keep:"Keep Bidding", bid_done_btn:"Done",
    // Registration
    reg_title:"Register & Deposit",
    reg_step1:"Your Information", reg_step2:"Deposit & Payment Preferences",
    reg_personal:"Personal Information",
    reg_first:"First Name", reg_last:"Last Name", reg_email:"Email", reg_phone:"Phone",
    reg_address:"Street Address", reg_city:"City", reg_state:"State", reg_zip:"Zip",
    reg_dl_title:"Driver's License (required for lien sale records)",
    reg_dl:"DL Number", reg_dl_state:"State",
    reg_privacy:"Privacy: Your identity is never shown publicly. Information is collected for lien sale compliance only.",
    reg_deposit_title:"Deposit Payment ($300 — refundable)",
    reg_final_title:"How will you pay your winning balance?",
    reg_final_sub:"Your $300 deposit is applied. Choose how you'll pay the remaining balance if you win. This can be different from your deposit method.",
    reg_deposit_box_lbl:"Refundable Deposit",
    reg_deposit_box_sub:"Applied to your winning bid. Non-winners refunded within 3–5 business days.",
    reg_keep_title:"Keep deposit on file until I win",
    reg_keep_on:"Your deposit rolls to future auctions automatically.",
    reg_keep_off:"Refunded after each auction if you don't win.",
    reg_continue:"Continue →", reg_submit:"Submit Registration", reg_confirm:"Confirm $300 Deposit",
    reg_pending_title:"Pending Approval", reg_confirmed_title:"Deposit Confirmed",
    reg_pending_body_zelle:"Your registration is received. Our office will verify your Zelle payment and activate your account within 1 business hour.",
    reg_pending_body_cash:"Your registration is received. Our office will verify your cash deposit and activate your account within 1 business hour.",
    reg_confirmed_body:"Your $300 deposit is confirmed. You are approved to bid.",
    reg_confirmed_keep:"Deposit stays on file until you win.",
    reg_payment_plan:"Your Payment Plan",
    reg_deposit_label:"Deposit", reg_balance_label:"Balance if you win",
    reg_start_bidding:"Start Bidding →",
    reg_got_it:"Got It — I'll wait for confirmation",
    reg_zelle_instructions:"Send $300 Zelle to: csrtowguysautoauction@gmail.com · Include your name in the memo. Approved within 1 business hour.",
    reg_cash_instructions:"Bring $300 cash to: 250 W Warm Springs Rd, Henderson (Tue) · 3823 Losee Rd, N. Las Vegas (Fri) · Staff will activate your account upon receipt.",
    reg_final_zelle_note:"If you win, we'll send you an invoice and you Zelle the balance to csrtowguysautoauction@gmail.com.",
    reg_final_cash_note:"If you win, bring the balance in cash at pickup. Staff will confirm your arrival time.",
    // Login
    login_title:"Sign In", login_sub:"Access your invoices and bid history",
    login_email:"Email Address", login_password:"Password",
    login_btn:"Sign In →", login_loading:"Signing in…",
    login_no_account:"No account?", login_register:"Register & deposit to bid",
    login_demo:"Demo: demo@example.com / demo123",
    // Contact
    contact_title:"Contact Us", contact_sub:"We're here to help",
    contact_address:"Auction Locations",
    contact_phone:"Phone", contact_email:"Email", contact_hours:"Hours",
    contact_form_title:"Send Us a Message",
    contact_name:"Your Name", contact_email_field:"Email Address",
    contact_subject:"Subject", contact_message:"Message",
    contact_send:"Send Message", contact_sent:"✓ Message Sent!",
    contact_sent_sub:"We'll get back to you within 1 business hour.",
    // Threshold
    threshold_title:"⚠ Additional Deposit Required",
    threshold_sub:"Your combined winning total has exceeded $5,000",
    threshold_total_lbl:"Your Current Winning Total",
    threshold_lots:"leading lots — threshold is",
    threshold_body:"You are the leading bidder on multiple vehicles. To continue bidding, an additional refundable $300 deposit is required. It will be applied toward your winning balances.",
    threshold_method:"Charge Method",
    threshold_card_note:"By clicking Approve, you authorize a $300 charge to the card on file. No new card info needed.",
    threshold_approve:"Approve — Charge $300 to Card on File",
    threshold_dismiss:"Dismiss — I may lose my leading bids",
    threshold_processing:"Processing charge…",
    threshold_done:"$300 Charged — You're Good to Bid!",
    threshold_done_sub:"Additional deposit approved. You may continue bidding. Returning you to the auction…",
    contact_send_another:"Send Another",
    // No results
    no_results_title:"No Lots Found", no_results_sub:"Try a different search or filter.",
  },
  es: {
    // Nav
    nav_auction:"Subasta", nav_signin:"Iniciar Sesión", nav_register:"Registrarse y Depositar", nav_contact:"Contacto", nav_faq:"Preguntas", nav_terms:"Términos", nav_howto:"Cómo Pujar",
    terms_title:"Términos y Condiciones", terms_sub:"Tow Guys Auto Auction — Venta de Embargo en Nevada · NRS Capítulo 108",
    terms_cta_title:"¿Listo para Pujar?", terms_cta_sub:"Registre su cuenta y pague su depósito para comenzar a pujar.",
    reg_title:"Proceso de Registro y Puja", reg_sub:"Cómo comenzar en Tow Guys Auto Auction",
    reg_new_users:"Usuarios Nuevos", reg_returning:"Usuarios Recurrentes",
    reg_location:"Ubicación", reg_phone:"Teléfono", reg_zelle:"Zelle", reg_hours:"Horario",
    reg_pickup:"Límite de Recogida", reg_deposit:"Depósito",
    reg_zelle_val:"Enviar a: ", reg_hours_val:"Lote abierto {open} · Visualización desde {start}",
    reg_deposit_val:"Depósito reembolsable de $300 requerido",
    reg_cta_title:"¿Listo para Registrarse?", reg_cta_sub:"Pague su depósito de $300 para activar su cuenta.",
    reg_cta_btn:"Registrarse y Pagar Depósito →", terms_cta_btn:"Registrarse y Depositar →",
    nav_myaccount:"Mi Cuenta", nav_approved:"Postor Aprobado", nav_pending:"Pendiente",
    // Banner
    banner_eyebrow:"Venta de Gravamen de Nevada · Cierra 2:00 PM",
    banner_title_1:"Subasta de", banner_title_2:"Vehículos en Vivo",
    banner_sub:"Vehículos de venta por gravamen regulada por el gobierno. Todas las ventas son finales, tal como están. Se requiere registro y depósito de $300 para pujar.",
    banner_total_lots:"Lotes Totales", banner_active:"Activos Ahora",
    banner_live:"● EN VIVO", banner_closes:"Cierra",
    // Toolbar
    filter_all:"Todos", filter_runs:"Enciende", filter_no_start:"No Enciende", filter_label:"Filtrar:",
    search_placeholder:"Buscar por marca, modelo o VIN…",
    terms_link:"Términos y Condiciones",
    // Auction card
    card_current_bid:"Oferta Actual", card_bids:"ofertas", card_bid:"oferta",
    card_min:"Mín", card_closed:"Subasta Cerrada",
    card_register:"Regístrese para Pujar", card_place_bid:"Hacer Oferta →", card_awaiting:"Aprobación Pendiente",
    card_mileage:"Kilometraje", card_increment:"Incremento", card_extended:"⚡ Extendido",
    card_active_bids:"✓ Ofertas activas", card_buy_now:"💰 Comprar Ya", card_make_offer:"✉ Hacer una Oferta",
    card_proxy_leading:"Vas ganando — tu oferta máxima", card_proxy_outbid:"Superado por una oferta máxima", card_proxy_active:"Tu oferta máxima está activa — máx",
    card_runs:"✓ Enciende", card_no_start:"✗ No Enciende",
    card_key_fee:"Tarifa de Llave", card_no_key:"Sin tarifa de llave",
    // Bid modal
    bid_title:"Hacer Oferta", bid_your_bid:"Tu Oferta", bid_quick:"Oferta Rápida",
    bid_min:"Mínimo", bid_increment:"Incremento",
    bid_confirm:"Confirmar", bid_cancel:"Cancelar",
    bid_auto_title:"🤖 Oferta Automática (Proxy)",
    bid_auto_sub:"Establece un máximo y el sistema puja por ti automáticamente hasta ese monto.",
    bid_auto_enable:"Activar", bid_auto_min_error:"La oferta máxima debe ser al menos tu oferta actual de",
    bid_auto_ok:"✓ El sistema pujará automáticamente hasta",
    bid_key_fee:"Tarifa de llave: {{amount}} se agrega a la factura.",
    bid_deposit_applied:"Depósito Aplicado: Tu depósito de $300 se aplica al saldo si ganas.",
    bid_max:"máx",
    // Bid done
    bid_done_title:"¡Oferta Realizada!", bid_done_body:"Tu oferta de {{amount}} en el {{vehicle}} está activa. Se te notificará si eres superado o si ganas.",
    bid_keep:"Seguir Pujando", bid_done_btn:"Listo",
    // Registration
    reg_title:"Registrarse y Depositar",
    reg_step1:"Tu Información", reg_step2:"Depósito y Preferencias de Pago",
    reg_personal:"Información Personal",
    reg_first:"Nombre", reg_last:"Apellido", reg_email:"Correo Electrónico", reg_phone:"Teléfono",
    reg_address:"Dirección", reg_city:"Ciudad", reg_state:"Estado", reg_zip:"Código Postal",
    reg_dl_title:"Licencia de Conducir (requerida para registros de gravamen)",
    reg_dl:"Número de Licencia", reg_dl_state:"Estado",
    reg_privacy:"Privacidad: Tu identidad nunca se muestra públicamente. La información se recopila solo para cumplimiento de ventas por gravamen.",
    reg_deposit_title:"Pago de Depósito ($300 — reembolsable)",
    reg_final_title:"¿Cómo pagarás tu saldo ganador?",
    reg_final_sub:"Tu depósito de $300 ya está aplicado. Elige cómo pagarás el saldo restante si ganas. Puede ser diferente al método de depósito.",
    reg_deposit_box_lbl:"Depósito Reembolsable",
    reg_deposit_box_sub:"Aplicado a tu oferta ganadora. Los no ganadores son reembolsados en 3–5 días hábiles.",
    reg_keep_title:"Mantener depósito en archivo hasta ganar",
    reg_keep_on:"Tu depósito se traslada automáticamente a subastas futuras.",
    reg_keep_off:"Reembolsado después de cada subasta si no ganas.",
    reg_continue:"Continuar →", reg_submit:"Enviar Registro", reg_confirm:"Confirmar Depósito de $300",
    reg_pending_title:"Aprobación Pendiente", reg_confirmed_title:"Depósito Confirmado",
    reg_pending_body_zelle:"Tu registro fue recibido. Nuestra oficina verificará tu pago por Zelle y activará tu cuenta en 1 hora hábil.",
    reg_pending_body_cash:"Tu registro fue recibido. Nuestra oficina verificará tu depósito en efectivo y activará tu cuenta en 1 hora hábil.",
    reg_confirmed_body:"Tu depósito de $300 está confirmado. Estás aprobado para pujar.",
    reg_confirmed_keep:"El depósito permanece en archivo hasta que ganes.",
    reg_start_bidding:"Comenzar a Pujar →",
    reg_got_it:"Entendido — Esperaré la confirmación",
    reg_zelle_instructions:"Envía $300 por Zelle a: csrtowguysautoauction@gmail.com · Incluye tu nombre en el memo. Aprobado en 1 hora hábil.",
    reg_cash_instructions:"Trae $300 en efectivo a: 250 W Warm Springs Rd, Henderson (Mar) · 3823 Losee Rd, N. Las Vegas (Vie) · El personal activará tu cuenta al recibirlo.",
    reg_final_zelle_note:"Si ganas, te enviaremos una factura y envías el saldo por Zelle a csrtowguysautoauction@gmail.com.",
    reg_final_cash_note:"Si ganas, trae el saldo en efectivo al recoger el vehículo. El personal confirmará tu hora de llegada.",
    reg_payment_plan:"Tu Plan de Pago",
    reg_deposit_label:"Depósito", reg_balance_label:"Saldo si ganas",
    // Login
    login_title:"Iniciar Sesión", login_sub:"Accede a tus facturas e historial",
    login_email:"Correo Electrónico", login_password:"Contraseña",
    login_btn:"Iniciar Sesión →", login_loading:"Iniciando sesión…",
    login_no_account:"¿No tienes cuenta?", login_register:"Regístrate y deposita para pujar",
    login_demo:"Demo: demo@example.com / demo123",
    // Contact
    contact_title:"Contáctenos", contact_sub:"Estamos aquí para ayudarte",
    contact_address:"Ubicaciones de Subasta",
    contact_phone:"Teléfono", contact_email:"Correo", contact_hours:"Horario",
    contact_form_title:"Envíanos un Mensaje",
    contact_name:"Tu Nombre", contact_email_field:"Correo Electrónico",
    contact_subject:"Asunto", contact_message:"Mensaje",
    contact_send:"Enviar Mensaje", contact_sent:"✓ ¡Mensaje Enviado!",
    contact_sent_sub:"Te responderemos en 1 hora hábil.",
    // Threshold
    threshold_title:"⚠ Se Requiere Depósito Adicional",
    threshold_sub:"Tu total ganador combinado ha superado $5,000",
    threshold_total_lbl:"Tu Total Ganador Actual",
    threshold_lots:"lotes líderes — el límite es",
    threshold_body:"Eres el postor líder en múltiples vehículos. Para continuar pujando, se requiere un depósito adicional reembolsable de $300. Se aplicará a tus saldos ganadores.",
    threshold_method:"Método de Cobro",
    threshold_card_note:"Al hacer clic en Aprobar, autorizas un cargo de $300 a la tarjeta registrada. No se necesita nueva información de tarjeta.",
    threshold_approve:"Aprobar — Cobrar $300 a la Tarjeta Registrada",
    threshold_dismiss:"Descartar — Puedo perder mis ofertas líderes",
    threshold_processing:"Procesando cargo…",
    threshold_done:"¡$300 Cobrado — Puedes Continuar Pujando!",
    threshold_done_sub:"Depósito adicional aprobado. Puedes continuar pujando. Regresando a la subasta…",
    // Terms
    terms_close:"Entiendo — Cerrar",
    contact_send_another:"Enviar Otro",
    no_results_title:"No Se Encontraron Lotes", no_results_sub:"Intenta con otra búsqueda o filtro.",
  }
};
const STAGGER_MS = STAGGER_SECONDS * 1000;
function buildAuctions() {
  const base = Date.now() + 2 * 60 * 60 * 1000;
  return [
    { id:"A001", lot:"LOT 001", wo:"TT-10482", year:2018, make:"Honda",     model:"Accord",        vin:"1HGCV1F34JA012345", mileage:82400,  condition:"runs",     keyFee:0,   minBid:2000, increment:100, currentBid:4200, bids:7,  views:41, shares:3, leader:"BID-001", autoBids:[{bidderNum:"BID-001",maxBid:5500},{bidderNum:"BID-002",maxBid:4500}], company:"titan", photos:["https://placehold.co/800x500/111/333?text=Photo+1","https://placehold.co/800x500/111/333?text=Photo+2","https://placehold.co/800x500/111/333?text=Photo+3","https://placehold.co/800x500/111/333?text=Photo+4"], closeTime:base, sold:true, winner:"BID-001", reserve:5000, buyNow:6500, offers:[], taxExempt:false, comments:[], titleType:"lien", conditionNotes:"Clean interior, minor door ding passenger side. AC blows cold.", bidHistory:[{bidder:"Bidder #3",amount:2000,ts:"9:02 AM"},{bidder:"Bidder #1",amount:2100,ts:"9:04 AM"},{bidder:"Bidder #3",amount:2300,ts:"9:05 AM"},{bidder:"Bidder #2",amount:3500,ts:"9:08 AM"},{bidder:"Bidder #1",amount:3700,ts:"9:11 AM"},{bidder:"Bidder #2",amount:4000,ts:"9:14 AM"},{bidder:"Bidder #1",amount:4200,ts:"9:15 AM"}],
      payments:[{id:"pay1",method:"card",amount:300,note:"Deposit — charged at registration",received:true,ts:"Mar 25, 9:00 AM",staff:"Auto"},{id:"pay2",method:"card",amount:3935,note:"Balance: bid $4,200 − deposit $300 + admin fee $35",received:false,ts:"",staff:""}], paperworkReceived:false },
    { id:"A002", lot:"LOT 002", wo:"TG-08811", year:2015, make:"Ford",       model:"F-150",         vin:"1FTEW1E82FFA00001", mileage:134900, condition:"no-start", keyFee:125, minBid:1500, increment:100, currentBid:3850, bids:4,  views:28, shares:5, leader:"BID-002", autoBids:[{bidderNum:"BID-002",maxBid:5000}], company:"tg",    photos:["https://placehold.co/800x500/111/333?text=Photo+1","https://placehold.co/800x500/111/333?text=Photo+2","https://placehold.co/800x500/111/333?text=Photo+3","https://placehold.co/800x500/111/333?text=Photo+4"], closeTime:base+STAGGER_MS*1, sold:false, winner:null, reserve:null, buyNow:5500, offers:[{id:"o1",bidderNum:"BID-002",amount:3000,note:"Cash offer",ts:"9:05 AM",status:"pending"}], taxExempt:false, comments:[], titleType:"lien", conditionNotes:"Cranks but won't start. Possible fuel pump issue. Body in good shape. Tires good.", bidHistory:[{bidder:"Bidder #4",amount:1500,ts:"9:00 AM"},{bidder:"Bidder #2",amount:2000,ts:"9:03 AM"},{bidder:"Bidder #4",amount:3000,ts:"9:09 AM"},{bidder:"Bidder #2",amount:3850,ts:"9:13 AM"}],
      payments:[], paperworkReceived:false },
    { id:"A003", lot:"LOT 003", wo:"KT-20031", year:2020, make:"Toyota",     model:"Camry",         vin:"4T1B11HK0LU123456", mileage:41200,  condition:"runs",     keyFee:0,   minBid:3500, increment:200, currentBid:7100, bids:12, views:67, shares:8, leader:"BID-003", autoBids:[{bidderNum:"BID-003",maxBid:8000},{bidderNum:"BID-001",maxBid:7500}], company:"kings", photos:["https://placehold.co/800x500/111/333?text=Photo+1","https://placehold.co/800x500/111/333?text=Photo+2","https://placehold.co/800x500/111/333?text=Photo+3","https://placehold.co/800x500/111/333?text=Photo+4"], closeTime:base+STAGGER_MS*2, sold:true, winner:"BID-003", reserve:8000, buyNow:null, offers:[], taxExempt:false, comments:[], titleType:"lien", conditionNotes:"Runs great. Low miles. Clean title.", bidHistory:[{bidder:"Bidder #1",amount:3500,ts:"9:01 AM"},{bidder:"Bidder #5",amount:4000,ts:"9:02 AM"},{bidder:"Bidder #3",amount:5000,ts:"9:04 AM"},{bidder:"Bidder #1",amount:5500,ts:"9:06 AM"},{bidder:"Bidder #5",amount:6000,ts:"9:07 AM"},{bidder:"Bidder #3",amount:6500,ts:"9:09 AM"},{bidder:"Bidder #1",amount:7000,ts:"9:12 AM"},{bidder:"Bidder #5",amount:7100,ts:"9:14 AM"}],
      payments:[{id:"pay3",method:"cash",amount:300,note:"Cash deposit received at Henderson office",received:true,ts:"Mar 25, 8:45 AM",staff:"Idan"},{id:"pay4",method:"zelle",amount:3500,note:"Zelle received — partial balance",received:true,ts:"Mar 26, 10:12 AM",staff:"Office1"},{id:"pay5",method:"cash",amount:3840,note:"Remaining balance in cash at pickup",received:false,ts:"",staff:""}], paperworkReceived:true },
    { id:"A004", lot:"LOT 004", wo:"ABC-44120",year:2012, make:"Chevrolet",  model:"Silverado 1500",vin:"3GCPKSE73CG100001", mileage:198000, condition:"no-start", keyFee:250, minBid:800,  increment:50,  currentBid:1400, bids:2,  views:14, shares:1, leader:null, autoBids:[], company:"abc",   photos:[], closeTime:base+STAGGER_MS*3, sold:false, winner:null, reserve:null, buyNow:null, offers:[], taxExempt:false, comments:[{id:"c1",staff:"Idan",text:"Called owner, no answer. Left voicemail.",ts:"Mar 25 · 9:14 AM"}], titleType:"salvage", conditionNotes:"High miles. No start. Rust on undercarriage. Key fee required.", bidHistory:[{bidder:"Bidder #6",amount:800,ts:"9:00 AM"},{bidder:"Bidder #2",amount:1400,ts:"9:11 AM"}],
      payments:[], paperworkReceived:false },
    { id:"A005", lot:"LOT 005", wo:"TT-10501", year:2019, make:"BMW",        model:"3 Series",      vin:"WBA5R1C50KAE12345", mileage:67800,  condition:"runs",     keyFee:350, minBid:5000, increment:200, currentBid:9300, bids:19, views:89, shares:12, leader:"BID-004", autoBids:[{bidderNum:"BID-004",maxBid:12000}], company:"titan", photos:["https://placehold.co/800x500/111/333?text=Photo+1","https://placehold.co/800x500/111/333?text=Photo+2"], closeTime:base+STAGGER_MS*4, sold:true, winner:"BID-004", reserve:10000, buyNow:13500, offers:[{id:"o2",bidderNum:"BID-004",amount:11000,note:"Dealer offer",ts:"8:55 AM",status:"pending"}], taxExempt:true, comments:[], titleType:"lien", conditionNotes:"Runs and drives. Check engine light on — code P0420 catalyst. Dealer key required.", bidHistory:[{bidder:"Bidder #1",amount:5000,ts:"9:00 AM"},{bidder:"Bidder #4",amount:6000,ts:"9:01 AM"},{bidder:"Bidder #1",amount:7000,ts:"9:03 AM"},{bidder:"Bidder #4",amount:8000,ts:"9:06 AM"},{bidder:"Bidder #1",amount:9000,ts:"9:12 AM"},{bidder:"Bidder #4",amount:9300,ts:"9:14 AM"}],
      payments:[{id:"pay6",method:"card",amount:300,note:"Deposit on file",received:true,ts:"Mar 20, 2:00 PM",staff:"Auto"},{id:"pay7",method:"card",amount:9085,note:"Full balance charged to card on file",received:true,ts:"Mar 25, 3:15 PM",staff:"Office1"}], paperworkReceived:true },
    { id:"A006", lot:"LOT 006", wo:"TG-08899", year:2017, make:"Nissan",     model:"Altima",        vin:"1N4AL3AP3HC123456", mileage:105300, condition:"runs",     keyFee:0,   minBid:1200, increment:100, currentBid:2900, bids:5,  views:22, shares:2, leader:"BID-001", autoBids:[{bidderNum:"BID-001",maxBid:4000}], company:"tg",    photos:["https://placehold.co/800x500/111/333?text=Photo+1","https://placehold.co/800x500/111/333?text=Photo+2","https://placehold.co/800x500/111/333?text=Photo+3","https://placehold.co/800x500/111/333?text=Photo+4"], closeTime:base+STAGGER_MS*5, sold:false, winner:null, reserve:null, buyNow:4200, offers:[], taxExempt:false, comments:[], titleType:"lien", conditionNotes:"Minor hail damage on roof and hood. Otherwise clean.", bidHistory:[{bidder:"Bidder #3",amount:1200,ts:"9:00 AM"},{bidder:"Bidder #6",amount:1600,ts:"9:04 AM"},{bidder:"Bidder #3",amount:2100,ts:"9:08 AM"},{bidder:"Bidder #6",amount:2500,ts:"9:11 AM"},{bidder:"Bidder #3",amount:2900,ts:"9:14 AM"}],
      payments:[], paperworkReceived:false },
  ];
}

// Past auctions archive (mock)
const PAST_AUCTIONS = [
  {
    id:"AUC-2026-03-18", label:"Tuesday Mar 18, 2026", date:"2026-03-18", location:"Henderson",
    lots:[
      { id:"P001", lot:"LOT 001", year:2016, make:"Jeep",    model:"Cherokee",  vin:"1C4PJMCB5GW123456", company:"titan", minBid:1800, finalBid:3200, condition:"runs",    keyFee:0,   status:"sold",    bids:8 },
      { id:"P002", lot:"LOT 002", year:2014, make:"Honda",   model:"Civic",     vin:"2HGFB2F59EH100001", company:"abc",   minBid:1000, finalBid:0,    condition:"no-start",keyFee:125, status:"no-sale", bids:0 },
      { id:"P003", lot:"LOT 003", year:2019, make:"Hyundai", model:"Elantra",   vin:"5NPD84LF9KH100002", company:"kings", minBid:2000, finalBid:4100, condition:"runs",    keyFee:0,   status:"sold",    bids:11 },
      { id:"P004", lot:"LOT 004", year:2013, make:"Dodge",   model:"Ram 1500",  vin:"1C6RR7KT5DS100003", company:"tg",    minBid:1200, finalBid:0,    condition:"no-start",keyFee:250, status:"no-sale", bids:1 },
      { id:"P005", lot:"LOT 005", year:2017, make:"Ford",    model:"Escape",    vin:"1FMCU0GD1HUA00004", company:"titan", minBid:1500, finalBid:2800, condition:"runs",    keyFee:0,   status:"sold",    bids:6 },
    ]
  },
  {
    id:"AUC-2026-03-14", label:"Friday Mar 14, 2026", date:"2026-03-14", location:"North Las Vegas",
    lots:[
      { id:"P101", lot:"LOT 001", year:2015, make:"Kia",     model:"Optima",    vin:"5XXGM4A7XFG100005", company:"tg",    minBid:1200, finalBid:2400, condition:"runs",    keyFee:0,   status:"sold",    bids:7 },
      { id:"P102", lot:"LOT 002", year:2011, make:"Toyota",  model:"Corolla",   vin:"2T1BU4EE5BC100006", company:"kings", minBid:800,  finalBid:0,    condition:"no-start",keyFee:0,   status:"no-sale", bids:0 },
      { id:"P103", lot:"LOT 003", year:2018, make:"Chevy",   model:"Malibu",    vin:"1G1ZD5ST0JF100007", company:"abc",   minBid:1800, finalBid:3600, condition:"runs",    keyFee:0,   status:"sold",    bids:9 },
    ]
  },
];

// Mock bidder registry
const INIT_BIDDERS = [
  {
    id:"B-001", first:"Michael", last:"R.", email:"m.r@gmail.com", phone:"(702) 555-0111",
    dl:"NV-7823", dlState:"NV", address:"1234 Main St", city:"Las Vegas", state:"NV", zip:"89101",
    payMethod:"card", finalPayMethod:"card",
    depositStatus:"approved", depositOnFile:true, keepOnFile:true, whitelist:false,
    bidderNum:"BID-001",
    depositNote:"", staffNotes:"",
    paymentComment:"",
    lienData:{first:"Michael",last:"R.",address:"1234 Main St",city:"Las Vegas",state:"NV",zip:"89101",dl:"NV-7823",dlState:"NV"},
    lienPrefilled:true,
  },
  {
    id:"B-002", first:"Sandra", last:"T.", email:"s.t@yahoo.com", phone:"(702) 555-0122",
    dl:"CA-4411", dlState:"CA", address:"456 Oak Ave", city:"Henderson", state:"NV", zip:"89002",
    payMethod:"zelle", finalPayMethod:"card",
    depositStatus:"pending", depositOnFile:false, keepOnFile:false, whitelist:false,
    bidderNum:"BID-002",
    depositNote:"Zelle sent $300 at 9:14am — awaiting confirmation", staffNotes:"",
    paymentComment:"",
    lienData:{first:"Sandra",last:"T.",address:"456 Oak Ave",city:"Henderson",state:"NV",zip:"89002",dl:"CA-4411",dlState:"CA"},
    lienPrefilled:false,
  },
  {
    id:"B-003", first:"James", last:"W.", email:"j.w@outlook.com", phone:"(702) 555-0133",
    dl:"NV-0032", dlState:"NV", address:"789 Desert Rd", city:"North Las Vegas", state:"NV", zip:"89030",
    payMethod:"cash", finalPayMethod:"cash",
    depositStatus:"approved", depositOnFile:true, keepOnFile:true, whitelist:true,
    bidderNum:"BID-003",
    depositNote:"Cash received in person at Henderson office — Idan 3/25", staffNotes:"Regular buyer — always pays same day.",
    paymentComment:"Coming Friday after 2pm to pay balance",
    lienData:{first:"James",last:"W.",address:"789 Desert Rd",city:"North Las Vegas",state:"NV",zip:"89030",dl:"NV-0032",dlState:"NV"},
    lienPrefilled:true,
  },
  {
    id:"B-004", first:"Auto", last:"Dealer LLC", email:"dealer@abc.com", phone:"(702) 555-0144",
    dl:"NV-9900", dlState:"NV", address:"100 Dealer Blvd", city:"Las Vegas", state:"NV", zip:"89119",
    payMethod:"card", finalPayMethod:"zelle",
    depositStatus:"approved", depositOnFile:true, keepOnFile:true, whitelist:true,
    bidderNum:"BID-004",
    depositNote:"", staffNotes:"Dealer account — tax exempt on all purchases.",
    paymentComment:"",
    lienData:{first:"Auto",last:"Dealer LLC",address:"100 Dealer Blvd",city:"Las Vegas",state:"NV",zip:"89119",dl:"NV-9900",dlState:"NV"},
    lienPrefilled:true,
  },
];

// Mock customer accounts (email → account)
const MOCK_CUSTOMERS = {
  "demo@example.com": {
    id:"B-001", bidderNum:"BID-001", first:"Michael", last:"R.",
    email:"demo@example.com", phone:"(702) 555-0101", dl:"NV-7823",
    password:"demo123",
    invoices:[
      {
        id:"TGA-A001-38821", date:"Mar 25, 2026", auctionDay:"Tuesday", location:"Henderson",
        lot:"LOT 001", year:2018, make:"Honda", model:"Accord", vin:"1HGCV1F34JA012345",
        condition:"runs", mileage:82400, keyFee:0, finalBid:4200, adminFee:35.47,
        taxRate:8.375, taxExempt:false, deposit:300, status:"balance-due",
        paymentStatus:"unpaid"
      },
      {
        id:"TGA-P003-29410", date:"Mar 18, 2026", auctionDay:"Tuesday", location:"Henderson",
        lot:"LOT 003", year:2019, make:"Hyundai", model:"Elantra", vin:"5NPD84LF9KH100002",
        condition:"runs", mileage:54200, keyFee:0, finalBid:4100, adminFee:35.47,
        taxRate:8.375, taxExempt:false, deposit:300, status:"paid",
        paymentStatus:"paid"
      },
      {
        id:"TGA-P101-18823", date:"Mar 14, 2026", auctionDay:"Friday", location:"North Las Vegas",
        lot:"LOT 001", year:2015, make:"Kia", model:"Optima", vin:"5XXGM4A7XFG100005",
        condition:"runs", mileage:88100, keyFee:0, finalBid:2400, adminFee:35.47,
        taxRate:8.375, taxExempt:false, deposit:300, status:"paid",
        paymentStatus:"paid"
      },
    ]
  }
};


// ─── AUTH — DB-backed with localStorage session cache ────────────────────────
const CUSTOMERS_KEY = "tga_customers_v1";

// Legacy localStorage fallback (for offline / backward compat)
function loadCustomers(){
  try{ const s=localStorage.getItem(CUSTOMERS_KEY); return s?JSON.parse(s):{}; }catch{ return {}; }
}
function saveCustomers(db){ try{ localStorage.setItem(CUSTOMERS_KEY,JSON.stringify(db)); }catch{} }

function authRegister(form, depositMethod, keepOnFile, password){
  var email = (form.email||"").toLowerCase().trim();
  if(!email) return Promise.resolve({error:"Email required"});

  // First check if a bidder already exists with this email (prevent duplicates)
  return fetch("/api/bidders/check-duplicate",{
    method:"POST",
    headers:{"Content-Type":"application/json"},
    body:JSON.stringify({email:email})
  }).then(function(r){return r.json();}).then(function(check){
    if(check && check.exists){
      // Account already exists — don't create a duplicate, just return it
      return {ok:true, bidder:{email:email, bidderNum:check.bidderNum, alreadyExists:true}};
    }
    // Continue with creation
    return createBidder(form, depositMethod, keepOnFile, password, email);
  }).catch(function(){
    return createBidder(form, depositMethod, keepOnFile, password, email);
  });
}

function createBidder(form, depositMethod, keepOnFile, password, email){

  // Register bidder via server API. ALL methods start as pending.
  // Card → becomes confirmed only after Stripe webhook fires.
  // Zelle/Cash → becomes confirmed only after admin manually approves.
  var username = (form.username||"").trim();
  var newId = "B-"+Date.now().toString(36)+Math.random().toString(36).slice(2,5);
  var newBidderNum = "BID-"+String(Date.now()).slice(-6);

  return fetch("/api/bidders",{
    method:"POST",
    headers:{"Content-Type":"application/json"},
    body:JSON.stringify({
      id: newId,
      bidderNum: newBidderNum,
      first: form.first||"", last: form.last||"",
      email: email, phone: form.phone||"",
      username: username,
      address: form.address||"", city: form.city||"",
      state: form.state||"NV", zip: form.zip||"",
      dl: form.dl||"", dlState: form.dlState||"NV",
      depositMethod: depositMethod,
      depositStatus: "pending",
      depositAmount: 0,
      keepOnFile: keepOnFile,
      creditThreshold: null,
      registeredForAuction: true,
    })
  })
  .then(function(r){ return r.json(); })
  .then(function(bidder){
    // Create login account (fire and forget) — stores username + email for login
    fetch("/api/auth/register",{
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body:JSON.stringify({email:email, username:username, password:password||bidder.bidderNum, bidderNum:bidder.bidderNum})
    }).catch(function(){});

    var account = Object.assign({}, bidder, {
      username: username,
      password: password||"",
      invoices: [],
      registeredAt: new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}),
    });
    var db = loadCustomers();
    db[email] = account;
    saveCustomers(db);
    return {ok:true, bidder:account};
  })
  .catch(function(){
    // Fallback to localStorage if server unavailable
    var db = loadCustomers();
    var count = Object.keys(db).length;
    var bidderNum = "BID-"+String(count+1001).padStart(4,"0");
    var bidder = {
      id: "B-"+Date.now(), bidderNum: bidderNum,
      first: form.first||"", last: form.last||"",
      email: email, phone: form.phone||"",
      address: form.address||"", city: form.city||"",
      state: form.state||"NV", zip: form.zip||"",
      dl: form.dl||"", dlState: form.dlState||"NV",
      password: password||"", depositMethod: depositMethod,
      depositStatus: (depositMethod==="card")?"confirmed":"pending",
      depositAmount: 300, keepOnFile: keepOnFile,
      creditThreshold: null, invoices: [],
      registeredAt: new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}),
    };
    db[email] = bidder;
    saveCustomers(db);
    return {ok:true, bidder:bidder};
  });
}

function authLogin(email, password){
  var key = (email||"").toLowerCase().trim();

  // Use /api/v2/login which returns full bidder data + username support
  return fetch("/api/v2/login",{
    method:"POST",
    headers:{"Content-Type":"application/json"},
    body:JSON.stringify({email:key, password:password})
  })
  .then(function(res){ return res.json(); })
  .then(function(data){
    if(data.user){
      var db = loadCustomers();
      db[key] = Object.assign({}, db[key]||{}, data.user, {password:password});
      saveCustomers(db);
      return {ok:true, bidder:db[key]};
    }
    if(data.error) return {error:data.error};
    var db2 = loadCustomers();
    var bidder = db2[key];
    if(!bidder) return {error:"No account found for that email."};
    if(bidder.password !== password) return {error:"Incorrect password."};
    return {ok:true, bidder:bidder};
  })
  .catch(function(){
    var db = loadCustomers();
    var bidder = db[key];
    if(!bidder) return {error:"No account found for that email."};
    if(bidder.password !== password) return {error:"Incorrect password."};
    return {ok:true, bidder:bidder};
  });
}

function authUpdate(email, updates){
  const db = loadCustomers();
  const key = (email||"").toLowerCase().trim();
  if(!db[key]) return;
  db[key] = {...db[key], ...updates};
  saveCustomers(db);

  // Sync password changes to server
  if(updates.password){
    fetch("/api/auth/change-password",{
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body:JSON.stringify({email:key, newPassword:updates.password})
    }).catch(function(){});
  }

  return db[key];
}

function authGetCurrent(){
  try{ const s=localStorage.getItem("tga_current_user"); return s?JSON.parse(s):null; }catch{ return null; }
}
function authSetCurrent(bidder){ try{ localStorage.setItem("tga_current_user",JSON.stringify(bidder)); }catch{} }
function authClearCurrent(){ try{ localStorage.removeItem("tga_current_user"); }catch{} }

const MOCK_DISPATCH_EXPORT = [
  { wo:"TT-10520", year:2016, make:"Jeep",     model:"Grand Cherokee", vin:"1C4RJFBG0GC400001", mileage:112000, condition:"runs",     keyFee:0,   company:"titan" },
  { wo:"TT-10521", year:2014, make:"Hyundai",  model:"Sonata",         vin:"5NPE24AF0EH800002", mileage:143000, condition:"no-start", keyFee:125, company:"titan" },
  { wo:"KT-20055", year:2021, make:"Kia",      model:"Sorento",        vin:"5XYPG4A50MG300003", mileage:38000,  condition:"runs",     keyFee:0,   company:"kings" },
  { wo:"TG-09010", year:2013, make:"Dodge",    model:"Charger",        vin:"2C3CDXAT0DH400004", mileage:167000, condition:"no-start", keyFee:200, company:"tg"   },
  { wo:"ABC-44210",year:2018, make:"Mercedes", model:"C300",           vin:"55SWF4JB0JU100005", mileage:75400,  condition:"runs",     keyFee:450, company:"abc"  },
];

// ─── UTILS ────────────────────────────────────────────────────────────────────
function fmtTime(ms) {
  if(ms<=0) return {h:"00",m:"00",s:"00",done:true};
  const s=Math.floor(ms/1000),h=Math.floor(s/3600),m=Math.floor((s%3600)/60),sec=s%60;
  return {h:String(h).padStart(2,"0"),m:String(m).padStart(2,"0"),s:String(sec).padStart(2,"0"),done:false};
}
function fmtCurrency(n){ return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(n||0); }
function genId(){ return "A"+Math.random().toString(36).slice(2,7).toUpperCase(); }
function genLot(n){ return `LOT ${String(n+1).padStart(3,"0")}`; }
function useCountdowns(auctions){
  const [now,setNow]=useState(Date.now());
  useEffect(()=>{const t=setInterval(()=>setNow(Date.now()),1000);return()=>clearInterval(t);},[]);
  return auctions.map(a=>fmtTime(a.closeTime-now));
}

// ─── CSS (moved to app.css) ───────────────────────────────────────────────────
const CSS=""; // CSS loaded via <link> in index.html
// ─── INVOICE MODAL ────────────────────────────────────────────────────────────
function InvoiceModal({auction, feeSettings, onClose, onNotify}){
  const invNum = `TGA-${auction.id}-${Date.now().toString().slice(-5)}`;
  const finalBid   = auction.currentBid || auction.minBid;
  const keyFee     = auction.keyFee || 0;
  const adminFee   = feeSettings.adminFee;
  const taxRate    = feeSettings.taxRate;
  const taxExempt  = auction.taxExempt;
  const deposit    = 300;
  const [sameDayDisc, setSameDayDisc] = useState(false);
  const DISC_AMT = 20;

  const taxable    = finalBid + keyFee + adminFee;
  const taxAmt     = taxExempt ? 0 : +(taxable * taxRate / 100).toFixed(2);
  const discount   = sameDayDisc ? DISC_AMT : 0;
  const total      = Math.max(0, taxable + taxAmt - discount);
  const balanceDue = total - deposit;

  return <div className="modal-bg"><div className="modal wide">
    <div className="inv-header">
      <div>
        <div className="inv-company">Tow Guys Auto Auction</div>
        <div className="inv-company-sub">
          250 W Warm Springs Rd, Henderson, NV 89011<br/>
          3823 Losee Rd, North Las Vegas, NV 89030<br/>
          (702) 677-0792 · towguysautoauction.com
        </div>
      </div>
      <div className="inv-num-block">
        <div className="inv-num-label">Invoice</div>
        <div className="inv-num">{invNum}</div>
        <div className="inv-date">{new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}</div>
      </div>
    </div>

    <div className="mbody">
      {/* Vehicle info */}
      <div className="inv-vehicle">
        {auction.photos?.[0]
          ? <img className="inv-thumb" src={auction.photos[0]} alt=""/>
          : <div className="inv-thumb" style={{display:"flex",alignItems:"center",justifyContent:"center",color:"var(--muted)",fontSize:"1.3rem"}}>📷</div>}
        <div className="inv-vehicle-info">
          <div className="inv-vehicle-name">{auction.year} {auction.make} {auction.model}</div>
          <div className="inv-vehicle-meta">
            {auction.lot} · VIN: {auction.vin}<br/>
            {(auction.mileage||0).toLocaleString()} mi · {auction.condition==="runs"?"Runs":"No Start"}{keyFee>0?` · Key Fee Required`:""}
          </div>
        </div>
        <div>
          <CoBadge id={auction.company}/>
          {taxExempt&&<div className="inv-exempt-badge" style={{marginTop:".3rem"}}>TAX EXEMPT</div>}
        </div>
      </div>

      {/* Fee table */}
      <table className="inv-table">
        <thead><tr><th>Description</th><th style={{textAlign:"right"}}>Amount</th></tr></thead>
        <tbody>
          <tr><td><strong>Winning Bid</strong></td><td style={{textAlign:"right"}}>{fmtCurrency(finalBid)}</td></tr>
          {keyFee>0&&<tr><td>Key Fee<br/><span style={{fontSize:".72rem",color:"var(--muted)"}}>Key replacement required</span></td><td style={{textAlign:"right"}}>{fmtCurrency(keyFee)}</td></tr>}
          <tr><td>Admin Fee</td><td style={{textAlign:"right"}}>{fmtCurrency(adminFee)}</td></tr>
          {!taxExempt
            ? <tr><td>Sales Tax <span style={{fontSize:".72rem",color:"var(--muted)"}}>({taxRate}%)</span></td><td style={{textAlign:"right"}}>{fmtCurrency(taxAmt)}</td></tr>
            : <tr><td>Sales Tax <span className="inv-exempt-badge" style={{marginLeft:".4rem"}}>EXEMPT</span></td><td style={{textAlign:"right",color:"var(--green)"}}>—</td></tr>}
          {discount>0&&<tr style={{color:"var(--green)"}}><td><strong>Same-Day Payment Discount</strong></td><td style={{textAlign:"right"}}>−{fmtCurrency(discount)}</td></tr>}
          <tr><td style={{color:"var(--green)",fontWeight:600}}>Deposit Applied</td><td style={{textAlign:"right",color:"var(--green)"}}>−{fmtCurrency(deposit)}</td></tr>
        </tbody>
      </table>

      {/* Totals */}
      <div style={{display:"flex",justifyContent:"flex-end"}}>
        <div className="inv-totals">
          <div className="inv-total-row"><span>Subtotal</span><span>{fmtCurrency(finalBid+keyFee+adminFee)}</span></div>
          <div className="inv-total-row"><span>Tax ({taxExempt?"Exempt":`${taxRate}%`})</span><span>{taxExempt?"—":fmtCurrency(taxAmt)}</span></div>
          {discount>0&&<div className="inv-total-row" style={{color:"var(--green)"}}><span>Same-Day Discount</span><span>−{fmtCurrency(discount)}</span></div>}
          <div className="inv-total-row"><span>Total</span><span>{fmtCurrency(total)}</span></div>
          <div className="inv-total-row"><span>Deposit</span><span style={{color:"var(--green)"}}>−{fmtCurrency(deposit)}</span></div>
          <div className="inv-total-row grand"><span>Balance Due</span><span>{fmtCurrency(balanceDue)}</span></div>
        </div>
      </div>

      {/* Discount + Tax exemption toggles */}
      <div style={{marginTop:"1rem",padding:".75rem 1rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",display:"flex",alignItems:"center",gap:"1.5rem",flexWrap:"wrap"}}>
        <label style={{display:"flex",alignItems:"center",gap:".5rem",cursor:"pointer",fontSize:".83rem",fontWeight:500}}>
          <input type="checkbox" checked={sameDayDisc} onChange={function(){setSameDayDisc(function(v){return !v;});}} style={{width:15,height:15,accentColor:"var(--green)"}}/>
          <span style={{color:sameDayDisc?"var(--green)":"inherit"}}>Same-day payment discount (−${DISC_AMT})</span>
        </label>
        <label style={{display:"flex",alignItems:"center",gap:".5rem",cursor:"pointer",fontSize:".83rem",fontWeight:500}}>
          <input type="checkbox" checked={taxExempt} readOnly style={{width:15,height:15,accentColor:"var(--accent)"}}/>
          Customer has tax exemption certificate
        </label>
        <span style={{fontSize:".72rem",color:"var(--muted)",marginLeft:"auto"}}>Toggle in lot settings to update invoice</span>
      </div>
    </div>

    <div className="mfoot" style={{justifyContent:"space-between",flexWrap:"wrap",gap:".5rem"}}>
      <button className="btn-g" onClick={onClose}>Close</button>
      <div style={{display:"flex",gap:".6rem"}}>
        <button className="btn-p" style={{background:"var(--green)"}} onClick={()=>window.print()}>🖨 Print / PDF</button>
        <button className="btn-p" onClick={onNotify}>📨 Send to Customer →</button>
      </div>
    </div>
  </div></div>;
}

// ─── NOTIFY MODAL ─────────────────────────────────────────────────────────────
function NotifyModal({auction, feeSettings, onClose}){
  const [methods,setMethods]=useState({email:true,sms:false});
  const [sent,setSent]=useState(false);
  const toggle=k=>setMethods(m=>({...m,[k]:!m[k]}));
  const finalBid=auction.currentBid||auction.minBid;
  const keyFee=auction.keyFee||0;
  const adminFee=feeSettings.adminFee;
  const taxRate=feeSettings.taxRate;
  const taxAmt=auction.taxExempt?0:+((finalBid+keyFee+adminFee)*taxRate/100).toFixed(2);
  const balanceDue=(finalBid+keyFee+adminFee+taxAmt)-300;

  const emailPreview=`Subject: Your Winning Bid – ${auction.lot} | ${auction.year} ${auction.make} ${auction.model}

Hi [Bidder Name],

Congratulations! You won ${auction.lot} at the Tow Guys Auto Auction.

Vehicle: ${auction.year} ${auction.make} ${auction.model}
VIN: ${auction.vin}
Winning Bid: ${fmtCurrency(finalBid)}
Admin Fee: ${fmtCurrency(adminFee)}${keyFee>0?`\nKey Fee: ${fmtCurrency(keyFee)}`:""}
Sales Tax: ${auction.taxExempt?"Exempt":fmtCurrency(taxAmt)}
Deposit Applied: −${fmtCurrency(300)}
──────────────────
Balance Due: ${fmtCurrency(balanceDue)}

Please contact us within 48 hours to arrange pickup.
(702) 677-0792 · towguysautoauction.com`;

  const smsPreview=`TowGuys Auction: Congrats! You won LOT ${auction.lot.replace("LOT ","")} – ${auction.year} ${auction.make} ${auction.model}. Balance due: ${fmtCurrency(balanceDue)}. Call (702) 677-0792 to arrange pickup.`;

  if(sent) return <div className="modal-bg"><div className="modal"><div className="mbody" style={{padding:"2.5rem",textAlign:"center"}}>
    <div className="succ-icon">📨</div>
    <div className="succ-title">Notification Sent!</div>
    <p style={{color:"var(--muted)",fontSize:".84rem",marginBottom:"1.4rem",lineHeight:1.6}}>
      {methods.email&&"Email sent with full invoice PDF. "}
      {methods.sms&&"SMS sent with balance summary."}
    </p>
    <button className="btn-p" style={{width:"100%"}} onClick={onClose}>Done</button>
  </div></div></div>;

  return <div className="modal-bg"><div className="modal wide">
    <div className="mhd"><div><div className="mtitle">Send Invoice to Customer</div><div className="msub">{auction.lot} · {auction.year} {auction.make} {auction.model}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="fsec-title" style={{marginBottom:".7rem"}}>Delivery Method</div>
      {[{k:"email",icon:"📧",label:"Email",sub:"Full invoice with PDF attachment"},{k:"sms",icon:"📱",label:"SMS / Text",sub:"Short summary with balance due"}].map(m=><div key={m.k} className={`notify-method${methods[m.k]?" sel":""}`} onClick={()=>toggle(m.k)}>
        <span style={{fontSize:"1.4rem"}}>{m.icon}</span>
        <div style={{flex:1}}><div style={{fontWeight:600,fontSize:".88rem"}}>{m.label}</div><div style={{fontSize:".72rem",color:"var(--muted)"}}>{m.sub}</div></div>
        <input type="checkbox" checked={methods[m.k]} readOnly style={{width:15,height:15,accentColor:"var(--accent)"}}/>
      </div>)}

      {methods.email&&<><div className="fsec-title" style={{margin:"1rem 0 .5rem"}}>Email Preview</div><div className="notify-preview">{emailPreview}</div></>}
      {methods.sms&&<><div className="fsec-title" style={{margin:"1rem 0 .5rem"}}>SMS Preview</div><div className="notify-preview">{smsPreview}</div></>}

      <div className="notice info" style={{marginBottom:0}}>
        <strong>In production:</strong> Email sends via SendGrid/Brevo with attached PDF invoice. SMS sends via Twilio (same number as your AI answering service).
      </div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Cancel</button>
      <button className="btn-p" disabled={!methods.email&&!methods.sms} onClick={()=>setSent(true)}>
        Send {[methods.email&&"Email",methods.sms&&"SMS"].filter(Boolean).join(" + ")} →
      </button>
    </div>
  </div></div>;
}

// ─── LOT COMMENTS PANEL ───────────────────────────────────────────────────────
function LotComments({auction, onAddComment}){
  const [text,setText]=useState("");
  const [staffName]=useState("Staff");
  const submit=()=>{
    if(!text.trim()) return;
    const now=new Date();
    const ts=now.toLocaleDateString("en-US",{month:"short",day:"numeric"})+" · "+now.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});
    onAddComment(auction.id,{id:"c"+Date.now(),staff:staffName,text:text.trim(),ts});
    setText("");
  };
  const comments=auction.comments||[];
  return <div style={{marginTop:".75rem",borderTop:"1px solid var(--border)",paddingTop:".75rem"}}>
    <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".5rem"}}>Staff Notes</div>
    {comments.length===0&&<div style={{fontSize:".75rem",color:"var(--muted)",marginBottom:".5rem",fontStyle:"italic"}}>No notes yet.</div>}
    <div style={{maxHeight:"140px",overflowY:"auto"}}>
      {comments.map(c=><div key={c.id} className="comment-item">
        <div className="comment-avatar">{c.staff.slice(0,2).toUpperCase()}</div>
        <div className="comment-body">
          <div className="comment-meta"><span className="comment-staff">{c.staff}</span><span className="comment-ts">{c.ts}</span></div>
          <div className="comment-text">{c.text}</div>
        </div>
      </div>)}
    </div>
    <div className="comment-input-row">
      <input className="finput" style={{flex:1,fontSize:".78rem"}} placeholder="Add note…" value={text} onChange={e=>setText(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
      <button className="btn-p" style={{flex:"0 0 auto",padding:".4rem .8rem",fontSize:".78rem"}} onClick={submit}>Post</button>
    </div>
  </div>;
}

// ─── SMALL UI COMPONENTS ──────────────────────────────────────────────────────
function CoBadge({id}){
  const c=COMPANY_MAP[id]; if(!c) return null;
  return <span className="co-badge" style={{background:c.color+"18",color:c.color,border:`1px solid ${c.color}33`}}><span style={{width:5,height:5,borderRadius:"50%",background:c.color,display:"inline-block"}}/>{c.label}</span>;
}
function CoSelect({value,onChange,cls=""}){
  return <select className={`finput fselect ${cls}`} value={value} onChange={e=>onChange(e.target.value)}><option value="">— Company —</option>{COMPANIES.map(c=><option key={c.id} value={c.id}>{c.label}</option>)}</select>;
}
function DispatchLink({auction}){
  const c=COMPANY_MAP[auction.company]; if(!c||!auction.wo) return null;
  return <a className="dispatch-link" href={`${c.dispatchUrl}/orders/${auction.wo}#lien`} target="_blank" rel="noopener noreferrer" onClick={e=>e.stopPropagation()}><span className="pulse"/>{c.label} · Lien Tab</a>;
}
function PhotoCarousel({photos}){
  const [idx,setIdx]=useState(0);
  useEffect(()=>{if(idx>=(photos||[]).length) setIdx(0);},[photos]);
  if(!photos||photos.length===0) return <div className="photo-wrap"><div className="photo-empty"><div style={{fontSize:"1.8rem",opacity:.3}}>📷</div><div style={{fontSize:".7rem",fontFamily:"DM Mono,monospace"}}>No photos</div></div></div>;
  const next=e=>{e.stopPropagation();setIdx(i=>(i+1)%photos.length);};
  const prev=e=>{e.stopPropagation();setIdx(i=>(i-1+photos.length)%photos.length);};
  return <div className="photo-wrap"><img src={photos[idx]} alt=""/>{photos.length>1&&<><button className="photo-arr prev" onClick={prev}>‹</button><button className="photo-arr next" onClick={next}>›</button></>}<div className="photo-nav">{photos.map((_,i)=><div key={i} className={`photo-dot${i===idx?" active":""}`} onClick={e=>{e.stopPropagation();setIdx(i);}}/>)}</div><div className="photo-cnt">{photos.length} photo{photos.length!==1?"s":""}</div></div>;
}
function Countdown({time, isOvertime}){
  if(time.done) return <span style={{fontSize:".75rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}}>CLOSED</span>;
  const hot=time.h==="00"&&time.m<"10";
  const closingSoon = time.h==="00" && time.m==="00";
  return <div className={`timer${hot?" hot":""}`}>
    {time.h!=="00"&&<><div className="timer-seg"><div className="timer-num">{time.h}</div><div className="timer-lbl">hr</div></div><span className="timer-col">:</span></>}
    <div className="timer-seg"><div className="timer-num">{time.m}</div><div className="timer-lbl">min</div></div>
    <span className="timer-col">:</span>
    <div className="timer-seg"><div className="timer-num">{time.s}</div><div className="timer-lbl">sec</div></div>
    {isOvertime&&<div style={{marginTop:".25rem",padding:".12rem .4rem",background:"#dc2626",color:"#fff",borderRadius:3,fontSize:".5rem",fontWeight:800,letterSpacing:".04em",fontFamily:"DM Mono,monospace",textAlign:"center",lineHeight:1}}>⏱ OVERTIME</div>}
  </div>;
}
function PhotoSlots({photos,onChange}){
  const p=photos||[]; const cnt=p.length;
  const st=cnt===0?"err":cnt<4?"warn":"ok";
  const stTxt=cnt===0?"⚠ No photos":cnt<4?`⚠ ${cnt}/4`:"✓ 4 photos";
  const click=i=>{const inp=document.createElement("input");inp.type="file";inp.accept="image/*";inp.onchange=e=>{const f=e.target.files[0];if(!f)return;const n=[...p];n[i]=URL.createObjectURL(f);onChange(n.filter(Boolean));};inp.click();};
  return <div><div className={`photo-status ${st}`}>{stTxt}</div><div className="photo-grid4">{[0,1,2,3].map(i=><div key={i} className="pslot" onClick={()=>!p[i]&&click(i)}>{p[i]?<><img src={p[i]} alt=""/><button className="pslot-rm" onClick={e=>{e.stopPropagation();const n=[...p];n.splice(i,1);onChange(n);}}>×</button></>:<div className="pslot-empty"><span style={{fontSize:".95rem",opacity:.3}}>+</span><span>Photo {i+1}</span></div>}</div>)}</div></div>;
}

// ─── AUCTION CARD ──────────────────────────────────────────────────────────────
function AuctionCard({auction, time, onBid, onBuyNow, onMakeOffer, onWatch, onRegister, bidderStatus, myProxy, watching, t=k=>k}){
  const hot=!time.done&&time.h==="00"&&time.m<"10";
  const canBid = bidderStatus==="approved";
  const nextBidAmt = Math.max(auction.minBid||0, (auction.currentBid||0) + (auction.increment||50));
  const btnText = time.done?t("card_closed"):!bidderStatus?t("card_register"):bidderStatus==="pending"?t("card_awaiting"):("Bid "+fmtCurrency(nextBidAmt));

  // Proxy status for this bidder on this lot
  const proxyActive = myProxy && myProxy > 0;
  const currentBid = auction.currentBid||auction.minBid;
  const myNum = (typeof authGetCurrent==="function" && authGetCurrent())?authGetCurrent().bidderNum:null;
  // Use winner (persisted in DB) as source of truth — leader is local-only and gets wiped by polling
  const currentLeader = auction.winner || auction.leader;
  const isLeading = myNum && currentLeader===myNum;
  const hasBidOnLot = myNum && (myProxy > 0 || (auction.bidHistory||[]).some(function(h){return h.bidderNum===myNum;}));
  const isOutbid = myNum && hasBidOnLot && currentLeader!==myNum && !time.done && !auction.sold;
  const lastBid = isOutbid && (auction.bidHistory||[]).length > 0 ? (auction.bidHistory||[])[(auction.bidHistory||[]).length - 1] : null;
  const outbidByMax = isOutbid && lastBid && lastBid.isAutoBid;

  const auctionEnded = auction.sold || time.done;
  return <div className={`card${hot?" closing-soon":""}${auctionEnded?" closed":""}`}>
    <div className="lot-tag">{auction.lot}</div>
    {auctionEnded&&<div style={{position:"absolute",top:"80px",right:"10px",zIndex:6,background:"rgba(0,0,0,.8)",color:"#fff",padding:".45rem 1rem",borderRadius:5,fontSize:".82rem",fontWeight:800,fontFamily:"Bebas Neue,sans-serif",letterSpacing:".08em",pointerEvents:"none",whiteSpace:"nowrap"}}>AUCTION ENDED</div>}
    <PhotoCarousel photos={auction.photos}/>
    <div className="card-body">
      <div style={{display:"flex",alignItems:"center",gap:".5rem",flexWrap:"wrap",marginBottom:".15rem"}}>
        <div className="car-name" style={{marginBottom:0}}>{auction.year} {auction.make} {auction.model}</div>
        {auction.condition&&<span style={{padding:".15rem .55rem",borderRadius:4,fontSize:".72rem",fontWeight:700,fontFamily:"DM Mono,monospace",letterSpacing:".03em",background:auction.condition==="runs"?"rgba(21,128,61,.12)":"rgba(220,38,38,.12)",color:auction.condition==="runs"?"#15803d":"#dc2626",border:"1px solid "+(auction.condition==="runs"?"rgba(21,128,61,.3)":"rgba(220,38,38,.3)")}}>{auction.condition==="runs"?t("card_runs"):t("card_no_start")}</span>}
      </div>
      <div style={{marginBottom:".35rem"}}><TitleBadge type={auction.titleType||"lien"}/></div>
      <div className="vin-txt">VIN: {auction.vin}</div>
      {auction.conditionNotes&&<div style={{margin:".4rem 0",padding:".45rem .6rem",background:"rgba(0,48,135,.04)",border:"1px solid var(--border)",borderRadius:5,fontSize:".8rem",color:"var(--text)",lineHeight:1.45}}>{auction.conditionNotes}</div>}
      <div className="meta-row">
        <div><div className="meta-lbl">{t("card_mileage")}</div><div className="meta-val">{(function(){var m=auction.mileage;if(!m||m==="0"||m===0)return "—";var ml=String(m).toLowerCase();if(ml.indexOf("unknown")>=0||ml.indexOf("exempt")>=0)return String(m);return (+m>0?(+m).toLocaleString()+" mi":String(m));})()}</div></div>
        <div><div className="meta-lbl">{t("card_key_fee")}</div><div className={`meta-val${auction.keyFee>0?" warn":""}`}>{auction.keyFee>0?fmtCurrency(auction.keyFee):"—"}</div></div>
        <div><div className="meta-lbl">{t("card_increment")}</div><div className="meta-val green">{fmtCurrency(auction.increment)}</div></div>
        <div><div className="meta-lbl">{t("card_bids")}</div><div className="meta-val">{auction.bids}</div></div>
      </div>
      <hr className="divider"/>
      <div className="bid-row">
        <div>
          <div className="bid-lbl">{t("card_current_bid")}</div>
          <div style={{display:"flex",alignItems:"center",gap:".45rem",flexWrap:"wrap"}}>
            <div className="bid-amt">{fmtCurrency(currentBid)}</div>
            {isLeading&&!auction.sold&&<span style={{background:"#15803d",color:"#fff",padding:".18rem .5rem",borderRadius:3,fontSize:".62rem",fontWeight:700,fontFamily:"DM Mono,monospace",letterSpacing:".04em",whiteSpace:"nowrap",boxShadow:"0 1px 4px rgba(21,128,61,.4)"}}>✓ YOU'RE THE HIGHEST BIDDER</span>}
            {isOutbid&&<span style={{background:"#ea580c",color:"#fff",padding:".18rem .5rem",borderRadius:3,fontSize:".62rem",fontWeight:700,fontFamily:"DM Mono,monospace",letterSpacing:".04em",whiteSpace:"nowrap",boxShadow:"0 1px 4px rgba(234,88,12,.4)"}}>{outbidByMax?"⚠ OUTBID BY MAX BID":"⚠ YOU'VE BEEN OUTBID"}</span>}
          </div>
          <div className="bid-min">Next Bid: {fmtCurrency(nextBidAmt)}</div>
        </div>
        <div style={{textAlign:"right"}}>
          <Countdown time={time} isOvertime={!!(auction.overtimeTriggered||auction.overtime_triggered)}/>
        </div>
      </div>

      {/* Auto-bid status — ONLY shown to the bidder who set it (myProxy is local to their browser) */}
      {proxyActive&&!isLeading&&<div className="proxy-status active" style={{background:"rgba(29,78,216,.08)",border:"1px solid rgba(29,78,216,.3)",color:"var(--blue)",padding:".35rem .75rem",borderRadius:5,fontSize:".75rem",marginBottom:".5rem"}}>
        🤖 Your auto-bid is active (max ${myProxy})
      </div>}
      {proxyActive&&isLeading&&<div className="proxy-status leading" style={{background:"rgba(21,128,61,.08)",border:"1px solid rgba(21,128,61,.3)",color:"var(--green)",padding:".35rem .75rem",borderRadius:5,fontSize:".75rem",marginBottom:".5rem"}}>
        ✓ You're leading (your max: ${myProxy})
      </div>}

      {!time.done&&!auction.sold&&canBid&&<button className="bid-btn" style={{background:"#1d4ed8",marginBottom:".4rem"}} onClick={(e)=>{e.stopPropagation();onBid({...(e||{}),autoBid:true});}}>🤖 Place Auto-Bid (Set Max)</button>}
      <button className="bid-btn" disabled={time.done} onClick={(e)=>{e.stopPropagation();if(!bidderStatus&&onRegister){onRegister();}else if(canBid){onBid(e);}}}>{btnText}</button>
      {onWatch&&<div className="watchlist-bar"><WatchButton auction={auction} watching={!!watching} onToggle={onWatch}/></div>}
      {!time.done&&!auction.sold&&<button className="offer-btn" onClick={(e)=>{e.stopPropagation();onMakeOffer(e);}}>{t("card_make_offer")}</button>}
    </div>
  </div>;
}

// ─── REGISTRATION + DEPOSIT MODAL ─────────────────────────────────────────────
function DepositModal({onClose,onSuccess,existingCustomer=null}){
  // Already-approved bidders see a friendly message — can't register twice for same auction
  const isAlreadyApproved = existingCustomer && (
    existingCustomer.whitelist ||
    ((existingCustomer.depositStatus==="confirmed"||existingCustomer.depositStatus==="applied") && existingCustomer.depositAppliedTo==null) ||
    (existingCustomer.keepOnFile && existingCustomer.depositStatus==="confirmed")
  );
  if(isAlreadyApproved){
    return <div className="modal-bg"><div className="modal">
      <div className="mhd">
        <div><div className="mtitle">Already Registered</div><div className="msub">You're approved for this auction</div></div>
        <button className="mclose" onClick={onClose}>×</button>
      </div>
      <div className="mbody" style={{padding:"2.5rem",textAlign:"center"}}>
        <div style={{fontSize:"3rem",marginBottom:".75rem"}}>✓</div>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:"var(--green)",marginBottom:".5rem"}}>You're Approved to Bid!</div>
        <div style={{fontSize:".88rem",color:"var(--muted)",lineHeight:1.6,marginBottom:"1rem"}}>
          {existingCustomer.whitelist
            ? "You're a whitelisted VIP — no deposit needed."
            : "Your deposit is on file and you can bid on any lot."}
        </div>
        <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:6,padding:".85rem 1rem",marginBottom:"1rem",fontSize:".82rem"}}>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:".25rem"}}>
            <span style={{color:"var(--muted)"}}>Bidder #</span>
            <strong>{existingCustomer.bidderNum||"—"}</strong>
          </div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:".25rem"}}>
            <span style={{color:"var(--muted)"}}>Status</span>
            <strong style={{color:"var(--green)"}}>Approved ✓</strong>
          </div>
          {existingCustomer.depositMethod&&<div style={{display:"flex",justifyContent:"space-between"}}>
            <span style={{color:"var(--muted)"}}>Deposit Method</span>
            <strong>{({card:"💳 Credit Card","card-office":"🏢 CC Office",zelle:"💸 Zelle",cash:"💵 Cash",arrange:"🤝 Staff",none:"🏷 No Deposit"})[existingCustomer.depositMethod]||existingCustomer.depositMethod}</strong>
          </div>}
        </div>
        <button className="btn-p" style={{width:"100%"}} onClick={onClose}>Continue Bidding →</button>
      </div>
    </div></div>;
  }
  // If logged in (existingCustomer), skip step 1 (personal info) and go straight to deposit
  const [step,setStep]=useState(existingCustomer ? 2 : 1);
  const [depositMethod,setDepositMethod]=useState("card");
  const [finalPayMethod,setFinalPayMethod]=useState("card");
  const [keepOnFile,setKeepOnFile]=useState(true);
  const [regError,setRegError]=useState("");
  const [ccAuthorized,setCcAuthorized]=useState(false);
  const [form,setForm]=useState({
    first:existingCustomer?.first||"",last:existingCustomer?.last||"",
    email:existingCustomer?.email||"",phone:existingCustomer?.phone||"",
    address:existingCustomer?.address||"",city:existingCustomer?.city||"",
    state:existingCustomer?.state||"NV",zip:existingCustomer?.zip||"",
    dl:existingCustomer?.dl||"",dlState:existingCustomer?.dlState||"NV",
    username:existingCustomer?.username||"",
    name:"",card:"",exp:"",cvv:"",
    password:"",password2:""
  });
  const set=k=>e=>setForm(f=>({...f,[k]:e.target.value}));
  // "card" goes to Stripe immediately. All others need staff approval.
  const needsApproval=depositMethod!=="card";
  const isCardMethod = depositMethod==="card"||depositMethod==="card-office";
  const noDeposit = depositMethod==="arrange";
  const baseDeposit = noDeposit ? 0 : 300;
  const ccFee = isCardMethod ? +(baseDeposit * CC_FEE_RATE / 100).toFixed(2) : 0;
  const depositTotal = baseDeposit + ccFee;

  if(step===3){
    return <div className="modal-bg"><div className="modal">
      <div className="mbody" style={{padding:"2.5rem"}}>
        <div className="succ-icon">{needsApproval?"⏳":"✓"}</div>
        <div className="succ-title">{needsApproval?"Pending Approval":"Deposit Confirmed"}</div>
        <p style={{textAlign:"center",color:"var(--muted)",fontSize:".84rem",marginBottom:"1.4rem",lineHeight:1.6}}>
          {needsApproval
            ?<>Your registration is received. {depositMethod==="arrange"
              ?<>Please call <strong style={{color:"var(--accent)"}}>(702) 677-0792</strong> to make deposit arrangements with our staff. Your account will be activated once confirmed.</>
              :<>Our office will verify your <strong style={{color:"var(--accent)"}}>{depositMethod==="zelle"?"Zelle payment":depositMethod==="card-office"?"in-person card swipe":"cash deposit"}</strong> and activate your account within 1 business hour.</>
            }</>
            :<>Your ${depositTotal.toFixed(2)} deposit is confirmed. You are approved to bid.{keepOnFile&&<><br/><strong style={{color:"var(--green)"}}>Deposit stays on file</strong> until you win.</>}</>}
        </p>
        {/* Final payment reminder */}
        <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:".85rem 1rem",marginBottom:"1rem",fontSize:".82rem"}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".35rem"}}>Your Payment Plan</div>
          <div style={{display:"flex",justifyContent:"space-between",marginBottom:".25rem"}}>
            <span style={{color:"var(--muted)"}}>Deposit ({(PAY_METHODS.find(p=>p.id===depositMethod)||{}).label||depositMethod})</span>
            <span style={{fontWeight:600}}>{noDeposit?"TBD":"$"+depositTotal.toFixed(2)}</span>
          </div>
          <div style={{display:"flex",justifyContent:"space-between"}}>
            <span style={{color:"var(--muted)"}}>Balance if you win ({finalPayMethod==="card"?"Credit Card":finalPayMethod==="zelle"?"Zelle":"Cash"})</span>
            <span style={{fontWeight:600,color:"var(--accent)"}}>TBD</span>
          </div>
        </div>
        {regError&&<div style={{background:"rgba(220,38,38,.08)",border:"1px solid rgba(220,38,38,.3)",borderRadius:6,padding:".75rem 1rem",marginBottom:"1rem",fontSize:".85rem",color:"#dc2626",lineHeight:1.5}}>
          <div style={{fontWeight:700,marginBottom:".25rem"}}>Account Already Exists</div>
          <div>An account with this email is already registered. Please <strong>Sign In</strong> instead. If you forgot your password, use <strong>Forgot Password</strong> on the sign-in screen.</div>
          <button className="btn-p" style={{width:"100%",marginTop:".75rem",fontSize:".85rem"}} onClick={function(){onClose();}}>Go to Sign In</button>
        </div>}
        {!regError&&depositMethod==="card"&&React.createElement("div",{style:{marginBottom:"1rem",padding:".75rem",background:"rgba(0,48,135,.04)",border:"1px solid var(--border)",borderRadius:6}},
          React.createElement("label",{style:{display:"flex",alignItems:"flex-start",gap:".6rem",cursor:"pointer"}},
            React.createElement("input",{type:"checkbox",checked:ccAuthorized,onChange:function(){setCcAuthorized(function(v){return !v;});},style:{width:18,height:18,flexShrink:0,marginTop:2,accentColor:"var(--accent)"}}),
            React.createElement("div",{style:{fontSize:".78rem",color:"#444",lineHeight:1.6}},
              "I authorize Tow Guys Auto Auction and acknowledge that I am giving consent to run my credit card for the payment of ",React.createElement("strong",null,"$300.00 (+ 3.5% CC fee)")," as a refundable deposit. I agree not to dispute the charges and understand that all vehicles are sold \"as-is\", no warranty applied."
            )
          )
        )}
        {!regError&&!needsApproval&&<button className="btn-p" style={{width:"100%",opacity:depositMethod==="card"&&!ccAuthorized?.5:1}} disabled={depositMethod==="card"&&!ccAuthorized} onClick={()=>{
          setRegError("");
          authRegister(form, depositMethod, keepOnFile, form.password).then(function(res){
            if(res.ok && res.bidder && res.bidder.alreadyExists){ setRegError("exists"); return; }
            var acct = res.ok ? res.bidder : Object.assign({}, form, {depositMethod:depositMethod, depositStatus:"pending", depositAmount:0, keepOnFile:keepOnFile, invoices:[]});
            authSetCurrent(acct);
            if(depositMethod==="card"){
              startStripeCheckout(form.email, acct.bidderNum||"", "deposit").then(function(stripeRes){
                if(stripeRes.error){
                  onSuccess();
                }
              });
              return;
            }
            onSuccess();
          });
        }}>{depositMethod==="card"?"Continue to Payment →":"Submit Registration"}</button>}
        {!regError&&needsApproval&&<button className="btn-g" style={{width:"100%"}} onClick={()=>{
          setRegError("");
          authRegister(form, depositMethod, keepOnFile, form.password).then(function(res){
            if(res.ok && res.bidder && res.bidder.alreadyExists){ setRegError("exists"); return; }
            var acct = res.ok ? Object.assign({}, res.bidder, {depositStatus:"pending", depositAmount:0}) : Object.assign({}, form, {depositMethod:depositMethod, depositStatus:"pending", depositAmount:0, keepOnFile:keepOnFile, invoices:[]});
            authSetCurrent(acct);
            onClose();
          });
        }}>Got It — I'll wait for confirmation</button>}
      </div>
    </div></div>;
  }

  return <div className="modal-bg"><div className="modal">
    <div className="mhd">
      <div>
        <div className="mtitle">{existingCustomer?"Register for Today's Auction":"Register & Deposit"}</div>
        <div className="msub">{existingCustomer
          ?"Choose your deposit method for this auction"
          :("Step "+step+" of 2 — "+(step===1?"Your Information":"Deposit & Payment Preferences"))}</div>
      </div>
      <button className="mclose" onClick={onClose}>×</button>
    </div>
    <div className="mbody">
      {step===1&&<>
        <div className="fsec">
          <div className="fsec-title">Personal Information</div>
          <div className="frow">
            <div className="fgrp"><label className="flbl">First Name</label><input className="finput" value={form.first} onChange={set("first")}/></div>
            <div className="fgrp"><label className="flbl">Last Name</label><input className="finput" value={form.last} onChange={set("last")}/></div>
          </div>
          <div className="frow">
            <div className="fgrp"><label className="flbl">Email</label><input className="finput" type="email" value={form.email} onChange={set("email")}/></div>
            <div className="fgrp"><label className="flbl">Phone</label><input className="finput" type="tel" value={form.phone} onChange={set("phone")}/></div>
          </div>
          <div className="frow s">
            <div className="fgrp"><label className="flbl">Street Address</label><input className="finput" placeholder="123 Main St" value={form.address} onChange={set("address")}/></div>
          </div>
          <div className="frow t">
            <div className="fgrp"><label className="flbl">City</label><input className="finput" value={form.city} onChange={set("city")}/></div>
            <div className="fgrp"><label className="flbl">State</label><select className="finput fselect" value={form.state} onChange={set("state")}>{["NV","CA","AZ","UT","TX","FL","OR","WA"].map(s=><option key={s}>{s}</option>)}</select></div>
            <div className="fgrp"><label className="flbl">Zip</label><input className="finput" value={form.zip} onChange={set("zip")}/></div>
          </div>
        </div>
        <div className="fsec">
          <div className="fsec-title">Driver's License (required for lien sale records)</div>
          <div className="frow">
            <div className="fgrp"><label className="flbl">DL Number</label><input className="finput" value={form.dl} onChange={set("dl")}/></div>
            <div className="fgrp"><label className="flbl">State</label><select className="finput fselect" value={form.dlState} onChange={set("dlState")}>{["NV","CA","AZ","UT","TX","FL","OR","WA"].map(s=><option key={s}>{s}</option>)}</select></div>
          </div>
        </div>
        <div className="fsec">
          <div className="fsec-title">Login Credentials</div>
          <div className="frow s">
            <div className="fgrp"><label className="flbl">Username</label><input className="finput" placeholder="Choose a username" value={form.username} onChange={set("username")} style={{fontFamily:"DM Mono,monospace"}}/></div>
          </div>
          <div className="frow">
            <div className="fgrp"><label className="flbl">Password</label><input className="finput" type="password" placeholder="Min 6 characters" value={form.password} onChange={set("password")}/></div>
            <div className="fgrp"><label className="flbl">Confirm Password</label><input className="finput" type="password" placeholder="Repeat password" value={form.password2} onChange={set("password2")}/></div>
          </div>
          {form.password&&form.password2&&form.password!==form.password2&&<div style={{color:"var(--red)",fontSize:".78rem",marginTop:".25rem"}}>Passwords don't match</div>}
          <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".3rem",fontFamily:"DM Mono,monospace"}}>Use your username or email to log in next time.</div>
        </div>
        <div className="notice"><strong>Privacy:</strong> Your identity is never shown publicly. Information is collected for lien sale compliance only.</div>
      </>}

      {step===2&&<>
        {/* Deposit payment method */}
        <div className="fsec">
          <div className="fsec-title">Deposit Payment ($300 — refundable)</div>
          {PAY_METHODS.map(pm=><div key={pm.id} className={`pay-card${depositMethod===pm.id?" selected":""}`} onClick={()=>setDepositMethod(pm.id)}>
            <div className="pay-icon">{pm.icon}</div>
            <div><div className="pay-label">{pm.label}</div><div className="pay-note">{pm.note}</div></div>
            <div className="pay-radio"/>
          </div>)}

          {depositMethod==="card"&&<div style={{marginTop:".5rem"}}>
            <div className="notice ok" style={{marginBottom:".5rem"}}>
              <strong>✓ You will be automatically approved to bid!</strong><br/>
              Your <strong>${depositTotal.toFixed(2)}</strong> deposit (includes {CC_FEE_RATE}% processing fee) will be collected securely via Stripe after you confirm. Start bidding immediately.
            </div>
          </div>}
          {depositMethod==="card-office"&&<div className="notice info" style={{marginTop:".5rem",marginBottom:0}}>
            <strong>Bring your credit card to:</strong><br/>
            250 W Warm Springs Rd, Henderson (Tue) · 3823 Losee Rd, N. Las Vegas (Fri)<br/>
            We'll swipe your card in person for ${depositTotal.toFixed(2)} (includes {CC_FEE_RATE}% processing fee). Account activated immediately upon swipe.
          </div>}
          {depositMethod==="zelle"&&<div className="notice info" style={{marginTop:".5rem",marginBottom:0}}>
            <strong>Send $300 Zelle to:</strong> (702) 677-0792<br/>Include your name in the memo. Approved within 1 business hour.
          </div>}
          {depositMethod==="cash"&&<div className="notice info" style={{marginTop:".5rem",marginBottom:0}}>
            <strong>Bring $300 cash to:</strong><br/>
            250 W Warm Springs Rd, Henderson (Tue) · 3823 Losee Rd, N. Las Vegas (Fri)<br/>Staff will activate your account upon receipt.
          </div>}
          {depositMethod==="arrange"&&<div className="notice info" style={{marginTop:".5rem",marginBottom:0}}>
            <strong>Contact our staff:</strong><br/>
            Call <strong>(702) 677-0792</strong> or visit us at the office to discuss deposit options. Your account will be activated once arrangements are confirmed.
          </div>}
        </div>

        {/* Final / winning bid payment method — separate choice */}
        <div className="fsec">
          <div className="fsec-title">How will you pay your winning balance?</div>
          <div style={{fontSize:".78rem",color:"var(--muted)",marginBottom:".65rem",lineHeight:1.5}}>
            Your $300 deposit is applied. Choose how you'll pay the remaining balance <em>if you win</em>. This can be different from your deposit method.
          </div>
          <div style={{display:"flex",gap:".5rem",flexWrap:"wrap"}}>
            {PAY_METHODS.map(pm=><button key={pm.id} className={`final-pay-opt${finalPayMethod===pm.id?" sel":""}`} onClick={()=>setFinalPayMethod(pm.id)}>
              {pm.icon} {pm.label}
            </button>)}
          </div>
          {finalPayMethod==="zelle"&&<div className="notice info" style={{marginTop:".65rem",marginBottom:0}}>
            If you win, we'll send you an invoice and you Zelle the balance to csrtowguysautoauction@gmail.com.
          </div>}
          {finalPayMethod==="cash"&&<div className="notice info" style={{marginTop:".65rem",marginBottom:0}}>
            If you win, bring the balance in cash at pickup. Staff will confirm your arrival time.
          </div>}
        </div>

        <div className="dep-box">
          <div style={{fontSize:".68rem",color:"var(--sub)",fontFamily:"DM Mono,monospace",textTransform:"uppercase",marginBottom:".35rem"}}>Refundable Deposit</div>
          <div className="dep-amt">{noDeposit?"TBD":"$"+depositTotal.toFixed(2)}</div>
          {isCardMethod && <div style={{fontSize:".72rem",color:"var(--amber)",marginTop:".35rem",fontFamily:"DM Mono,monospace"}}>$300.00 + ${ccFee.toFixed(2)} ({CC_FEE_RATE}% card fee)</div>}
          {noDeposit && <div style={{fontSize:".75rem",color:"var(--muted)",marginTop:".35rem",lineHeight:1.5}}>Deposit amount will be determined after speaking with our staff.</div>}
          {!noDeposit && <div style={{fontSize:".75rem",color:"var(--muted)",marginTop:".35rem",lineHeight:1.5}}>Applied to your winning bid. Non-winners refunded within 3–5 business days.{isCardMethod && " Card fee is non-refundable."}</div>}
        </div>

        <div className={`kof-toggle${keepOnFile?"":" off"}`} onClick={()=>setKeepOnFile(k=>!k)}>
          <div className="kof-icon">{keepOnFile?"🔒":"🔓"}</div>
          <div className="kof-text">
            <div className="kof-title">Keep deposit on file until I win</div>
            <div className="kof-sub">{keepOnFile?"Rolls to future auctions automatically.":"Refunded after each auction if you don't win."}</div>
          </div>
          <div className={`toggle-pill${keepOnFile?" on":""}`}/>
        </div>
      </>}
    </div>
    <div className="mfoot">
      {step>1&&!existingCustomer&&<button className="btn-g" onClick={()=>setStep(s=>s-1)}>Back</button>}
      <button className="btn-p" disabled={step===1&&(!form.first||!form.last||!form.username||!form.email)} onClick={()=>{
        if(step===1){
          if(!form.first||!form.last||!form.username||!form.email){window.alert("Please fill in First Name, Last Name, Username, and Email.");return;}
          setStep(2);
        } else setStep(3);
      }}>
        {step===1?"Continue →":needsApproval?"Submit Registration":noDeposit?"Submit Registration":"Confirm $"+depositTotal.toFixed(2)+" Deposit"}
      </button>
    </div>
  </div></div>;
}

// ─── BID MODAL ────────────────────────────────────────────────────────────────
function BidModal({auction,time,onClose,onSubmit,defaultMax=false}){
  const min=Math.max(auction.minBid,(auction.currentBid||0)+auction.increment);
  const [bid,setBid]=useState(min);
  const [maxBid,setMaxBid]=useState("");
  const [showMax,setShowMax]=useState(defaultMax);
  const quickBid=amt=>setBid(Math.max(min,amt));
  const hasMax=showMax&&maxBid&&+maxBid>=bid;
  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Place Bid</div><div className="msub">{auction.lot} · {auction.year} {auction.make} {auction.model}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="bid-car-row">
        {auction.photos?.[0]?<img className="bid-thumb" src={auction.photos[0]} alt=""/>:<div className="bid-thumb" style={{fontSize:"1.2rem"}}>📷</div>}
        <div><div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.15rem"}}>{auction.year} {auction.make} {auction.model}</div><div style={{fontFamily:"DM Mono,monospace",fontSize:".67rem",color:"var(--muted)",marginTop:"4px"}}>Current: <strong style={{color:"var(--accent)"}}>{fmtCurrency(auction.currentBid||auction.minBid)}</strong> · Min: {fmtCurrency(auction.minBid)}</div></div>
      </div>
      <div className="fsec-title" style={{marginBottom:".6rem"}}>Your Bid</div>
      <div className="bid-in-row"><div className="bid-in-pre">$</div><input className="finput bid-in" type="number" value={bid} min={min} step={auction.increment} onChange={e=>setBid(+e.target.value)}/></div>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)",marginBottom:".9rem"}}>Minimum: {fmtCurrency(min)} · Increment: {fmtCurrency(auction.increment)}</div>
      <div style={{marginBottom:"1rem"}}>
        <div className="fsec-title" style={{marginBottom:".5rem"}}>Quick Bid</div>
        <div className="inc-group">
          {[min, min+auction.increment, min+auction.increment*2, min+auction.increment*5].map(v=><button key={v} className={`inc-btn${bid===v?" sel":""}`} onClick={()=>quickBid(v)}>{fmtCurrency(v)}</button>)}
        </div>
      </div>

      {/* Auto-bid (proxy) */}
      <div style={{border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:".75rem .9rem",marginBottom:".85rem",background:"var(--navy-light)"}}>
        <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:showMax?".65rem":"0"}}>
          <div>
            <div style={{fontSize:".85rem",fontWeight:600}}>🤖 Auto-Bid (Proxy)</div>
            <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".1rem"}}>Set a max and the system bids for you automatically up to that amount.</div>
          </div>
          <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",flexShrink:0}}>
            <input type="checkbox" checked={showMax} onChange={e=>setShowMax(e.target.checked)} style={{width:15,height:15,accentColor:"var(--accent)"}}/>
            <span style={{fontSize:".78rem",fontFamily:"DM Mono,monospace"}}>Enable</span>
          </label>
        </div>
        {showMax&&<div style={{display:"flex",alignItems:"center",gap:".5rem"}}>
          <span style={{fontFamily:"DM Mono,monospace",fontSize:".85rem",color:"var(--accent)"}}>$</span>
          <input className="finput" type="number" style={{flex:1}} placeholder={`Min ${fmtCurrency(bid)} — enter your max`} value={maxBid} min={bid} step={auction.increment} onChange={e=>setMaxBid(e.target.value)}/>
        </div>}
        {showMax&&maxBid&&+maxBid<bid&&<div style={{fontSize:".72rem",color:"var(--red)",marginTop:".35rem"}}>Max bid must be at least your current bid of {fmtCurrency(bid)}</div>}
        {showMax&&hasMax&&<div style={{fontSize:".72rem",color:"var(--green)",marginTop:".35rem",fontFamily:"DM Mono,monospace"}}>✓ System will auto-bid up to {fmtCurrency(+maxBid)} for you</div>}
      </div>

      {auction.keyFee>0&&<div className="notice"><strong>Key Fee:</strong> {fmtCurrency(auction.keyFee)} added at invoice.</div>}
      <div className="notice"><strong>Deposit Applied:</strong> Your $300 deposit goes toward the balance if you win.</div>
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Cancel</button><button className="btn-p" disabled={bid<min} onClick={()=>onSubmit(bid, hasMax?+maxBid:null)}>Confirm — {fmtCurrency(bid)}{hasMax?` (max ${fmtCurrency(+maxBid)})`:""}</button></div>
  </div></div>;
}

// ─── ADD/EDIT LOT MODAL ────────────────────────────────────────────────────────
function LotModal({existing,auctions,onSave,onClose}){
  const isEdit=!!existing;
  const [form,setForm]=useState(existing||{year:"",make:"",model:"",vin:"",mileage:"",condition:"runs",keyFee:"0",company:"",wo:"",minBid:"500",increment:"100",photos:[],conditionNotes:"",titleType:"lien"});
  const set=k=>e=>setForm(f=>({...f,[k]:e.target.value}));
  const canSave=form.year&&form.make&&form.model&&form.vin&&form.company;
  return <div className="modal-bg"><div className="modal wide">
    <div className="mhd"><div><div className="mtitle">{isEdit?"Edit Lot":"Add New Lot"}</div><div className="msub">{isEdit?`${existing.lot} · ${existing.wo||""}`:"Enter vehicle details"}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="fsec"><div className="fsec-title">Company & Dispatch Source</div>
        <div className="frow"><div className="fgrp"><label className="flbl">Company *</label><CoSelect value={form.company} onChange={v=>setForm(f=>({...f,company:v}))}/></div><div className="fgrp"><label className="flbl">Work Order # (Dispatch)</label><input className="finput" placeholder="e.g. TT-10482" value={form.wo||""} onChange={set("wo")}/></div></div>
        {form.company&&form.wo&&<div className="notice info">Dispatch link active — admins can jump to the lien tab in {COMPANY_MAP[form.company]?.label} Dispatch.</div>}
      </div>
      <div className="fsec"><div className="fsec-title">Vehicle Details</div>
        <div className="frow t"><div className="fgrp"><label className="flbl">Year *</label><input className="finput" value={form.year} onChange={set("year")}/></div><div className="fgrp"><label className="flbl">Make *</label><input className="finput" value={form.make} onChange={set("make")}/></div><div className="fgrp"><label className="flbl">Model *</label><input className="finput" value={form.model} onChange={set("model")}/></div></div>
        <div className="frow"><div className="fgrp"><label className="flbl">VIN *</label><input className="finput" style={{fontFamily:"DM Mono,monospace",fontSize:".78rem"}} value={form.vin} onChange={set("vin")}/></div><div className="fgrp"><label className="flbl">Mileage</label><input className="finput" type="number" value={form.mileage} onChange={set("mileage")}/></div></div>
        <div className="frow"><div className="fgrp"><label className="flbl">Condition</label><select className="finput fselect" value={form.condition} onChange={set("condition")}><option value="runs">Runs</option><option value="no-start">No Start</option></select></div><div className="fgrp"><label className="flbl">Key Fee ($)</label><input className="finput" type="number" value={form.keyFee} onChange={set("keyFee")}/></div></div>
        <div className="frow"><div className="fgrp"><label className="flbl">Title Type</label>
          <select className="finput fselect" value={form.titleType||"lien"} onChange={set("titleType")}>
            {TITLE_TYPES.map(t=><option key={t.id} value={t.id}>{t.icon} {t.label}</option>)}
          </select>
        </div><div className="fgrp" style={{alignSelf:"flex-end"}}>
          {form.titleType&&<div style={{padding:".45rem .7rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"5px",fontSize:".75rem",color:"var(--muted)",lineHeight:1.5}}>
            {TITLE_TYPES.find(t=>t.id===form.titleType)?.desc}
          </div>}
        </div></div>
        <div className="frow s"><div className="fgrp"><label className="flbl">Condition Notes (visible to bidders)</label><textarea className="finput" style={{minHeight:"68px",resize:"vertical",fontSize:".82rem"}} placeholder="e.g. Engine light on, AC works, minor body damage…" value={form.conditionNotes||""} onChange={e=>setForm(f=>({...f,conditionNotes:e.target.value}))}/></div></div>
      </div>
      <div className="fsec"><div className="fsec-title">Bidding Rules</div>
        <div className="frow"><div className="fgrp"><label className="flbl">Minimum Bid ($)</label><input className="finput" type="number" value={form.minBid} onChange={set("minBid")}/></div><div className="fgrp"><label className="flbl">Bid Increment</label>
          <div className="inc-group" style={{marginTop:".25rem"}}>{BID_INCREMENTS.map(v=><button key={v} type="button" className={`inc-btn${+form.increment===v?" sel":""}`} onClick={()=>setForm(f=>({...f,increment:String(v)}))}>{fmtCurrency(v)}</button>)}</div>
        </div></div>
      </div>
      <div className="fsec"><div className="fsec-title">Photos</div>
        <PhotoSlots photos={form.photos||[]} onChange={p=>setForm(f=>({...f,photos:p}))}/>
        <div className="notice" style={{marginTop:".65rem"}}><strong>Tip:</strong> Name files <strong>VIN_1.jpg</strong> through <strong>VIN_4.jpg</strong> to use Bulk Photo Upload.</div>
      </div>
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Cancel</button><button className="btn-p" disabled={!canSave} onClick={()=>onSave(form)}>{isEdit?"Save Changes":"Add to Auction"}</button></div>
  </div></div>;
}

// ─── SIMPLE AUTO-BID MODAL ────────────────────────────────────────────────────
function AutoBidModal({auction, onClose, onSubmit}){
  const nextBid = Math.max(auction.minBid,(auction.currentBid||0)+auction.increment);
  const min = (auction.currentBid||0) + 1;
  const [maxBid, setMaxBid] = useState(nextBid);
  const canSubmit = +maxBid > (auction.currentBid||0);
  return <div className="modal-bg"><div className="modal" style={{maxWidth:420}}>
    <div className="mhd">
      <div><div className="mtitle">🤖 Set Auto-Bid (Proxy)</div><div className="msub">{auction.lot} · {auction.year} {auction.make} {auction.model}</div></div>
      <button className="mclose" onClick={onClose}>×</button>
    </div>
    <div className="mbody">
      <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:6,padding:".75rem 1rem",marginBottom:"1rem",fontSize:".82rem"}}>
        <div style={{display:"flex",justifyContent:"space-between",marginBottom:".2rem"}}>
          <span style={{color:"var(--muted)"}}>Current Bid</span>
          <strong style={{color:"var(--accent)"}}>{fmtCurrency(auction.currentBid||auction.minBid)}</strong>
        </div>
        <div style={{display:"flex",justifyContent:"space-between"}}>
          <span style={{color:"var(--muted)"}}>Next Bid Increment</span>
          <strong>{fmtCurrency(nextBid)}</strong>
        </div>
      </div>
      <div className="fgrp">
        <label className="flbl">Your Maximum Bid *</label>
        <div className="bid-in-row">
          <div className="bid-in-pre">$</div>
          <input className="finput bid-in" type="number" value={maxBid} min={min} step={1}
            onChange={e=>setMaxBid(e.target.value)} onKeyDown={e=>e.key==="Enter"&&canSubmit&&onSubmit(nextBid,+maxBid)}
            autoFocus/>
        </div>
        <div style={{fontSize:".75rem",color:"var(--muted)",marginTop:".35rem",lineHeight:1.5}}>
          Set any amount above the current bid ({fmtCurrency(auction.currentBid||0)}). We'll bid on your behalf up to <strong>{fmtCurrency(+maxBid||0)}</strong>. Your max is never shown to other bidders.
        </div>
      </div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Cancel</button>
      <button className="btn-p" disabled={!canSubmit} onClick={()=>onSubmit(nextBid,+maxBid)}>
        Set Auto-Bid up to {fmtCurrency(+maxBid||0)} →
      </button>
    </div>
  </div></div>;
}

// ─── BULK IMPORT MODAL ─────────────────────────────────────────────────────────
function BulkImportModal({auctions,onImport,onClose}){
  const [step,setStep]=useState(1);
  const [rows,setRows]=useState(MOCK_DISPATCH_EXPORT.map(r=>({...r,selected:true,minBid:"500",increment:"100"})));
  const [aDay,setADay]=useState("tuesday");
  const all=rows.every(r=>r.selected);
  const toggleAll=()=>setRows(rs=>rs.map(r=>({...r,selected:!all})));
  const toggle=i=>setRows(rs=>rs.map((r,j)=>j===i?{...r,selected:!r.selected}:r));
  const setCo=(i,v)=>setRows(rs=>rs.map((r,j)=>j===i?{...r,company:v}:r));
  const sel=rows.filter(r=>r.selected).length;
  const doImport=()=>{
    const base=Date.now()+2*60*60*1000;
    onImport(rows.filter(r=>r.selected).map((r,i)=>({id:genId(),lot:genLot(auctions.length+i),wo:r.wo,year:r.year,make:r.make,model:r.model,vin:r.vin,mileage:r.mileage,condition:r.condition,keyFee:r.keyFee,company:r.company,minBid:+r.minBid,increment:+r.increment,currentBid:0,bids:0,photos:[],sold:false,closeTime:base+STAGGER_MS*(auctions.length+i)})));
    setStep(3);
  };
  return <div className="modal-bg"><div className="modal xl">
    <div className="mhd"><div><div className="mtitle">Import from Dispatch</div><div className="msub">{step===1?"Select auction & load vehicles":step===2?"Review before creating lots":"Lots created"}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    {step===1&&<><div className="mbody">
      <div className="notice info"><strong>How it works:</strong> In each dispatch system, mark vehicles as "Ready for Auction" on the Lien Processing tab. They appear here for you to review and push to the live auction.</div>
      <div className="fgrp" style={{marginBottom:"1.2rem"}}><label className="flbl">Auction Day</label><select className="finput fselect" value={aDay} onChange={e=>setADay(e.target.value)}><option value="tuesday">Tuesday — 250 W Warm Springs Rd, Henderson</option><option value="friday">Friday — 3823 Losee Rd, North Las Vegas</option></select></div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(2,1fr)",gap:".65rem"}}>{COMPANIES.map(c=><div key={c.id} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"6px",padding:".8rem 1rem",display:"flex",alignItems:"center",gap:".65rem"}}><span style={{width:8,height:8,borderRadius:"50%",background:c.color,flexShrink:0}}/><div style={{flex:1}}><div style={{fontSize:".85rem"}}>{c.label}</div><div style={{fontFamily:"DM Mono,monospace",fontSize:".63rem",color:"var(--muted)"}}>{c.dispatchUrl}</div></div><div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--green)"}}>{MOCK_DISPATCH_EXPORT.filter(r=>r.company===c.id).length} ready</div></div>)}</div>
    </div><div className="mfoot"><button className="btn-g" onClick={onClose}>Cancel</button><button className="btn-p" onClick={()=>setStep(2)}>Load {MOCK_DISPATCH_EXPORT.length} Vehicles →</button></div></>}
    {step===2&&<><div className="mbody" style={{padding:0}}>
      <div style={{padding:".85rem 1.4rem",borderBottom:"1px solid var(--border)",display:"flex",gap:"1rem",alignItems:"center"}}><label style={{display:"flex",alignItems:"center",gap:".45rem",cursor:"pointer",fontSize:".78rem",color:"var(--sub)"}}><input type="checkbox" className="ichk" checked={all} onChange={toggleAll}/> Select All</label><span style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}}>{sel}/{rows.length} selected</span></div>
      <div style={{overflowX:"auto"}}><table className="itbl"><thead><tr><th style={{width:32}}></th><th>WO#</th><th>Vehicle</th><th>VIN</th><th>Cond.</th><th>Key Fee</th><th>Company</th><th>Min Bid</th><th>Increment</th></tr></thead><tbody>{rows.map((r,i)=><tr key={i} className={r.selected?"sel":""}><td><input type="checkbox" className="ichk" checked={r.selected} onChange={()=>toggle(i)}/></td><td style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{r.wo}</td><td style={{fontWeight:500,whiteSpace:"nowrap"}}>{r.year} {r.make} {r.model}</td><td style={{fontFamily:"DM Mono,monospace",fontSize:".64rem",color:"var(--muted)"}}>{r.vin}</td><td><span className={`tag ${r.condition==="runs"?"tag-runs":"tag-ns"}`}>{r.condition==="runs"?"Runs":"No Start"}</span></td><td>{r.keyFee>0?fmtCurrency(r.keyFee):"—"}</td><td><CoSelect value={r.company} onChange={v=>setCo(i,v)}/></td><td><input className="finput sinput" type="number" value={r.minBid} style={{width:"80px"}} onChange={e=>setRows(rs=>rs.map((x,j)=>j===i?{...x,minBid:e.target.value}:x))}/></td><td><div className="inc-group">{[50,100,200].map(v=><button key={v} type="button" className={`inc-btn${+r.increment===v?" sel":""}`} onClick={()=>setRows(rs=>rs.map((x,j)=>j===i?{...x,increment:String(v)}:x))}>${v}</button>)}</div></td></tr>)}</tbody></table></div>
    </div><div className="mfoot"><button className="btn-g" onClick={()=>setStep(1)}>Back</button><button className="btn-p" disabled={sel===0} onClick={doImport}>Create {sel} Lot{sel!==1?"s":""} →</button></div></>}
    {step===3&&<div className="mbody" style={{padding:"2.5rem",textAlign:"center"}}><div className="succ-icon">✓</div><div className="succ-title">{sel} Lots Created</div><p style={{color:"var(--muted)",fontSize:".84rem",marginBottom:"1.4rem",lineHeight:1.6}}>Dispatch links are active. Use <strong style={{color:"var(--accent)"}}>Bulk Photos</strong> to attach photos.</p><button className="btn-p" style={{width:"100%"}} onClick={onClose}>Done</button></div>}
  </div></div>;
}

// ─── BULK PHOTO MODAL ──────────────────────────────────────────────────────────
function BulkPhotoModal({auctions,onMatch,onClose}){
  const [dragOver,setDragOver]=useState(false);
  const [matches,setMatches]=useState([]);
  const fileRef=useRef();
  const process=files=>{
    const res=[];
    Array.from(files).forEach(file=>{
      const name=file.name.replace(/\.[^.]+$/,"");
      const vin=name.split(/[_\-\s]/).find(p=>p.length===17&&/^[A-HJ-NPR-Z0-9]{17}$/i.test(p));
      const hit=vin?auctions.find(a=>a.vin.toUpperCase()===vin.toUpperCase()):null;
      res.push({file,name:file.name,vin:vin||null,hit:hit||null,url:URL.createObjectURL(file)});
    });
    setMatches(res);
  };
  const mc=matches.filter(m=>m.hit).length;
  const apply=()=>{const g={};matches.forEach(m=>{if(m.hit){if(!g[m.hit.id])g[m.hit.id]=[];g[m.hit.id].push(m.url);}});onMatch(g);onClose();};
  return <div className="modal-bg"><div className="modal wide">
    <div className="mhd"><div><div className="mtitle">Bulk Photo Upload</div><div className="msub">Auto-match by VIN in filename</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="notice"><strong>Naming:</strong> <span style={{fontFamily:"DM Mono,monospace",color:"var(--text)",fontSize:".76rem"}}>VIN_1.jpg · VIN_2.jpg · VIN_3.jpg · VIN_4.jpg</span><br/>Example: <span style={{fontFamily:"DM Mono,monospace",color:"var(--accent)",fontSize:".73rem"}}>1HGCV1F34JA012345_2.jpg</span></div>
      {matches.length===0?<div className={`drop-zone${dragOver?" over":""}`} onDrop={e=>{e.preventDefault();setDragOver(false);process(e.dataTransfer.files);}} onDragOver={e=>{e.preventDefault();setDragOver(true);}} onDragLeave={()=>setDragOver(false)} onClick={()=>fileRef.current.click()}><div className="dz-icon">📂</div><div className="dz-title">Drop All Photos Here</div><div className="dz-sub">Drag entire batch at once · <strong>JPG · PNG · HEIC</strong><br/>The VIN in the filename routes each photo to the right vehicle</div><input ref={fileRef} type="file" accept="image/*" multiple style={{display:"none"}} onChange={e=>process(e.target.files)}/></div>
      :<div><div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:".65rem"}}><div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}}>{mc}/{matches.length} matched</div><button className="btn-sm" onClick={()=>setMatches([])}>Clear</button></div><div style={{maxHeight:"330px",overflowY:"auto"}}>{matches.map((m,i)=><div key={i} className="match-item"><img className="match-thumb" src={m.url} alt=""/><div style={{flex:1,minWidth:0}}><div className="match-name">{m.name}</div>{m.hit?<div className="match-st ok">✓ → {m.hit.year} {m.hit.make} {m.hit.model} ({m.hit.lot})</div>:<div className="match-st warn">⚠ {m.vin?`VIN ${m.vin} not found`:"No VIN in filename"}</div>}</div></div>)}</div></div>}
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Cancel</button><button className="btn-p" disabled={mc===0} onClick={apply}>Apply {mc} Photo{mc!==1?"s":""} →</button></div>
  </div></div>;
}

// ─── HISTORY TAB ──────────────────────────────────────────────────────────────
function HistoryTab({onMoveToAuction}){
  const [expanded,setExpanded]=useState({[PAST_AUCTIONS[0].id]:true});
  const [selectedNoSales,setSelectedNoSales]=useState({});
  const [showMoveModal,setShowMoveModal]=useState(false);

  const toggleExpand=id=>setExpanded(e=>({...e,[id]:!e[id]}));
  const toggleSel=(auctionId,lotId)=>setSelectedNoSales(s=>{const k=`${auctionId}::${lotId}`;return {...s,[k]:!s[k]};});
  const isSel=(aId,lId)=>!!selectedNoSales[`${aId}::${lId}`];
  const totalSel=Object.values(selectedNoSales).filter(Boolean).length;

  const getSelectedLots=()=>{
    const lots=[];
    PAST_AUCTIONS.forEach(a=>a.lots.forEach(l=>{if(isSel(a.id,l.id)) lots.push(l);}));
    return lots;
  };

  return <div>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1.2rem",flexWrap:"wrap",gap:".75rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)"}}>{PAST_AUCTIONS.length} past auctions · {PAST_AUCTIONS.flatMap(a=>a.lots).filter(l=>l.status==="no-sale").length} total no-sales</div>
      {totalSel>0&&<button className="cta" onClick={()=>setShowMoveModal(true)}>Move {totalSel} No-Sale{totalSel!==1?"s":""} to Next Auction →</button>}
    </div>

    {PAST_AUCTIONS.map(a=>{
      const sold=a.lots.filter(l=>l.status==="sold");
      const noSale=a.lots.filter(l=>l.status==="no-sale");
      const revenue=sold.reduce((s,l)=>s+l.finalBid,0);
      return <div key={a.id} className="hist-auction">
        <div className="hist-auction-hd" onClick={()=>toggleExpand(a.id)}>
          <div>
            <div className="hist-auction-title">{a.label}</div>
            <div className="hist-auction-meta">{a.location} · {a.lots.length} lots</div>
          </div>
          <div style={{display:"flex",alignItems:"center",gap:"1.5rem"}}>
            <div className="hist-stats">
              <div><div className="hist-stat-val">{sold.length}</div><div className="hist-stat-lbl">Sold</div></div>
              <div><div className="hist-stat-val" style={{color:"var(--red)"}}>{noSale.length}</div><div className="hist-stat-lbl">No Sale</div></div>
              <div><div className="hist-stat-val">{fmtCurrency(revenue)}</div><div className="hist-stat-lbl">Revenue</div></div>
            </div>
            <span style={{color:"var(--muted)",fontSize:"1.1rem"}}>{expanded[a.id]?"▲":"▼"}</span>
          </div>
        </div>
        {expanded[a.id]&&a.lots.map(l=><div key={l.id} className={`hist-lot-row${l.status==="no-sale"?" no-sale":""}`}>
          {l.status==="no-sale"&&<input type="checkbox" className="hist-check" checked={isSel(a.id,l.id)} onChange={()=>toggleSel(a.id,l.id)}/>}
          {l.status==="sold"&&<div style={{width:15,flexShrink:0}}/>}
          <div style={{flex:1,minWidth:0}}>
            <div style={{fontSize:".85rem",fontWeight:500}}>{l.year} {l.make} {l.model}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)"}}>{l.lot} · VIN: {l.vin}</div>
          </div>
          <CoBadge id={l.company}/>
          <div style={{textAlign:"right",minWidth:"80px"}}>
            <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem",color:l.status==="sold"?"var(--accent)":"var(--muted)"}}>{l.status==="sold"?fmtCurrency(l.finalBid):"—"}</div>
            <div style={{fontSize:".62rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}}>Min: {fmtCurrency(l.minBid)}</div>
          </div>
          <span className={`tag ${l.condition==="runs"?"tag-runs":"tag-ns"}`}>{l.condition==="runs"?"Runs":"No Start"}</span>
          {l.status==="no-sale"?<span className="nosale-tag">NO SALE</span>:<span className="sold-tag">SOLD</span>}
          <div style={{fontSize:".7rem",fontFamily:"DM Mono,monospace",color:"var(--muted)"}}>{l.bids} bid{l.bids!==1?"s":""}</div>
        </div>)}
      </div>;
    })}

    {showMoveModal&&<MoveNoSaleModal lots={getSelectedLots()} onClose={()=>setShowMoveModal(false)} onConfirm={(lots,day)=>{onMoveToAuction(lots,day);setShowMoveModal(false);setSelectedNoSales({});}}/>}
  </div>;
}

// ─── MOVE NO-SALE MODAL ────────────────────────────────────────────────────────
function MoveNoSaleModal({lots,onClose,onConfirm}){
  const [day,setDay]=useState("tuesday");
  const [resetBids,setResetBids]=useState(true);
  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Move to Next Auction</div><div className="msub">{lots.length} no-sale lot{lots.length!==1?"s":""} selected</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div style={{marginBottom:"1rem",maxHeight:"200px",overflowY:"auto"}}>
        {lots.map(l=><div key={l.id} style={{display:"flex",alignItems:"center",gap:".75rem",padding:".5rem .65rem",background:"var(--card)",borderRadius:"5px",marginBottom:".4rem",border:"1px solid var(--border)"}}><div style={{flex:1}}><div style={{fontSize:".85rem",fontWeight:500}}>{l.year} {l.make} {l.model}</div><div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)"}}>{l.vin}</div></div><CoBadge id={l.company}/><span className="nosale-tag">NO SALE</span></div>)}
      </div>
      <div className="fgrp" style={{marginBottom:"1rem"}}><label className="flbl">Target Auction Day</label><select className="finput fselect" value={day} onChange={e=>setDay(e.target.value)}><option value="tuesday">Next Tuesday — Henderson</option><option value="friday">Next Friday — North Las Vegas</option></select></div>
      <div className={`kof-toggle${resetBids?"":" off"}`} style={{marginTop:0}} onClick={()=>setResetBids(r=>!r)}>
        <div className="kof-icon">{resetBids?"🔄":"⏸"}</div>
        <div className="kof-text"><div className="kof-title">Reset bid history</div><div className="kof-sub">{resetBids?"These lots will start fresh — no prior bids shown to bidders.":"Bid history will carry over from previous auction."}</div></div>
        <div className={`toggle-pill${resetBids?" on":""}`}/>
      </div>
      <div className="notice" style={{marginTop:".85rem"}}><strong>Lot numbers</strong> will be reassigned based on position in the next auction.</div>
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Cancel</button><button className="btn-p" onClick={()=>onConfirm(lots,day)}>Move {lots.length} Lot{lots.length!==1?"s":""} →</button></div>
  </div></div>;
}

// ─── BIDDER MANAGEMENT TAB ────────────────────────────────────────────────────
function BiddersTab({bidders,setBidders}){
  const [filter,setFilter]=useState("all");
  const [expanded,setExpanded]=useState({});
  const [editLien,setEditLien]=useState({});

  const pending=bidders.filter(b=>b.depositStatus==="pending");
  const shown=bidders.filter(b=>
    filter==="all"||filter===b.depositStatus||(filter==="whitelist"&&b.whitelist)||(filter==="pending-pay"&&b.depositStatus==="pending")
  );

  const update=(id,patch)=>setBidders(bs=>bs.map(b=>b.id===id?{...b,...patch}:b));
  const updateLien=(id,patch)=>setBidders(bs=>bs.map(b=>b.id===id?{...b,lienData:{...b.lienData,...patch}}:b));
  const toggleExpand=id=>setExpanded(e=>({...e,[id]:!e[id]}));
  const approveDeposit=(id,staffNote)=>{
    const now=new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+", "+new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});
    update(id,{depositStatus:"approved",depositOnFile:true,depositConfirmedAt:now,depositNote:staffNote||""});
  };
  const revokeDeposit=id=>update(id,{depositOnFile:false,depositStatus:"pending",depositConfirmedAt:null});

  const payIcon=m=>PAY_METHODS.find(p=>p.id===m)?.icon||"💳";
  const payLabel=m=>PAY_METHODS.find(p=>p.id===m)?.label||m;

  return <div>
    {pending.length>0&&<div className="notice warn" style={{marginBottom:"1.1rem"}}>
      <strong>⏳ {pending.length} bidder{pending.length!==1?"s":""} awaiting deposit approval</strong> — verify payment and check the box below.
    </div>}

    {/* Filter bar */}
    <div style={{display:"flex",gap:".5rem",marginBottom:"1.1rem",flexWrap:"wrap"}}>
      {[["all","All"],["approved","Approved"],["pending","Pending"],["whitelist","★ VIP"]].map(([f,l])=>
        <button key={f} className={`filter-btn${filter===f?" active":""}`} onClick={()=>setFilter(f)}>
          {l}{f==="pending"&&pending.length>0&&<span style={{background:"var(--red)",color:"#fff",borderRadius:"10px",padding:"0 .35rem",fontSize:".62rem",marginLeft:"4px"}}>{pending.length}</span>}
        </button>)}
    </div>

    {shown.map(b=>{
      const open=!!expanded[b.id];
      const isPending=b.depositStatus==="pending";
      const needsManualApproval=b.payMethod==="cash"||b.payMethod==="zelle";
      return <div key={b.id} className="bdr-card">

        {/* Card header */}
        <div className="bdr-card-hd" onClick={()=>toggleExpand(b.id)}>
          <div style={{flex:1,minWidth:0}}>
            <div style={{display:"flex",alignItems:"center",gap:".5rem",flexWrap:"wrap"}}>
              <div className="bdr-name">{b.first} {b.last}</div>
              {b.whitelist&&<span className="wl-badge">★ VIP</span>}
              {isPending&&<span className="pend-badge">⏳ Pending</span>}
              {!isPending&&<span className="appr-badge">✓ Approved</span>}
            </div>
            <div className="bdr-meta">{b.bidderNum} · {b.email} · {b.phone}</div>
          </div>
          <div style={{display:"flex",alignItems:"center",gap:".6rem",flexShrink:0}}>
            <span style={{fontSize:".78rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}}>
              {payIcon(b.payMethod)} Dep · {payIcon(b.finalPayMethod)} Win
            </span>
            <span style={{color:"var(--muted)",fontSize:".85rem"}}>{open?"▲":"▼"}</span>
          </div>
        </div>

        {open&&<div className="bdr-card-body">

          {/* ── DEPOSIT APPROVAL ── */}
          <div className="bdr-section">
            <div className="bdr-section-title">Deposit Status</div>
            <div className="deposit-approval-box">

              {/* Card — auto-approved, no action needed */}
              {b.payMethod==="card"&&<>
                <div style={{display:"flex",alignItems:"center",gap:".6rem",marginBottom:".45rem"}}>
                  <div style={{width:26,height:26,borderRadius:"50%",background:"rgba(21,128,61,.15)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:".85rem",flexShrink:0}}>✓</div>
                  <div>
                    <div style={{fontSize:".88rem",fontWeight:700,color:"var(--green)"}}>💳 Auto-Approved — Card Charged</div>
                    <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".1rem"}}>Credit card was charged $300 automatically at registration. No manual approval needed.</div>
                  </div>
                </div>
              </>}

              {/* Zelle or Cash — requires manual staff confirmation */}
              {needsManualApproval&&<>
                {!b.depositOnFile
                  ? /* Pending — show confirmation form */
                    <div style={{padding:".75rem",background:"rgba(220,38,38,.04)",border:"1.5px solid rgba(220,38,38,.2)",borderRadius:"6px",marginBottom:".55rem"}}>
                      <div style={{display:"flex",alignItems:"center",gap:".5rem",marginBottom:".55rem"}}>
                        <div style={{width:26,height:26,borderRadius:"50%",background:"rgba(220,38,38,.12)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:".8rem",flexShrink:0}}>⏳</div>
                        <div>
                          <div style={{fontSize:".88rem",fontWeight:700,color:"var(--red)"}}>
                            {b.payMethod==="zelle"?"💸 Zelle Payment — Awaiting Confirmation":"💵 Cash Deposit — Awaiting Confirmation"}
                          </div>
                          <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".1rem"}}>
                            {b.payMethod==="zelle"
                              ?"Bidder claims to have sent $300 via Zelle. Verify in your Zelle account before approving."
                              :"Bidder will bring $300 cash. Confirm in person before approving."}
                          </div>
                        </div>
                      </div>
                      <div className="fgrp" style={{marginBottom:".55rem"}}>
                        <label className="flbl">Staff Confirmation Note <span style={{color:"var(--red)"}}>*</span></label>
                        <input className="pay-comment-input"
                          placeholder={b.payMethod==="zelle"?"e.g. Zelle received from Sandra T. at 9:14am — Idan":"e.g. $300 cash received at Henderson office — Office1"}
                          value={b.depositNote||""}
                          onChange={e=>update(b.id,{depositNote:e.target.value})}/>
                      </div>
                      <button
                        disabled={!b.depositNote?.trim()}
                        className="btn-approve"
                        style={{width:"100%",padding:".55rem",fontSize:".85rem",opacity:b.depositNote?.trim()?1:.45,cursor:b.depositNote?.trim()?"pointer":"not-allowed"}}
                        onClick={()=>approveDeposit(b.id,b.depositNote)}>
                        ✓ Confirm ${b.payMethod==="zelle"?"Zelle":"Cash"} Deposit Received — Approve Bidder
                      </button>
                    </div>
                  : /* Approved — show confirmation receipt */
                    <div style={{padding:".65rem .85rem",background:"rgba(21,128,61,.06)",border:"1.5px solid rgba(21,128,61,.25)",borderRadius:"6px",marginBottom:".45rem"}}>
                      <div style={{display:"flex",alignItems:"center",gap:".5rem",marginBottom:b.depositConfirmedAt?".35rem":"0"}}>
                        <div style={{width:26,height:26,borderRadius:"50%",background:"rgba(21,128,61,.15)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:".85rem",flexShrink:0}}>✓</div>
                        <div style={{flex:1}}>
                          <div style={{fontSize:".88rem",fontWeight:700,color:"var(--green)"}}>
                            {b.payMethod==="zelle"?"💸 Zelle Deposit Confirmed":"💵 Cash Deposit Confirmed"}
                          </div>
                          {b.depositConfirmedAt&&<div style={{fontSize:".7rem",fontFamily:"DM Mono,monospace",color:"var(--muted)",marginTop:".1rem"}}>Confirmed: {b.depositConfirmedAt}</div>}
                        </div>
                        <button onClick={()=>revokeDeposit(b.id)} style={{background:"none",border:"1px solid rgba(220,38,38,.3)",borderRadius:"4px",color:"var(--red)",cursor:"pointer",fontSize:".72rem",padding:".22rem .6rem",flexShrink:0}}>Revoke</button>
                      </div>
                      {b.depositNote&&<div style={{fontSize:".78rem",color:"var(--sub)",fontStyle:"italic",paddingLeft:"2.2rem"}}>"{b.depositNote}"</div>}
                    </div>}
              </>}

              <div style={{display:"flex",gap:"1.5rem",marginTop:".45rem",fontSize:".78rem",color:"var(--muted)",flexWrap:"wrap"}}>
                <span>Keep on file: <strong style={{color:b.keepOnFile?"var(--green)":"var(--text)"}}>{b.keepOnFile?"Yes":"No"}</strong></span>
                <span>Final pay method: <strong>{payIcon(b.finalPayMethod)} {payLabel(b.finalPayMethod)}</strong></span>
              </div>
            </div>
          </div>

          {/* ── BIDDER INFO ── */}
          <div className="bdr-section">
            <div className="bdr-section-title">Personal Information</div>
            <div className="bdr-row"><span className="bdr-row-lbl">Full Name</span><span className="bdr-row-val">{b.first} {b.last}</span></div>
            <div className="bdr-row"><span className="bdr-row-lbl">Email</span><span className="bdr-row-val" style={{fontFamily:"DM Mono,monospace",fontSize:".78rem"}}>{b.email}</span></div>
            <div className="bdr-row"><span className="bdr-row-lbl">Phone</span><span className="bdr-row-val">{b.phone}</span></div>
            <div className="bdr-row"><span className="bdr-row-lbl">Address</span><span className="bdr-row-val">{b.address}, {b.city}, {b.state} {b.zip}</span></div>
            <div className="bdr-row"><span className="bdr-row-lbl">Driver's License</span><span className="bdr-row-val" style={{fontFamily:"DM Mono,monospace"}}>{b.dl} ({b.dlState})</span></div>
          </div>

          {/* ── LIEN SALE PACKET ── */}
          <div className="bdr-section">
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:".65rem"}}>
              <div className="bdr-section-title" style={{marginBottom:0}}>Lien Sale Packet — Buyer Info</div>
              <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",fontSize:".75rem",color:"var(--muted)"}}>
                <input type="checkbox" checked={!!b.lienPrefilled} style={{width:13,height:13,accentColor:"var(--green)"}}
                  onChange={()=>update(b.id,{lienPrefilled:!b.lienPrefilled,lienData:!b.lienPrefilled?{first:b.first,last:b.last,address:b.address,city:b.city,state:b.state,zip:b.zip,dl:b.dl,dlState:b.dlState}:b.lienData})}/>
                Auto-fill from registration
              </label>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".55rem",marginBottom:".6rem"}}>
              <div className="fgrp"><label className="flbl">First Name</label><input className="finput" style={{fontSize:".8rem"}} value={b.lienData?.first||""} onChange={e=>updateLien(b.id,{first:e.target.value})}/></div>
              <div className="fgrp"><label className="flbl">Last Name</label><input className="finput" style={{fontSize:".8rem"}} value={b.lienData?.last||""} onChange={e=>updateLien(b.id,{last:e.target.value})}/></div>
            </div>
            <div className="fgrp" style={{marginBottom:".55rem"}}><label className="flbl">Street Address</label><input className="finput" style={{fontSize:".8rem"}} value={b.lienData?.address||""} onChange={e=>updateLien(b.id,{address:e.target.value})}/></div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:".55rem",marginBottom:".55rem"}}>
              <div className="fgrp"><label className="flbl">City</label><input className="finput" style={{fontSize:".8rem"}} value={b.lienData?.city||""} onChange={e=>updateLien(b.id,{city:e.target.value})}/></div>
              <div className="fgrp"><label className="flbl">State</label><select className="finput fselect" style={{fontSize:".8rem"}} value={b.lienData?.state||"NV"} onChange={e=>updateLien(b.id,{state:e.target.value})}>{["NV","CA","AZ","UT","TX","FL","OR","WA"].map(s=><option key={s}>{s}</option>)}</select></div>
              <div className="fgrp"><label className="flbl">Zip</label><input className="finput" style={{fontSize:".8rem"}} value={b.lienData?.zip||""} onChange={e=>updateLien(b.id,{zip:e.target.value})}/></div>
            </div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".55rem"}}>
              <div className="fgrp"><label className="flbl">DL Number</label><input className="finput" style={{fontSize:".8rem",fontFamily:"DM Mono,monospace"}} value={b.lienData?.dl||""} onChange={e=>updateLien(b.id,{dl:e.target.value})}/></div>
              <div className="fgrp"><label className="flbl">DL State</label><select className="finput fselect" style={{fontSize:".8rem"}} value={b.lienData?.dlState||"NV"} onChange={e=>updateLien(b.id,{dlState:e.target.value})}>{["NV","CA","AZ","UT","TX","FL","OR","WA"].map(s=><option key={s}>{s}</option>)}</select></div>
            </div>
          </div>

          {/* ── PAYMENT COMMENT ── */}
          <div className="bdr-section">
            <div className="bdr-section-title">Payment / Pickup Comment</div>
            <div style={{fontSize:".78rem",color:"var(--muted)",marginBottom:".5rem"}}>Customer or staff note on when they're coming to pay the balance or pick up the vehicle.</div>
            {b.paymentComment&&<div className="pay-comment-box" style={{marginBottom:".5rem"}}>"{b.paymentComment}"</div>}
            <textarea className="staff-note-area" placeholder="e.g. Coming Friday after 2pm · Calling to schedule pickup · Needs 48hr notice…"
              value={b.paymentComment||""}
              onChange={e=>update(b.id,{paymentComment:e.target.value})}
              rows={2}/>
          </div>

          {/* ── STAFF NOTES ── */}
          <div className="bdr-section">
            <div className="bdr-section-title">Internal Staff Notes</div>
            <textarea className="staff-note-area" placeholder="Internal notes — not visible to customer…"
              value={b.staffNotes||""}
              onChange={e=>update(b.id,{staffNotes:e.target.value})}
              rows={2}/>
          </div>

          {/* ── ACTIONS ── */}
          <div style={{display:"flex",gap:".5rem",flexWrap:"wrap"}}>
            {isPending&&needsManualApproval&&<button className="btn-approve" style={{flex:1,opacity:b.depositNote?.trim()?1:.45}} disabled={!b.depositNote?.trim()} onClick={()=>approveDeposit(b.id,b.depositNote)}>✓ Approve Bidder</button>}
            <button className="btn-sm" style={{borderColor:"rgba(0,48,135,.25)",color:"var(--accent)"}} onClick={()=>setBadgeBidder(b)}>🎫 Print Badge</button>
            <button className="btn-sm" style={{borderColor:"rgba(245,158,11,.3)",color:"#92400e"}} onClick={()=>setRateModal(b)}>⭐ Rate</button>
            <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",padding:".4rem .8rem",border:"1px solid rgba(59,130,246,.25)",borderRadius:"4px",background:"rgba(59,130,246,.06)",fontSize:".78rem",color:"var(--blue)"}}>
              <input type="checkbox" checked={b.whitelist} onChange={()=>update(b.id,{whitelist:!b.whitelist})} style={{width:14,height:14,accentColor:"var(--blue)"}}/>
              ★ VIP / Whitelist
            </label>
            <button className="btn-danger" onClick={()=>setBidders(bs=>bs.filter(x=>x.id!==b.id))}>Remove</button>
          </div>

        </div>}
      </div>;
    })}
  </div>;
}

// ─── VEHICLE DETAIL MODAL ────────────────────────────────────────────────────
function VehicleDetailModal({auction, time, feeSettings, bidderStatus, onBid, onShare, onClose}){
  const [activePhoto,setActivePhoto]=useState(0);
  const photos=auction.photos||[];
  const canBid=bidderStatus==="approved"&&!time.done;
  return <div className="modal-bg"><div className="modal wide" style={{maxWidth:860}}>
    <div className="mhd">
      <div>
        <div className="mtitle">{auction.year} {auction.make} {auction.model}</div>
        <div className="msub">{auction.lot} · VIN: {auction.vin}</div>
      </div>
      <button className="mclose" onClick={onClose}>×</button>
    </div>
    <div className="mbody">
      {/* Photos */}
      {photos.length>0&&<div className="vd-photos">
        <img className="vd-photo main" src={photos[activePhoto]} alt="vehicle"/>
        {photos.map((p,i)=><img key={i} className="vd-photo" src={p} alt="" style={{cursor:"pointer",opacity:i===activePhoto?.4:1,border:i===activePhoto?"2px solid var(--accent)":"1px solid var(--border)"}} onClick={()=>setActivePhoto(i)}/>)}
      </div>}
      {photos.length===0&&<div style={{textAlign:"center",padding:"2rem",background:"var(--navy-light)",borderRadius:"6px",marginBottom:"1rem",color:"var(--muted)",fontSize:"2rem"}}>📷</div>}

      {/* Info grid */}
      <div className="vd-info-grid">
        <div className="vd-field"><div className="vd-lbl">Year / Make / Model</div><div className="vd-val">{auction.year} {auction.make} {auction.model}</div></div>
        <div className="vd-field"><div className="vd-lbl">Mileage</div><div className="vd-val">{(auction.mileage||0).toLocaleString()} mi</div></div>
        <div className="vd-field full"><div className="vd-lbl">VIN</div><div className="vd-val" style={{fontFamily:"DM Mono,monospace",fontSize:".85rem"}}>{auction.vin}</div></div>
        <div className="vd-field"><div className="vd-lbl">Condition</div><div className="vd-val">{auction.condition?<span className={`cond-tag ${auction.condition==="runs"?"runs":"no-start"}`} style={{position:"static",padding:".2rem .55rem"}}>{auction.condition==="runs"?"✓ Runs":"✗ No Start"}</span>:<span style={{color:"var(--muted)"}}>—</span>}</div></div>
        <div className="vd-field"><div className="vd-lbl">Title Type</div><div className="vd-val"><TitleBadge type={auction.titleType||"lien"}/></div></div>
        <div className="vd-field"><div className="vd-lbl">Key Fee</div><div className="vd-val" style={{color:auction.keyFee>0?"var(--accent2)":"var(--green)"}}>{auction.keyFee>0?fmtCurrency(auction.keyFee):"No key fee"}</div></div>
        <div className="vd-field"><div className="vd-lbl">Min Bid</div><div className="vd-val">{fmtCurrency(auction.minBid)}</div></div>
        <div className="vd-field"><div className="vd-lbl">Bid Increment</div><div className="vd-val">{fmtCurrency(auction.increment)}</div></div>
        {auction.conditionNotes&&<div className="vd-field full"><div className="vd-lbl">Condition Notes</div><div className="vd-val" style={{fontSize:".83rem",lineHeight:1.55}}>{auction.conditionNotes}</div></div>}
        <div className="vd-field full">
          <div className="vd-lbl">Admin Fee + Tax Note</div>
          <div className="vd-val" style={{fontSize:".78rem",color:"var(--muted)"}}>
            Admin fee {fmtCurrency(feeSettings.adminFee)} · Sales tax {auction.taxExempt?"exempt":`${feeSettings.taxRate}%`} · All bids are starting prices — final invoice calculated at close
          </div>
        </div>
      </div>

      {/* Bid history */}
      {(auction.bidHistory||[]).length>0&&<div style={{marginBottom:"1rem"}}>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".55rem"}}>{auction.bids} Bids Placed</div>
        <div style={{maxHeight:"180px",overflowY:"auto"}}>
          {[...(auction.bidHistory||[])].reverse().map((b,i)=><div key={i} className={`bid-hist-item${i===0?" winning":""}`}>
            <span style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)"}}>{b.ts}</span>
            <span style={{flex:1,paddingLeft:".75rem",fontSize:".8rem",color:"var(--muted)"}}>Bidder {(auction.bidHistory.length - (auction.bidHistory.length - 1 - i)).toString().padStart(2,"0")}{i===0&&<span style={{marginLeft:".4rem",fontSize:".65rem",color:"var(--green)",fontWeight:700}}>LEADING</span>}</span>
            <span style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:i===0?"var(--accent)":"var(--text)"}}>{fmtCurrency(b.amount)}</span>
          </div>)}
        </div>
      </div>}

      {/* Status / Timer */}
      <div style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:".75rem 1rem",background:"var(--navy-light)",borderRadius:"6px"}}>
        <div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.6rem",color:"var(--accent)"}}>{fmtCurrency(auction.currentBid||auction.minBid)}</div>
          <div style={{fontSize:".72rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}}>Current bid · {auction.bids} bid{auction.bids!==1?"s":""}</div>
        </div>
        <Countdown time={time}/>
      </div>
    </div>
    <div className="mfoot" style={{flexDirection:"column",gap:".65rem",alignItems:"stretch"}}>
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",flexWrap:"wrap",gap:".5rem"}}>
        <div style={{fontSize:".75rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}}>
          👁 {auction.views||0} view{(auction.views||0)!==1?"s":""} · ↗ {auction.shares||0} share{(auction.shares||0)!==1?"s":""}
        </div>
        <ShareBar auction={auction} onShare={onShare}/>
      </div>
      <div style={{display:"flex",gap:".65rem"}}>
        <button className="btn-g" onClick={onClose}>Close</button>
        {canBid&&<button className="btn-p" style={{flex:1}} onClick={()=>{onClose();onBid(auction);}}>Place Bid →</button>}
      </div>
    </div>
  </div></div>;
}

// ─── AUCTION CHECKLIST ────────────────────────────────────────────────────────
function AuctionChecklist({auctions}){
  const photoPending=auctions.filter(a=>!a.photos||a.photos.length<4).length;
  const CHECKLIST={
    "Pre-Auction Setup":[
      {id:"c1",text:"All lot photos uploaded (4 per vehicle)",auto:photoPending===0,autoMsg:`${photoPending} lot${photoPending!==1?"s":""} missing photos`},
      {id:"c2",text:"Min bids and increments set for all lots"},
      {id:"c3",text:"Closing time confirmed and stagger interval set"},
      {id:"c4",text:"Auction status set to LIVE"},
    ],
    "Bidder Approvals":[
      {id:"c5",text:"All pending cash/Zelle deposits verified and approved"},
      {id:"c6",text:"Whitelist accounts confirmed for VIP bidders"},
    ],
    "Day Of Auction":[
      {id:"c7",text:"Vehicles accessible and ready for inspection"},
      {id:"c8",text:"Staff present at auction location"},
      {id:"c9",text:"Phone available for bidder questions"},
    ],
    "Post-Auction":[
      {id:"c10",text:"Winners notified via email and/or SMS"},
      {id:"c11",text:"No-sale lots reviewed and queued for next auction"},
      {id:"c12",text:"Invoices generated for all winning bidders"},
      {id:"c13",text:"Deposit refunds initiated for non-winners"},
    ],
  };
  const allItems=Object.values(CHECKLIST).flat();
  const [checked,setChecked]=useState(()=>{
    const init={};
    allItems.forEach(i=>{ if(i.auto) init[i.id]=true; });
    return init;
  });
  const toggle=id=>setChecked(c=>({...c,[id]:!c[id]}));
  const doneCount=allItems.filter(i=>checked[i.id]).length;
  const pct=Math.round(doneCount/allItems.length*100);

  return <div>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:".75rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".08em"}}>{doneCount}/{allItems.length} complete</div>
      <span style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:pct===100?"var(--green)":"var(--accent)"}}>{pct}%</span>
    </div>
    <div className="check-progress"><div className="check-progress-bar" style={{width:`${pct}%`,background:pct===100?"var(--green)":"var(--accent)"}}/></div>
    {Object.entries(CHECKLIST).map(([section,items])=><div key={section} className="checklist-section">
      <div className="checklist-title">{section}</div>
      {items.map(item=><div key={item.id} className={`check-item${checked[item.id]?" done":""}`} onClick={()=>toggle(item.id)}>
        <input type="checkbox" checked={!!checked[item.id]} onChange={()=>toggle(item.id)} onClick={e=>e.stopPropagation()}/>
        <span className="check-item-text">{item.text}</span>
        {item.auto&&!checked[item.id]&&<span style={{fontSize:".68rem",color:"var(--red)",fontFamily:"DM Mono,monospace"}}>{item.autoMsg}</span>}
        {checked[item.id]&&<span style={{fontSize:".75rem",color:"var(--green)"}}>✓</span>}
      </div>)}
    </div>)}
  </div>;
}

// ─── AUCTION ROSTER (printable) ───────────────────────────────────────────────
function RosterModal({auctions, auctionDate, auctionDayLabel, onClose}){
  const ev = AUCTION_EVENTS[auctionDayLabel||"tuesday"];
  const fmtDate = auctionDate
    ? new Date(auctionDate+"T12:00:00").toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"})
    : new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"});

  const TERMINOLOGY = [
    {term:"Runs / Engine Starts", desc:"Vehicle engine starts and runs. Bidders may inspect in person before bidding."},
    {term:"No Start / Engine Does Not Start", desc:"Vehicle does not start. May have mechanical issues. Tow or transport required."},
    {term:"As-Is", desc:"All vehicles sold in their present condition. No warranties expressed or implied. No returns."},
    {term:"Min Bid", desc:"The lowest opening bid accepted. Bids must meet or exceed this amount."},
    {term:"Lien Sale", desc:"Government-regulated sale under Nevada NRS Chapter 108 to recover unpaid towing and storage fees."},
    {term:"$300 Deposit", desc:"A refundable deposit required to bid. Applied to winning bid balance. Refunded to non-winners."},
  ];

  return <div className="modal-bg"><div className="modal wide">
    <div className="mhd">
      <div>
        <div className="mtitle">Auction Day Roster</div>
        <div className="msub">{auctions.length} lots · {fmtDate}</div>
      </div>
      <button className="mclose" onClick={onClose}>×</button>
    </div>
    <div className="mbody">
      {/* Printable header */}
      <div style={{background:"var(--accent)",color:"#fff",padding:".85rem 1.1rem",borderRadius:"6px",marginBottom:"1rem",display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"1rem",flexWrap:"wrap"}}>
        <div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",letterSpacing:".05em"}}>Tow Guys Auto Auction</div>
          <div style={{fontSize:".72rem",opacity:.8,marginTop:".15rem"}}>{ev?.address} · (702) 677-0792 · csrtowguysautoauction@gmail.com</div>
        </div>
        <div style={{textAlign:"right",fontFamily:"DM Mono,monospace",fontSize:".72rem",opacity:.85,lineHeight:1.7}}>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",letterSpacing:".04em",opacity:1}}>{fmtDate}</div>
          <div>Auction Closes: <strong style={{color:"#fff"}}>2:00 PM</strong></div>
          <div>Nevada Lien Sale — NRS Ch. 108</div>
        </div>
      </div>

      {/* Lot table — no WO# */}
      <div style={{overflowX:"auto",marginBottom:"1.2rem"}}>
        <table className="roster-table">
          <thead><tr>
            <th>Lot #</th>
            <th>Vehicle</th>
            <th>VIN</th>
            <th>Miles</th>
            <th>Condition</th>
            <th style={{textAlign:"right"}}>Min Bid</th>
            <th style={{textAlign:"right"}}>Key Fee</th>
          </tr></thead>
          <tbody>{auctions.map(a=><tr key={a.id}>
            <td style={{fontFamily:"DM Mono,monospace",fontWeight:700,color:"var(--accent)",fontSize:".88rem"}}>{a.lot}</td>
            <td><strong>{a.year} {a.make} {a.model}</strong></td>
            <td style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)"}}>{a.vin}</td>
            <td style={{fontFamily:"DM Mono,monospace",fontSize:".78rem"}}>{(a.mileage||0).toLocaleString()}</td>
            <td>
              <span className={`tag ${a.condition==="runs"?"tag-runs":"tag-ns"}`} style={{fontSize:".72rem"}}>
                {a.condition==="runs"?"✓ Runs":"✗ No Start"}
              </span>
              {a.conditionNotes&&<div style={{fontSize:".65rem",color:"var(--muted)",marginTop:"3px",maxWidth:"180px",lineHeight:1.3}}>{a.conditionNotes.slice(0,70)}{a.conditionNotes.length>70?"…":""}</div>}
            </td>
            <td style={{fontWeight:700,color:"var(--accent)",textAlign:"right"}}>{fmtCurrency(a.minBid)}</td>
            <td style={{textAlign:"right"}}>{a.keyFee>0?<span style={{color:"#d97706",fontWeight:600}}>{fmtCurrency(a.keyFee)}</span>:<span style={{color:"var(--muted)"}}>—</span>}</td>
          </tr>)}
          </tbody>
        </table>
      </div>

      {/* Terminology legend */}
      <div style={{border:"1px solid var(--border)",borderRadius:"7px",overflow:"hidden"}}>
        <div style={{background:"var(--navy-light)",padding:".65rem 1rem",borderBottom:"1px solid var(--border)",fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)"}}>
          Auction Terminology &amp; Buyer Guide
        </div>
        <div style={{padding:".75rem 1rem",display:"grid",gridTemplateColumns:"1fr 1fr",gap:".55rem .75rem"}}>
          {TERMINOLOGY.map((t,i)=><div key={i} style={{fontSize:".78rem",lineHeight:1.55,padding:".45rem .65rem",background:i%2===0?"var(--navy-light)":"transparent",borderRadius:"4px"}}>
            <div style={{fontWeight:700,color:"var(--text)",marginBottom:".2rem"}}>{t.term}</div>
            <div style={{color:"var(--muted)"}}>{t.desc}</div>
          </div>)}
        </div>
        <div style={{padding:".65rem 1rem",borderTop:"1px solid var(--border)",fontSize:".72rem",color:"var(--muted)",lineHeight:1.6,background:"var(--navy-light)"}}>
          <strong>All sales are final and as-is.</strong> A $300 refundable deposit is required to bid. Winners must pay balance and remove vehicle within 3 business days.
        </div>
      </div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Close</button>
      <button className="btn-p" onClick={()=>window.print()}>🖨 Print Roster</button>
    </div>
  </div></div>;
}

// ─── CSV EXPORT ───────────────────────────────────────────────────────────────
function csvDownload(filename, rows, headers){
  const escape=v=>typeof v==="string"&&v.includes(",")? `"${v}"`:String(v??"-");
  const lines=[headers.join(","),...rows.map(r=>r.map(escape).join(","))];
  const blob=new Blob([lines.join("\n")],{type:"text/csv"});
  const a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=filename; a.click();
}
function ExportsPanel({auctions, bidders, feeSettings}){
  const exportLots=()=>csvDownload("lots.csv",auctions.map(a=>[a.lot,a.year,a.make,a.model,a.vin,a.mileage,a.condition==="runs"?"Runs":"No Start",a.minBid,a.increment,a.currentBid||a.minBid,a.bids,a.wo||"",a.company]),["Lot","Year","Make","Model","VIN","Mileage","Condition","Min Bid","Increment","Current Bid","Bids","WO#","Company"]);
  const exportBidders=()=>csvDownload("bidders.csv",bidders.map(b=>[b.bidderNum,b.first,b.last,b.email,b.phone,b.dl,b.payMethod,b.finalPayMethod,b.depositStatus,b.depositOnFile?"Yes":"No",b.keepOnFile?"Yes":"No",b.whitelist?"Yes":"No"]),["Bidder#","First","Last","Email","Phone","DL","Deposit Method","Final Pay Method","Deposit Status","Deposit On File","Keep On File","Whitelist"]);
  const exportInvoices=()=>{
    const rows=auctions.filter(a=>a.sold&&a.winner).map(a=>{
      const taxable=(a.currentBid||a.minBid)+(a.keyFee||0)+feeSettings.adminFee;
      const tax=a.taxExempt?0:+(taxable*feeSettings.taxRate/100).toFixed(2);
      const total=taxable+tax; const balance=total-300;
      return [a.lot,a.year,a.make,a.model,a.vin,a.winner||"",a.currentBid||a.minBid,a.keyFee||0,feeSettings.adminFee,a.taxExempt?"Exempt":tax,300,total,balance,a.taxExempt?"Exempt":"Taxable"];
    });
    if(rows.length===0){ alert("No sold lots with winners assigned yet."); return; }
    csvDownload("invoices.csv",rows,["Lot","Year","Make","Model","VIN","Winner","Winning Bid","Key Fee","Admin Fee","Tax","Deposit Applied","Total","Balance Due","Tax Status"]);
  };
  const EXPORTS=[
    {label:"Active Lots",sub:"All current auction lots with VIN, mileage, bids, condition",fn:exportLots,color:"var(--accent)"},
    {label:"Bidder Registry",sub:"All registered bidders with payment method and status",fn:exportBidders,color:"var(--blue)"},
    {label:"Invoice Summary",sub:"Won lots — winning bid, fees, tax, and balance due",fn:exportInvoices,color:"var(--green)"},
  ];
  return <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden"}}>
    <div style={{padding:"1rem 1.2rem",borderBottom:"1px solid var(--border)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem",color:"var(--accent)"}}>Export to CSV</div>
    {EXPORTS.map(ex=><div key={ex.label} className="export-row">
      <div><div className="export-desc">{ex.label}</div><div className="export-sub">{ex.sub}</div></div>
      <button className="btn-export" style={{background:ex.color}} onClick={ex.fn}>⬇ Download</button>
    </div>)}
  </div>;
}

// ─── TERMS & CONDITIONS MODAL ─────────────────────────────────────────────────
// ─── TITLE TYPE BADGE ─────────────────────────────────────────────────────────
const TITLE_TYPES = [
  { id:"lien",    label:"Lien Sale",     icon:"⚖️",  desc:"Title transferred via Nevada lien sale — NRS Chapter 108" },
  { id:"clean",   label:"Clean Title",   icon:"✅",  desc:"Clear title, no encumbrances" },
  { id:"salvage", label:"Salvage",       icon:"⚠️",  desc:"DMV has designated this vehicle as salvage" },
  { id:"rebuild", label:"Rebuilt Title", icon:"🔧",  desc:"Rebuilt/reconstructed title — vehicle was previously salvage, now repaired and re-certified" },
];

function TitleBadge({type, style={}}){
  const t = TITLE_TYPES.find(x=>x.id===type)||TITLE_TYPES[0];
  return <span className={`title-badge ${t.id}`} style={style} title={t.desc}>
    {t.icon} {t.label}
  </span>;
}

function TermsModal({onClose}){
  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Terms & Conditions</div><div className="msub">Tow Guys Auto Auction — Nevada Lien Sale</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="terms-body">
        <h3>1. All Sales Are Final</h3>
        <p>All vehicles are sold as-is, where-is, with no warranty expressed or implied. Buyer assumes all risk of mechanical, structural, and cosmetic condition. No refunds or returns will be accepted after the auction closes, except as specifically provided in Section 11 (Post-Sale Title Designation).</p>

        <h3>2. Lien Sale — Government Regulated</h3>
        <p>These auctions are conducted under Nevada lien sale law (NRS Chapter 108). Vehicles are sold to recover unpaid towing and storage fees. Tow Guys Auto Auction acts as the authorized agent of the towing company.</p>

        <h3>3. Title Type Disclosure</h3>
        <p>Each vehicle is listed with its known title designation at the time of sale. Title types include:</p>
        <ul>
          <li><strong>⚖️ Lien Sale</strong> — Title transferred under Nevada NRS Chapter 108 lien sale authority. Buyer receives a lien sale certificate. DMV title issuance is the buyer's responsibility.</li>
          <li><strong>✅ Clean Title</strong> — Vehicle has a clear title with no known encumbrances at time of sale.</li>
          <li><strong>⚠️ Salvage</strong> — DMV has designated this vehicle as a salvage vehicle. A salvage title application is required before the vehicle may be repaired and re-registered.</li>
          <li><strong>🔧 Rebuilt Title</strong> — Vehicle was previously designated as salvage, has since been repaired and inspected, and has been re-titled as rebuilt/reconstructed by the DMV.</li>
        </ul>
        <p>Buyers are responsible for verifying the title status through the Nevada DMV prior to bidding. Title designations are provided in good faith based on information available at the time of auction.</p>

        <h3>4. Bidder Eligibility</h3>
        <ul>
          <li>Bidders must be 18 years or older.</li>
          <li>A valid government-issued photo ID and driver's license are required.</li>
          <li>A refundable $300 deposit is required prior to bidding and will be applied to the winning bid.</li>
          <li>Bidders with outstanding balances from prior auctions are not eligible to bid until the balance is cleared.</li>
        </ul>

        <h3>5. Payment</h3>
        <p>Winning bidders must pay the remaining balance within 48 hours of auction close. Accepted payment methods: credit/debit card, Zelle, or cash. Failure to pay forfeits the deposit and the vehicle may be re-auctioned.</p>

        <h3>6. Key Fee</h3>
        <p>Vehicles requiring key replacement will include a key fee on the final invoice. This fee is non-negotiable and represents the cost to produce or program a replacement key. The fee is listed on each lot prior to bidding.</p>

        <h3>7. Vehicle Pickup</h3>
        <p>Vehicles must be picked up within 3 business days of auction close. Vehicle title will be released only upon receipt of full payment.</p>

        <h3>8. Deposits</h3>
        <p>The $300 deposit is fully refundable if the bidder does not win any lots. Refunds are processed within 3–5 business days to the original payment method. Bidders who elect to keep the deposit on file will have it rolled to future auctions.</p>

        <h3>9. Bidder Identity</h3>
        <p>Bidder identities are never disclosed publicly on this site. Bid histories are anonymized. All personal information collected during registration is used solely for lien sale compliance and payment processing.</p>

        <h3>10. Disputes</h3>
        <p>Any disputes regarding auction results must be submitted in writing to csrtowguysautoauction@gmail.com within 24 hours of auction close. The auctioneer's decision is final.</p>

        <h3>11. Post-Sale Salvage Title Designation</h3>
        <p>Tow Guys Auto Auction conducts lien sales in full compliance with Nevada law. In some cases, the Nevada DMV may receive and process a salvage designation report <em>after</em> a lien sale has already been completed — resulting in a vehicle's title being reclassified as salvage subsequent to purchase. This is not the fault of the buyer or of Tow Guys Auto Auction.</p>
        <p>In the event that a purchased vehicle's title is reclassified as salvage by the DMV after the date of sale, the buyer may elect one of the following three remedies. The buyer must notify Tow Guys Auto Auction in writing at csrtowguysautoauction@gmail.com within 10 business days of receiving notice of the reclassification:</p>
        <ul>
          <li><strong>Option 1 — Keep the vehicle at a 20% discount.</strong> Buyer retains the vehicle and receives a 20% refund of the final sale price. Buyer must come to our office to complete a Nevada DMV salvage title application. All fees associated with the salvage title application are the buyer's responsibility.</li>
          <li><strong>Option 2 — Return the vehicle for auction credit.</strong> Buyer returns the vehicle in the same condition as purchased and receives a credit equal to the full purchase price (including fees paid) toward any future Tow Guys Auto Auction purchase. Credit is non-transferable and expires 12 months from the date of issue.</li>
          <li><strong>Option 3 — Return the vehicle for a full refund.</strong> Buyer returns the vehicle and receives a full refund of all amounts paid, provided that no more than 10 miles have been added to the vehicle's odometer since the date of pickup. Mileage will be verified at the time of return against the pickup odometer reading recorded by our staff.</li>
        </ul>
        <p>These remedies are available exclusively in the event of a post-sale DMV salvage reclassification and do not apply to vehicles listed as salvage at the time of auction. Remedies are void if the vehicle has been altered, partially disassembled, or involved in an accident after pickup.</p>

        <h3>12. Contact</h3>
        <p>Tow Guys Auto Auction · (702) 677-0792 · csrtowguysautoauction@gmail.com<br/>250 W Warm Springs Rd, Henderson, NV 89011 (Tue) · 3823 Losee Rd, N. Las Vegas, NV 89030 (Fri)</p>
      </div>
    </div>
    <div className="mfoot"><button className="btn-p" style={{width:"100%"}} onClick={onClose}>I Understand — Close</button></div>
  </div></div>;
}

// ─── AUCTION SUMMARY DASHBOARD ────────────────────────────────────────────────
function SummaryDashboard({auctions, feeSettings}){
  const sold=auctions.filter(a=>a.sold&&a.currentBid>0);
  const noSale=auctions.filter(a=>a.sold===false||a.currentBid===0);
  const totalRevenue=sold.reduce((s,a)=>s+(a.currentBid||0),0);
  const totalFees=sold.length*feeSettings.adminFee;
  const totalTax=sold.filter(a=>!a.taxExempt).reduce((s,a)=>{
    const taxable=(a.currentBid||0)+(a.keyFee||0)+feeSettings.adminFee;
    return s+parseFloat((taxable*feeSettings.taxRate/100).toFixed(2));
  },0);
  const avgBid=sold.length>0?Math.round(totalRevenue/sold.length):0;
  const maxLot=sold.length>0?sold.reduce((m,a)=>(a.currentBid||0)>(m.currentBid||0)?a:m):null;

  return <div>
    <div className="summary-grid">
      {[
        {val:auctions.length,lbl:"Total Lots",color:"var(--accent)"},
        {val:sold.length,lbl:"Sold",color:"var(--green)"},
        {val:auctions.length-sold.length,lbl:"No Sale",color:"var(--red)"},
        {val:fmtCurrency(totalRevenue),lbl:"Gross Revenue",color:"var(--accent)"},
        {val:fmtCurrency(totalFees),lbl:"Admin Fees",color:"var(--blue)"},
        {val:fmtCurrency(totalTax),lbl:"Sales Tax",color:"var(--muted)"},
        {val:fmtCurrency(avgBid),lbl:"Avg Winning Bid",color:"var(--accent)"},
        {val:auctions.reduce((s,a)=>s+a.bids,0),lbl:"Total Bids",color:"var(--sub)"},
      ].map(s=><div key={s.lbl} className="summary-card"><div className="summary-val" style={{color:s.color}}>{s.val}</div><div className="summary-lbl">{s.lbl}</div></div>)}
    </div>

    {maxLot&&<div className="notice ok" style={{marginBottom:"1.2rem"}}>
      <strong>Top Lot:</strong> {maxLot.lot} — {maxLot.year} {maxLot.make} {maxLot.model} · <strong>{fmtCurrency(maxLot.currentBid)}</strong>
    </div>}

    <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".65rem"}}>Revenue by Company</div>
    {COMPANIES.map(c=>{
      const cLots=sold.filter(a=>a.company===c.id);
      const rev=cLots.reduce((s,a)=>s+(a.currentBid||0),0);
      const maxRev=sold.reduce((s,a)=>s+(a.currentBid||0),1);
      return <div key={c.id} className="summary-bar-row">
        <div className="summary-bar-label">{c.label}</div>
        <div className="summary-bar-track"><div className="summary-bar-fill" style={{width:`${Math.round(rev/maxRev*100)}%`,background:c.color}}/></div>
        <div className="summary-bar-val">{fmtCurrency(rev)}</div>
      </div>;
    })}

    {noSale.length>0&&<div style={{marginTop:"1.2rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--red)",marginBottom:".55rem"}}>{noSale.length} No-Sale Lot{noSale.length!==1?"s":""}</div>
      {noSale.map(a=><div key={a.id} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:".4rem .7rem",border:"1px solid var(--border)",borderRadius:"4px",marginBottom:".35rem",fontSize:".8rem"}}>
        <span>{a.lot} — {a.year} {a.make} {a.model}</span>
        <span className="nosale-tag">NO SALE</span>
      </div>)}
    </div>}
  </div>;
}

// ─── LOT REORDER ──────────────────────────────────────────────────────────────
function ReorderModal({auctions, setAuctions, onClose}){
  const [list,setList]=useState([...auctions]);
  const [dragIdx,setDragIdx]=useState(null);
  const onDragStart=i=>{setDragIdx(i);};
  const onDragOver=(e,i)=>{
    e.preventDefault();
    if(dragIdx===null||dragIdx===i) return;
    const updated=[...list];
    const [moved]=updated.splice(dragIdx,1);
    updated.splice(i,0,moved);
    setList(updated);
    setDragIdx(i);
  };
  const save=()=>{
    const renumbered=list.map((a,i)=>({...a,lot:genLot(i)}));
    setAuctions(renumbered);
    onClose();
  };
  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Reorder Lots</div><div className="msub">Drag to reorder — lot numbers update automatically</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="notice" style={{marginBottom:".9rem"}}>Drag any lot up or down. Lot numbers will be reassigned in order when you save.</div>
      <div className="reorder-list">
        {list.map((a,i)=><div key={a.id} className={`reorder-item${dragIdx===i?" dragging":""}`}
          draggable onDragStart={()=>onDragStart(i)} onDragOver={e=>onDragOver(e,i)} onDragEnd={()=>setDragIdx(null)}>
          <span className="reorder-handle">⠿</span>
          <span className="reorder-lot">{genLot(i)}</span>
          <div className="reorder-name">{a.year} {a.make} {a.model}</div>
          <CoBadge id={a.company}/>
          <span className={`cond-tag ${a.condition==="runs"?"runs":"no-start"}`} style={{position:"static",fontSize:".62rem",padding:".15rem .4rem"}}>{a.condition==="runs"?"✓":"✗"}</span>
        </div>)}
      </div>
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Cancel</button><button className="btn-p" onClick={save}>Save Order</button></div>
  </div></div>;
}

// ─── PAYMENT TRACKER ──────────────────────────────────────────────────────────
const PT_METHODS = [
  { id:"card",   label:"Credit Card", icon:"💳" },
  { id:"zelle",  label:"Zelle",       icon:"💸" },
  { id:"cash",   label:"Cash",        icon:"💵" },
  { id:"check",  label:"Check",       icon:"🧾" },
  { id:"venmo",  label:"Venmo",       icon:"📲" },
];

function PaymentTracker({auctions, setAuctions, feeSettings, bidders}){
  // Auction date tabs: current + past
  const auctionDates = [
    { id:"current", label:"Current Auction", lots:auctions },
    ...PAST_AUCTIONS.map(pa=>({ id:pa.id, label:pa.label, lots:pa.lots.map(l=>({
      ...l, payments:[], paperworkReceived:false,
      currentBid:l.finalBid, sold:l.status==="sold", winner:l.status==="sold"?"BID-EXT":null
    }))}))
  ];

  const [activeDate, setActiveDate] = useState("current");
  const [expanded, setExpanded] = useState({});
  const [addingFor, setAddingFor] = useState(null);
  const [newPay, setNewPay] = useState({method:"card", amount:"", note:"", staff:""});

  const activeLots = auctionDates.find(d=>d.id===activeDate)?.lots || [];
  const soldLots = activeLots.filter(a=>a.sold&&(a.winner||a.status==="sold"));

  // Only manage payments on current auction (past are read-only mock)
  const isCurrentAuction = activeDate==="current";

  const toggleExpand = id => setExpanded(e=>({...e,[id]:!e[id]}));

  const calcBalance = (a) => {
    if(!a.currentBid) return 0;
    const taxable = (a.currentBid||0)+(a.keyFee||0)+feeSettings.adminFee;
    const tax = a.taxExempt?0:+(taxable*feeSettings.taxRate/100).toFixed(2);
    return taxable+tax;
  };

  const totalReceived = (a) =>
    (a.payments||[]).filter(p=>p.received).reduce((s,p)=>s+(+p.amount||0),0);

  const markReceived = (lotId, payId, val) => {
    if(!isCurrentAuction) return;
    const now = new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+", "+new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,payments:(a.payments||[]).map(p=>p.id!==payId?p:{...p,received:val,ts:val?now:p.ts})}));
  };

  const togglePaperwork = (lotId) => {
    if(!isCurrentAuction) return;
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,paperworkReceived:!a.paperworkReceived}));
  };

  const deletePayment = (lotId, payId) => {
    if(!isCurrentAuction) return;
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,payments:(a.payments||[]).filter(p=>p.id!==payId)}));
  };

  const updatePayMethod = (lotId, payId, method) => {
    if(!isCurrentAuction) return;
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,payments:(a.payments||[]).map(p=>p.id!==payId?p:{...p,method})}));
  };

  const updatePayNote = (lotId, payId, note) => {
    if(!isCurrentAuction) return;
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,payments:(a.payments||[]).map(p=>p.id!==payId?p:{...p,note})}));
  };

  const addPayment = (lotId) => {
    if(!newPay.amount || !isCurrentAuction) return;
    const now = new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+", "+new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,payments:[...(a.payments||[]),{id:"pay"+Date.now(),method:newPay.method,amount:+newPay.amount,note:newPay.note,received:false,ts:now,staff:newPay.staff||"Staff"}]}));
    setNewPay({method:"card",amount:"",note:"",staff:""});
    setAddingFor(null);
  };

  // Summary stats for current view
  const totalInvoiced = soldLots.reduce((s,a)=>s+calcBalance(a),0);
  const totalCollected = soldLots.reduce((s,a)=>s+totalReceived(a),0);
  const fullyPaid = soldLots.filter(a=>totalReceived(a)>=calcBalance(a)&&calcBalance(a)>0).length;
  const paperworkDone = soldLots.filter(a=>a.paperworkReceived).length;

  const progressPill = (a) => {
    const bal = calcBalance(a);
    const rec = totalReceived(a);
    if(rec>=bal&&bal>0) return <span className="pt-progress-pill full">✓ Paid in Full</span>;
    if(rec>0) return <span className="pt-progress-pill partial">Partial — {fmtCurrency(rec)} / {fmtCurrency(bal)}</span>;
    return <span className="pt-progress-pill none">Unpaid</span>;
  };

  const methodIcon = id => PT_METHODS.find(m=>m.id===id)?.icon||"💰";
  const methodLabel = id => PT_METHODS.find(m=>m.id===id)?.label||id;

  return <div>
    {/* Auction date toggle */}
    <div className="pt-auction-toggle">
      {auctionDates.map(d=><button key={d.id} className={`pt-auction-btn${activeDate===d.id?" active":""}`} onClick={()=>{setActiveDate(d.id);setExpanded({});setAddingFor(null);}}>
        {d.label}
        <span style={{marginLeft:".4rem",fontFamily:"DM Mono,monospace",fontSize:".65rem",opacity:.7}}>
          ({d.lots.filter(l=>l.sold||l.status==="sold").length} sold)
        </span>
      </button>)}
    </div>

    {/* Summary stats */}
    <div className="pt-summary-bar">
      <div className="pt-stat"><div className="pt-stat-val">{soldLots.length}</div><div className="pt-stat-lbl">Sold Lots</div></div>
      <div className="pt-stat"><div className="pt-stat-val">{fmtCurrency(totalInvoiced)}</div><div className="pt-stat-lbl">Total Invoiced</div></div>
      <div className="pt-stat green"><div className="pt-stat-val">{fmtCurrency(totalCollected)}</div><div className="pt-stat-lbl">Collected</div></div>
      <div className="pt-stat red"><div className="pt-stat-val">{fmtCurrency(Math.max(0,totalInvoiced-totalCollected))}</div><div className="pt-stat-lbl">Outstanding</div></div>
      <div className="pt-stat green"><div className="pt-stat-val">{fullyPaid}/{soldLots.length}</div><div className="pt-stat-lbl">Paid in Full</div></div>
      <div className="pt-stat"><div className="pt-stat-val">{paperworkDone}/{soldLots.length}</div><div className="pt-stat-lbl">Paperwork ✓</div></div>
    </div>

    {soldLots.length===0&&<div style={{textAlign:"center",padding:"3rem",color:"var(--muted)",background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px"}}>
      <div style={{fontSize:"2rem",opacity:.3,marginBottom:".6rem"}}>📋</div>
      <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)"}}>No Sold Lots</div>
      <div style={{fontSize:".82rem",marginTop:".3rem"}}>Lots appear here once marked as Sold on the Lots tab.</div>
    </div>}

    {soldLots.map(a=>{
      const payments = a.payments||[];
      const bal = calcBalance(a);
      const rec = totalReceived(a);
      const isComplete = rec>=bal&&bal>0&&a.paperworkReceived;
      const open = !!expanded[a.id];
      const winnerBidder = bidders.find(b=>b.bidderNum===a.winner);

      return <div key={a.id} className={`pt-lot-card${isComplete?" complete":""}${(!a.sold&&a.status!=="sold")?" no-sale":""}`}>

        {/* Header */}
        <div className="pt-lot-hd" onClick={()=>toggleExpand(a.id)}>
          <div style={{flex:1,minWidth:0}}>
            <div style={{display:"flex",alignItems:"center",gap:".5rem",flexWrap:"wrap"}}>
              <div className="pt-lot-title">{a.lot} — {a.year} {a.make} {a.model}</div>
              {progressPill(a)}
              {a.paperworkReceived&&<span style={{fontSize:".68rem",color:"var(--green)",fontFamily:"DM Mono,monospace",fontWeight:600}}>📄 Paperwork ✓</span>}
            </div>
            <div className="pt-lot-sub">
              VIN: {a.vin} · Winner: {a.winner||"—"}
              {winnerBidder&&<span style={{marginLeft:".4rem"}}>({winnerBidder.first} {winnerBidder.last})</span>}
              {" · "}{fmtCurrency(a.currentBid||0)} winning bid
            </div>
          </div>
          <div style={{display:"flex",alignItems:"center",gap:".75rem",flexShrink:0}}>
            <div style={{textAlign:"right"}}>
              <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:rec>=bal&&bal>0?"var(--green)":"var(--red)"}}>{fmtCurrency(rec)}</div>
              <div style={{fontSize:".62rem",fontFamily:"DM Mono,monospace",color:"var(--muted)"}}>of {fmtCurrency(bal)}</div>
            </div>
            <span style={{color:"var(--muted)",fontSize:".85rem"}}>{open?"▲":"▼"}</span>
          </div>
        </div>

        {open&&<div className="pt-lot-body">

          {/* Payment rows */}
          {payments.length===0&&<div style={{fontSize:".8rem",color:"var(--muted)",fontStyle:"italic",marginBottom:".6rem",padding:".4rem .6rem"}}>No payment entries yet. Add one below.</div>}

          {payments.map(p=><div key={p.id} className={`pt-pay-row${p.received?" received":" pending"}`}>
            <div className="pt-pay-method-icon">{methodIcon(p.method)}</div>
            <div className="pt-pay-amount">{fmtCurrency(p.amount)}</div>
            {/* Method — editable dropdown */}
            {isCurrentAuction
              ? <select
                  value={p.method}
                  onChange={e=>updatePayMethod(a.id,p.id,e.target.value)}
                  onClick={e=>e.stopPropagation()}
                  style={{fontSize:".72rem",padding:".18rem .45rem",borderRadius:"4px",border:`1px solid ${p.received?"rgba(21,128,61,.35)":"rgba(220,38,38,.25)"}`,background:p.received?"rgba(21,128,61,.07)":"rgba(220,38,38,.05)",color:p.received?"var(--green)":"var(--red)",fontFamily:"DM Mono,monospace",fontWeight:600,cursor:"pointer",outline:"none",flexShrink:0}}>
                  {PT_METHODS.map(m=><option key={m.id} value={m.id}>{m.icon} {m.label}</option>)}
                </select>
              : <span style={{fontSize:".7rem",background:p.received?"rgba(21,128,61,.12)":"rgba(220,38,38,.08)",color:p.received?"var(--green)":"var(--red)",border:`1px solid ${p.received?"rgba(21,128,61,.25)":"rgba(220,38,38,.2)"}`,padding:".12rem .45rem",borderRadius:"3px",fontFamily:"DM Mono,monospace",fontWeight:600,flexShrink:0}}>
                  {methodLabel(p.method)}
                </span>}
            {/* Note — editable inline */}
            {isCurrentAuction
              ? <input
                  className="pt-pay-note"
                  value={p.note||""}
                  onChange={e=>updatePayNote(a.id,p.id,e.target.value)}
                  placeholder="Add note…"
                  style={{background:"transparent",border:"none",borderBottom:"1px dashed var(--border)",outline:"none",fontSize:".78rem",color:"var(--sub)",minWidth:"80px",flex:1,padding:".1rem 0"}}/>
              : <div className="pt-pay-note">{p.note||"—"}</div>}
            {p.received&&p.ts&&<div className="pt-pay-ts">{p.ts}</div>}
            {p.received&&p.staff&&<div className="pt-pay-staff">{p.staff}</div>}
            <label className="pt-received-toggle">
              <input type="checkbox" checked={p.received} onChange={e=>markReceived(a.id,p.id,e.target.checked)}/>
              <span style={{color:p.received?"var(--green)":"var(--muted)"}}>{p.received?"Received":"Mark Received"}</span>
            </label>
            {isCurrentAuction&&<button onClick={()=>deletePayment(a.id,p.id)} style={{background:"none",border:"none",color:"var(--muted)",cursor:"pointer",fontSize:".85rem",padding:"0 .2rem",flexShrink:0}} title="Remove">✕</button>}
          </div>)}

          {/* Add payment form */}
          {isCurrentAuction&&<>
            {addingFor===a.id
              ? <div style={{border:"1.5px solid var(--navy-mid)",borderRadius:"6px",padding:".85rem",background:"var(--navy-light)",marginBottom:".5rem"}}>
                  <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".6rem"}}>Add Payment Entry</div>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",marginBottom:".5rem"}}>
                    <div className="fgrp">
                      <label className="flbl">Method</label>
                      <select className="finput fselect" style={{fontSize:".82rem"}} value={newPay.method} onChange={e=>setNewPay(p=>({...p,method:e.target.value}))}>
                        {PT_METHODS.map(m=><option key={m.id} value={m.id}>{m.icon} {m.label}</option>)}
                      </select>
                    </div>
                    <div className="fgrp">
                      <label className="flbl">Amount ($)</label>
                      <input className="finput" type="number" style={{fontSize:".82rem"}} placeholder="0.00" value={newPay.amount} onChange={e=>setNewPay(p=>({...p,amount:e.target.value}))} onKeyDown={e=>e.key==="Enter"&&addPayment(a.id)}/>
                    </div>
                  </div>
                  <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",marginBottom:".65rem"}}>
                    <div className="fgrp">
                      <label className="flbl">Note (optional)</label>
                      <input className="finput" style={{fontSize:".82rem"}} placeholder="e.g. Balance payment, deposit, partial…" value={newPay.note} onChange={e=>setNewPay(p=>({...p,note:e.target.value}))}/>
                    </div>
                    <div className="fgrp">
                      <label className="flbl">Staff Name</label>
                      <input className="finput" style={{fontSize:".82rem"}} placeholder="Your name" value={newPay.staff} onChange={e=>setNewPay(p=>({...p,staff:e.target.value}))}/>
                    </div>
                  </div>
                  <div style={{display:"flex",gap:".5rem"}}>
                    <button className="btn-g" style={{flex:"0 0 auto",padding:".4rem .9rem",fontSize:".8rem"}} onClick={()=>{setAddingFor(null);setNewPay({method:"card",amount:"",note:"",staff:""});}}>Cancel</button>
                    <button className="btn-p" style={{flex:1,padding:".4rem",fontSize:".8rem"}} disabled={!newPay.amount} onClick={()=>addPayment(a.id)}>Add Payment Entry</button>
                  </div>
                </div>
              : <button onClick={()=>{setAddingFor(a.id);setNewPay({method:"card",amount:"",note:"",staff:""}); }}
                  style={{width:"100%",border:"1.5px dashed var(--navy-mid)",borderRadius:"5px",padding:".55rem",background:"var(--navy-light)",color:"var(--accent)",cursor:"pointer",fontSize:".8rem",fontWeight:600,marginBottom:".5rem",fontFamily:"DM Sans,sans-serif"}}>
                  + Add Payment Entry
                </button>}
          </>}

          {/* Balance line */}
          <div style={{display:"flex",justifyContent:"space-between",padding:".45rem .65rem",background:"var(--navy-light)",borderRadius:"5px",marginBottom:".55rem",fontSize:".83rem",borderTop:"2px solid var(--navy-mid)"}}>
            <span style={{color:"var(--muted)"}}>Total Invoice</span><span style={{fontWeight:600}}>{fmtCurrency(bal)}</span>
          </div>
          <div style={{display:"flex",justifyContent:"space-between",padding:".45rem .65rem",background:"rgba(21,128,61,.07)",borderRadius:"5px",marginBottom:".45rem",fontSize:".83rem",border:"1px solid rgba(21,128,61,.2)"}}>
            <span style={{color:"var(--green)",fontWeight:600}}>Received</span><span style={{fontWeight:600,color:"var(--green)"}}>{fmtCurrency(rec)}</span>
          </div>
          {bal-rec>0&&<div style={{display:"flex",justifyContent:"space-between",padding:".45rem .65rem",background:"rgba(220,38,38,.07)",borderRadius:"5px",marginBottom:".55rem",fontSize:".83rem",border:"1px solid rgba(220,38,38,.18)"}}>
            <span style={{color:"var(--red)",fontWeight:600}}>Outstanding</span><span style={{fontWeight:700,color:"var(--red)"}}>{fmtCurrency(bal-rec)}</span>
          </div>}

          {/* Paperwork checkbox */}
          <div className={`pt-paperwork${a.paperworkReceived?" done":""}`} onClick={()=>togglePaperwork(a.id)}>
            <input type="checkbox" checked={!!a.paperworkReceived} onChange={()=>togglePaperwork(a.id)} onClick={e=>e.stopPropagation()}/>
            <div style={{flex:1}}>
              <div className={`pt-paperwork-label${a.paperworkReceived?" done":""}`}>
                {a.paperworkReceived?"✓ Paperwork & Title Documents Received":"Mark Paperwork & Title Documents as Received"}
              </div>
              <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".15rem"}}>Check this once you have the signed title, lien release, and any other required documents from the buyer.</div>
            </div>
          </div>

        </div>}
      </div>;
    })}
  </div>;
}

// ─── AUCTION REPORT ───────────────────────────────────────────────────────────
const REPORT_RECIPIENTS = [
  "idan@mainiventerprises.com",
  "csrtowguysautoauction@gmail.com",
];

function AuctionReport({auctions, feeSettings, bidders}){
  const [sentLog, setSentLog] = useState([
    {id:"r1", date:"Tue Mar 18, 2026 · 8:00 PM", auction:"Tuesday Mar 18", lots:5, totalRevenue:"$10,100", status:"sent"},
    {id:"r2", date:"Fri Mar 14, 2026 · 8:00 PM", auction:"Friday Mar 14", lots:3, totalRevenue:"$6,000", status:"sent"},
  ]);
  const [sendingNow, setSendingNow] = useState(false);
  const [justSent, setJustSent] = useState(false);
  const [recipients, setRecipients] = useState(REPORT_RECIPIENTS.join(", "));
  const [auctionDay, setAuctionDay] = useState("tuesday");
  const [extraNote, setExtraNote] = useState("");

  // Fee calc helpers
  const calcFees = (a) => {
    const bid = a.currentBid || a.minBid || 0;
    const keyFee = a.keyFee || 0;
    const adminFee = feeSettings.adminFee;
    const taxable = bid + keyFee + adminFee;
    const tax = a.taxExempt ? 0 : parseFloat((taxable * feeSettings.taxRate / 100).toFixed(2));
    const total = taxable + tax;
    const deposited = 300;
    const collected = (a.payments||[]).filter(p=>p.received).reduce((s,p)=>s+(+p.amount||0),0);
    return {bid, keyFee, adminFee, tax, total, deposited, collected, outstanding: Math.max(0, total - collected)};
  };

  const soldLots = auctions.filter(a => a.sold && a.winner);
  const noSaleLots = auctions.filter(a => a.sold && !a.winner);

  const totalRevenue = soldLots.reduce((s,a) => s + calcFees(a).bid, 0);
  const totalCollected = soldLots.reduce((s,a) => s + calcFees(a).collected, 0);
  const totalOutstanding = soldLots.reduce((s,a) => s + calcFees(a).outstanding, 0);
  const totalTax = soldLots.reduce((s,a) => s + calcFees(a).tax, 0);
  const totalAdmin = soldLots.length * feeSettings.adminFee;
  const grandTotal = soldLots.reduce((s,a) => s + calcFees(a).total, 0);

  const methodIcon = id => ({card:"💳",zelle:"💸",cash:"💵",check:"🧾",venmo:"📲"})[id]||"💰";
  const methodLabel = id => ({card:"Card",zelle:"Zelle",cash:"Cash",check:"Check",venmo:"Venmo"})[id]||id;

  // Next scheduled send times
  const nextSend = (dayOfWeek) => {
    const now = new Date();
    const target = new Date(now);
    const diff = (dayOfWeek - now.getDay() + 7) % 7 || 7;
    target.setDate(now.getDate() + diff);
    target.setHours(20, 0, 0, 0);
    return target.toLocaleDateString("en-US",{weekday:"long",month:"short",day:"numeric"}) + " at 8:00 PM";
  };

  const handleSend = () => {
    setSendingNow(true);
    setTimeout(() => {
      setSendingNow(false);
      setJustSent(true);
      const now = new Date().toLocaleDateString("en-US",{weekday:"short",month:"short",day:"numeric",year:"numeric"})+" · "+new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});
      setSentLog(prev => [{id:"r"+Date.now(), date:now, auction:`${auctionDay==="tuesday"?"Tuesday":"Friday"} Auction`, lots:soldLots.length, totalRevenue:fmtCurrency(totalRevenue), status:"sent"}, ...prev]);
      setTimeout(() => setJustSent(false), 3000);
    }, 1200);
  };

  const bidderName = (bidderNum) => {
    const b = bidders.find(x => x.bidderNum === bidderNum);
    return b ? `${b.first} ${b.last}` : bidderNum;
  };

  return <div className="rpt-wrap">

    {/* Schedule status */}
    <div className="rpt-schedule-bar">
      {[{day:"Tuesday", dow:2, label:"Tuesday Auction", location:"Henderson"}, {day:"Friday", dow:5, label:"Friday Auction", location:"North Las Vegas"}].map(ev=><div key={ev.day} className="rpt-schedule-card">
        <div className="rpt-schedule-day">📅 {ev.label}</div>
        <div className="rpt-schedule-time">Report sends every {ev.day} at 8:00 PM</div>
        <div className="rpt-schedule-next">Next: {nextSend(ev.dow)}</div>
        <div className="rpt-schedule-status pending">● Scheduled</div>
      </div>)}
    </div>

    {/* Recipients & send now */}
    <div className="rpt-send-bar">
      <div className="rpt-recipients" style={{flex:2}}>
        <div className="rpt-recipients-label">Report Recipients</div>
        <input className="finput" style={{fontSize:".8rem",marginTop:".3rem"}} value={recipients} onChange={e=>setRecipients(e.target.value)} placeholder="email1@domain.com, email2@domain.com"/>
      </div>
      <div style={{flex:1,minWidth:140}}>
        <div className="rpt-recipients-label">Auction</div>
        <select className="finput fselect" style={{fontSize:".8rem",marginTop:".3rem"}} value={auctionDay} onChange={e=>setAuctionDay(e.target.value)}>
          <option value="tuesday">Tuesday — Henderson</option>
          <option value="friday">Friday — N. Las Vegas</option>
        </select>
      </div>
      <button className="btn-p" style={{padding:".6rem 1.4rem",flexShrink:0,fontSize:".85rem",background:justSent?"var(--green)":"var(--accent)",transition:"background .3s"}} onClick={handleSend} disabled={sendingNow||soldLots.length===0}>
        {sendingNow?"Sending…":justSent?"✓ Sent!":"Send Report Now"}
      </button>
    </div>

    {/* Extra note */}
    <div className="fgrp" style={{marginBottom:"1.2rem"}}>
      <label className="flbl">Optional Note (included in email)</label>
      <textarea className="finput" rows={2} style={{resize:"vertical",fontSize:".82rem"}} placeholder="e.g. Next auction is Tuesday Apr 1 — vehicles available for preview Monday 10am–4pm." value={extraNote} onChange={e=>setExtraNote(e.target.value)}/>
    </div>

    {/* Report Preview */}
    <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".65rem"}}>Report Preview</div>
    <div className="rpt-preview">
      <div className="rpt-preview-hd">
        <div>
          <div className="rpt-preview-title">Tow Guys Auto Auction — Post-Auction Report</div>
          <div className="rpt-preview-sub">
            {auctionDay==="tuesday"?"Tuesday Auction · 250 W Warm Springs Rd, Henderson":"Friday Auction · 3823 Losee Rd, North Las Vegas"} · Closes 2:00 PM
          </div>
        </div>
        <div className="rpt-preview-meta">
          {new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"})}<br/>
          Generated {new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})}
        </div>
      </div>
      <div className="rpt-preview-body">

        {soldLots.length===0&&<div style={{textAlign:"center",padding:"2rem",color:"var(--muted)",fontSize:".85rem"}}>No sold lots yet — report will populate once lots are marked as sold on the Lots tab.</div>}

        {/* Sold lots */}
        {soldLots.map(a => {
          const {bid, keyFee, adminFee, tax, total, deposited, collected, outstanding} = calcFees(a);
          const fullyPaid = outstanding <= 0;
          const payments = a.payments || [];
          const depositPayments = payments.filter(p => p.note?.toLowerCase().includes("deposit") || p.amount <= 300);
          const balancePayments = payments.filter(p => p.received && !depositPayments.find(d=>d.id===p.id));
          const allReceived = payments.filter(p=>p.received);

          return <div key={a.id} className="rpt-lot-row">
            <div className="rpt-lot-hd">
              <div>
                <div className="rpt-lot-name">{a.lot} — {a.year} {a.make} {a.model}</div>
                <div className="rpt-lot-vin">VIN: {a.vin} · {(a.mileage||0).toLocaleString()} mi · {a.condition==="runs"?"Runs":"No Start"}</div>
              </div>
              <div style={{display:"flex",gap:".5rem",alignItems:"center",flexShrink:0}}>
                <CoBadge id={a.company}/>
                {fullyPaid
                  ? <span className="rpt-pay-chip received">✓ Paid in Full</span>
                  : <span className="rpt-pay-chip pending">Outstanding: {fmtCurrency(outstanding)}</span>}
              </div>
            </div>
            <div className="rpt-lot-body">
              {/* Winner */}
              <div style={{marginBottom:".65rem",fontSize:".8rem",color:"var(--muted)"}}>
                <span style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".08em"}}>Winner: </span>
                <strong style={{color:"var(--text)"}}>{bidderName(a.winner)}</strong>
                <span style={{marginLeft:".5rem",fontFamily:"DM Mono,monospace",fontSize:".65rem"}}>{a.winner}</span>
              </div>
              {/* Fee breakdown grid */}
              <div className="rpt-fee-grid">
                <div className="rpt-fee-item"><div className="rpt-fee-lbl">Winning Bid</div><div className="rpt-fee-val accent">{fmtCurrency(bid)}</div></div>
                <div className="rpt-fee-item"><div className="rpt-fee-lbl">Key Fee</div><div className="rpt-fee-val">{keyFee>0?fmtCurrency(keyFee):"—"}</div></div>
                <div className="rpt-fee-item"><div className="rpt-fee-lbl">Admin Fee</div><div className="rpt-fee-val">{fmtCurrency(adminFee)}</div></div>
                <div className="rpt-fee-item"><div className="rpt-fee-lbl">Sales Tax {a.taxExempt?"(Exempt)":""}</div><div className="rpt-fee-val">{a.taxExempt?"—":fmtCurrency(tax)}</div></div>
                <div className="rpt-fee-item"><div className="rpt-fee-lbl">Deposit Applied</div><div className="rpt-fee-val green">−{fmtCurrency(deposited)}</div></div>
                <div className="rpt-fee-item"><div className="rpt-fee-lbl">Balance Due</div><div className={`rpt-fee-val ${fullyPaid?"green":"red"}`}>{fmtCurrency(Math.max(0,total-deposited))}</div></div>
              </div>
              {/* Total bar */}
              <div className="rpt-total-bar">
                <span className="rpt-total-label">Invoice Total</span>
                <span className="rpt-total-val">{fmtCurrency(total)}</span>
              </div>
              {/* Payment methods */}
              <div className="rpt-payments-title">Deposit Method</div>
              <div style={{marginBottom:".55rem"}}>
                {depositPayments.length>0
                  ? depositPayments.map(p=><span key={p.id} className={`rpt-pay-chip ${p.received?"received":"pending"}`}>{methodIcon(p.method)} {methodLabel(p.method)} {fmtCurrency(p.amount)}</span>)
                  : <span style={{fontSize:".75rem",color:"var(--muted)",fontStyle:"italic"}}>No deposit entry recorded</span>}
              </div>
              {fullyPaid&&allReceived.length>0&&<>
                <div className="rpt-payments-title">Paid In Full — Payment Breakdown</div>
                <div>
                  {allReceived.map(p=><span key={p.id} className="rpt-pay-chip received">{methodIcon(p.method)} {methodLabel(p.method)} {fmtCurrency(p.amount)}{p.ts?<span style={{opacity:.7,fontSize:".62rem",marginLeft:".25rem"}}>{p.ts}</span>:null}</span>)}
                </div>
              </>}
              {!fullyPaid&&balancePayments.length>0&&<>
                <div className="rpt-payments-title">Partial Payments Received</div>
                <div>
                  {balancePayments.map(p=><span key={p.id} className="rpt-pay-chip received">{methodIcon(p.method)} {methodLabel(p.method)} {fmtCurrency(p.amount)}</span>)}
                </div>
              </>}
            </div>
          </div>;
        })}

        {/* No-sale section */}
        {noSaleLots.length>0&&<div style={{marginTop:"1rem",padding:".85rem 1rem",background:"rgba(220,38,38,.04)",border:"1px solid rgba(220,38,38,.15)",borderRadius:"7px"}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--red)",marginBottom:".55rem"}}>{noSaleLots.length} No-Sale Lot{noSaleLots.length!==1?"s":""}</div>
          {noSaleLots.map(a=><div key={a.id} style={{display:"flex",justifyContent:"space-between",alignItems:"center",fontSize:".82rem",padding:".3rem 0",borderBottom:"1px solid rgba(220,38,38,.1)"}}>
            <span><strong>{a.lot}</strong> — {a.year} {a.make} {a.model}</span>
            <span style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)"}}>Min bid: {fmtCurrency(a.minBid)}</span>
          </div>)}
        </div>}

        {/* Extra note */}
        {extraNote&&<div style={{marginTop:"1rem",padding:".75rem 1rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",fontSize:".83rem",color:"var(--sub)",lineHeight:1.6,fontStyle:"italic"}}>"{extraNote}"</div>}

        {/* Summary footer */}
        {soldLots.length>0&&<div className="rpt-summary-footer">
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".6rem"}}>Auction Summary</div>
          <div className="rpt-summary-row"><span>Lots Sold</span><span>{soldLots.length} of {auctions.length}</span></div>
          <div className="rpt-summary-row"><span>Total Winning Bids</span><span>{fmtCurrency(totalRevenue)}</span></div>
          <div className="rpt-summary-row"><span>Key Fees</span><span>{fmtCurrency(soldLots.reduce((s,a)=>s+(a.keyFee||0),0))}</span></div>
          <div className="rpt-summary-row"><span>Admin Fees</span><span>{fmtCurrency(totalAdmin)}</span></div>
          <div className="rpt-summary-row"><span>Sales Tax</span><span>{fmtCurrency(totalTax)}</span></div>
          <div className="rpt-summary-row grand"><span>Grand Total Invoiced</span><span>{fmtCurrency(grandTotal)}</span></div>
          <div className="rpt-summary-row" style={{marginTop:".4rem"}}><span style={{color:"var(--green)",fontWeight:600}}>Collected</span><span style={{color:"var(--green)",fontWeight:700}}>{fmtCurrency(totalCollected)}</span></div>
          {totalOutstanding>0&&<div className="rpt-summary-row"><span style={{color:"var(--red)"}}>Outstanding</span><span style={{color:"var(--red)",fontWeight:700}}>{fmtCurrency(totalOutstanding)}</span></div>}
        </div>}

      </div>
    </div>

    {/* Sent log */}
    <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".65rem",marginTop:"1.5rem"}}>Send History</div>
    <div className="rpt-sent-log">
      {sentLog.map(r=><div key={r.id} className="rpt-sent-row">
        <span className="appr-badge">✓ Sent</span>
        <div style={{flex:1}}><div style={{fontWeight:500}}>{r.auction}</div><div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{r.date}</div></div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)"}}>{r.lots} lots · {r.totalRevenue}</div>
        <div style={{fontSize:".72rem",color:"var(--muted)"}}>→ {recipients.split(",").length} recipient{recipients.split(",").length!==1?"s":""}</div>
      </div>)}
    </div>

  </div>;
}

// ─── BID TABLE ───────────────────────────────────────────────────────────────
const DEPOSIT_THRESHOLD = 5000; // global default — overridden per bidder via admin

function BidTable({auctions, setAuctions, bidders, stagger}){
  const [overtime, setOvertime] = useState(1); // minutes
  const [overtimeEnabled, setOvertimeEnabled] = useState(true);
  const [tick, setTick] = useState(0);
  const [expandedBids, setExpandedBids] = useState({});

  // Live clock — refresh every second
  useEffect(()=>{
    const t = setInterval(()=>setTick(n=>n+1), 1000);
    return ()=>clearInterval(t);
  },[]);

  const now = Date.now();

  const fmtCountdown = (closeTime) => {
    const diff = closeTime - now;
    if(diff<=0) return {label:"CLOSED", cls:"done"};
    const s = Math.floor(diff/1000);
    const m = Math.floor(s/60);
    const h = Math.floor(m/60);
    if(h>1) return {label:`${h}h ${m%60}m`, cls:"ok"};
    if(m>=10) return {label:`${m}m ${s%60}s`, cls:"ok"};
    if(m>=3) return {label:`${m}m ${s%60}s`, cls:"soon"};
    return {label:`${m}m ${s%60}s`, cls:"urgent"};
  };

  const getBidderName = (num) => {
    if(!num) return null;
    const b = bidders.find(x=>x.bidderNum===num);
    return b ? `${b.first} ${b.last}` : num;
  };

  const getLeaderAutoBid = (a) => {
    if(!a.leader) return null;
    const ab = (a.autoBids||[]).find(x=>x.bidderNum===a.leader);
    return ab ? ab.maxBid : null;
  };

  // Simulate placing a bid from the bid table (admin manual override)
  const adminBid = (lotId, amount, bidderNum) => {
    const now = new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit"});
    setAuctions(prev=>prev.map(a=>{
      if(a.id!==lotId) return a;
      // Overtime: if bid lands within overtime window of close, extend
      const diffMs = a.closeTime - Date.now();
      const overtimeMs = overtime * 60 * 1000;
      const newClose = overtimeEnabled && diffMs>0 && diffMs<overtimeMs
        ? a.closeTime + overtimeMs
        : a.closeTime;
      return {
        ...a,
        currentBid: amount,
        bids: a.bids + 1,
        leader: bidderNum||a.leader,
        closeTime: newClose,
        isOvertime: overtimeEnabled && diffMs>0 && diffMs<overtimeMs,
        bidHistory: [...(a.bidHistory||[]), {bidder: bidderNum||"Manual", amount, ts:now}]
      };
    }));
  };

  const activeLots = auctions.filter(a=>!a.sold);
  const soldLots = auctions.filter(a=>a.sold);
  const totalActiveBids = activeLots.reduce((s,a)=>s+a.bids,0);
  const lotsClosingSoon = activeLots.filter(a=>a.closeTime-now < 5*60*1000 && a.closeTime>now).length;

  return <div className="bt-wrap">
    {/* Controls */}
    <div className="bt-controls">
      <div className="bt-stat"><strong>{activeLots.length}</strong>Active Lots</div>
      <div className="bt-stat"><strong>{soldLots.length}</strong>Sold</div>
      <div className="bt-stat"><strong>{totalActiveBids}</strong>Total Bids</div>
      {lotsClosingSoon>0&&<div className="bt-stat" style={{borderColor:"var(--red)"}}><strong style={{color:"var(--red)"}}>{lotsClosingSoon}</strong><span style={{color:"var(--red)"}}>Closing &lt;5 min</span></div>}
      <div style={{marginLeft:"auto",display:"flex",alignItems:"center",gap:".75rem",flexWrap:"wrap"}}>
        <label style={{display:"flex",alignItems:"center",gap:".4rem",fontSize:".8rem",cursor:"pointer"}}>
          <input type="checkbox" checked={overtimeEnabled} onChange={e=>setOvertimeEnabled(e.target.checked)} style={{width:14,height:14,accentColor:"var(--accent)"}}/>
          <span>Overtime</span>
        </label>
        {overtimeEnabled&&<div style={{display:"flex",alignItems:"center",gap:".35rem",fontSize:".8rem"}}>
          <input type="number" value={overtime} min={1} max={30} onChange={e=>setOvertime(+e.target.value)}
            style={{width:52,padding:".28rem .5rem",border:"1px solid var(--border)",borderRadius:"4px",fontFamily:"DM Mono,monospace",fontSize:".82rem",textAlign:"center"}}/>
          <span style={{color:"var(--muted)"}}>min extension on late bids</span>
        </div>}
      </div>
    </div>

    {/* Table — horizontally scrollable on mobile */}
    <div style={{position:"relative"}}>
      <div className="bt-scroll-wrap" style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px"}}>
        <table className="bt-table">
        <thead><tr>
          <th style={{width:80}}>Lot</th>
          <th>Vehicle</th>
          <th style={{width:130}}>VIN / Cond.</th>
          <th className="right" style={{width:130}}>Min Bid</th>
          <th className="right" style={{width:150,background:"rgba(255,255,255,.12)"}}>💰 Current Bid</th>
          <th style={{width:140}}>Auto-Bid</th>
          <th style={{width:160}}>Leader</th>
          <th className="right" style={{width:110}}>Closes</th>
          <th style={{width:80}}>Status</th>
        </tr></thead>
        <tbody>
          {auctions.map(a=>{
            const countdown = fmtCountdown(a.closeTime);
            const leaderName = getBidderName(a.leader);
            const leaderAutoBid = getLeaderAutoBid(a);
            const allAutoBids = a.autoBids||[];
            const isOT = !!a.isOvertime;
            const isSold = !!a.sold;
            const isLive = !isSold && a.closeTime > now;

            return <>
              <tr key={a.id}
                className={`${isSold?"bt-sold-row":""}${isOT?" bt-overtime":""}${a.leader&&isLive?" bt-leader":""}`}
                onClick={()=>setExpandedBids(e=>({...e,[a.id]:!e[a.id]}))}
                style={{cursor:"pointer"}}>
                <td><div className="bt-lot-num">{a.lot}</div></td>
                <td>
                  <div className="bt-vehicle">{a.year} {a.make} {a.model}</div>
                  <CoBadge id={a.company}/>
                </td>
                <td>
                  <div className="bt-vin" style={{marginBottom:"3px"}}>…{a.vin.slice(-8)}</div>
                  <span className={`bt-condition ${a.condition==="runs"?"runs":"ns"}`}>{a.condition==="runs"?"RUN":"N/S"}</span>
                </td>
                <td style={{textAlign:"right"}}>
                  <div style={{fontFamily:"DM Mono,monospace",fontSize:".82rem",color:"var(--muted)"}}>{fmtCurrency(a.minBid)}</div>
                  <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",marginTop:"2px"}}>+{fmtCurrency(a.increment)}/bid</div>
                </td>
                <td style={{textAlign:"right",background:"rgba(0,48,135,.03)"}}>
                  <div className="bt-bid" style={{fontSize:"1.2rem"}}>{fmtCurrency(a.currentBid||a.minBid)}</div>
                  <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)"}}>{a.bids} bid{a.bids!==1?"s":""}</div>
                </td>
                <td>
                  {leaderAutoBid
                    ? <div>
                        <span className="bt-autobid">🤖 max {fmtCurrency(leaderAutoBid)}</span>
                        {allAutoBids.length>1&&<div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",marginTop:"2px"}}>{allAutoBids.length} proxy{allAutoBids.length!==1?"s":""}</div>}
                      </div>
                    : allAutoBids.length>0
                      ? <span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{allAutoBids.length} proxy</span>
                      : <span style={{color:"var(--muted)",fontSize:".75rem"}}>—</span>}
                </td>
                <td>
                  {leaderName
                    ? <div>
                        <div className="bt-leader-tag winning">{a.leader}</div>
                        <div style={{fontSize:".7rem",color:"var(--muted)",marginTop:"2px"}}>{leaderName}</div>
                      </div>
                    : <span className="bt-leader-tag none">—</span>}
                </td>
                <td style={{textAlign:"right"}}>
                  <div className={`bt-time ${isSold?"done":countdown.cls}`}>
                    {isSold?"—":countdown.label}
                    {isOT&&<span className="bt-overtime-badge">OT</span>}
                  </div>
                </td>
                <td>
                  {isSold
                    ? <span className="lot-status-badge sold">SOLD</span>
                    : isLive
                      ? <span className="lot-status-badge live">LIVE</span>
                      : <span className="lot-status-badge no-sale">CLOSED</span>}
                </td>
              </tr>
              {/* Expanded bid history row */}
              {expandedBids[a.id]&&<tr key={a.id+"-exp"}>
                <td colSpan={9} style={{padding:0,background:"var(--navy-light)",borderTop:"none"}}>
                  <div style={{padding:".85rem 1.1rem"}}>
                    <div style={{display:"flex",alignItems:"flex-start",gap:"2rem",flexWrap:"wrap"}}>
                      {/* Bid history */}
                      <div style={{flex:1,minWidth:260}}>
                        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".5rem"}}>Bid History ({a.bids})</div>
                        <div style={{maxHeight:160,overflowY:"auto"}}>
                          {[...(a.bidHistory||[])].reverse().map((b,i)=><div key={i} style={{display:"flex",justifyContent:"space-between",padding:".28rem .5rem",borderRadius:"3px",background:i===0?"rgba(0,48,135,.08)":"transparent",marginBottom:"2px",fontSize:".78rem"}}>
                            <span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{b.ts}</span>
                            <span style={{flex:1,paddingLeft:".6rem",color:"var(--sub)"}}>{b.bidder}</span>
                            <span style={{fontFamily:"Bebas Neue,sans-serif",fontSize:".95rem",color:i===0?"var(--accent)":"var(--text)"}}>{fmtCurrency(b.amount)}</span>
                          </div>)}
                        </div>
                      </div>
                      {/* All proxy bids */}
                      {allAutoBids.length>0&&<div style={{minWidth:200}}>
                        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--blue)",marginBottom:".5rem"}}>Proxy / Auto-Bids</div>
                        {allAutoBids.map((ab,i)=><div key={i} style={{display:"flex",justifyContent:"space-between",alignItems:"center",padding:".28rem .5rem",background:"rgba(59,130,246,.06)",border:"1px solid rgba(59,130,246,.15)",borderRadius:"4px",marginBottom:".3rem",fontSize:".78rem"}}>
                          <span style={{fontFamily:"DM Mono,monospace",fontSize:".7rem"}}>{ab.bidderNum}</span>
                          <span style={{fontFamily:"DM Mono,monospace",fontSize:".7rem"}}>{getBidderName(ab.bidderNum)}</span>
                          <span className="bt-autobid">max {fmtCurrency(ab.maxBid)}</span>
                        </div>)}
                      </div>}
                      {/* Overtime note */}
                      <div style={{minWidth:180}}>
                        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--muted)",marginBottom:".5rem"}}>Overtime Settings</div>
                        <div style={{fontSize:".78rem",color:"var(--sub)",lineHeight:1.6}}>
                          {overtimeEnabled
                            ? <>Extension: <strong>{overtime} min</strong> per late bid<br/>
                                Any bid within {overtime} min of close extends by {overtime} min.<br/>
                                {isOT&&<span style={{color:"var(--accent2)",fontWeight:600}}>⚡ This lot is currently in overtime.</span>}</>
                            : <>Overtime is <strong>disabled</strong>.</>}
                        </div>
                      </div>
                    </div>
                  </div>
                </td>
              </tr>}
            </>;
          })}
        </tbody>
      </table>
      </div>
      {/* Mobile scroll hint */}
      <div style={{display:"none"}} className="bt-scroll-hint">← Scroll to see all columns →</div>
    </div>
  </div>;
}

// ─── THRESHOLD DEPOSIT MODAL ──────────────────────────────────────────────────
function ThresholdDepositModal({bidder, totalExposure, threshold, nextThreshold, onApprove, onDismiss}){
  const [step, setStep] = useState("confirm"); // "confirm" | "processing" | "approved"

  // Get the card on file from bidder's deposit method
  const cardOnFile = bidder?.payMethod === "card";
  const depositMethod = bidder?.payMethod || "card";
  const methodLabel = {card:"Credit Card on file", zelle:"Zelle", cash:"Cash"}[depositMethod]||"Card on file";
  const methodIcon = {card:"💳", zelle:"💸", cash:"💵"}[depositMethod]||"💳";

  const handleApprove = () => {
    setStep("processing");
    setTimeout(()=>{ setStep("approved"); }, 1200);
    setTimeout(()=>{ onApprove(); }, 2400);
  };

  return <div className="modal-bg" style={{zIndex:600}}>
    <div className="modal">
      <div className="mhd" style={{background: step==="approved"?"rgba(21,128,61,.08)":"rgba(220,38,38,.08)", borderBottom:`1px solid ${step==="approved"?"rgba(21,128,61,.25)":"rgba(220,38,38,.2)"}`}}>
        <div>
          <div className="mtitle" style={{color: step==="approved"?"var(--green)":"var(--red)"}}>
            {step==="approved" ? "✓ Deposit Approved" : "⚠ Additional Deposit Required"}
          </div>
          <div className="msub">
            {step==="approved"
              ? "$300 charged — you may continue bidding"
              : `Your combined winning total has exceeded ${fmtCurrency(threshold)}`}
          </div>
        </div>
      </div>

      <div className="mbody">
        {step!=="approved"&&<>
          {/* Exposure summary */}
          <div style={{background:"rgba(220,38,38,.05)",border:"1px solid rgba(220,38,38,.18)",borderRadius:"8px",padding:"1rem",marginBottom:"1rem",textAlign:"center"}}>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--red)",textTransform:"uppercase",letterSpacing:".1em",marginBottom:".3rem"}}>Your Combined Bid Total</div>
            <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"2.2rem",color:"var(--red)",lineHeight:1}}>{fmtCurrency(totalExposure)}</div>
            <div style={{fontSize:".75rem",color:"var(--muted)",marginTop:".2rem"}}>across {bidder?.leadingLots||"multiple"} leading lots — your limit is {fmtCurrency(threshold)}</div>
          </div>

          <p style={{fontSize:".84rem",color:"var(--sub)",lineHeight:1.65,marginBottom:"1rem"}}>
            Your combined bids have reached your credit limit. To place this bid, an additional refundable <strong style={{color:"var(--text)"}}>$300 deposit</strong> is required. Your new bidding limit will be raised to <strong style={{color:"var(--green)"}}>{fmtCurrency(nextThreshold||threshold+5000)}</strong>.
          </p>

          {/* Card on file charge box */}
          <div style={{background:"var(--navy-light)",border:"1.5px solid var(--navy-mid)",borderRadius:"8px",padding:"1rem 1.1rem",marginBottom:"1rem"}}>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".6rem"}}>
              Charge Method
            </div>
            <div style={{display:"flex",alignItems:"center",gap:".85rem"}}>
              <div style={{fontSize:"1.5rem",flexShrink:0}}>{methodIcon}</div>
              <div style={{flex:1}}>
                <div style={{fontWeight:700,fontSize:".9rem"}}>{methodLabel}</div>
                {cardOnFile&&<div style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)",marginTop:".15rem"}}>
                  Card ending •••• {bidder?.cardLast4||"on file"} · Charged immediately upon approval
                </div>}
                {!cardOnFile&&<div style={{fontSize:".75rem",color:"var(--muted)",marginTop:".15rem"}}>
                  {depositMethod==="zelle"
                    ? "Send $300 to csrtowguysautoauction@gmail.com — staff will confirm before activating."
                    : "Bring $300 cash to the auction site — staff will confirm receipt."}
                </div>}
              </div>
              <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:"var(--accent)",flexShrink:0}}>$300</div>
            </div>
            {cardOnFile&&<div style={{marginTop:".75rem",padding:".55rem .75rem",background:"rgba(21,128,61,.07)",border:"1px solid rgba(21,128,61,.2)",borderRadius:"5px",fontSize:".78rem",color:"var(--green)",fontFamily:"DM Mono,monospace"}}>
              ✓ By clicking Approve, you authorize a $300 charge to the card on file. No new card info needed.
            </div>}
          </div>

          <div className="notice" style={{marginBottom:0}}>This deposit is fully refundable if you do not win additional lots. It will be credited toward your invoice balance.</div>
        </>}

        {step==="approved"&&<div style={{textAlign:"center",padding:"1.5rem 1rem"}}>
          <div style={{fontSize:"3rem",marginBottom:".75rem"}}>✅</div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:"var(--green)",marginBottom:".4rem"}}>$300 Charged — Bid Placed!</div>
          <div style={{fontSize:".83rem",color:"var(--muted)",lineHeight:1.6}}>Your bid is in. New credit limit: <strong style={{color:"var(--green)"}}>{fmtCurrency(nextThreshold||threshold+5000)}</strong>. Returning you to the auction…</div>
        </div>}

        {step==="processing"&&<div style={{textAlign:"center",padding:"1.5rem 1rem"}}>
          <div style={{fontSize:"2rem",marginBottom:".75rem",animation:"spin 1s linear infinite",display:"inline-block"}}>⏳</div>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".82rem",color:"var(--muted)"}}>Processing charge…</div>
        </div>}
      </div>

      {step==="confirm"&&<div className="mfoot" style={{flexDirection:"column",gap:".55rem"}}>
        {cardOnFile
          ? <button className="btn-p" style={{width:"100%",fontSize:".92rem",padding:".7rem"}} onClick={handleApprove}>
              Approve — Charge $300 to Card on File
            </button>
          : <button className="btn-p" style={{width:"100%"}} onClick={handleApprove}>
              I Understand — I Will Send {methodIcon} $300
            </button>}
        <button className="btn-g" style={{width:"100%",color:"var(--red)",borderColor:"rgba(220,38,38,.25)",fontSize:".82rem"}} onClick={onDismiss}>
          Dismiss — I may lose my leading bids
        </button>
      </div>}
    </div>
  </div>;
}

// ─── DAILY REVENUE WIDGET ─────────────────────────────────────────────────────
function DailyRevenueWidget({auctions, feeSettings}){
  const today = new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric"});
  const sold = auctions.filter(a=>a.sold&&a.winner);
  const calcTotal = a=>{
    const bid=a.currentBid||0, kf=a.keyFee||0, af=feeSettings.adminFee;
    const tax=a.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
    return bid+kf+af+tax;
  };
  const totalInvoiced = sold.reduce((s,a)=>s+calcTotal(a),0);
  const totalCollected = sold.reduce((s,a)=>s+(a.payments||[]).filter(p=>p.received).reduce((x,p)=>x+(+p.amount||0),0),0);
  const outstanding = Math.max(0,totalInvoiced-totalCollected);
  const paidFull = sold.filter(a=>{
    const tot=calcTotal(a);
    const col=(a.payments||[]).filter(p=>p.received).reduce((x,p)=>x+(+p.amount||0),0);
    return col>=tot;
  }).length;

  return <div className="rev-widget">
    <div style={{flex:"0 0 auto"}}>
      <div className="rev-widget-title">Today's Revenue Snapshot</div>
      <div className="rev-widget-sub">{today}</div>
    </div>
    {[
      {val:sold.length, lbl:"Lots Sold"},
      {val:fmtCurrency(totalInvoiced), lbl:"Invoiced"},
      {val:fmtCurrency(totalCollected), lbl:"Collected"},
      {val:fmtCurrency(outstanding), lbl:"Outstanding"},
      {val:`${paidFull}/${sold.length}`, lbl:"Paid in Full"},
    ].map(s=><div key={s.lbl} className="rev-widget-stat">
      <div className="rev-widget-val">{s.val}</div>
      <div className="rev-widget-lbl">{s.lbl}</div>
    </div>)}
  </div>;
}

// ─── BIDDER HISTORY + FLAGGED ─────────────────────────────────────────────────
function BidderHistoryTab({bidders, setBidders, auctions, feeSettings}){
  const [expanded, setExpanded] = useState({});
  const [flagNote, setFlagNote] = useState({});
  const [filterFlag, setFilterFlag] = useState("all");
  const toggle = id => setExpanded(e=>({...e,[id]:!e[id]}));
  const toggleFlag = id => setBidders(bs=>bs.map(b=>b.id===id?{...b,flagged:!b.flagged,flagNote:b.flagged?"":b.flagNote}:b));
  const setFlag = (id,note) => setBidders(bs=>bs.map(b=>b.id===id?{...b,flagNote:note}:b));

  const calcBidderStats = (bidderNum) => {
    const wins = auctions.filter(a=>a.winner===bidderNum&&a.sold);
    const totalSpend = wins.reduce((s,a)=>{
      const bid=a.currentBid||0, kf=a.keyFee||0, af=feeSettings.adminFee;
      const tax=a.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
      return s+bid+kf+af+tax;
    },0);
    const collected = wins.reduce((s,a)=>s+(a.payments||[]).filter(p=>p.received).reduce((x,p)=>x+(+p.amount||0),0),0);
    return {wins: wins.length, totalSpend, collected, outstanding: Math.max(0,totalSpend-collected)};
  };

  const shown = bidders.filter(b=>filterFlag==="all"||(filterFlag==="flagged"&&b.flagged)||(filterFlag==="vip"&&b.whitelist)||(filterFlag==="clear"&&!b.flagged));

  return <div>
    {/* Stats bar */}
    <div style={{display:"flex",gap:".75rem",marginBottom:"1.2rem",flexWrap:"wrap"}}>
      {[["all","All",bidders.length],["flagged","⚑ Flagged",bidders.filter(b=>b.flagged).length],["vip","★ VIP",bidders.filter(b=>b.whitelist).length],["clear","✓ Clear",bidders.filter(b=>!b.flagged).length]].map(([f,l,ct])=>
        <button key={f} className={`filter-btn${filterFlag===f?" active":""}`} onClick={()=>setFilterFlag(f)}>
          {l} <span style={{marginLeft:".3rem",opacity:.7,fontSize:".75rem"}}>({ct})</span>
        </button>)}
    </div>

    {shown.map(b=>{
      const stats = calcBidderStats(b.bidderNum);
      const bidderWins = auctions.filter(a=>a.winner===b.bidderNum&&a.sold);
      const open = !!expanded[b.id];
      return <div key={b.id} className="bh-card">
        <div className="bh-card-hd" onClick={()=>toggle(b.id)}>
          <div style={{flex:1}}>
            <div style={{display:"flex",alignItems:"center",gap:".5rem",flexWrap:"wrap"}}>
              <div className="bh-name">{b.first} {b.last}</div>
              {b.flagged&&<span className="flag-badge flagged">⚑ FLAGGED</span>}
              {b.whitelist&&<span className="flag-badge vip">★ VIP</span>}
              {!b.flagged&&<span className="flag-badge clear">✓ Clear</span>}
            </div>
            <div className="bh-meta">{b.bidderNum} · {b.email} · Dep: {b.payMethod}</div>
          </div>
          <div style={{display:"flex",gap:"1.2rem",alignItems:"center",flexShrink:0}}>
            <div style={{textAlign:"right"}}>
              <div className="bh-stat">{stats.wins}</div>
              <div className="bh-stat-lbl">Wins</div>
            </div>
            <div style={{textAlign:"right"}}>
              <div className="bh-stat">{fmtCurrency(stats.totalSpend)}</div>
              <div className="bh-stat-lbl">Total Spend</div>
            </div>
            {stats.outstanding>0&&<div style={{textAlign:"right"}}>
              <div className="bh-stat" style={{color:"var(--red)"}}>{fmtCurrency(stats.outstanding)}</div>
              <div className="bh-stat-lbl" style={{color:"var(--red)"}}>Outstanding</div>
            </div>}
            <span style={{color:"var(--muted)",fontSize:".85rem"}}>{open?"▲":"▼"}</span>
          </div>
        </div>

        {open&&<div className="bh-card-body">
          {/* Flag controls */}
          <div style={{background:b.flagged?"rgba(220,38,38,.05)":"var(--navy-light)",border:`1px solid ${b.flagged?"rgba(220,38,38,.2)":"var(--border)"}`,borderRadius:"6px",padding:".75rem .9rem",marginBottom:"1rem"}}>
            <div style={{display:"flex",alignItems:"center",gap:".75rem",marginBottom:b.flagged?".55rem":"0"}}>
              <label style={{display:"flex",alignItems:"center",gap:".5rem",cursor:"pointer",flex:1}}>
                <input type="checkbox" checked={!!b.flagged} onChange={()=>toggleFlag(b.id)} style={{width:15,height:15,accentColor:"var(--red)"}}/>
                <span style={{fontWeight:600,fontSize:".88rem",color:b.flagged?"var(--red)":"var(--text)"}}>
                  {b.flagged?"⚑ Bidder Flagged — Restricted":"Flag this bidder (non-payment, dispute, chargeback…)"}
                </span>
              </label>
              {b.flagged&&<button className="btn-sm" style={{borderColor:"rgba(220,38,38,.3)",color:"var(--red)"}} onClick={()=>toggleFlag(b.id)}>Clear Flag</button>}
            </div>
            {b.flagged&&<div>
              <label className="flbl" style={{marginBottom:".3rem",display:"block"}}>Flag Reason</label>
              <input className="finput" style={{fontSize:".82rem"}} placeholder="e.g. Non-payment on LOT 003 Mar 18 — balance of $2,400 still owed"
                value={b.flagNote||""} onChange={e=>setFlag(b.id,e.target.value)}/>
              {b.flagNote&&<div style={{fontSize:".75rem",color:"var(--red)",marginTop:".35rem",fontStyle:"italic"}}>⚑ "{b.flagNote}"</div>}
            </div>}
          </div>

          {/* Win history */}
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".55rem"}}>
            Auction History ({bidderWins.length} wins)
          </div>
          {bidderWins.length===0
            ? <div style={{fontSize:".82rem",color:"var(--muted)",fontStyle:"italic",padding:".4rem .6rem"}}>No wins recorded in current auction.</div>
            : bidderWins.map(a=>{
                const bid=a.currentBid||0, kf=a.keyFee||0, af=feeSettings.adminFee;
                const tax=a.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
                const total=bid+kf+af+tax;
                const col=(a.payments||[]).filter(p=>p.received).reduce((x,p)=>x+(+p.amount||0),0);
                const paid=col>=total;
                return <div key={a.id} className="bh-auction-row">
                  <div style={{fontFamily:"Bebas Neue,sans-serif",color:"var(--accent)",fontSize:".9rem",flexShrink:0}}>{a.lot}</div>
                  <div style={{flex:1}}>
                    <div style={{fontWeight:500}}>{a.year} {a.make} {a.model}</div>
                    <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{a.vin}</div>
                  </div>
                  <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:"var(--accent)"}}>{fmtCurrency(total)}</div>
                  <span className={`appr-badge${paid?"":""}`} style={paid?{background:"rgba(21,128,61,.1)",color:"var(--green)"}:{background:"rgba(220,38,38,.08)",color:"var(--red)"}}>
                    {paid?"✓ Paid":`Owes ${fmtCurrency(total-col)}`}
                  </span>
                </div>;
              })}

          {/* Personal + deposit info */}
          <div style={{marginTop:".85rem",display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",fontSize:".8rem"}}>
            <div style={{background:"var(--navy-light)",border:"1px solid var(--border)",borderRadius:"5px",padding:".6rem .8rem"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",marginBottom:".35rem"}}>Contact</div>
              <div>{b.phone}</div><div style={{color:"var(--muted)"}}>{b.email}</div>
            </div>
            <div style={{background:"var(--navy-light)",border:"1px solid var(--border)",borderRadius:"5px",padding:".6rem .8rem"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",marginBottom:".35rem"}}>Deposit</div>
              <div>{b.payMethod==="card"?"💳 Card auto":"💸 Manual"} · {b.depositStatus==="approved"?"✓ Approved":"⏳ Pending"}</div>
              <div style={{color:"var(--muted)"}}>{b.keepOnFile?"On file (rolling)":"Per-auction"}</div>
            </div>
          </div>
        </div>}
      </div>;
    })}
  </div>;
}

// ─── BATCH INVOICE GENERATOR ──────────────────────────────────────────────────
function BatchInvoiceGenerator({auctions, feeSettings, bidders}){
  const soldLots = auctions.filter(a=>a.sold&&a.winner);
  const [selected, setSelected] = useState(()=>Object.fromEntries(soldLots.map(a=>[a.id,true])));
  const toggleSel = id => setSelected(s=>({...s,[id]:!s[id]}));
  const selAll = () => setSelected(Object.fromEntries(soldLots.map(a=>[a.id,true])));
  const selNone = () => setSelected({});

  const calcInv = a=>{
    const bid=a.currentBid||0, kf=a.keyFee||0, af=feeSettings.adminFee;
    const tax=a.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
    const total=bid+kf+af+tax;
    return {bid,kf,af,tax,total,balance:total-300};
  };
  const getBidderInfo = num => bidders.find(b=>b.bidderNum===num)||{first:"Unknown",last:"",email:"—",phone:"—",address:"—",city:"",state:"",zip:""};
  const printSelected = () => window.print();

  const invDate = new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"});
  const selectedLots = soldLots.filter(a=>selected[a.id]);

  return <div className="bi-wrap">
    {/* Controls */}
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",padding:"1rem 1.2rem",marginBottom:"1.2rem",display:"flex",alignItems:"center",gap:"1rem",flexWrap:"wrap"}}>
      <div>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)"}}>Batch Invoice Generator</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}}>{soldLots.length} sold lots · {selectedLots.length} selected</div>
      </div>
      <div style={{display:"flex",gap:".5rem",marginLeft:"auto",flexWrap:"wrap"}}>
        <button className="btn-sm" onClick={selAll}>Select All</button>
        <button className="btn-sm" onClick={selNone}>Clear</button>
        <button className="btn-p" disabled={selectedLots.length===0} onClick={printSelected}>🖨 Print {selectedLots.length} Invoice{selectedLots.length!==1?"s":""}</button>
      </div>
    </div>

    {/* Lot selector */}
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden",marginBottom:"1.5rem"}}>
      {soldLots.map(a=>{
        const {total}=calcInv(a);
        return <label key={a.id} style={{display:"flex",alignItems:"center",gap:".85rem",padding:".7rem 1.1rem",borderBottom:"1px solid var(--border)",cursor:"pointer",background:selected[a.id]?"rgba(0,48,135,.04)":"#fff",transition:"background .15s"}}>
          <input type="checkbox" checked={!!selected[a.id]} onChange={()=>toggleSel(a.id)} style={{width:16,height:16,accentColor:"var(--accent)"}}/>
          <div style={{flex:1}}>
            <div style={{fontWeight:600,fontSize:".88rem"}}>{a.lot} — {a.year} {a.make} {a.model}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{a.vin} · Winner: {a.winner}</div>
          </div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:"var(--accent)"}}>{fmtCurrency(total)}</div>
        </label>;
      })}
      {soldLots.length===0&&<div style={{padding:"2rem",textAlign:"center",color:"var(--muted)",fontSize:".85rem"}}>No sold lots with winners assigned. Close lots and assign winners on the Lots tab.</div>}
    </div>

    {/* Print preview of invoices */}
    {selectedLots.map((a,idx)=>{
      const {bid,kf,af,tax,total,balance}=calcInv(a);
      const bdr=getBidderInfo(a.winner);
      const invNum=`TGA-${a.id}-${a.lot.replace(" ","")}`;
      return <div key={a.id} className="bi-invoice">
        <div className="bi-inv-header">
          <div>
            <div className="bi-inv-title">Tow Guys Auto Auction</div>
            <div className="bi-inv-sub">250 W Warm Springs Rd, Henderson · 3823 Losee Rd, N. Las Vegas · (702) 677-0792</div>
            <div className="bi-inv-num">Invoice #{invNum}</div>
          </div>
          <div style={{textAlign:"right",fontFamily:"DM Mono,monospace",fontSize:".72rem",opacity:.8}}>
            {invDate}<br/>
            Nevada Lien Sale<br/>
            NRS Chapter 108
          </div>
        </div>
        <div className="bi-inv-body">
          {/* Winner info */}
          <div className="bi-winner-box">
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".45rem"}}>Buyer</div>
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".35rem .75rem",fontSize:".83rem"}}>
              <div><span style={{color:"var(--muted)"}}>Name: </span><strong>{bdr.first} {bdr.last}</strong></div>
              <div><span style={{color:"var(--muted)"}}>Bidder #: </span><strong style={{fontFamily:"DM Mono,monospace"}}>{a.winner}</strong></div>
              <div><span style={{color:"var(--muted)"}}>Phone: </span>{bdr.phone}</div>
              <div><span style={{color:"var(--muted)"}}>Email: </span>{bdr.email}</div>
              <div style={{gridColumn:"1/-1"}}><span style={{color:"var(--muted)"}}>Address: </span>{bdr.address}{bdr.city?`, ${bdr.city}`:""}{bdr.state?`, ${bdr.state}`:""} {bdr.zip}</div>
            </div>
          </div>

          {/* Vehicle */}
          <div className="bi-inv-vehicle">
            <div>
              <div className="bi-inv-vehicle-name">{a.year} {a.make} {a.model} — {a.lot}</div>
              <div className="bi-inv-vehicle-meta">VIN: {a.vin} · {(a.mileage||0).toLocaleString()} mi · {a.condition==="runs"?"Runs":"No Start"}</div>
            </div>
            <CoBadge id={a.company}/>
          </div>

          {/* Fee table */}
          <table className="bi-fee-table">
            <tbody>
              <tr><td className="lbl">Winning Bid</td><td className="val">{fmtCurrency(bid)}</td></tr>
              {kf>0&&<tr><td className="lbl">Key Fee</td><td className="val">{fmtCurrency(kf)}</td></tr>}
              <tr><td className="lbl">Admin Fee</td><td className="val">{fmtCurrency(af)}</td></tr>
              <tr><td className="lbl">Sales Tax {a.taxExempt?"(Exempt)":""}</td><td className="val">{a.taxExempt?"—":fmtCurrency(tax)}</td></tr>
              <tr className="total-row"><td>Invoice Total</td><td style={{textAlign:"right"}}>{fmtCurrency(total)}</td></tr>
              <tr className="deposit-row"><td>Deposit Applied</td><td className="val" style={{color:"var(--green)"}}>−{fmtCurrency(300)}</td></tr>
              <tr className="balance-row"><td style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem"}}>Balance Due</td><td className="val" style={{color:"var(--accent)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem"}}>{fmtCurrency(balance)}</td></tr>
            </tbody>
          </table>

          {/* Payment info */}
          {(a.payments||[]).length>0&&<div style={{marginBottom:".85rem",fontSize:".8rem"}}>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--muted)",marginBottom:".4rem"}}>Payments Received</div>
            {(a.payments||[]).filter(p=>p.received).map((p,i)=><div key={i} style={{display:"flex",justifyContent:"space-between",padding:".25rem 0",borderBottom:"1px solid var(--border)"}}>
              <span style={{color:"var(--muted)"}}>{({card:"💳 Card",zelle:"💸 Zelle",cash:"💵 Cash",check:"🧾 Check",venmo:"📲 Venmo"})[p.method]||"💰"} — {p.note||"Payment"}</span>
              <span style={{fontWeight:600,color:"var(--green)"}}>{fmtCurrency(p.amount)}</span>
            </div>)}
          </div>}

          {/* Signature area */}
          <div className="bi-signature-area">
            <div><div className="bi-sig-line"/><div className="bi-sig-label">Buyer Signature</div></div>
            <div><div className="bi-sig-line"/><div className="bi-sig-label">Date of Payment / Pickup</div></div>
            <div><div className="bi-sig-line"/><div className="bi-sig-label">Staff Signature</div></div>
            <div><div className="bi-sig-line"/><div className="bi-sig-label">Title Released By</div></div>
          </div>

          <div style={{marginTop:"1rem",padding:".65rem",background:"var(--navy-light)",borderRadius:"5px",fontSize:".72rem",color:"var(--muted)",lineHeight:1.6,borderTop:"1px solid var(--border)"}}>
            All sales are final, as-is. Vehicle must be picked up within 3 business days of auction close. Storage fees apply after 72 hours. Title released upon receipt of full payment. Nevada Lien Sale — NRS Chapter 108.
          </div>
        </div>
      </div>;
    })}
  </div>;
}

// ─── LIEN DOCUMENT GENERATOR ──────────────────────────────────────────────────
const LIEN_DOCS = [
  { id:"vp015", label:"VP-015", title:"Application for Certificate of Title (Lien Seller)", desc:"Primary title transfer document — completed by lien seller (Tow Guys)" },
  { id:"vp201", label:"VP-201", title:"Odometer Disclosure Statement", desc:"Required for vehicles under 10 years old with odometer under 99,999 mi" },
  { id:"vp147", label:"VP-147", title:"Bill of Sale", desc:"Proof of sale document given to buyer — attach to invoice" },
];

function LienDocGenerator({auctions, feeSettings, bidders}){
  const soldLots = auctions.filter(a=>a.sold&&a.winner);
  const [selectedLot, setSelectedLot] = useState(soldLots[0]?.id||"");
  const [overrides, setOverrides] = useState({});
  const [expandedDoc, setExpandedDoc] = useState({vp015:true,vp201:false,vp147:false});
  const [printed, setPrinted] = useState({});

  const lot = auctions.find(a=>a.id===selectedLot);
  const bidderNum = lot?.winner;
  const bdr = bidders.find(b=>b.bidderNum===bidderNum)||{};
  const lien = bdr.lienData||{};

  const fld = (key, fallback="") => overrides[key]!==undefined ? overrides[key] : (lien[key]||bdr[key]||fallback);
  const setFld = (key,val) => setOverrides(o=>({...o,[key]:val}));

  const today = new Date().toLocaleDateString("en-US",{month:"2-digit",day:"2-digit",year:"numeric"});
  const calcBid = () => {
    if(!lot) return {bid:0,total:0};
    const bid=lot.currentBid||0, kf=lot.keyFee||0, af=feeSettings.adminFee;
    const tax=lot.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
    return {bid, total:bid+kf+af+tax};
  };
  const {bid,total}=calcBid();

  const markPrinted = id => setPrinted(p=>({...p,[id]:true}));
  const allPrinted = LIEN_DOCS.every(d=>printed[d.id]);

  return <div className="lien-wrap">
    {/* Lot selector */}
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",padding:"1rem 1.2rem",marginBottom:"1.2rem",display:"flex",gap:"1rem",alignItems:"center",flexWrap:"wrap"}}>
      <div style={{flex:1}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",marginBottom:".35rem"}}>Lien Sale Document Packet</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}}>Select a sold lot to generate VP-015 / VP-201 / VP-147 pre-filled with buyer data</div>
      </div>
      <select className="finput fselect" style={{minWidth:260,fontSize:".85rem"}} value={selectedLot} onChange={e=>{setSelectedLot(e.target.value);setOverrides({});setPrinted({});}}>
        <option value="">Select a sold lot…</option>
        {soldLots.map(a=><option key={a.id} value={a.id}>{a.lot} — {a.year} {a.make} {a.model} · {a.winner}</option>)}
      </select>
    </div>

    {!lot&&<div style={{textAlign:"center",padding:"3rem",color:"var(--muted)",background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px"}}>
      <div style={{fontSize:"2rem",opacity:.3,marginBottom:".6rem"}}>📄</div>
      <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)"}}>Select a sold lot above to generate documents</div>
    </div>}

    {lot&&<>
      {/* Packet status */}
      <div style={{display:"flex",gap:".65rem",marginBottom:"1.2rem",flexWrap:"wrap"}}>
        {LIEN_DOCS.map(d=><div key={d.id} style={{display:"flex",alignItems:"center",gap:".4rem",padding:".4rem .85rem",borderRadius:"5px",background:printed[d.id]?"rgba(21,128,61,.1)":"var(--navy-light)",border:`1px solid ${printed[d.id]?"rgba(21,128,61,.25)":"var(--border)"}`,fontSize:".78rem",fontFamily:"DM Mono,monospace"}}>
          <span style={{color:printed[d.id]?"var(--green)":"var(--muted)"}}>{printed[d.id]?"✓":""}</span>
          <span style={{fontWeight:700,color:printed[d.id]?"var(--green)":"var(--accent)"}}>{d.label}</span>
          <span style={{color:"var(--muted)"}}>{printed[d.id]?"Printed":"Pending"}</span>
        </div>)}
        {allPrinted&&<div style={{padding:".4rem .85rem",borderRadius:"5px",background:"rgba(21,128,61,.1)",border:"1px solid rgba(21,128,61,.25)",fontSize:".78rem",fontFamily:"DM Mono,monospace",color:"var(--green)",fontWeight:700}}>✓ Full Packet Complete</div>}
      </div>

      {/* Shared buyer data (editable) */}
      <div className="lien-doc-card" style={{marginBottom:"1.2rem"}}>
        <div className="lien-doc-hd">
          <div>
            <div className="lien-doc-title">Buyer Information — Pre-filled from Registration</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:".15rem"}}>Edit any field — changes apply to all three documents below</div>
          </div>
        </div>
        <div className="lien-doc-body">
          <div className="lien-field-grid two" style={{marginBottom:".55rem"}}>
            {[["first","First Name"],["last","Last Name"]].map(([k,l])=><div key={k} className="lien-field"><div className="lien-field-lbl">{l}</div><div className="lien-field-val"><input value={fld(k)} onChange={e=>setFld(k,e.target.value)}/></div></div>)}
          </div>
          <div className="lien-field-grid full" style={{marginBottom:".55rem"}}>
            <div className="lien-field"><div className="lien-field-lbl">Street Address</div><div className="lien-field-val"><input value={fld("address")} onChange={e=>setFld("address",e.target.value)}/></div></div>
          </div>
          <div className="lien-field-grid" style={{marginBottom:".55rem"}}>
            {[["city","City"],["state","State"],["zip","Zip"]].map(([k,l])=><div key={k} className="lien-field"><div className="lien-field-lbl">{l}</div><div className="lien-field-val"><input value={fld(k)} onChange={e=>setFld(k,e.target.value)}/></div></div>)}
          </div>
          <div className="lien-field-grid two">
            {[["dl","Driver's License #"],["dlState","DL State"]].map(([k,l])=><div key={k} className="lien-field"><div className="lien-field-lbl">{l}</div><div className="lien-field-val"><input value={fld(k)} onChange={e=>setFld(k,e.target.value)}/></div></div>)}
          </div>
        </div>
      </div>

      {/* Individual documents */}
      {LIEN_DOCS.map(doc=><div key={doc.id} className="lien-doc-card">
        <div className="lien-doc-hd" style={{cursor:"pointer"}} onClick={()=>setExpandedDoc(e=>({...e,[doc.id]:!e[doc.id]}))}>
          <div>
            <div className="lien-doc-title">{doc.label} — {doc.title}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:".15rem"}}>{doc.desc}</div>
          </div>
          <div style={{display:"flex",gap:".5rem",alignItems:"center"}}>
            {printed[doc.id]&&<span style={{fontSize:".72rem",color:"var(--green)",fontFamily:"DM Mono,monospace",fontWeight:600}}>✓ Printed</span>}
            <button className="lien-print-btn" onClick={e=>{e.stopPropagation();markPrinted(doc.id);window.print();}}>🖨 Print {doc.label}</button>
            <span style={{color:"var(--muted)",fontSize:".85rem"}}>{expandedDoc[doc.id]?"▲":"▼"}</span>
          </div>
        </div>
        {expandedDoc[doc.id]&&<div className="lien-doc-body">
          <div className="lien-doc-form">
            <div className="lien-doc-form-title">Document Preview — {doc.label}</div>

            {/* Common header for all docs */}
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:".5rem",marginBottom:".65rem"}}>
              <div className="lien-field"><div className="lien-field-lbl">Date</div><div className="lien-field-val"><input defaultValue={today}/></div></div>
              <div className="lien-field"><div className="lien-field-lbl">Bidder #</div><div className="lien-field-val" style={{fontFamily:"DM Mono,monospace"}}><input value={bidderNum||""} readOnly style={{color:"var(--accent)"}}/></div></div>
              <div className="lien-field"><div className="lien-field-lbl">Lot #</div><div className="lien-field-val"><input value={lot?.lot||""} readOnly/></div></div>
            </div>

            {/* Vehicle block */}
            <div style={{marginBottom:".65rem",padding:".65rem .85rem",background:"var(--navy-light)",borderRadius:"5px",border:"1px solid var(--navy-mid)"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".45rem"}}>Vehicle</div>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:".4rem",fontSize:".82rem"}}>
                {[["Year",lot?.year],["Make",lot?.make],["Model",lot?.model],["VIN",lot?.vin],["Mileage",`${(lot?.mileage||0).toLocaleString()} mi`],["Condition",lot?.condition==="runs"?"Runs":"No Start"]].map(([l,v])=><div key={l}><span style={{color:"var(--muted)"}}>{l}: </span><strong>{v}</strong></div>)}
              </div>
            </div>

            {/* Buyer block */}
            <div style={{marginBottom:".65rem",padding:".65rem .85rem",background:"var(--navy-light)",borderRadius:"5px",border:"1px solid var(--navy-mid)"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".45rem"}}>Buyer (New Owner)</div>
              <div style={{fontSize:".82rem"}}>
                <div><strong>{fld("first")} {fld("last")}</strong></div>
                <div style={{color:"var(--muted)"}}>{fld("address")}{fld("city")?`, ${fld("city")}`:""}{fld("state")?`, ${fld("state")}`:""} {fld("zip")}</div>
                <div style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",marginTop:".2rem"}}>DL: {fld("dl")} ({fld("dlState")})</div>
              </div>
            </div>

            {/* Doc-specific fields */}
            {doc.id==="vp015"&&<>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",marginBottom:".5rem"}}>
                <div className="lien-field"><div className="lien-field-lbl">Sale Price</div><div className="lien-field-val"><input defaultValue={fmtCurrency(bid)}/></div></div>
                <div className="lien-field"><div className="lien-field-lbl">Lien Amount</div><div className="lien-field-val"><input defaultValue={fmtCurrency(total)}/></div></div>
              </div>
              <div className="lien-field" style={{marginBottom:".5rem"}}><div className="lien-field-lbl">Seller (Lien Holder)</div><div className="lien-field-val"><input defaultValue="Tow Guys / Mai Niv Enterprises Inc."/></div></div>
              <div className="lien-field"><div className="lien-field-lbl">Seller Address</div><div className="lien-field-val"><input defaultValue="250 W Warm Springs Rd, Henderson, NV 89011"/></div></div>
            </>}
            {doc.id==="vp201"&&<>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",marginBottom:".5rem"}}>
                <div className="lien-field"><div className="lien-field-lbl">Odometer Reading</div><div className="lien-field-val"><input defaultValue={(lot?.mileage||0).toLocaleString()}/></div></div>
                <div className="lien-field"><div className="lien-field-lbl">Odometer Status</div><div className="lien-field-val"><input defaultValue="Actual Mileage"/></div></div>
              </div>
            </>}
            {doc.id==="vp147"&&<>
              <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",marginBottom:".5rem"}}>
                <div className="lien-field"><div className="lien-field-lbl">Sale Amount</div><div className="lien-field-val"><input defaultValue={fmtCurrency(bid)}/></div></div>
                <div className="lien-field"><div className="lien-field-lbl">Total w/ Fees</div><div className="lien-field-val"><input defaultValue={fmtCurrency(total)}/></div></div>
              </div>
              <div className="lien-field"><div className="lien-field-lbl">As-Is Statement</div><div className="lien-field-val" style={{fontSize:".75rem",color:"var(--muted)",padding:".3rem 0"}}>Vehicle sold as-is, where-is. No warranties expressed or implied. Nevada Lien Sale — NRS Chapter 108.</div></div>
            </>}

            {/* Signature lines */}
            <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"1.5rem",marginTop:"1rem",paddingTop:".75rem",borderTop:"1px solid var(--border)"}}>
              <div><div className="bi-sig-line"/><div className="bi-sig-label">Seller Signature / Tow Guys Staff</div></div>
              <div><div className="bi-sig-line"/><div className="bi-sig-label">Buyer Signature</div></div>
            </div>
          </div>
        </div>}
      </div>)}
    </>}
  </div>;
}

// ─── AUCTION CLOSE WIZARD ─────────────────────────────────────────────────────
function AuctionCloseWizard({auctions, setAuctions, feeSettings, bidders, setBidders, onDone}){
  const [step, setStep] = useState(1);
  const [refundQueued, setRefundQueued] = useState({});
  const [notifSent, setNotifSent] = useState({});
  const [reAuctionDay, setReAuctionDay] = useState({});

  const soldLots = auctions.filter(a=>a.sold&&a.winner);
  const noSaleLots = auctions.filter(a=>a.sold&&!a.winner);
  const pendingLots = auctions.filter(a=>!a.sold);
  const losers = bidders.filter(b=>!soldLots.some(a=>a.winner===b.bidderNum));
  const winners = soldLots.map(a=>({...a, bidder:bidders.find(x=>x.bidderNum===a.winner)}));

  const calcBalance = a=>{
    const bid=a.currentBid||0,kf=a.keyFee||0,af=feeSettings.adminFee;
    const tax=a.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
    return bid+kf+af+tax-300;
  };

  const STEPS = ["Confirm Winners","Send Invoices","Deposit Refunds","No-Sale Lots","Complete"];
  const allWinnersSet = pendingLots.length===0;
  const allNotifsent = soldLots.every(a=>notifSent[a.id]);
  const allRefunds = losers.every(b=>refundQueued[b.id]);
  const allNoSales = noSaleLots.every(a=>reAuctionDay[a.id]);

  return <div>
    {/* Step bar */}
    <div className="wiz-step-bar">
      {STEPS.map((s,i)=><div key={i} className={`wiz-step${step===i+1?" active":step>i+1?" done":""}`}>
        <span className="wiz-step-num">{step>i+1?"✓":i+1}</span>
        <span className="wiz-step-lbl">{s}</span>
      </div>)}
    </div>

    {/* Step 1: Confirm Winners */}
    {step===1&&<div>
      {pendingLots.length>0&&<div className="notice warn" style={{marginBottom:"1rem"}}>
        <strong>{pendingLots.length} lot{pendingLots.length!==1?"s":""} not yet closed.</strong> Go to the Lots tab to assign winners or mark as No Sale before continuing.
      </div>}
      <div className="wiz-section">
        <div className="wiz-section-hd">
          Winners Confirmed ({soldLots.length} sold · {noSaleLots.length} no-sale)
        </div>
        {soldLots.map(a=><div key={a.id} className="wiz-lot-row">
          <div style={{flex:1}}>
            <div className="wiz-lot-name">{a.lot} — {a.year} {a.make} {a.model}</div>
            <div className="wiz-lot-sub">Winner: {a.winner} · Balance due: {fmtCurrency(calcBalance(a))}</div>
          </div>
          <span className="appr-badge">✓ {a.winner}</span>
        </div>)}
        {noSaleLots.map(a=><div key={a.id} className="wiz-lot-row">
          <div style={{flex:1}}>
            <div className="wiz-lot-name">{a.lot} — {a.year} {a.make} {a.model}</div>
            <div className="wiz-lot-sub">No bids met minimum</div>
          </div>
          <span className="nosale-tag">NO SALE</span>
        </div>)}
        {pendingLots.map(a=><div key={a.id} className="wiz-lot-row" style={{opacity:.6}}>
          <div style={{flex:1}}>
            <div className="wiz-lot-name">{a.lot} — {a.year} {a.make} {a.model}</div>
            <div className="wiz-lot-sub" style={{color:"var(--red)"}}>⚠ Not yet closed</div>
          </div>
          <span className="pend-badge">Pending</span>
        </div>)}
      </div>
      <div className="wiz-action-row">
        <button className="btn-p" onClick={()=>setStep(2)}>Next: Send Invoices →</button>
      </div>
    </div>}

    {/* Step 2: Send Invoices */}
    {step===2&&<div>
      <div className="notice" style={{marginBottom:"1rem"}}>Send each winner their invoice via email and/or SMS. Check each box once sent.</div>
      <div className="wiz-section">
        <div className="wiz-section-hd">
          Winner Notifications <span style={{fontSize:".75rem",fontWeight:400,color:"var(--muted)"}}>{Object.keys(notifSent).length}/{soldLots.length} sent</span>
        </div>
        {winners.map(({id,lot,year,make,model,winner,bidder,...rest})=>{
          const a = auctions.find(x=>x.id===id);
          return <div key={id} className="wiz-lot-row">
            <div style={{flex:1}}>
              <div className="wiz-lot-name">{lot} — {year} {make} {model}</div>
              <div className="wiz-lot-sub">{winner} · {bidder?.email||"no email"} · Balance: {fmtCurrency(calcBalance({...rest,id,lot,year,make,model,winner}))}</div>
            </div>
            <div style={{display:"flex",gap:".5rem",flexShrink:0}}>
              {notifSent[id]
                ? <span className="appr-badge">✓ Sent</span>
                : <button className="btn-approve" onClick={()=>setNotifSent(n=>({...n,[id]:true}))}>Send Invoice →</button>}
            </div>
          </div>;
        })}
      </div>
      <div className="wiz-action-row">
        <button className="btn-g" onClick={()=>setStep(1)}>← Back</button>
        <button className="btn-p" onClick={()=>setStep(3)}>Next: Refunds →</button>
      </div>
    </div>}

    {/* Step 3: Deposit Refunds */}
    {step===3&&<div>
      <div className="notice" style={{marginBottom:"1rem"}}>Queue deposit refunds for all bidders who did not win any lots. Winners' deposits are applied to their balance.</div>
      <div className="wiz-section">
        <div className="wiz-section-hd">
          Deposit Refunds <span style={{fontSize:".75rem",fontWeight:400,color:"var(--muted)"}}>{Object.keys(refundQueued).length}/{losers.length} queued</span>
        </div>
        {losers.length===0&&<div style={{padding:"1.2rem",fontSize:".84rem",color:"var(--muted)",textAlign:"center"}}>All approved bidders won at least one lot — no refunds needed.</div>}
        {losers.map(b=><div key={b.id} className="wiz-lot-row">
          <div style={{flex:1}}>
            <div className="wiz-lot-name">{b.first} {b.last} <span style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)"}}>{b.bidderNum}</span></div>
            <div className="wiz-lot-sub">{b.payMethod==="card"?"💳 Card":"💸 Manual"} · {b.keepOnFile?"Keep on file (will roll to next auction)":"Refund $300"}</div>
          </div>
          {b.keepOnFile
            ? <span style={{fontSize:".78rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}}>Rolls to next auction</span>
            : refundQueued[b.id]
              ? <span className="appr-badge">✓ Queued</span>
              : <button className="btn-approve" onClick={()=>setRefundQueued(r=>({...r,[b.id]:true}))}>Queue Refund $300</button>}
        </div>)}
      </div>
      <div className="wiz-action-row">
        <button className="btn-g" onClick={()=>setStep(2)}>← Back</button>
        <button className="btn-p" onClick={()=>setStep(4)}>Next: No-Sale Lots →</button>
      </div>
    </div>}

    {/* Step 4: No-Sale Lots */}
    {step===4&&<div>
      <div className="notice" style={{marginBottom:"1rem"}}>Choose what to do with each no-sale lot — re-queue for Tuesday or Friday, or archive.</div>
      <div className="wiz-section">
        <div className="wiz-section-hd">No-Sale Lots ({noSaleLots.length})</div>
        {noSaleLots.length===0&&<div style={{padding:"1.2rem",fontSize:".84rem",color:"var(--muted)",textAlign:"center"}}>🎉 No no-sale lots — everything sold!</div>}
        {noSaleLots.map(a=><div key={a.id} className="wiz-lot-row">
          <div style={{flex:1}}>
            <div className="wiz-lot-name">{a.lot} — {a.year} {a.make} {a.model}</div>
            <div className="wiz-lot-sub">VIN: {a.vin} · Min bid: {fmtCurrency(a.minBid)}</div>
          </div>
          <select className="finput fselect" style={{fontSize:".78rem",width:160}} value={reAuctionDay[a.id]||""}
            onChange={e=>setReAuctionDay(d=>({...d,[a.id]:e.target.value}))}>
            <option value="">Choose action…</option>
            <option value="tuesday">→ Next Tuesday</option>
            <option value="friday">→ Next Friday</option>
            <option value="archive">Archive — do not re-list</option>
          </select>
        </div>)}
      </div>
      <div className="wiz-action-row">
        <button className="btn-g" onClick={()=>setStep(3)}>← Back</button>
        <button className="btn-p" onClick={()=>setStep(5)}>Complete Auction →</button>
      </div>
    </div>}

    {/* Step 5: Done */}
    {step===5&&<div>
      <div className="wiz-done-box">
        <div className="wiz-done-icon">🏁</div>
        <div className="wiz-done-title">Auction Closed Successfully</div>
        <p style={{color:"var(--sub)",fontSize:".85rem",lineHeight:1.7,marginBottom:"1.1rem"}}>
          <strong>{soldLots.length}</strong> lots sold · <strong>{fmtCurrency(soldLots.reduce((s,a)=>s+(a.currentBid||0),0))}</strong> total revenue<br/>
          <strong>{Object.keys(notifSent).length}</strong> winners notified · <strong>{Object.keys(refundQueued).length}</strong> refunds queued<br/>
          <strong>{noSaleLots.length}</strong> no-sale lots processed
        </p>
        <div style={{display:"flex",gap:".75rem",justifyContent:"center",flexWrap:"wrap"}}>
          <button className="btn-p" onClick={onDone}>Go to Payment Tracker</button>
          <button className="btn-g" onClick={onDone}>Back to Dashboard</button>
        </div>
      </div>
    </div>}
  </div>;
}

// ─── AUCTION SCOREBOARD (countdown clock) ─────────────────────────────────────
function AuctionScoreboard({auctions, onClose}){
  const [tick,setTick]=useState(0);
  useEffect(()=>{ const t=setInterval(()=>setTick(n=>n+1),1000); return ()=>clearInterval(t); },[]);
  const now=Date.now();

  const fmtT=ms=>{
    if(ms<=0) return {label:"CLOSED",cls:"done"};
    const s=Math.floor(ms/1000), m=Math.floor(s/60), h=Math.floor(m/60);
    if(h>0) return {label:`${h}h ${m%60}m`,cls:"ok"};
    if(m>=5) return {label:`${m}m ${s%60}s`,cls:"ok"};
    if(m>=1) return {label:`${m}m ${s%60}s`,cls:"soon"};
    return {label:`${s}s`,cls:"urgent"};
  };

  const active=auctions.filter(a=>!a.sold&&a.closeTime>now).length;
  const sold=auctions.filter(a=>a.sold&&a.winner).length;
  const totalBids=auctions.reduce((s,a)=>s+a.bids,0);
  const closingSoon=auctions.filter(a=>!a.sold&&a.closeTime-now<3*60*1000&&a.closeTime>now).length;

  return <div className="scoreboard-wrap">
    <div className="scoreboard-header">
      <div>
        <div className="scoreboard-title">Tow Guys Auto Auction — Live</div>
        <div className="scoreboard-subtitle">{new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit"})} · {active} lots active · {sold} sold</div>
      </div>
      <div style={{display:"flex",gap:".85rem",alignItems:"center"}}>
        <div className="sc-stats-bar">
          {[{val:active,lbl:"Active"},{val:sold,lbl:"Sold"},{val:totalBids,lbl:"Bids"},{val:closingSoon,lbl:"< 3 min"}].map(s=><div key={s.lbl} className="sc-stat"><div className="sc-stat-val" style={{color:s.lbl==="< 3 min"&&s.val>0?"#ef4444":"#60a5fa"}}>{s.val}</div><div className="sc-stat-lbl">{s.lbl}</div></div>)}
        </div>
        <button className="sc-close-btn" onClick={onClose}>✕ Exit Scoreboard</button>
      </div>
    </div>
    <div className="scoreboard-grid">
      {auctions.map(a=>{
        const diff=a.closeTime-now;
        const {label,cls}=fmtT(diff);
        const isSold=a.sold;
        const isLive=!isSold&&diff>0;
        const isClosing=!isSold&&diff>0&&diff<3*60*1000;
        const reserveMet=!a.reserve||(a.currentBid||0)>=a.reserve;
        const reservePct=a.reserve?Math.min(100,Math.round(((a.currentBid||0)/a.reserve)*100)):100;
        return <div key={a.id} className={`scoreboard-card${isClosing?" closing":isSold?" sold":isLive?" live":" closed"}`}>
          <div className={`sc-status-badge${isClosing?" closing":isSold?" sold":" live"}`}>
            {isSold?"✓ SOLD":isClosing?"⚡ CLOSING":isLive?"● LIVE":"CLOSED"}
          </div>
          <div className="sc-lot">{a.lot}</div>
          <div className="sc-vehicle">{a.year} {a.make} {a.model}</div>
          <div className="sc-vin">{a.vin}</div>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-end"}}>
            <div>
              <div className="sc-bid-lbl">{isSold?"Final Bid":"Current Bid"}</div>
              <div className="sc-bid">{fmtCurrency(a.currentBid||a.minBid)}</div>
              <div className="sc-leader">{a.leader?t("card_active_bids"):`${t("card_min")}: ${fmtCurrency(a.minBid)}`}</div>
              {a.reserve&&<div style={{fontSize:".62rem",fontFamily:"DM Mono,monospace",marginTop:".2rem",color:reserveMet?"#4ade80":"#f87171"}}>
                Reserve: {fmtCurrency(a.reserve)} {reserveMet?"✓ Met":"— Not met"}
              </div>}
            </div>
            <div style={{textAlign:"right"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"rgba(255,255,255,.35)",marginBottom:".2rem"}}>{isSold?"Closed":isLive?"Closes in":""}</div>
              <div className={`sc-time ${cls}`}>{isSold?`${a.bids} bids`:label}{a.isOvertime&&<span className="sc-overtime">OT</span>}</div>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"rgba(255,255,255,.3)",marginTop:".2rem"}}>{a.bids} bid{a.bids!==1?"s":""}</div>
            </div>
          </div>
          {a.reserve&&!isSold&&<div className="sc-reserve-bar"><div className="sc-reserve-fill" style={{width:`${reservePct}%`}}/></div>}
        </div>;
      })}
    </div>
  </div>;
}

// ─── EMAIL PREVIEW FOR WINNERS ────────────────────────────────────────────────
function WinnerEmailPreview({auction, feeSettings, bidder, onClose}){
  const bid=auction.currentBid||auction.minBid;
  const kf=auction.keyFee||0;
  const af=feeSettings.adminFee;
  const taxable=bid+kf+af;
  const tax=auction.taxExempt?0:parseFloat((taxable*feeSettings.taxRate/100).toFixed(2));
  const total=taxable+tax;
  const balance=total-300;
  const winnerName=bidder?`${bidder.first} ${bidder.last}`:"Winner";
  const auctionDate=new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"});

  return <div className="modal-bg"><div className="modal wide" style={{maxWidth:680}}>
    <div className="mhd"><div><div className="mtitle">Email Preview — Winner Notification</div><div className="msub">{auction.lot} · {auction.winner}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:".65rem .9rem",marginBottom:"1rem",fontSize:".8rem"}}>
        <div><span style={{color:"var(--muted)"}}>To: </span>{bidder?.email||auction.winner}</div>
        <div><span style={{color:"var(--muted)"}}>From: </span>csrtowguysautoauction@gmail.com</div>
        <div><span style={{color:"var(--muted)"}}>Subject: </span><strong>🏆 You Won — {auction.lot}: {auction.year} {auction.make} {auction.model} — Balance Due: {fmtCurrency(balance)}</strong></div>
      </div>
      <div className="email-preview-wrap">
        <div className="email-preview-chrome">
          <div className="email-preview-dot" style={{background:"#ef4444"}}/>
          <div className="email-preview-dot" style={{background:"#f59e0b"}}/>
          <div className="email-preview-dot" style={{background:"#22c55e"}}/>
          <div className="email-preview-bar">csrtowguysautoauction@gmail.com</div>
        </div>
        <div className="email-preview-body">
          <div className="email-preview-header">
            <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",letterSpacing:".05em"}}>🏆 Congratulations — You Won!</div>
            <div style={{fontSize:".78rem",opacity:.8,marginTop:".2rem"}}>Tow Guys Auto Auction · Nevada Lien Sale</div>
          </div>
          <p style={{fontSize:".88rem",lineHeight:1.7,marginBottom:"1rem"}}>Hi <strong>{winnerName}</strong>,</p>
          <p style={{fontSize:".88rem",lineHeight:1.7,marginBottom:"1rem"}}>Great news — you are the winning bidder on <strong>{auction.lot}: {auction.year} {auction.make} {auction.model}</strong> at the {auctionDate} auction. Here are your invoice details:</p>

          <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:"1rem",marginBottom:"1rem"}}>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".6rem"}}>Invoice Summary</div>
            {[["Vehicle",`${auction.year} ${auction.make} ${auction.model}`],["VIN",auction.vin],["Lot",auction.lot],["Winning Bid",fmtCurrency(bid)],...(kf>0?[["Key Fee",fmtCurrency(kf)]]:[]),["Admin Fee",fmtCurrency(af)],["Sales Tax",auction.taxExempt?"Exempt":fmtCurrency(tax)],["Deposit Applied",`−${fmtCurrency(300)}`]].map(([l,v])=><div key={l} style={{display:"flex",justifyContent:"space-between",padding:".25rem 0",borderBottom:"1px solid var(--border)",fontSize:".83rem"}}>
              <span style={{color:"var(--muted)"}}>{l}</span><span style={{fontWeight:500}}>{v}</span>
            </div>)}
            <div style={{display:"flex",justifyContent:"space-between",padding:".45rem .6rem",marginTop:".5rem",background:"var(--accent)",color:"#fff",borderRadius:"5px",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.15rem"}}>
              <span>Balance Due</span><span>{fmtCurrency(balance)}</span>
            </div>
          </div>

          <p style={{fontSize:".85rem",lineHeight:1.7,marginBottom:".75rem"}}><strong>Payment is due within 48 hours.</strong> We accept Credit Card, Zelle ({`csrtowguysautoauction@gmail.com`}), and Cash.</p>
          <p style={{fontSize:".85rem",lineHeight:1.7,marginBottom:".75rem"}}>Vehicle must be picked up within 3 business days. Please contact us to schedule your pickup.</p>
          <div style={{textAlign:"center",margin:"1.2rem 0"}}>
            <div style={{display:"inline-block",background:"var(--accent)",color:"#fff",padding:".7rem 2rem",borderRadius:"6px",fontWeight:700,fontSize:".9rem",fontFamily:"DM Sans,sans-serif"}}>Pay Balance → {fmtCurrency(balance)}</div>
          </div>
          <div className="email-preview-footer">
            Tow Guys Auto Auction · (702) 677-0792 · csrtowguysautoauction@gmail.com<br/>
            250 W Warm Springs Rd, Henderson, NV 89011 (Tue) · 3823 Losee Rd, N. Las Vegas, NV 89030 (Fri)<br/>
            All sales are final, as-is. Nevada Lien Sale — NRS Chapter 108.
          </div>
        </div>
      </div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Close</button>
      <button className="btn-p" onClick={()=>alert("Email sent! (In production, this sends via SendGrid/Brevo)")}>Send Email Now</button>
    </div>
  </div></div>;
}

// ─── BIDDER BADGE ─────────────────────────────────────────────────────────────
function BidderBadgeModal({bidder, onClose}){
  const [selected,setSelected]=useState(bidder?.id||null);
  const [printBidder,setPrintBidder]=useState(bidder||null);
  const qrPattern=(n)=>{
    // Deterministic pseudo-QR grid from bidder number string
    const seed=n.split("").reduce((s,c)=>s+c.charCodeAt(0),0);
    const cells=[];
    for(let i=0;i<7;i++) for(let j=0;j<7;j++){
      const v=((seed*17+i*7+j*3)%31)>14;
      cells.push(<div key={`${i}-${j}`} style={{width:10,height:10,background:v?"#003087":"transparent"}}/>);
    }
    return <div style={{display:"grid",gridTemplateColumns:"repeat(7,10px)",gap:0,border:"2px solid #003087",padding:3,background:"#fff"}}>{cells}</div>;
  };
  const b=printBidder;
  if(!b) return null;

  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Bidder Badge</div><div className="msub">{b.bidderNum} · {b.first} {b.last}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="notice" style={{marginBottom:"1rem"}}>Print this badge and hand it to the bidder at check-in. The QR code encodes their bidder number.</div>
      <div className="badge-card">
        <div className="badge-logo">Tow Guys Auto Auction</div>
        <div className="badge-name">{b.first} {b.last}</div>
        <div className="badge-num">{b.bidderNum}</div>
        <div style={{display:"flex",gap:"1rem",alignItems:"flex-start"}}>
          <div style={{flex:1}}>
            <div className="badge-info-row">DL: <span className="badge-info-val" style={{fontFamily:"DM Mono,monospace"}}>{b.dl} ({b.dlState})</span></div>
            <div className="badge-info-row">Deposit: <span className="badge-info-val">{({card:"💳 Card",zelle:"💸 Zelle",cash:"💵 Cash"})[b.payMethod]||b.payMethod}</span></div>
            <div className="badge-info-row">Final Pay: <span className="badge-info-val">{({card:"💳 Card",zelle:"💸 Zelle",cash:"💵 Cash"})[b.finalPayMethod]||b.finalPayMethod}</span></div>
            {b.whitelist&&<div className="badge-deposit" style={{background:"rgba(59,130,246,.1)",borderColor:"rgba(59,130,246,.25)",color:"#2563eb"}}>★ VIP Whitelist</div>}
            <div className="badge-deposit">✓ $300 Deposit on File</div>
          </div>
          <div style={{flexShrink:0}}>
            {qrPattern(b.bidderNum)}
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textAlign:"center",marginTop:".3rem"}}>{b.bidderNum}</div>
          </div>
        </div>
        <div style={{marginTop:".85rem",paddingTop:".65rem",borderTop:"1px solid var(--border)",fontSize:".68rem",color:"var(--muted)",fontFamily:"DM Mono,monospace",lineHeight:1.5}}>
          Nevada Lien Sale · Closes 2:00 PM<br/>
          All sales final, as-is · (702) 677-0792
        </div>
      </div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Close</button>
      <button className="btn-p" onClick={()=>window.print()}>🖨 Print Badge</button>
    </div>
  </div></div>;
}

// ─── PRE-REGISTRATION LINK ────────────────────────────────────────────────────
function PreRegLinkModal({onClose}){
  const baseUrl=typeof window!=="undefined"?window.location.origin:"https://towguysautoauction.com";
  const link=`${baseUrl}?register=1`;
  const [copied,setCopied]=useState(false);
  const copy=()=>{ navigator.clipboard?.writeText(link).catch(()=>{}); setCopied(true); setTimeout(()=>setCopied(false),2000); };

  const SMS_TEMPLATES=[
    {label:"Standard",msg:`Hi! Register to bid at Tow Guys Auto Auction: ${link}\n$300 refundable deposit required. Auction closes 2:00 PM.`},
    {label:"Tuesday",msg:`Tuesday auction — register now to bid on repo vehicles! ${link}\nDeposit: $300 refundable. Gov't lien sale.`},
    {label:"Friday",msg:`Friday auction at our North Las Vegas location — bid on lien sale vehicles! ${link}\n$300 deposit to bid.`},
  ];
  const [selTemplate,setSelTemplate]=useState(0);

  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Pre-Registration Link</div><div className="msub">Share with potential bidders before auction day</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div style={{marginBottom:"1rem"}}>
        <label className="flbl">Registration URL</label>
        <div style={{display:"flex",gap:".5rem",marginTop:".35rem"}}>
          <input className="finput" value={link} readOnly style={{fontFamily:"DM Mono,monospace",fontSize:".78rem",flex:1}}/>
          <button className="btn-approve" style={{flexShrink:0}} onClick={copy}>{copied?"✓ Copied!":"Copy"}</button>
        </div>
        <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".35rem"}}>Opening this link takes the user directly to the registration modal on the public auction page.</div>
      </div>

      <div className="fsec-title" style={{marginBottom:".6rem"}}>SMS / Text Templates</div>
      <div style={{display:"flex",gap:".4rem",marginBottom:".65rem",flexWrap:"wrap"}}>
        {SMS_TEMPLATES.map((t,i)=><button key={i} className={`filter-btn${selTemplate===i?" active":""}`} onClick={()=>setSelTemplate(i)}>{t.label}</button>)}
      </div>
      <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:"1rem",marginBottom:".65rem",position:"relative"}}>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".45rem"}}>Text Message Preview</div>
        <div style={{fontSize:".85rem",lineHeight:1.65,color:"var(--text)",whiteSpace:"pre-wrap"}}>{SMS_TEMPLATES[selTemplate].msg}</div>
      </div>
      <div style={{display:"flex",gap:".5rem"}}>
        <button className="btn-g" style={{flex:1}} onClick={()=>{ navigator.clipboard?.writeText(SMS_TEMPLATES[selTemplate].msg).catch(()=>{}); setCopied(true); setTimeout(()=>setCopied(false),2000); }}>Copy Text</button>
        <a href={`sms:?body=${encodeURIComponent(SMS_TEMPLATES[selTemplate].msg)}`} style={{flex:1,textDecoration:"none"}}>
          <button className="btn-p" style={{width:"100%"}}>Open in Messages</button>
        </a>
      </div>
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Close</button></div>
  </div></div>;
}

// ─── AUCTION CLOSE SUMMARY (PDF layout) ───────────────────────────────────────
function AuctionCloseSummaryModal({auctions, feeSettings, bidders, auctionDate, auctionDayLabel, onClose}){
  const ev=AUCTION_EVENTS[auctionDayLabel||"tuesday"];
  const fmtDate=auctionDate?new Date(auctionDate+"T12:00:00").toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"}):new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"});

  const sold=auctions.filter(a=>a.sold&&a.winner);
  const noSale=auctions.filter(a=>a.sold&&!a.winner);
  const totalRevenue=sold.reduce((s,a)=>s+(a.currentBid||0),0);
  const totalKeyFees=sold.reduce((s,a)=>s+(a.keyFee||0),0);
  const totalAdmin=sold.length*feeSettings.adminFee;
  const totalTax=sold.filter(a=>!a.taxExempt).reduce((s,a)=>{const t=((a.currentBid||0)+(a.keyFee||0)+feeSettings.adminFee)*feeSettings.taxRate/100; return s+parseFloat(t.toFixed(2));},0);
  const grandTotal=totalRevenue+totalKeyFees+totalAdmin+totalTax;
  const totalCollected=sold.reduce((s,a)=>s+(a.payments||[]).filter(p=>p.received).reduce((x,p)=>x+(+p.amount||0),0),0);

  const getBidder=num=>bidders.find(b=>b.bidderNum===num)||{};

  const byCompany=COMPANIES.map(c=>{
    const cSold=sold.filter(a=>a.company===c.id);
    return {...c,count:cSold.length,rev:cSold.reduce((s,a)=>s+(a.currentBid||0),0)};
  }).filter(c=>c.count>0);

  return <div className="modal-bg"><div className="modal wide" style={{maxWidth:820}}>
    <div className="mhd"><div><div className="mtitle">Auction Close Summary</div><div className="msub">{fmtDate}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div className="pdf-summary">
        {/* Header */}
        <div className="pdf-summary-header">
          <div>
            <div className="pdf-summary-title">Post-Auction Summary</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".75rem",opacity:.8,marginTop:".2rem"}}>Tow Guys Auto Auction · {ev?.address}</div>
          </div>
          <div className="pdf-summary-meta">
            {fmtDate}<br/>
            Nevada Lien Sale — NRS Ch. 108<br/>
            Generated: {new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})}
          </div>
        </div>

        {/* Stats grid */}
        <div className="pdf-summary-section">
          <div className="pdf-summary-section-title">Auction Overview</div>
          <div className="pdf-stat-grid">
            {[{val:auctions.length,lbl:"Total Lots"},{val:sold.length,lbl:"Sold"},{val:noSale.length,lbl:"No Sale"},{val:fmtCurrency(totalRevenue),lbl:"Gross Revenue"},{val:fmtCurrency(totalAdmin),lbl:"Admin Fees"},{val:fmtCurrency(totalTax),lbl:"Sales Tax"},{val:fmtCurrency(grandTotal),lbl:"Grand Total"},{val:fmtCurrency(totalCollected),lbl:"Collected"}].map(s=><div key={s.lbl} className="pdf-stat-box"><div className="pdf-stat-val">{s.val}</div><div className="pdf-stat-lbl">{s.lbl}</div></div>)}
          </div>
        </div>

        {/* Revenue by company */}
        {byCompany.length>0&&<div className="pdf-summary-section">
          <div className="pdf-summary-section-title">Revenue by Company</div>
          <div className="rev-chart-wrap">
            {byCompany.map(c=><div key={c.id} className="rev-chart-bar-row">
              <div className="rev-chart-label" style={{color:c.color}}>{c.label}</div>
              <div className="rev-chart-track">
                <div className="rev-chart-fill" style={{width:`${totalRevenue>0?Math.round(c.rev/totalRevenue*100):0}%`,background:c.color}}>
                  <span className="rev-chart-fill-label">{totalRevenue>0?`${Math.round(c.rev/totalRevenue*100)}%`:""}</span>
                </div>
              </div>
              <div className="rev-chart-val">{fmtCurrency(c.rev)}</div>
              <div className="rev-chart-count">{c.count} lot{c.count!==1?"s":""}</div>
            </div>)}
          </div>
        </div>}

        {/* Sold lots detail */}
        <div className="pdf-summary-section">
          <div className="pdf-summary-section-title">Sold Lots ({sold.length})</div>
          {sold.map(a=>{
            const b=getBidder(a.winner);
            const bal=(a.currentBid||0)+(a.keyFee||0)+feeSettings.adminFee+(a.taxExempt?0:parseFloat((((a.currentBid||0)+(a.keyFee||0)+feeSettings.adminFee)*feeSettings.taxRate/100).toFixed(2)))-300;
            const col=(a.payments||[]).filter(p=>p.received).reduce((s,p)=>s+(+p.amount||0),0);
            const paid=col>=(bal+300);
            return <div key={a.id} className="pdf-lot-row">
              <span style={{fontFamily:"Bebas Neue,sans-serif",color:"var(--accent)",fontSize:".9rem",flexShrink:0}}>{a.lot}</span>
              <span style={{flex:1,fontWeight:600,minWidth:0}}>{a.year} {a.make} {a.model}</span>
              <span style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)",flexShrink:0}}>{a.winner} — {b.first} {b.last}</span>
              <span style={{fontFamily:"Bebas Neue,sans-serif",color:"var(--accent)",flexShrink:0}}>{fmtCurrency(a.currentBid||0)}</span>
              <span style={{flexShrink:0}}>{paid?<span className="appr-badge">✓ Paid</span>:<span className="pend-badge">Owes {fmtCurrency(Math.max(0,(bal+300)-col))}</span>}</span>
            </div>;
          })}
          {sold.length===0&&<div style={{fontSize:".83rem",color:"var(--muted)",fontStyle:"italic"}}>No lots sold.</div>}
        </div>

        {/* No-sale lots */}
        {noSale.length>0&&<div className="pdf-summary-section">
          <div className="pdf-summary-section-title">No-Sale Lots ({noSale.length})</div>
          {noSale.map(a=><div key={a.id} className="pdf-lot-row">
            <span style={{fontFamily:"Bebas Neue,sans-serif",color:"var(--muted)",fontSize:".9rem"}}>{a.lot}</span>
            <span style={{flex:1,color:"var(--muted)"}}>{a.year} {a.make} {a.model}</span>
            <span className="nosale-tag">NO SALE</span>
            <span style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)"}}>Min: {fmtCurrency(a.minBid)}</span>
          </div>)}
        </div>}

        {/* Footer */}
        <div style={{padding:".85rem 1.5rem",background:"var(--navy-light)",borderTop:"2px solid var(--navy-mid)",fontSize:".72rem",color:"var(--muted)",lineHeight:1.7}}>
          This document is for internal records only. All sales are final under Nevada lien sale law NRS Chapter 108. Tow Guys Auto Auction / Mai Niv Enterprises Inc.
        </div>
      </div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Close</button>
      <button className="btn-p" onClick={()=>window.print()}>🖨 Print / Save PDF</button>
    </div>
  </div></div>;
}

// ─── ENHANCED SUMMARY with revenue chart ──────────────────────────────────────
function RevenueByCompanyChart({auctions}){
  const sold=auctions.filter(a=>a.sold&&a.winner);
  const totalRev=sold.reduce((s,a)=>s+(a.currentBid||0),0)||1;
  return <div>
    <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".85rem"}}>Revenue by Company — Visual Breakdown</div>
    <div className="rev-chart-wrap">
      {COMPANIES.map(c=>{
        const cSold=sold.filter(a=>a.company===c.id);
        const rev=cSold.reduce((s,a)=>s+(a.currentBid||0),0);
        const pct=Math.round(rev/totalRev*100);
        return <div key={c.id} className="rev-chart-bar-row">
          <div className="rev-chart-label" style={{color:c.color}}>{c.label}</div>
          <div className="rev-chart-track">
            <div className="rev-chart-fill" style={{width:`${pct}%`,background:c.color}}>
              {pct>=8&&<span className="rev-chart-fill-label">{pct}%</span>}
            </div>
          </div>
          <div className="rev-chart-val">{fmtCurrency(rev)}</div>
          <div className="rev-chart-count">{cSold.length} lot{cSold.length!==1?"s":""}</div>
        </div>;
      })}
    </div>
  </div>;
}

// ─── BULK SMS BLAST ───────────────────────────────────────────────────────────
const SMS_CHAR_LIMIT = 160;

const SMS_TEMPLATES = [
  {
    id:"auction_live",
    label:"🔴 Auction Is Live",
    text:"Tow Guys Auto Auction is LIVE now! {N} vehicles available — bid before 2:00 PM. Register & bid: towguysautoauction.com · (702) 677-0792",
  },
  {
    id:"custom",
    label:"✏️ Custom Message",
    text:"",
  },
];

function BulkSMSBlast({bidders, auctions}){
  const approved = bidders.filter(b=>b.depositStatus==="approved"&&b.phone);
  const [selected, setSelected] = useState(()=>Object.fromEntries(approved.map(b=>[b.id,true])));
  const [templateIdx, setTemplateIdx] = useState(0);
  const [message, setMessage] = useState(SMS_TEMPLATES[0].text.replace("{N}",auctions.filter(a=>!a.sold).length));
  const [sentLog, setSentLog] = useState([]);
  const [justSent, setJustSent] = useState(false);
  const [showRecipients, setShowRecipients] = useState(true);

  // Keep selected in sync as approved list changes (new bidders auto-added)
  useEffect(()=>{
    setSelected(prev=>{
      const next={...prev};
      approved.forEach(b=>{ if(!(b.id in next)) next[b.id]=true; });
      return next;
    });
  },[approved.length]);

  const toggleAll = (val) => setSelected(Object.fromEntries(approved.map(b=>[b.id,val])));
  const toggle = (id) => setSelected(s=>({...s,[id]:!s[id]}));
  const selectedBidders = approved.filter(b=>selected[b.id]);
  const charCount = message.length;
  const over = charCount > SMS_CHAR_LIMIT;
  const segments = Math.ceil(charCount/SMS_CHAR_LIMIT)||1;

  const pickTemplate = (idx) => {
    setTemplateIdx(idx);
    if(SMS_TEMPLATES[idx].id!=="custom")
      setMessage(SMS_TEMPLATES[idx].text.replace("{N}", auctions.filter(a=>!a.sold).length));
    else
      setMessage("");
  };

  const handleSend = () => {
    if(!message.trim()||selectedBidders.length===0) return;
    // Open native sms: URI — works on iPhone/Android, opens Messages pre-filled
    const nums = selectedBidders.map(b=>b.phone.replace(/\D/g,"")).join(",");
    window.open(`sms:${nums}?body=${encodeURIComponent(message)}`,"_self");
    // Log it
    const now = new Date().toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"});
    setSentLog(prev=>[{id:"s"+Date.now(),ts:now,recipients:selectedBidders.length,preview:message.slice(0,55)+(message.length>55?"…":""),template:SMS_TEMPLATES[templateIdx].label},...prev]);
    setJustSent(true);
    setTimeout(()=>setJustSent(false),3000);
  };

  return <div className="sms-wrap">

    {/* Templates */}
    <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".65rem"}}>Choose Message</div>
    <div className="sms-template-grid" style={{gridTemplateColumns:"1fr 1fr"}}>
      {SMS_TEMPLATES.map((tpl,i)=><button key={tpl.id} className={`sms-template-btn${templateIdx===i?" active":""}`} onClick={()=>pickTemplate(i)}>
        <div className="sms-template-label">{tpl.label}</div>
        <div className="sms-template-preview">{tpl.text||"Write your own message…"}</div>
      </button>)}
    </div>

    {/* Compose */}
    <div className="sms-compose">
      <div className="sms-compose-lbl">Message Text</div>
      <textarea className="sms-textarea" value={message} onChange={e=>setMessage(e.target.value)} placeholder="Type your message…"/>
      <div className={`sms-char-count ${over?"over":"ok"}`}>
        {charCount}/{SMS_CHAR_LIMIT}{segments>1?` · ${segments} segments`:""}{over&&<span style={{color:"var(--red)",marginLeft:".4rem"}}>⚠ splits into {segments} messages</span>}
      </div>
    </div>

    {/* Stats */}
    <div style={{display:"flex",gap:".75rem",marginBottom:"1rem",flexWrap:"wrap"}}>
      {[
        {val:approved.length,lbl:"On List",color:"var(--accent)"},
        {val:selectedBidders.length,lbl:"Will Receive",color:"var(--green)"},
        {val:approved.length-selectedBidders.length,lbl:"Excluded",color:"var(--muted)"},
      ].map(s=><div key={s.lbl} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"7px",padding:".6rem 1rem",flex:1,minWidth:90}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.5rem",color:s.color,lineHeight:1}}>{s.val}</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".07em",marginTop:".12rem"}}>{s.lbl}</div>
      </div>)}
    </div>

    {/* Recipients list */}
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden",marginBottom:"1.1rem"}}>
      <div style={{padding:".7rem 1rem",borderBottom:"1px solid var(--border)",display:"flex",alignItems:"center",justifyContent:"space-between",background:"var(--navy-light)",cursor:"pointer"}} onClick={()=>setShowRecipients(r=>!r)}>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)"}}>
          Recipients — {selectedBidders.length}/{approved.length} · New bidders auto-added ✓
        </div>
        <div style={{display:"flex",gap:".5rem",alignItems:"center"}}>
          <button className="btn-sm" style={{fontSize:".72rem"}} onClick={e=>{e.stopPropagation();toggleAll(true);}}>All</button>
          <button className="btn-sm" style={{fontSize:".72rem"}} onClick={e=>{e.stopPropagation();toggleAll(false);}}>None</button>
          <span style={{color:"var(--muted)",fontSize:".85rem"}}>{showRecipients?"▲":"▼"}</span>
        </div>
      </div>
      {showRecipients&&<div style={{maxHeight:280,overflowY:"auto"}}>
        {approved.length===0&&<div style={{padding:"1.5rem",textAlign:"center",color:"var(--muted)",fontSize:".83rem"}}>No approved bidders with phone numbers yet. They'll appear here automatically once approved.</div>}
        {approved.map(b=><label key={b.id} className="sms-recipient-card" style={{cursor:"pointer"}}>
          <input type="checkbox" className="sms-recipient-check" checked={!!selected[b.id]} onChange={()=>toggle(b.id)}/>
          <div style={{flex:1,minWidth:0}}>
            <div style={{fontWeight:600,fontSize:".84rem"}}>{b.first} {b.last}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)",marginTop:"1px"}}>{b.phone} · {b.bidderNum}</div>
          </div>
          <div style={{display:"flex",gap:".4rem",flexShrink:0,alignItems:"center"}}>
            {b.whitelist&&<span style={{fontSize:".65rem",fontFamily:"DM Mono,monospace",color:"var(--blue)",fontWeight:600}}>★ VIP</span>}
            <span className="appr-badge" style={{fontSize:".65rem"}}>✓</span>
          </div>
        </label>)}
      </div>}
    </div>

    {/* Send button */}
    <button className="sms-send-btn" disabled={!message.trim()||selectedBidders.length===0} onClick={handleSend} style={{background:justSent?"var(--green)":"var(--green)"}}>
      {justSent?`✓ Messages App Opened — ${selectedBidders.length} recipients`:`📱 Open Messages — Send to ${selectedBidders.length} Bidder${selectedBidders.length!==1?"s":""}`}
    </button>

    {/* Log */}
    {sentLog.length>0&&<div style={{marginTop:"1.5rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".6rem"}}>Send History</div>
      <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden"}}>
        {sentLog.map(s=><div key={s.id} className="sms-log-row">
          <span className="sms-sent-badge">✓ Sent</span>
          <div style={{flex:1,minWidth:0}}>
            <div style={{fontSize:".82rem",fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}>{s.preview}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:"2px"}}>{s.template} · {s.ts}</div>
          </div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:".9rem",color:"var(--accent)",flexShrink:0}}>{s.recipients} sent</div>
        </div>)}
      </div>
    </div>}
  </div>;
}

// ─── RECURRING BIDDER ACCOUNTS ────────────────────────────────────────────────
function RecurringBidderAccounts({bidders, setBidders, auctions, feeSettings}){
  const [search, setSearch] = useState("");
  const [expandedId, setExpandedId] = useState(null);

  const calcStats = (bidderNum) => {
    const wins = auctions.filter(a=>a.winner===bidderNum&&a.sold);
    const totalSpend = wins.reduce((s,a)=>{
      const bid=a.currentBid||0, kf=a.keyFee||0, af=feeSettings.adminFee;
      const tax=a.taxExempt?0:parseFloat(((bid+kf+af)*feeSettings.taxRate/100).toFixed(2));
      return s+bid+kf+af+tax;
    },0);
    const paid = wins.reduce((s,a)=>s+(a.payments||[]).filter(p=>p.received).reduce((x,p)=>x+(+p.amount||0),0),0);
    const auctionsParticipated = auctions.filter(a=>(a.bidHistory||[]).some(b=>b.bidder?.includes(bidderNum))).length;
    return {wins:wins.length, totalSpend, paid, outstanding:Math.max(0,totalSpend-paid), auctionsParticipated};
  };

  const returning = bidders.filter(b=>{
    const stats = calcStats(b.bidderNum);
    return stats.wins>0 || stats.auctionsParticipated>0;
  });

  const shown = bidders.filter(b=>{
    if(!search) return true;
    const q=search.toLowerCase();
    return `${b.first} ${b.last} ${b.email} ${b.bidderNum} ${b.phone}`.toLowerCase().includes(q);
  });

  const autoApproveReturning = (id) => {
    setBidders(bs=>bs.map(b=>b.id!==id?b:{
      ...b,
      depositStatus:"approved",
      depositOnFile:true,
      depositConfirmedAt:new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})+", "+new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"}),
      depositNote:"Auto-approved — returning bidder with clean payment history",
    }));
  };

  const isReturning = (bidderNum) => {
    const s=calcStats(bidderNum);
    return s.wins>0||s.auctionsParticipated>0;
  };

  const hasOutstanding = (bidderNum) => calcStats(bidderNum).outstanding>0;

  return <div>
    {/* Summary */}
    <div style={{display:"flex",gap:".75rem",marginBottom:"1.2rem",flexWrap:"wrap"}}>
      {[
        {val:bidders.length, lbl:"Total Bidders", color:"var(--accent)"},
        {val:returning.length, lbl:"Returning", color:"var(--green)"},
        {val:bidders.filter(b=>b.depositStatus==="approved").length, lbl:"Approved", color:"var(--green)"},
        {val:bidders.filter(b=>b.flagged).length, lbl:"Flagged", color:"var(--red)"},
        {val:bidders.filter(b=>hasOutstanding(b.bidderNum)).length, lbl:"Outstanding Balance", color:"var(--accent2)"},
      ].map(s=><div key={s.lbl} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"7px",padding:".6rem .9rem",flex:1,minWidth:90}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:s.color,lineHeight:1}}>{s.val}</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".07em",marginTop:".12rem"}}>{s.lbl}</div>
      </div>)}
    </div>

    {/* Search */}
    <div className="search-wrap" style={{maxWidth:"100%",marginBottom:"1rem"}}>
      <span className="search-icon">🔍</span>
      <input className="search-input" placeholder="Search by name, email, phone, or bidder #…" value={search} onChange={e=>setSearch(e.target.value)}/>
      {search&&<button className="search-clear" onClick={()=>setSearch("")}>×</button>}
    </div>

    {/* Bidder rows */}
    {shown.map(b=>{
      const stats = calcStats(b.bidderNum);
      const isRet = isReturning(b.bidderNum);
      const hasOut = stats.outstanding>0;
      const open = expandedId===b.id;
      return <div key={b.id} style={{background:"var(--card)",border:`1px solid ${b.flagged?"rgba(220,38,38,.3)":hasOut?"rgba(245,158,11,.3)":isRet?"rgba(21,128,61,.2)":"var(--border)"}`,borderRadius:"8px",marginBottom:".7rem",overflow:"hidden"}}>
        <div style={{padding:".75rem 1.1rem",display:"flex",alignItems:"center",gap:".85rem",cursor:"pointer",background:b.flagged?"rgba(220,38,38,.03)":isRet?"rgba(21,128,61,.03)":"var(--navy-light)",flexWrap:"wrap"}} onClick={()=>setExpandedId(open?null:b.id)}>
          <div style={{flex:1,minWidth:0}}>
            <div style={{display:"flex",alignItems:"center",gap:".5rem",flexWrap:"wrap"}}>
              <div style={{fontWeight:700,fontSize:".9rem"}}>{b.first} {b.last}</div>
              {isRet&&<span style={{background:"rgba(21,128,61,.1)",color:"var(--green)",border:"1px solid rgba(21,128,61,.2)",borderRadius:"3px",padding:".1rem .45rem",fontSize:".65rem",fontFamily:"DM Mono,monospace",fontWeight:600}}>↩ Returning</span>}
              {b.flagged&&<span className="flag-badge flagged">⚑ Flagged</span>}
              {b.whitelist&&<span className="flag-badge vip">★ VIP</span>}
              {hasOut&&<span style={{background:"rgba(245,158,11,.12)",color:"#92400e",border:"1px solid rgba(245,158,11,.3)",borderRadius:"3px",padding:".1rem .45rem",fontSize:".65rem",fontFamily:"DM Mono,monospace",fontWeight:600}}>Owes {fmtCurrency(stats.outstanding)}</span>}
            </div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:"2px"}}>{b.bidderNum} · {b.phone} · {b.email}</div>
          </div>
          <div style={{display:"flex",gap:"1.2rem",alignItems:"center",flexShrink:0}}>
            <div style={{textAlign:"right"}}>
              <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:"var(--accent)"}}>{stats.wins} wins</div>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)"}}>{fmtCurrency(stats.totalSpend)}</div>
            </div>
            <div style={{fontSize:".75rem",color:b.depositStatus==="approved"?"var(--green)":"var(--red)",fontFamily:"DM Mono,monospace",fontWeight:600}}>
              {b.depositStatus==="approved"?"✓ Apprvd":"⏳ Pending"}
            </div>
            <span style={{color:"var(--muted)",fontSize:".85rem"}}>{open?"▲":"▼"}</span>
          </div>
        </div>

        {open&&<div style={{padding:"1rem 1.1rem",borderTop:"1px solid var(--border)"}}>
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:".5rem",marginBottom:"1rem"}}>
            {[
              {lbl:"Total Wins",val:stats.wins,color:"var(--green)"},
              {lbl:"Total Spend",val:fmtCurrency(stats.totalSpend),color:"var(--accent)"},
              {lbl:"Paid",val:fmtCurrency(stats.paid),color:"var(--green)"},
              {lbl:"Outstanding",val:fmtCurrency(stats.outstanding),color:hasOut?"var(--red)":"var(--muted)"},
              {lbl:"Deposit Method",val:PAY_METHODS.find(p=>p.id===b.payMethod)?.icon+" "+PAY_METHODS.find(p=>p.id===b.payMethod)?.label,color:"var(--sub)"},
              {lbl:"Keep on File",val:b.keepOnFile?"Yes":"No",color:b.keepOnFile?"var(--green)":"var(--muted)"},
            ].map(s=><div key={s.lbl} style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"5px",padding:".5rem .7rem"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".08em",marginBottom:".2rem"}}>{s.lbl}</div>
              <div style={{fontWeight:600,fontSize:".85rem",color:s.color}}>{s.val}</div>
            </div>)}
          </div>

          {/* Contact */}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:".5rem",marginBottom:"1rem",fontSize:".8rem"}}>
            <div style={{padding:".55rem .75rem",background:"var(--navy-light)",border:"1px solid var(--border)",borderRadius:"5px"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",marginBottom:".2rem"}}>Address</div>
              <div>{b.address}, {b.city}, {b.state} {b.zip}</div>
            </div>
            <div style={{padding:".55rem .75rem",background:"var(--navy-light)",border:"1px solid var(--border)",borderRadius:"5px"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",marginBottom:".2rem"}}>Driver's License</div>
              <div style={{fontFamily:"DM Mono,monospace"}}>{b.dl} ({b.dlState})</div>
            </div>
          </div>

          {/* Actions */}
          <div style={{display:"flex",gap:".5rem",flexWrap:"wrap"}}>
            {b.depositStatus==="pending"&&isRet&&!b.flagged&&!hasOut&&
              <button className="btn-approve" style={{flex:1}} onClick={()=>autoApproveReturning(b.id)}>
                ↩ Auto-Approve — Returning Bidder
              </button>}
            {b.depositStatus==="pending"&&!(isRet&&!b.flagged&&!hasOut)&&
              <button className="btn-approve" style={{flex:1}} onClick={()=>setBidders(bs=>bs.map(x=>x.id===b.id?{...x,depositStatus:"approved",depositOnFile:true}:x))}>
                ✓ Approve
              </button>}
            {b.depositStatus==="approved"&&
              <button className="btn-g" onClick={()=>setBidders(bs=>bs.map(x=>x.id===b.id?{...x,depositStatus:"pending",depositOnFile:false}:x))}>
                Revoke Approval
              </button>}
            <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",padding:".4rem .8rem",border:"1px solid rgba(59,130,246,.25)",borderRadius:"4px",background:"rgba(59,130,246,.06)",fontSize:".78rem",color:"var(--blue)"}}>
              <input type="checkbox" checked={!!b.whitelist} onChange={()=>setBidders(bs=>bs.map(x=>x.id===b.id?{...x,whitelist:!x.whitelist}:x))} style={{width:14,height:14,accentColor:"var(--blue)"}}/>
              ★ VIP
            </label>
            <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",padding:".4rem .8rem",border:"1px solid rgba(220,38,38,.25)",borderRadius:"4px",background:"rgba(220,38,38,.04)",fontSize:".78rem",color:"var(--red)"}}>
              <input type="checkbox" checked={!!b.flagged} onChange={()=>setBidders(bs=>bs.map(x=>x.id===b.id?{...x,flagged:!x.flagged}:x))} style={{width:14,height:14,accentColor:"var(--red)"}}/>
              ⚑ Flag
            </label>
          </div>
          {b.depositConfirmedAt&&<div style={{marginTop:".6rem",fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>Last approved: {b.depositConfirmedAt}</div>}
        </div>}
      </div>;
    })}
    {shown.length===0&&<div style={{textAlign:"center",padding:"2.5rem",color:"var(--muted)",background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",fontSize:".83rem"}}>No bidders match your search.</div>}
  </div>;
}

// ─── SOCIAL SHARE BAR ─────────────────────────────────────────────────────────
function ShareBar({auction, onShare}){
  const [copied, setCopied] = useState(false);
  const baseUrl = "https://towguysautoauction.com";
  const lotUrl = `${baseUrl}?lot=${auction.id}`;
  const title = `${auction.year} ${auction.make} ${auction.model} — ${auction.lot}`;
  const desc = `Bid on this ${auction.year} ${auction.make} ${auction.model} at Tow Guys Auto Auction. Current bid: ${fmtCurrency(auction.currentBid||auction.minBid)}. Nevada lien sale — register to bid at ${baseUrl}`;

  const share = (platform) => {
    let url;
    if(platform==="facebook")  url=`https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(lotUrl)}&quote=${encodeURIComponent(desc)}`;
    if(platform==="tiktok")    url=`https://www.tiktok.com/share?url=${encodeURIComponent(lotUrl)}&title=${encodeURIComponent(title)}`;
    if(platform==="instagram") url=`https://www.instagram.com/`;   // IG has no direct share URL — copy link instead
    if(platform==="snapchat")  url=`https://www.snapchat.com/scan?attachmentUrl=${encodeURIComponent(lotUrl)}`;
    if(url) window.open(url,"_blank","noopener");
    onShare?.(auction.id, platform);
  };

  const copy = () => {
    navigator.clipboard?.writeText(`${title}\n${desc}\n\n${lotUrl}`).catch(()=>{});
    setCopied(true); setTimeout(()=>setCopied(false),2000);
    onShare?.(auction.id,"copy");
  };

  return <div className="share-bar">
    <button className="share-btn fb"    onClick={()=>share("facebook")} title="Share on Facebook">𝑓 Facebook</button>
    <button className="share-btn tiktok" onClick={()=>share("tiktok")} title="Share on TikTok">♪ TikTok</button>
    <button className="share-btn snap"  onClick={()=>share("snapchat")} title="Share on Snapchat">👻 Snap</button>
    <button className="share-btn ig"    onClick={()=>{share("instagram");copy();}} title="Instagram — copies link (IG has no direct share URL)">📷 Instagram</button>
    <button className="share-btn copy"  onClick={copy}>{copied?"✓ Copied!":"🔗 Copy Link"}</button>
  </div>;
}

// ─── VIEW TRACKER ADMIN TAB ────────────────────────────────────────────────────
function ViewTrackerTab({auctions}){
  const maxViews = Math.max(...auctions.map(a=>a.views||0), 1);
  const sorted = [...auctions].sort((a,b)=>(b.views||0)-(a.views||0));

  const totalViews = auctions.reduce((s,a)=>s+(a.views||0),0);
  const totalShares = auctions.reduce((s,a)=>s+(a.shares||0),0);
  const hotLot = sorted[0];

  return <div>
    {/* Summary */}
    <div style={{display:"flex",gap:".75rem",marginBottom:"1.3rem",flexWrap:"wrap"}}>
      {[
        {val:totalViews, lbl:"Total Views", color:"var(--accent)"},
        {val:totalShares, lbl:"Total Shares", color:"var(--blue)"},
        {val:hotLot?`${hotLot.lot}`:"-", lbl:"Most Viewed Lot", color:"var(--accent2)"},
        {val:hotLot?`${hotLot.views||0} views`:"-", lbl:"Top View Count", color:"var(--accent)"},
      ].map(s=><div key={s.lbl} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"7px",padding:".65rem 1rem",flex:1,minWidth:110}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:s.color,lineHeight:1}}>{s.val}</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".07em",marginTop:".12rem"}}>{s.lbl}</div>
      </div>)}
    </div>

    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden"}}>
      <table className="vt-table">
        <thead><tr>
          <th>Lot</th>
          <th>Vehicle</th>
          <th>Title</th>
          <th>Views</th>
          <th style={{minWidth:120}}>View Bar</th>
          <th>Shares</th>
          <th>Bids</th>
          <th>Status</th>
        </tr></thead>
        <tbody>
          {sorted.map(a=>{
            const views=a.views||0;
            const pct=Math.round(views/maxViews*100);
            const isHot=views===maxViews&&views>0;
            return <tr key={a.id}>
              <td><div style={{fontFamily:"Bebas Neue,sans-serif",color:"var(--accent)",fontSize:".95rem"}}>{a.lot}</div></td>
              <td><div style={{fontWeight:600,fontSize:".85rem"}}>{a.year} {a.make} {a.model}</div><CoBadge id={a.company}/></td>
              <td><TitleBadge type={a.titleType||"lien"}/></td>
              <td>
                <span className={`views-badge${isHot?" hot":""}`}>
                  {isHot?"🔥 ":""}{views.toLocaleString()}
                </span>
              </td>
              <td>
                <div className="vt-bar-track">
                  <div className="vt-bar-fill" style={{width:`${pct}%`,background:isHot?"var(--accent2)":"var(--accent)"}}/>
                </div>
              </td>
              <td style={{fontFamily:"DM Mono,monospace",fontSize:".8rem",color:"var(--blue)"}}>{a.shares||0} ↗</td>
              <td style={{fontFamily:"DM Mono,monospace",fontSize:".8rem"}}>{a.bids}</td>
              <td>{a.sold?<span className="lot-status-badge sold">SOLD</span>:<span className="lot-status-badge live">LIVE</span>}</td>
            </tr>;
          })}
        </tbody>
      </table>
    </div>

    <div className="notice" style={{marginTop:"1rem"}}>
      View counts are tracked when a bidder opens a lot's detail card. Share counts increment per platform click. In production, these persist to your database and reset per auction.
    </div>
  </div>;
}

// ─── EMAIL BLAST WITH ROSTER ───────────────────────────────────────────────────
function EmailBlastPanel({auctions, auctionDate, auctionDayLabel}){
  const ev = AUCTION_EVENTS[auctionDayLabel||"tuesday"];
  const fmtDate = auctionDate
    ? new Date(auctionDate+"T12:00:00").toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"})
    : new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"});

  const activeLots = auctions.filter(a=>!a.sold);
  const [emails, setEmails] = useState([
    "buyer1@gmail.com","bidder2@yahoo.com","customer3@hotmail.com","dealer@example.com"
  ]);
  const [newEmail, setNewEmail] = useState("");
  const [subject, setSubject] = useState(`New Auction — ${fmtDate} · ${activeLots.length} Vehicles Available`);
  const [sent, setSent] = useState(false);
  const [copied, setCopied] = useState(false);

  const addEmail = () => {
    const e = newEmail.trim().toLowerCase();
    if(e&&e.includes("@")&&!emails.includes(e)){ setEmails(p=>[...p,e]); setNewEmail(""); }
  };
  const removeEmail = (e) => setEmails(p=>p.filter(x=>x!==e));

  const buildBody = () => {
    const lotRows = activeLots.map(a=>`• ${a.lot}: ${a.year} ${a.make} ${a.model} — VIN ${a.vin} — Min Bid: ${fmtCurrency(a.minBid)} — ${a.condition==="runs"?"Runs":"No Start"}`).join("\n");
    return [
      `Tow Guys Auto Auction — ${fmtDate}`,
      `${ev?.address}`,
      `Auction closes at 2:00 PM`,
      ``,
      `NEW LOTS AVAILABLE (${activeLots.length} vehicles):`,
      ``,
      lotRows,
      ``,
      `Register & bid at: towguysautoauction.com`,
      `$300 refundable deposit required to bid.`,
      `All sales final — Nevada Lien Sale (NRS Chapter 108)`,
      ``,
      `Questions? Call (702) 677-0792 or email csrtowguysautoauction@gmail.com`,
      ``,
      `To unsubscribe, reply STOP.`,
    ].join("\n");
  };

  const handleSend = () => {
    if(emails.length===0) return;
    const body = buildBody();
    const bcc = emails.join(",");
    const mailto = `mailto:?bcc=${encodeURIComponent(bcc)}&subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
    window.open(mailto,"_blank");
    setSent(true);
    setTimeout(()=>setSent(false),4000);
  };

  const copyBody = () => {
    navigator.clipboard?.writeText(buildBody()).catch(()=>{});
    setCopied(true); setTimeout(()=>setCopied(false),2000);
  };

  return <div className="eb-wrap">
    {/* Subject */}
    <div style={{marginBottom:"1rem"}}>
      <label className="flbl">Subject Line</label>
      <input className="finput" value={subject} onChange={e=>setSubject(e.target.value)} style={{marginTop:".35rem"}}/>
    </div>

    {/* Email list */}
    <div style={{marginBottom:"1rem"}}>
      <label className="flbl" style={{display:"block",marginBottom:".5rem"}}>
        Recipient List — {emails.length} email{emails.length!==1?"s":""}
        <span style={{color:"var(--muted)",fontWeight:400,marginLeft:".4rem",fontSize:".72rem"}}>(sent as BCC)</span>
      </label>
      <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:".6rem .75rem",marginBottom:".5rem",minHeight:54,display:"flex",flexWrap:"wrap",alignItems:"center",gap:".2rem"}}>
        {emails.map(e=><span key={e} className="eb-email-chip">{e}<button onClick={()=>removeEmail(e)}>×</button></span>)}
      </div>
      <div style={{display:"flex",gap:".5rem"}}>
        <input className="finput" style={{flex:1}} type="email" placeholder="Add email address…" value={newEmail}
          onChange={e=>setNewEmail(e.target.value)} onKeyDown={e=>e.key==="Enter"&&addEmail()}/>
        <button className="btn-approve" onClick={addEmail}>Add</button>
      </div>
    </div>

    {/* Lot roster preview */}
    <div style={{marginBottom:"1rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".55rem"}}>
        Roster Preview — {activeLots.length} lots included
      </div>
      <div className="eb-roster-preview">
        {activeLots.map(a=><div key={a.id} className="eb-roster-row">
          <div style={{fontFamily:"Bebas Neue,sans-serif",color:"var(--accent)",fontSize:".9rem",flexShrink:0,width:70}}>{a.lot}</div>
          <div style={{flex:1}}>
            <div style={{fontWeight:600,fontSize:".83rem"}}>{a.year} {a.make} {a.model}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{a.vin}</div>
          </div>
          <TitleBadge type={a.titleType||"lien"}/>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".75rem",color:"var(--green)",fontWeight:600,flexShrink:0}}>{fmtCurrency(a.minBid)}</div>
          <span className={`tag ${a.condition==="runs"?"tag-runs":"tag-ns"}`} style={{fontSize:".65rem",flexShrink:0}}>{a.condition==="runs"?"Run":"N/S"}</span>
        </div>)}
        {activeLots.length===0&&<div style={{padding:"1.2rem",textAlign:"center",color:"var(--muted)",fontSize:".83rem"}}>No active lots — all sold or no lots added yet.</div>}
      </div>
    </div>

    <div className="notice" style={{marginBottom:"1rem"}}>
      Clicking Send opens your email app with all recipients in BCC and the lot roster in the body. One send, everyone gets it privately. For automated delivery, connect SendGrid or Brevo in production.
    </div>

    {/* Actions */}
    <div style={{display:"flex",gap:".65rem"}}>
      <button className="btn-g" onClick={copyBody}>{copied?"✓ Copied!":"📋 Copy Email Body"}</button>
      <button className="btn-p" style={{flex:1,background:sent?"var(--green)":"var(--accent)"}} disabled={emails.length===0||activeLots.length===0} onClick={handleSend}>
        {sent?"✓ Email App Opened!":"📧 Send Blast — " + emails.length + " Recipients"}
      </button>
    </div>
  </div>;
}

// ─── SEO PANEL ────────────────────────────────────────────────────────────────
function SEOPanel({auctions, auctionDate, auctionDayLabel}){
  const fmtDate = auctionDate
    ? new Date(auctionDate+"T12:00:00").toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"})
    : new Date().toLocaleDateString("en-US",{weekday:"long",month:"long",day:"numeric",year:"numeric"});

  const activeLots = auctions.filter(a=>!a.sold);
  const baseUrl = "https://towguysautoauction.com";
  const [copiedKey, setCopiedKey] = useState(null);
  const copyText = (text, key) => { navigator.clipboard?.writeText(text).catch(()=>{}); setCopiedKey(key); setTimeout(()=>setCopiedKey(null),2200); };
  const CopyBtn = ({text,k,label="Copy"}) => <button className="btn-sm" style={{fontSize:".72rem",marginLeft:".5rem"}} onClick={()=>copyText(text,k)}>{copiedKey===k?"✓ Copied!":label}</button>;

  const checks = [
    {done:true,  title:"Page Title",              detail:`"Tow Guys Auto Auction — Nevada Lien Sale Vehicles" — set dynamically on every load. ✓ Live`},
    {done:true,  title:"Meta Description",        detail:"Injected into <head> with target keywords: nevada lien sale, bid online, Henderson & North Las Vegas. ✓ Live"},
    {done:true,  title:"Open Graph Tags",         detail:"og:title, og:description, og:url, og:type injected on load. Per-lot OG tags update via ?lot= URL. ✓ Live"},
    {done:true,  title:"Canonical URL",           detail:`Set via og:url. Add <link rel='canonical' href='${baseUrl}'> to HTML at deploy time.`},
    {done:true,  title:"Lot Deep-Link URLs",      detail:`?lot=A001 opens that vehicle directly + updates OG tags for sharing. ✓ Live`},
    {done:true,  title:"Structured Data (JSON-LD)",detail:"AuctionEvent schema.org markup injected into <head> on load. Powers Google rich results. ✓ Live"},
    {done:true,  title:"Mobile-Responsive",       detail:"Fully responsive — Google uses mobile-first indexing. ✓ Confirmed"},
    {done:false, title:"Sitemap.xml",             detail:`Copy XML below → save as sitemap.xml in your web root → submit URL to Google Search Console.`},
    {done:false, title:"Robots.txt",              detail:`Copy below → save as robots.txt in your web root. Allows all bots, blocks admin panel.`},
    {done:false, title:"Page Speed — Nginx",      detail:"Copy Nginx config below → add to your server block → reload. Enables gzip + 30-day asset caching."},
    {done:false, title:"Google Search Console",   detail:"Verify domain, submit sitemap. Free. Sign up at search.google.com/search-console"},
    {done:false, title:"Google Business Profile", detail:"Claim both locations at business.google.com — critical for 'car auction henderson nv' local searches"},
    {done:false, title:"Backlinks",               detail:"Get listed on: Nevada DMV directory, ATIA.org, Yelp, BBB, Las Vegas Chamber of Commerce, Craigslist LV"},
  ];
  const done = checks.filter(c=>c.done).length;
  const score = Math.round(done/checks.length*100);
  const scoreClass = score>=75?"good":score>=50?"warn":"bad";
  const keywords = ["tow guys auto auction","nevada lien sale","lien sale vehicles las vegas","repo car auction henderson nv","government auction vehicles nevada","used car auction las vegas","towing auction north las vegas","lien sale cars nrs 108","buy repo cars las vegas","vehicle auction henderson nv"];

  const today = new Date().toISOString().slice(0,10);
  const sitemapXml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url><loc>${baseUrl}/</loc><lastmod>${today}</lastmod><changefreq>daily</changefreq><priority>1.0</priority></url>
  <url><loc>${baseUrl}?view=contact</loc><lastmod>${today}</lastmod><changefreq>monthly</changefreq><priority>0.6</priority></url>${auctions.map(a=>`
  <url><loc>${baseUrl}?lot=${a.id}</loc><lastmod>${today}</lastmod><changefreq>hourly</changefreq><priority>0.9</priority></url>`).join("")}
</urlset>`;

  const robotsTxt = `User-agent: *\nAllow: /\nSitemap: ${baseUrl}/sitemap.xml\n\n# Block admin panel\nDisallow: /?admin\nDisallow: /?adminLogin`;

  const nginxConf = `# Add inside server {} block in /etc/nginx/sites-available/towguysautoauction.com

gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
gzip_comp_level 6;
gzip_min_length 256;

location ~* \\.(js|css|png|jpg|jpeg|webp|svg|ico|woff2)$ {
    expires 30d;
    add_header Cache-Control "public, immutable";
}
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "strict-origin-when-cross-origin";

location = /sitemap.xml { root /var/www/towguysautoauction; }
location = /robots.txt  { root /var/www/towguysautoauction; }

# Then reload: sudo nginx -t && sudo systemctl reload nginx`;

  const jsonLdSnippet = `<script type="application/ld+json">
{
  "@context":"https://schema.org","@type":"AuctionEvent",
  "name":"Tow Guys Auto Auction — Nevada Lien Sale",
  "url":"${baseUrl}",
  "organizer":{"@type":"Organization","name":"Tow Guys Auto Auction","telephone":"(702) 677-0792"},
  "location":[
    {"@type":"Place","name":"Henderson","address":"250 W Warm Springs Rd, Henderson, NV 89011"},
    {"@type":"Place","name":"North Las Vegas","address":"3823 Losee Rd, North Las Vegas, NV 89030"}
  ],
  "offers":{"@type":"AggregateOffer","offerCount":${activeLots.length},"priceCurrency":"USD"}
}
</script>`;

  const Code = ({children}) => <pre style={{background:"#0f172a",color:"#7dd3fc",borderRadius:"6px",padding:".85rem 1rem",fontSize:".68rem",fontFamily:"DM Mono,monospace",overflowX:"auto",lineHeight:1.65,whiteSpace:"pre-wrap",margin:0}}>{children}</pre>;

  return <div className="seo-wrap">
    {/* Score */}
    <div style={{display:"flex",gap:"1.1rem",alignItems:"center",background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",padding:"1rem 1.2rem",marginBottom:"1.1rem",flexWrap:"wrap"}}>
      <div className={`seo-score-ring ${scoreClass}`}>{score}</div>
      <div style={{flex:1}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",letterSpacing:".04em"}}>SEO Readiness — {score}%</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)",marginTop:".2rem"}}>{done}/{checks.length} implemented · {checks.filter(c=>!c.done).length} remaining</div>
      </div>
      <div style={{fontSize:".78rem",textAlign:"right"}}>
        <div style={{color:"var(--green)",fontWeight:600}}>✅ {done} live</div>
        <div style={{color:"var(--accent2)",fontWeight:600}}>○ {checks.length-done} pending</div>
      </div>
    </div>

    {/* Google preview */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">Google Search Preview</div></div>
      <div className="seo-body">
        <div className="seo-meta-preview">
          <div className="seo-meta-title">Tow Guys Auto Auction — Nevada Lien Sale Vehicles</div>
          <div className="seo-meta-url">{baseUrl}</div>
          <div className="seo-meta-desc">Government-regulated lien sale vehicles — bid online, closes 2:00 PM. {activeLots.length} lots available. $300 refundable deposit. Henderson & North Las Vegas, NV.</div>
        </div>
        <div style={{fontSize:".75rem",color:"var(--green)",fontFamily:"DM Mono,monospace"}}>✓ Title + meta description injected into {"<head>"} on every load. OG tags update per lot when shared.</div>
      </div>
    </div>

    {/* Checklist */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">SEO Checklist</div></div>
      <div className="seo-body">
        {checks.map((c,i)=><div key={i} className="seo-check-row">
          <div className="seo-check-icon">{c.done?"✅":"⬜"}</div>
          <div style={{flex:1}}>
            <div style={{fontWeight:600,fontSize:".85rem",color:c.done?"var(--green)":"var(--text)",marginBottom:".15rem"}}>{c.title}</div>
            <div style={{fontSize:".78rem",color:"var(--muted)",lineHeight:1.55}}>{c.detail}</div>
          </div>
        </div>)}
      </div>
    </div>

    {/* Sitemap */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">sitemap.xml</div><CopyBtn text={sitemapXml} k="sitemap" label="📋 Copy XML"/></div>
      <div className="seo-body">
        <div style={{fontSize:".78rem",color:"var(--muted)",marginBottom:".65rem",lineHeight:1.6}}>Save as <code style={{background:"var(--navy-light)",padding:".1rem .35rem",borderRadius:"3px",fontFamily:"DM Mono,monospace"}}>sitemap.xml</code> in <code style={{background:"var(--navy-light)",padding:".1rem .35rem",borderRadius:"3px",fontFamily:"DM Mono,monospace"}}>/var/www/towguysautoauction/</code> — then submit <code style={{background:"var(--navy-light)",padding:".1rem .35rem",borderRadius:"3px",fontFamily:"DM Mono,monospace"}}>{baseUrl}/sitemap.xml</code> to Google Search Console. Includes all {auctions.length} lot deep-links.</div>
        <Code>{sitemapXml}</Code>
      </div>
    </div>

    {/* Robots */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">robots.txt</div><CopyBtn text={robotsTxt} k="robots" label="📋 Copy"/></div>
      <div className="seo-body">
        <div style={{fontSize:".78rem",color:"var(--muted)",marginBottom:".65rem"}}>Save as <code style={{background:"var(--navy-light)",padding:".1rem .35rem",borderRadius:"3px",fontFamily:"DM Mono,monospace"}}>robots.txt</code> in your web root. Tells all bots to crawl freely; blocks admin URL.</div>
        <Code>{robotsTxt}</Code>
      </div>
    </div>

    {/* Nginx */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">Nginx — Gzip + Caching</div><CopyBtn text={nginxConf} k="nginx" label="📋 Copy Config"/></div>
      <div className="seo-body">
        <div style={{fontSize:".78rem",color:"var(--muted)",marginBottom:".65rem",lineHeight:1.6}}>Add to your Nginx server block → run <code style={{background:"var(--navy-light)",padding:".1rem .35rem",borderRadius:"3px",fontFamily:"DM Mono,monospace"}}>sudo nginx -t && sudo systemctl reload nginx</code>. Enables gzip, 30-day asset caching, and security headers.</div>
        <Code>{nginxConf}</Code>
      </div>
    </div>

    {/* JSON-LD */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">Structured Data — Already Active ✓</div><CopyBtn text={jsonLdSnippet} k="jsonld" label="📋 Copy Tag"/></div>
      <div className="seo-body">
        <div style={{fontSize:".78rem",color:"var(--green)",marginBottom:".65rem",fontFamily:"DM Mono,monospace"}}>✓ Already injected into document.head on every page load.</div>
        <Code>{jsonLdSnippet}</Code>
      </div>
    </div>

    {/* Keywords */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">Target Keywords</div></div>
      <div className="seo-body">
        <div style={{display:"flex",flexWrap:"wrap",gap:".2rem",marginBottom:".8rem"}}>{keywords.map(k=><span key={k} className="seo-tag">{k}</span>)}</div>
        <div style={{fontSize:".8rem",color:"var(--muted)",lineHeight:1.65}}><strong>Quick wins:</strong> Use these in lot condition notes, Google Business description, and your contact page. "Henderson NV" and "North Las Vegas NV" are high-value local modifiers — use both in every title.</div>
      </div>
    </div>

    {/* Action plan */}
    <div className="seo-section">
      <div className="seo-section-hd"><div className="seo-section-title">Go-Live Checklist</div></div>
      <div className="seo-body">
        {[
          {phase:"✅ Already Live — In App", color:"var(--green)", items:["Page title + meta description injected on load","Open Graph tags (Facebook, iMessage previews)","JSON-LD AuctionEvent structured data","Lot deep-links (?lot=A001) with per-lot OG tags","Mobile-responsive design"]},
          {phase:"🔧 Before Launch — Your Server", color:"var(--accent)", items:["Copy sitemap.xml → /var/www/towguysautoauction/ (above)","Copy robots.txt → /var/www/towguysautoauction/ (above)","Apply Nginx gzip + caching config (above)","Add <link rel='canonical'> to HTML head at deploy"]},
          {phase:"📋 At Launch — External", color:"var(--blue)", items:["Google Search Console → verify domain, submit sitemap","Google Business Profile → claim both Henderson + N. Las Vegas locations","Submit to Yelp, BBB, Las Vegas Chamber of Commerce"]},
          {phase:"📅 Ongoing", color:"var(--muted)", items:["Share each lot (Facebook, TikTok, Snap) on auction day","SMS Blast to bidders when auction goes live","Post vehicle walkaround Reels/TikToks on auction morning","Collect Google reviews from buyers after each auction"]},
        ].map(p=><div key={p.phase} style={{marginBottom:"1rem"}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".08em",color:p.color,marginBottom:".4rem"}}>{p.phase}</div>
          {p.items.map((item,i)=><div key={i} style={{display:"flex",gap:".5rem",fontSize:".82rem",padding:".28rem 0",color:"var(--sub)",borderBottom:i<p.items.length-1?"1px solid var(--border)":"none"}}>
            <span style={{color:p.color,flexShrink:0}}>→</span>{item}
          </div>)}
        </div>)}
      </div>
    </div>
  </div>;
}

// ─── BIDDER RATINGS PANEL (admin tab) ────────────────────────────────────────
function BidderRatingsPanel({bidders, setBidders}){
  const [rateModal, setRateModal] = useState(null);
  const rated = bidders.filter(b=>(b.ratings||[]).length>0);
  const unrated = bidders.filter(b=>!(b.ratings||[]).length);

  const RatingBar = ({avg}) => {
    const cls = avg>=4?"great":avg>=3?"ok":"poor";
    const label = avg>=4?"⭐ Great":avg>=3?"👍 OK":"⚠ Poor";
    return <span className={`rating-chip ${cls}`}>{label} {avg.toFixed(1)}</span>;
  };

  return <div>
    <div style={{display:"flex",gap:".75rem",marginBottom:"1.2rem",flexWrap:"wrap"}}>
      {[
        {val:bidders.length, lbl:"Total Bidders", color:"var(--accent)"},
        {val:rated.length, lbl:"Rated", color:"var(--green)"},
        {val:unrated.length, lbl:"Not Yet Rated", color:"var(--muted)"},
        {val:rated.length>0?(rated.reduce((s,b)=>s+(b.avgRating||0),0)/rated.length).toFixed(1):"—", lbl:"Avg Rating", color:"#f59e0b"},
      ].map(s=><div key={s.lbl} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"7px",padding:".6rem .9rem",flex:1,minWidth:90}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:s.color,lineHeight:1}}>{s.val}</div>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".07em",marginTop:".12rem"}}>{s.lbl}</div>
      </div>)}
    </div>

    <div className="notice info" style={{marginBottom:"1rem"}}>Rate bidders after each auction to build a history of payment speed, pickup reliability, and communication. Ratings are staff-only and never shown publicly.</div>

    {/* Rated bidders */}
    {rated.length>0&&<div style={{marginBottom:"1.5rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".65rem"}}>Rated Bidders</div>
      {rated.map(b=><div key={b.id} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"7px",padding:".85rem 1.1rem",marginBottom:".6rem",display:"flex",alignItems:"flex-start",gap:".85rem",flexWrap:"wrap"}}>
        <div style={{flex:1,minWidth:0}}>
          <div style={{display:"flex",alignItems:"center",gap:".55rem",flexWrap:"wrap",marginBottom:".3rem"}}>
            <div style={{fontWeight:700,fontSize:".9rem"}}>{b.first} {b.last}</div>
            <span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{b.bidderNum}</span>
            <RatingBar avg={b.avgRating||0}/>
          </div>
          <div style={{display:"flex",alignItems:"center",gap:".35rem",flexWrap:"wrap"}}>
            <StarRating value={Math.round(b.avgRating||0)} readonly/>
            <span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{(b.ratings||[]).length} rating{(b.ratings||[]).length!==1?"s":""}</span>
          </div>
          {/* Latest rating note */}
          {(b.ratings||[]).slice(-1)[0]?.note&&<div style={{fontSize:".78rem",color:"var(--muted)",fontStyle:"italic",marginTop:".4rem"}}>
            "{(b.ratings||[]).slice(-1)[0].note}" — {(b.ratings||[]).slice(-1)[0].ts}
          </div>}
          {/* Category breakdown */}
          {(b.ratings||[]).length>0&&<div style={{display:"flex",gap:".75rem",marginTop:".5rem",flexWrap:"wrap"}}>
            {["payment","pickup","communication"].map(cat=>{
              const vals=(b.ratings||[]).filter(r=>r[cat]>0).map(r=>r[cat]);
              if(!vals.length) return null;
              const avg=vals.reduce((s,v)=>s+v,0)/vals.length;
              return <div key={cat} style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--sub)"}}>
                {cat.charAt(0).toUpperCase()+cat.slice(1)}: <strong style={{color:avg>=4?"var(--green)":avg>=3?"#92400e":"var(--red)"}}>{avg.toFixed(1)}★</strong>
              </div>;
            })}
          </div>}
        </div>
        <button className="btn-sm" style={{flexShrink:0,borderColor:"rgba(245,158,11,.3)",color:"#92400e"}} onClick={()=>setRateModal(b)}>+ Add Rating</button>
      </div>)}
    </div>}

    {/* Unrated bidders */}
    {unrated.length>0&&<div>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--muted)",marginBottom:".65rem"}}>Not Yet Rated ({unrated.length})</div>
      {unrated.map(b=><div key={b.id} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"7px",padding:".75rem 1.1rem",marginBottom:".5rem",display:"flex",alignItems:"center",gap:".85rem",flexWrap:"wrap"}}>
        <div style={{flex:1}}>
          <div style={{fontWeight:600,fontSize:".88rem"}}>{b.first} {b.last}</div>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:"2px"}}>{b.bidderNum} · {b.phone}</div>
        </div>
        <button className="btn-approve" style={{background:"rgba(245,158,11,.12)",color:"#92400e",borderColor:"rgba(245,158,11,.3)"}} onClick={()=>setRateModal(b)}>⭐ Rate This Bidder</button>
      </div>)}
    </div>}

    {rateModal&&<RateBidderModal bidder={rateModal} onClose={()=>setRateModal(null)} onSave={rating=>{
      setBidders(bs=>bs.map(b=>{
        if(b.id!==rateModal.id) return b;
        const newRatings=[...(b.ratings||[]),rating];
        const avg=+(newRatings.reduce((s,r)=>s+r.overall,0)/newRatings.length).toFixed(1);
        return {...b, ratings:newRatings, avgRating:avg};
      }));
      setRateModal(null);
    }}/>}
  </div>;
}

// ─── ADMIN PANEL ──────────────────────────────────────────────────────────────
function AdminPanel({auctions,setAuctions,stagger,setStagger,adminUsers,setAdminUsers,currentAdmin,signups=[],setSignups=()=>{}}){
  const [tab,setTab]=useState("lots");
  const [showAdd,setShowAdd]=useState(false);
  const [editLot,setEditLot]=useState(null);
  const [showImport,setShowImport]=useState(false);
  const [showPhotos,setShowPhotos]=useState(false);
  const [showRoster,setShowRoster]=useState(false);
  const [showReorder,setShowReorder]=useState(false);
  const [showScoreboard,setShowScoreboard]=useState(false);
  const [showSummaryPdf,setShowSummaryPdf]=useState(false);
  const [showPreReg,setShowPreReg]=useState(false);
  const [emailPreviewLot,setEmailPreviewLot]=useState(null);
  const [badgeBidder,setBadgeBidder]=useState(null);
  const [rateModal,setRateModal]=useState(null);
  const [auctionDate,setAuctionDate]=useState(()=>new Date().toISOString().slice(0,10));
  const [auctionDayLabel,setAuctionDayLabel]=useState("tuesday");
  const [fCo,setFCo]=useState("");
  const [bidders,setBidders]=useState(INIT_BIDDERS);
  const [feeSettings,setFeeSettings]=useState({adminFee:DEFAULT_ADMIN_FEE, taxRate:DEFAULT_TAX_RATE});
  const [invoiceLot,setInvoiceLot]=useState(null);
  const [notifyLot,setNotifyLot]=useState(null);

  const lots=fCo?auctions.filter(a=>a.company===fCo):auctions;
  const photoPending=auctions.filter(a=>!a.photos||a.photos.length<4).length;
  const pendingDeposits=bidders.filter(b=>b.depositStatus==="pending").length;
  const approvedBidders=bidders.filter(b=>b.depositStatus==="approved");

  const saveLot=form=>{
    if(editLot){setAuctions(p=>p.map(a=>a.id===editLot.id?{...a,...form,year:+form.year,mileage:+form.mileage,keyFee:+form.keyFee,minBid:+form.minBid,increment:+form.increment}:a));setEditLot(null);}
    else{const base=Date.now()+2*60*60*1000;setAuctions(p=>[...p,{id:genId(),lot:genLot(p.length),...form,year:+form.year,mileage:+form.mileage,keyFee:+form.keyFee,minBid:+form.minBid,increment:+form.increment,currentBid:0,bids:0,sold:false,bidHistory:[],conditionNotes:form.conditionNotes||"",closeTime:base+stagger*p.length*1000}]);}
    setShowAdd(false);
  };
  const handleMatch=g=>setAuctions(p=>p.map(a=>g[a.id]?{...a,photos:[...(a.photos||[]),...g[a.id]].slice(0,4)}:a));
  const handleMoveToAuction=(lots,day)=>{
    const base=Date.now()+2*60*60*1000;
    const newLots=lots.map((l,i)=>({id:genId(),lot:genLot(auctions.length+i),wo:l.wo||"",year:l.year,make:l.make,model:l.model,vin:l.vin,mileage:l.mileage||0,condition:l.condition,keyFee:l.keyFee||0,company:l.company,minBid:l.minBid,increment:l.increment||100,currentBid:0,bids:0,sold:false,photos:[],conditionNotes:"",bidHistory:[],closeTime:base+stagger*(auctions.length+i)*1000}));
    setAuctions(p=>[...p,...newLots]);
    setTab("lots");
  };
  const addComment=(id,comment)=>setAuctions(p=>p.map(a=>a.id===id?{...a,comments:[...(a.comments||[]),comment]}:a));
  const toggleTaxExempt=id=>setAuctions(p=>p.map(a=>a.id===id?{...a,taxExempt:!a.taxExempt}:a));
  const markSold=(id,winner)=>setAuctions(p=>p.map(a=>a.id===id?{...a,sold:true,winner}:a));
  const markNoSale=id=>setAuctions(p=>p.map(a=>a.id===id?{...a,sold:true,winner:null,currentBid:0}:a));

  return <div className="admin-wrap">
    <div className="admin-hd">
      <div><div className="admin-title">Admin Dashboard</div><div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}}>Mai Niv Enterprises · Tow Guys Auto Auction</div></div>
      <div className="admin-actions">
        <button className="btn-sm" onClick={()=>setShowScoreboard(true)}>🏟 Scoreboard</button>
        <button className="btn-sm" onClick={()=>setShowPreReg(true)}>🔗 Pre-Reg Link</button>
        <button className="btn-sm" onClick={()=>setShowSummaryPdf(true)}>📊 Close Summary</button>
        <button className="btn-sm" onClick={()=>setShowReorder(true)}>⇅ Reorder</button>
        <button className="btn-sm" onClick={()=>setShowRoster(true)}>📋 Roster</button>
        <button className="btn-sm" onClick={()=>setShowPhotos(true)}>📷 Photos{photoPending>0&&<span style={{background:"var(--accent)",color:"#fff",borderRadius:"10px",padding:"0 .38rem",fontSize:".62rem",marginLeft:"3px"}}>{photoPending}</span>}</button>
        <button className="btn-sm" onClick={()=>setShowImport(true)}>⬆ Import</button>
        <button className="cta" onClick={()=>setShowAdd(true)}>+ Add Lot</button>
      </div>
    </div>

    <div className="tabs">
      {[
        ["lots",`Lots (${auctions.length})`],
        ["bidtable","📊 Bid Table"],
        ["offers",`📬 Offers${auctions.flatMap(a=>a.offers||[]).filter(o=>o.status==="pending").length>0?" ⚠"+auctions.flatMap(a=>a.offers||[]).filter(o=>o.status==="pending").length:""}`],
        ["sms","📱 SMS Blast"],
        ["emailblast","📧 Email Blast"],
        ["auctionlist","🔔 Auction List"],
        ["views","📈 View Tracker"],
        ["seo","🔍 SEO"],
        ["publish","⏰ Publishing"],
        ["ratings","⭐ Ratings"],
        ["recurring","↩ Recurring Bidders"],
        ["bidders",`Bidders${pendingDeposits>0?` ⚠${pendingDeposits}`:""}`],
        ["deposits","Deposits"],
        ["payments","💰 Payments"],
        ["report","📧 Report"],
        ["wizard","🏁 Close Wizard"],
        ["batch","🖨 Batch Invoice"],
        ["lien","📄 Lien Docs"],
        ["bidhistory","👤 Bidder History"],
        ["checklist","Checklist"],
        ["summary","Summary"],
        ["exports","Exports"],
        ["history","History"],
        ["settings","Settings"],
        ["staff","Staff"],
      ].map(([id,lbl])=><div key={id} className={`tab${tab===id?" active":""}`} onClick={()=>setTab(id)} style={id==="bidders"&&pendingDeposits>0?{color:"var(--red)"}:{}}>{lbl}</div>)}
    </div>

    {tab==="bidtable"&&<BidTable auctions={auctions} setAuctions={setAuctions} bidders={bidders} stagger={stagger}/>}
    {tab==="offers"&&<OffersInbox auctions={auctions} setAuctions={setAuctions}/>}
    {tab==="sms"&&<BulkSMSBlast bidders={bidders} auctions={auctions}/>}
    {tab==="emailblast"&&<EmailBlastPanel auctions={auctions} auctionDate={auctionDate} auctionDayLabel={auctionDayLabel}/>}
    {tab==="auctionlist"&&<AuctionListAdmin signups={signups} setSignups={setSignups}/>}
    {tab==="views"&&<ViewTrackerTab auctions={auctions}/>}
    {tab==="seo"&&<SEOPanel auctions={auctions} auctionDate={auctionDate} auctionDayLabel={auctionDayLabel}/>}
    {tab==="publish"&&<ScheduledPublishingPanel auctions={auctions} setAuctions={setAuctions}/>}
    {tab==="ratings"&&<BidderRatingsPanel bidders={bidders} setBidders={setBidders}/>}
    {tab==="recurring"&&<RecurringBidderAccounts bidders={bidders} setBidders={setBidders} auctions={auctions} feeSettings={feeSettings}/>}
    {tab==="wizard"&&<div><DailyRevenueWidget auctions={auctions} feeSettings={feeSettings}/><AuctionCloseWizard auctions={auctions} setAuctions={setAuctions} feeSettings={feeSettings} bidders={bidders} setBidders={setBidders} onDone={()=>setTab("payments")}/></div>}
    {tab==="batch"&&<BatchInvoiceGenerator auctions={auctions} feeSettings={feeSettings} bidders={bidders}/>}
    {tab==="lien"&&<LienDocGenerator auctions={auctions} feeSettings={feeSettings} bidders={bidders}/>}
    {tab==="bidhistory"&&<div><DailyRevenueWidget auctions={auctions} feeSettings={feeSettings}/><BidderHistoryTab bidders={bidders} setBidders={setBidders} auctions={auctions} feeSettings={feeSettings}/></div>}
    {tab==="lots"&&<>
      <div style={{display:"flex",gap:".5rem",marginBottom:"1.1rem",flexWrap:"wrap"}}>
        <button className={`filter-btn${!fCo?" active":""}`} onClick={()=>setFCo("")}>All</button>
        {COMPANIES.map(c=><button key={c.id} className={`filter-btn${fCo===c.id?" active":""}`} style={fCo===c.id?{borderColor:c.color,color:c.color,background:`${c.color}12`}:{}} onClick={()=>setFCo(fCo===c.id?"":c.id)}>{c.label}</button>)}
      </div>
      <div className="admin-grid">{lots.map(a=>{
        const isSold=a.sold;
        const isWon=isSold&&a.winner;
        const isNoSale=isSold&&!a.winner;
        return <div className="acard" key={a.id} style={isNoSale?{opacity:.65}:isWon?{borderColor:"rgba(21,128,61,.35)"}:{}}>
          <div className="acard-hd">
            <div>
              <div style={{display:"flex",alignItems:"center",gap:".4rem",flexWrap:"wrap"}}>
                <div className="acard-title">{a.lot} · {a.year} {a.make} {a.model}</div>
                {isWon&&<span className="lot-status-badge sold">SOLD</span>}
                {isNoSale&&<span className="lot-status-badge no-sale">NO SALE</span>}
                {!isSold&&<span className="lot-status-badge live">LIVE</span>}
              </div>
              <CoBadge id={a.company}/>
            </div>
            <div style={{display:"flex",gap:".35rem",flexShrink:0}}>
              <button className="btn-sm" onClick={()=>setEditLot(a)}>Edit</button>
              <button className="btn-sm" style={{borderColor:"rgba(239,68,68,.3)",color:"var(--red)"}} onClick={()=>setAuctions(p=>p.filter(x=>x.id!==a.id))}>✕</button>
            </div>
          </div>
          <div className="acard-body">
            <PhotoSlots photos={a.photos||[]} onChange={p=>setAuctions(prev=>prev.map(x=>x.id===a.id?{...x,photos:p}:x))}/>
            <div className="arow"><span className="arow-lbl">WO#</span><span className="arow-val" style={{fontFamily:"DM Mono,monospace",fontSize:".7rem"}}>{a.wo||"—"}</span></div>
            <div className="arow"><span className="arow-lbl">VIN</span><span className="arow-val" style={{fontFamily:"DM Mono,monospace",fontSize:".68rem"}}>{a.vin}</span></div>
            <div className="arow"><span className="arow-lbl">Condition</span><span className={`tag ${a.condition==="runs"?"tag-runs":"tag-ns"}`}>{a.condition==="runs"?"Runs":"No Start"}</span></div>
            <div className="arow"><span className="arow-lbl">Title Type</span><TitleBadge type={a.titleType||"lien"}/></div>
            {a.conditionNotes&&<div className="arow"><span className="arow-lbl">Notes</span><span className="arow-val" style={{fontSize:".72rem",color:"var(--muted)",textAlign:"right",maxWidth:"160px"}}>{a.conditionNotes.slice(0,60)}{a.conditionNotes.length>60?"…":""}</span></div>}
            <div className="arow"><span className="arow-lbl">Min Bid</span><span className="arow-val">{fmtCurrency(a.minBid)}</span></div>
            <div className="arow">
              <span className="arow-lbl">Increment</span>
              <div style={{display:"flex",alignItems:"center",gap:".35rem"}}>
                <span style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)"}}>$</span>
                <input className="bt-inc-input" type="number" value={a.increment} min={25} step={25}
                  onChange={e=>setAuctions(p=>p.map(x=>x.id===a.id?{...x,increment:+e.target.value}:x))}
                  title="Override bid increment"/>
              </div>
            </div>
            <div className="arow">
              <span className="arow-lbl">Reserve</span>
              <div style={{display:"flex",alignItems:"center",gap:".35rem"}}>
                <span style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)"}}>$</span>
                <input className="bt-inc-input" type="number" style={{width:85}} placeholder="None"
                  value={a.reserve||""} min={0}
                  onChange={e=>setAuctions(p=>p.map(x=>x.id===a.id?{...x,reserve:e.target.value?+e.target.value:null}:x))}
                  title="Hidden reserve price — lot auto-marks No Sale if not met"/>
                {a.reserve&&<span className={`reserve-badge ${(a.currentBid||0)>=a.reserve?"met":"unmet"}`}>
                  {(a.currentBid||0)>=a.reserve?"✓ Met":"Not met"}
                </span>}
                {!a.reserve&&<span className="reserve-badge none">None</span>}
              </div>
            </div>
            <div className="arow"><span className="arow-lbl">Current Bid</span><span className="arow-val" style={{color:"var(--accent)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem"}}>{fmtCurrency(a.currentBid||a.minBid)}</span></div>
            <div className="arow"><span className="arow-lbl">Bids</span><span className="arow-val">{a.bids} {(a.bidHistory||[]).length>0&&<span style={{color:"var(--muted)",fontSize:".68rem",fontFamily:"DM Mono,monospace"}}>(history available)</span>}</span></div>
            <div className="arow">
              <span className="arow-lbl">Tax Exempt</span>
              <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer"}}>
                <input type="checkbox" checked={!!a.taxExempt} onChange={()=>toggleTaxExempt(a.id)} style={{width:14,height:14,accentColor:"var(--accent)"}}/>
                <span style={{fontSize:".75rem",color:a.taxExempt?"var(--green)":"var(--muted)"}}>{a.taxExempt?"Exempt":"Taxable"}</span>
              </label>
            </div>

            {/* Winner assignment */}
            {!isSold&&<div style={{marginTop:".7rem",padding:".65rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"5px"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".45rem"}}>Close Lot</div>
              <div style={{display:"flex",gap:".4rem",alignItems:"center",marginBottom:".4rem",flexWrap:"wrap"}}>
                <select className="finput winner-select" style={{flex:1}} onChange={e=>{if(e.target.value) markSold(a.id,e.target.value);}}>
                  <option value="">Assign winner…</option>
                  {approvedBidders.map(b=><option key={b.id} value={b.bidderNum}>{b.bidderNum} — {b.first} {b.last}</option>)}
                </select>
              </div>
              <div className="close-action-bar">
                <button className="btn-nosale" onClick={()=>markNoSale(a.id)}>✕ No Sale</button>
              </div>
            </div>}

            {isWon&&<div style={{marginTop:".7rem",padding:".65rem",background:"rgba(21,128,61,.06)",border:"1px solid rgba(21,128,61,.2)",borderRadius:"5px"}}>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--green)",marginBottom:".3rem"}}>WINNER</div>
              <div style={{fontSize:".85rem",fontWeight:600}}>{a.winner}</div>
              <button className="btn-sm" style={{marginTop:".45rem",width:"100%",borderColor:"rgba(0,48,135,.25)",color:"var(--accent)"}} onClick={()=>setInvoiceLot(a)}>📄 Invoice</button>
              <button className="btn-sm" style={{marginTop:".3rem",width:"100%",borderColor:"rgba(59,130,246,.25)",color:"var(--blue)"}} onClick={()=>setEmailPreviewLot(a)}>📧 Preview Email</button>
            </div>}

            <div style={{marginTop:".7rem",display:"flex",gap:".4rem",flexWrap:"wrap"}}>
              <DispatchLink auction={a}/>
              {!isWon&&<button className="btn-sm" style={{borderColor:"rgba(0,48,135,.3)",color:"var(--accent)"}} onClick={()=>setInvoiceLot(a)}>📄 Invoice</button>}
            </div>
            <LotComments auction={a} onAddComment={addComment}/>
          </div>
        </div>;
      })}</div>
    </>}

    {tab==="bidders"&&<BiddersTab bidders={bidders} setBidders={setBidders}/>}

    {tab==="deposits"&&<div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden"}}>
      <div style={{padding:"1rem 1.2rem",borderBottom:"1px solid var(--border)",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
        <span style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem"}}>Deposit Ledger</span>
        <span style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem",color:"var(--accent)"}}>{fmtCurrency(bidders.filter(b=>b.depositOnFile).length*300)} held</span>
      </div>
      {/* Pending banner */}
      {bidders.filter(b=>b.depositStatus==="pending"&&(b.payMethod==="cash"||b.payMethod==="zelle")).length>0&&
        <div style={{padding:".75rem 1.2rem",background:"rgba(220,38,38,.06)",borderBottom:"1px solid rgba(220,38,38,.15)",fontSize:".82rem",color:"var(--red)",display:"flex",alignItems:"center",gap:".5rem"}}>
          <span>⏳</span>
          <span><strong>{bidders.filter(b=>b.depositStatus==="pending"&&(b.payMethod==="cash"||b.payMethod==="zelle")).length} unconfirmed deposit{bidders.filter(b=>b.depositStatus==="pending"&&(b.payMethod==="cash"||b.payMethod==="zelle")).length!==1?"s":""}</strong> — open Bidders tab to verify and approve</span>
        </div>}
      {bidders.map(b=><div key={b.id} style={{padding:".82rem 1.2rem",borderBottom:"1px solid var(--border)",display:"flex",alignItems:"center",gap:".9rem",flexWrap:"wrap"}}>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)",width:"62px"}}>{b.bidderNum}</div>
        <div style={{flex:1,minWidth:120}}>
          <div style={{fontSize:".83rem",fontWeight:500}}>{b.first} {b.last}</div>
          <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:"2px",display:"flex",alignItems:"center",gap:".4rem",flexWrap:"wrap"}}>
            <span>{PAY_METHODS.find(p=>p.id===b.payMethod)?.icon} {PAY_METHODS.find(p=>p.id===b.payMethod)?.label}</span>
            {b.payMethod==="card"&&<span style={{color:"var(--green)",fontFamily:"DM Mono,monospace",fontSize:".65rem"}}>· auto-approved</span>}
            {b.depositConfirmedAt&&<span style={{color:"var(--muted)",fontFamily:"DM Mono,monospace",fontSize:".65rem"}}>· confirmed {b.depositConfirmedAt}</span>}
            <span style={{color:"var(--muted)"}}>· {b.keepOnFile?"On file (rolling)":"Per-auction"}</span>
          </div>
          {b.depositNote&&<div style={{fontSize:".7rem",color:"var(--sub)",fontStyle:"italic",marginTop:"2px"}}>"{b.depositNote}"</div>}
        </div>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:"var(--accent)"}}>$300</div>
        {b.depositStatus==="pending"
          ? <span className="pend-badge">⏳ {b.payMethod==="card"?"Pending charge":"Awaiting confirmation"}</span>
          : <span className="appr-badge">✓ {b.payMethod==="card"?"Auto-approved":"Staff confirmed"}</span>}
        {b.depositStatus==="approved"&&b.depositOnFile&&<button className="btn-sm" onClick={()=>setBidders(bs=>bs.map(x=>x.id===b.id?{...x,depositOnFile:false,depositStatus:"pending",depositConfirmedAt:null}:x))}>Refund</button>}
      </div>)}
    </div>}

    {tab==="checklist"&&<AuctionChecklist auctions={auctions}/>}
    {tab==="payments"&&<PaymentTracker auctions={auctions} setAuctions={setAuctions} feeSettings={feeSettings} bidders={bidders}/>}
    {tab==="report"&&<AuctionReport auctions={auctions} feeSettings={feeSettings} bidders={bidders}/>}
    {tab==="summary"&&<div><DailyRevenueWidget auctions={auctions} feeSettings={feeSettings}/><RevenueByCompanyChart auctions={auctions}/><SummaryDashboard auctions={auctions} feeSettings={feeSettings}/></div>}
    {tab==="exports"&&<ExportsPanel auctions={auctions} bidders={bidders} feeSettings={feeSettings}/>}
    {tab==="history"&&<HistoryTab onMoveToAuction={handleMoveToAuction}/>}
    {tab==="staff"&&<StaffAccountsTab adminUsers={adminUsers} setAdminUsers={setAdminUsers}/>}

    {tab==="settings"&&<div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden",maxWidth:"560px"}}>
      <div style={{padding:"1rem 1.2rem",borderBottom:"1px solid var(--border)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem"}}>Auction Configuration</div>
      {/* Auction date — used on roster printout */}
      <div style={{padding:".65rem 1.2rem",background:"rgba(0,48,135,.06)",borderBottom:"1px solid var(--border)"}}><div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)"}}>Current Auction Date</div></div>
      <div className="srow">
        <div className="slbl"><div className="slbl-main">Auction Date</div><div className="slbl-sub">Printed on the roster and all documents</div></div>
        <input className="finput" type="date" value={auctionDate} onChange={e=>setAuctionDate(e.target.value)} style={{width:"160px"}}/>
      </div>
      <div className="srow">
        <div className="slbl"><div className="slbl-main">Auction Day</div><div className="slbl-sub">Tuesday (Henderson) or Friday (N. Las Vegas)</div></div>
        <select className="finput fselect" style={{width:"200px"}} value={auctionDayLabel} onChange={e=>setAuctionDayLabel(e.target.value)}>
          <option value="tuesday">Tuesday — Henderson</option>
          <option value="friday">Friday — North Las Vegas</option>
        </select>
      </div>
      <div style={{borderTop:"1px solid var(--border)"}}/>
      {["tuesday","friday"].map((day,di)=><span key={day}><div style={{padding:".65rem 1.2rem",background:"var(--navy-light)",borderBottom:"1px solid var(--border)",borderTop:di>0?"1px solid var(--border)":"none"}}><div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".15rem"}}>{AUCTION_EVENTS[day].label}</div><div style={{fontSize:".75rem",color:"var(--muted)"}}>{AUCTION_EVENTS[day].address}</div></div><div className="srow"><div className="slbl"><div className="slbl-main">Close Time</div><div className="slbl-sub">All lots close starting here (staggered)</div></div><input className="finput" type="time" defaultValue="14:00" style={{width:"125px"}}/></div></span>)}
      <div style={{borderTop:"1px solid var(--border)"}}/>
      <div style={{padding:".65rem 1.2rem",background:"var(--navy-light)",borderBottom:"1px solid var(--border)"}}><div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)"}}>Invoice & Fees</div></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">Admin Fee</div><div className="slbl-sub">Added to every winning invoice</div></div><div style={{display:"flex",alignItems:"center",gap:".4rem"}}><span style={{color:"var(--accent)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem"}}>$</span><input className="finput sinput" type="number" step="0.01" value={feeSettings.adminFee} onChange={e=>setFeeSettings(f=>({...f,adminFee:+e.target.value}))}/></div></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">Sales Tax Rate</div><div className="slbl-sub">Applied unless lot is marked tax exempt</div></div><div style={{display:"flex",alignItems:"center",gap:".4rem"}}><input className="finput sinput" type="number" step="0.001" value={feeSettings.taxRate} onChange={e=>setFeeSettings(f=>({...f,taxRate:+e.target.value}))}/><span style={{fontSize:".75rem",color:"var(--muted)"}}>%</span></div></div>
      <div style={{borderTop:"1px solid var(--border)"}}/>
      <div style={{padding:".65rem 1.2rem",background:"var(--navy-light)",borderBottom:"1px solid var(--border)"}}><div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)"}}>Notifications</div></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">Email Notifications</div><div className="slbl-sub">Invoice PDF on auction close</div></div><button className="cta" style={{fontSize:".78rem",background:"var(--green)"}}>● Enabled</button></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">SMS Notifications</div><div className="slbl-sub">Balance summary on auction close</div></div><button className="cta" style={{fontSize:".78rem",background:"var(--green)"}}>● Enabled</button></div>
      <div style={{borderTop:"1px solid var(--border)"}}/>
      <div className="srow"><div className="slbl"><div className="slbl-main">Lot Stagger Interval</div><div className="slbl-sub">Seconds between each lot closing</div></div><div style={{display:"flex",alignItems:"center",gap:".4rem"}}><input className="finput sinput" type="number" value={stagger} min={10} step={5} onChange={e=>setStagger(+e.target.value)}/><span style={{fontSize:".75rem",color:"var(--muted)"}}>sec</span></div></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">Required Deposit</div></div><div style={{display:"flex",alignItems:"center",gap:".4rem"}}><span style={{color:"var(--accent)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.05rem"}}>$</span><input className="finput sinput" type="number" defaultValue={300}/></div></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">Accepted Payment Methods</div></div><div style={{display:"flex",gap:".4rem",flexWrap:"wrap"}}>{PAY_METHODS.map(p=><button key={p.id} className="filter-btn active" style={{fontSize:".72rem"}}>{p.icon} {p.label}</button>)}</div></div>
      <div className="srow"><div className="slbl"><div className="slbl-main">Auction Status</div></div><button className="cta" style={{fontSize:".78rem"}}>● LIVE</button></div>
      <div style={{padding:"1rem 1.2rem"}}><button className="btn-p" style={{width:"100%"}}>Save Settings</button></div>
    </div>}

    {(showAdd||editLot)&&<LotModal existing={editLot} auctions={auctions} onSave={saveLot} onClose={()=>{setShowAdd(false);setEditLot(null);}}/>}
    {showImport&&<BulkImportModal auctions={auctions} onImport={lots=>setAuctions(p=>[...p,...lots])} onClose={()=>setShowImport(false)}/>}
    {showPhotos&&<BulkPhotoModal auctions={auctions} onMatch={handleMatch} onClose={()=>setShowPhotos(false)}/>}
    {showRoster&&<RosterModal auctions={auctions} auctionDate={auctionDate} auctionDayLabel={auctionDayLabel} onClose={()=>setShowRoster(false)}/>}
    {showReorder&&<ReorderModal auctions={auctions} setAuctions={setAuctions} onClose={()=>setShowReorder(false)}/>}
    {showScoreboard&&<AuctionScoreboard auctions={auctions} onClose={()=>setShowScoreboard(false)}/>}
    {showSummaryPdf&&<AuctionCloseSummaryModal auctions={auctions} feeSettings={feeSettings} bidders={bidders} auctionDate={auctionDate} auctionDayLabel={auctionDayLabel} onClose={()=>setShowSummaryPdf(false)}/>}
    {showPreReg&&<PreRegLinkModal onClose={()=>setShowPreReg(false)}/>}
    {emailPreviewLot&&<WinnerEmailPreview auction={emailPreviewLot} feeSettings={feeSettings} bidder={bidders.find(b=>b.bidderNum===emailPreviewLot.winner)} onClose={()=>setEmailPreviewLot(null)}/>}
    {badgeBidder&&<BidderBadgeModal bidder={badgeBidder} onClose={()=>setBadgeBidder(null)}/>}
    {rateModal&&<RateBidderModal bidder={rateModal} onClose={()=>setRateModal(null)} onSave={rating=>{
      setBidders(bs=>bs.map(b=>b.id!==rateModal.id?b:{...b,
        ratings:[...(b.ratings||[]),rating],
        avgRating:+((([...(b.ratings||[]),rating].reduce((s,r)=>s+r.overall,0))/([...(b.ratings||[]),rating].length)).toFixed(1))
      }));
      setRateModal(null);
    }}/>}
    {invoiceLot&&<InvoiceModal auction={invoiceLot} feeSettings={feeSettings} onClose={()=>setInvoiceLot(null)} onNotify={()=>{setNotifyLot(invoiceLot);setInvoiceLot(null);}}/>}
    {notifyLot&&<NotifyModal auction={notifyLot} feeSettings={feeSettings} onClose={()=>setNotifyLot(null)}/>}
  </div>;
}

// ─── CUSTOMER LOGIN ───────────────────────────────────────────────────────────
function CustomerLogin({onLogin, onRegister}){
  const [email,setEmail]=useState("");
  const [pass,setPass]=useState("");
  const [err,setErr]=useState("");
  const [loading,setLoading]=useState(false);

  const submit=()=>{
    setErr(""); setLoading(true);
    authLogin(email, pass).then(function(result){
      if(result.ok){ authSetCurrent(result.bidder); onLogin(result.bidder); }
      else setErr(result.error||"Email or password incorrect.");
      setLoading(false);
    }).catch(function(){ setErr("Login failed. Please try again."); setLoading(false); });
  };

  return <div className="login-wrap">
    <div className="login-card">
      <div className="login-logo">Tow Guys Auto Auction</div>
      <div className="login-sub">Sign in to view your invoices and bid history</div>
      {err&&<div className="login-error">{err}</div>}
      <div className="fgrp" style={{marginBottom:".75rem"}}>
        <label className="flbl">Username or Email</label>
        <input className="finput" type="text" placeholder="Your username or email" value={email} onChange={e=>setEmail(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
      </div>
      <div className="fgrp" style={{marginBottom:"1.2rem"}}>
        <label className="flbl">Password</label>
        <input className="finput" type="password" placeholder="••••••••" value={pass} onChange={e=>setPass(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
      </div>
      <button className="btn-p" style={{width:"100%"}} disabled={loading||!email||!pass} onClick={submit}>
        {loading?"Signing in…":"Sign In →"}
      </button>
      <div className="login-footer">
        Don't have an account?{" "}
        <button className="login-link" onClick={onRegister}>Register & deposit to bid</button>
      </div>

    </div>
  </div>;
}

// ─── MY INVOICES PAGE ─────────────────────────────────────────────────────────
function MyInvoicesPage({customer, onLogout, feeSettings}){
  const [liveInvoices, setLiveInvoices] = useState(null);
  useEffect(function(){
    if(!customer||!customer.bidderNum) return;
    fetch("/api/bidders/"+encodeURIComponent(customer.bidderNum)+"/invoices")
      .then(function(r){return r.json();}).then(function(arr){ if(Array.isArray(arr)) setLiveInvoices(arr); })
      .catch(function(){});
  },[customer&&customer.bidderNum]);
  const invoices = liveInvoices || customer.invoices || [];
  // Use an enriched customer-like object so all downstream reads get the real data
  customer = Object.assign({}, customer, {invoices:invoices});
  const [expanded,setExpanded]=useState({});
  const [payModal,setPayModal]=useState(null);
  const toggleExpand=id=>setExpanded(e=>({...e,[id]:!e[id]}));

  const calcInvoice=(inv)=>{
    const taxable=inv.finalBid+(inv.keyFee||0)+inv.adminFee;
    const taxAmt=inv.taxExempt?0:+(taxable*inv.taxRate/100).toFixed(2);
    const total=taxable+taxAmt;
    const balance=total-inv.deposit;
    return {taxAmt,total,balance};
  };

  const totalOwed=(customer.invoices||[])
    .filter(i=>i.paymentStatus==="unpaid")
    .reduce((s,i)=>s+calcInvoice(i).balance,0);

  return <div className="portal-wrap">
    {/* Hero */}
    <div className="portal-hero">
      <div>
        <div className="portal-hero-name">Welcome back, {customer.first} {customer.last}</div>
        <div className="portal-hero-sub">{customer.bidderNum} · {customer.email}</div>
      </div>
      <div style={{display:"flex",gap:".65rem",alignItems:"center",flexWrap:"wrap"}}>
        {totalOwed>0&&<div style={{background:"rgba(220,38,38,.2)",border:"1px solid rgba(220,38,38,.4)",color:"#fff",padding:".4rem 1rem",borderRadius:"20px",fontSize:".82rem",fontFamily:"DM Mono,monospace"}}>
          Balance Due: {fmtCurrency(totalOwed)}
        </div>}
        <div className="portal-hero-badge">{(customer.invoices||[]).length} Invoice{(customer.invoices||[]).length!==1?"s":""}</div>
        <button className="btn-g" style={{background:"rgba(255,255,255,.1)",border:"1px solid rgba(255,255,255,.25)",color:"#fff",padding:".35rem .85rem",fontSize:".78rem"}} onClick={onLogout}>Sign Out</button>
      </div>
    </div>

    {/* Summary bar */}
    <div style={{display:"flex",gap:"1rem",marginBottom:"1.5rem",flexWrap:"wrap"}}>
      {[
        {lbl:"Total Auctions",val:(customer.invoices||[]).length,color:"var(--accent)"},
        {lbl:"Paid",val:(customer.invoices||[]).filter(i=>i.paymentStatus==="paid").length,color:"var(--green)"},
        {lbl:"Balance Due",val:(customer.invoices||[]).filter(i=>i.paymentStatus==="unpaid").length,color:"var(--red)"},
      ].map(s=><div key={s.lbl} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",padding:".85rem 1.2rem",flex:1,minWidth:"120px",boxShadow:"0 1px 4px rgba(0,48,135,.05)"}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.6rem",color:s.color}}>{s.val}</div>
        <div style={{fontSize:".68rem",fontFamily:"DM Mono,monospace",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".08em"}}>{s.lbl}</div>
      </div>)}
    </div>

    {/* Invoice list */}
    {(customer.invoices||[]).length===0
      ? <div className="portal-empty"><div className="portal-empty-icon">🏷️</div><div className="portal-empty-title">No Invoices Yet</div><p>Your winning bids will appear here.</p></div>
      : (customer.invoices||[]).map(inv=>{
          const {taxAmt,total,balance}=calcInvoice(inv);
          const open=!!expanded[inv.id];
          return <div key={inv.id} className="inv-card">
            <div className="inv-card-hd" onClick={()=>toggleExpand(inv.id)}>
              <div>
                <div className="inv-card-title">{inv.year} {inv.make} {inv.model} — {inv.lot}</div>
                <div className="inv-card-meta">{inv.date} · {inv.auctionDay} · {inv.location} · #{inv.id}</div>
              </div>
              <div className="inv-card-right">
                <div style={{textAlign:"right"}}>
                  <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:inv.paymentStatus==="unpaid"?"var(--red)":"var(--accent)"}}>
                    {inv.paymentStatus==="unpaid"?`${fmtCurrency(balance)} due`:fmtCurrency(total)}
                  </div>
                  <div style={{fontSize:".65rem",fontFamily:"DM Mono,monospace",color:"var(--muted)"}}>
                    {inv.paymentStatus==="paid"?"Total paid":"Balance remaining"}
                  </div>
                </div>
                <span className={`inv-status ${inv.paymentStatus==="paid"?"paid":"unpaid"}`}>
                  {inv.paymentStatus==="paid"?"✓ Paid":"⚠ Unpaid"}
                </span>
                <span style={{color:"var(--muted)",fontSize:".9rem"}}>{open?"▲":"▼"}</span>
              </div>
            </div>

            {open&&<div className="inv-card-body">
              {/* Vehicle strip */}
              <div className="inv-vehicle-strip">
                <div style={{flex:1}}>
                  <div className="inv-vs-name">{inv.year} {inv.make} {inv.model}</div>
                  <div className="inv-vs-meta">VIN: {inv.vin} · {(inv.mileage||0).toLocaleString()} mi · {inv.condition==="runs"?"Runs":"No Start"}</div>
                </div>
                <div style={{textAlign:"right"}}>
                  <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)"}}>Invoice</div>
                  <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:"var(--accent)"}}>#{inv.id}</div>
                </div>
              </div>

              {/* Fee breakdown */}
              <div className="inv-breakdown">
                <div className="inv-line"><span>Winning Bid</span><span><strong>{fmtCurrency(inv.finalBid)}</strong></span></div>
                {(inv.keyFee||0)>0&&<div className="inv-line"><span>Key Fee</span><span>{fmtCurrency(inv.keyFee)}</span></div>}
                <div className="inv-line"><span>Admin Fee</span><span>{fmtCurrency(inv.adminFee)}</span></div>
                <div className="inv-line">
                  <span>Sales Tax {inv.taxExempt?"(Exempt)":`(${inv.taxRate}%)`}</span>
                  <span>{inv.taxExempt?"—":fmtCurrency(taxAmt)}</span>
                </div>
                <div className="inv-line deposit-line"><span>Deposit Applied</span><span>−{fmtCurrency(inv.deposit)}</span></div>
                <div className="inv-line balance-line">
                  <span>{inv.paymentStatus==="paid"?"Total Paid":"Balance Due"}</span>
                  <span>{inv.paymentStatus==="paid"?fmtCurrency(total):fmtCurrency(balance)}</span>
                </div>
              </div>

              {/* Actions */}
              <div style={{display:"flex",gap:".6rem",flexWrap:"wrap"}}>
                <button className="btn-g" style={{flex:1,minWidth:"140px"}} onClick={()=>window.print()}>🖨 Print Invoice</button>
              </div>
            </div>}
          </div>;
        })
    }

    {/* Pay modal */}
    {payModal&&<div className="modal-bg"><div className="modal">
      <div className="mhd"><div><div className="mtitle">Pay Balance</div><div className="msub">{payModal.year} {payModal.make} {payModal.model}</div></div><button className="mclose" onClick={()=>setPayModal(null)}>×</button></div>
      <div className="mbody">
        <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:"1rem",marginBottom:"1rem",textAlign:"center"}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--muted)",marginBottom:".3rem"}}>Amount Due</div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"2.5rem",color:"var(--accent)"}}>{fmtCurrency(calcInvoice(payModal).balance)}</div>
          <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".2rem"}}>Invoice #{payModal.id}</div>
        </div>
        <div className="fsec-title" style={{marginBottom:".6rem"}}>Card Details</div>
        <div className="frow s"><div className="fgrp"><label className="flbl">Name on Card</label><input className="finput" placeholder="John Smith"/></div></div>
        <div className="frow s"><div className="fgrp"><label className="flbl">Card Number</label><input className="finput" placeholder="•••• •••• •••• ••••"/></div></div>
        <div className="frow">
          <div className="fgrp"><label className="flbl">Expiry</label><input className="finput" placeholder="MM/YY"/></div>
          <div className="fgrp"><label className="flbl">CVV</label><input className="finput" placeholder="•••"/></div>
        </div>
        <div className="notice ok" style={{marginBottom:0}}>Payment processed securely via Stripe. Your balance will be marked as paid immediately.</div>
      </div>
      <div className="mfoot">
        <button className="btn-g" onClick={()=>setPayModal(null)}>Cancel</button>
        <button className="btn-p" onClick={()=>setPayModal(null)}>Pay {fmtCurrency(calcInvoice(payModal).balance)} →</button>
      </div>
    </div></div>}
  </div>;
}

// ─── ADMIN LOGIN ──────────────────────────────────────────────────────────────
function AdminLogin({adminUsers, onLogin, onCancel}){
  const [username,setUsername]=useState("");
  const [password,setPassword]=useState("");
  const [err,setErr]=useState("");
  const [loading,setLoading]=useState(false);
  const [showPw,setShowPw]=useState(false);

  const submit=()=>{
    setErr(""); setLoading(true);
    setTimeout(()=>{
      const user=adminUsers.find(u=>u.username===username.trim().toLowerCase()&&u.password===password&&u.active);
      if(user) onLogin(user);
      else setErr("Invalid credentials or account inactive.");
      setLoading(false);
    },500);
  };

  return <div className="admin-login-wrap">
    <div className="admin-login-card">
      <div className="admin-login-logo">Tow Guys Auto Auction</div>
      <div className="admin-login-title">⚙ Staff Portal — Authorized Access Only</div>
      {err&&<div className="admin-login-err">{err}</div>}
      <label className="admin-login-label">Username</label>
      <input className="admin-login-input" placeholder="username" autoCapitalize="none" value={username}
        onChange={e=>setUsername(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
      <label className="admin-login-label">Password</label>
      <div style={{position:"relative",marginBottom:".75rem"}}>
        <input className="admin-login-input" style={{marginBottom:0,paddingRight:"2.8rem"}}
          type={showPw?"text":"password"} placeholder="••••••••" value={password}
          onChange={e=>setPassword(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
        <button onClick={()=>setShowPw(s=>!s)} style={{position:"absolute",right:".6rem",top:"50%",transform:"translateY(-50%)",background:"none",border:"none",color:"#4a6fa5",cursor:"pointer",fontSize:".8rem"}}>
          {showPw?"Hide":"Show"}
        </button>
      </div>
      <button className="admin-login-btn" disabled={loading||!username||!password} onClick={submit}>
        {loading?"Authenticating…":"Sign In to Admin →"}
      </button>
      <div style={{textAlign:"center",marginTop:"1rem"}}>
        <button onClick={onCancel} style={{background:"none",border:"none",color:"#4a6fa5",cursor:"pointer",fontSize:".72rem",fontFamily:"DM Mono,monospace"}}>← Back to Auction</button>
      </div>
    </div>
  </div>;
}

// ─── STAFF ACCOUNTS TAB ───────────────────────────────────────────────────────
function StaffAccountsTab({adminUsers, setAdminUsers}){
  const [editId,setEditId]=useState(null);
  const [newPw,setNewPw]=useState("");
  const [showPw,setShowPw]=useState({});
  const [addMode,setAddMode]=useState(false);
  const [newUser,setNewUser]=useState({name:"",username:"",password:"",role:"office",active:true});
  const toggleShow=id=>setShowPw(s=>({...s,[id]:!s[id]}));

  const savePassword=id=>{
    if(!newPw.trim()) return;
    setAdminUsers(u=>u.map(x=>x.id===id?{...x,password:newPw}:x));
    setEditId(null); setNewPw("");
  };
  const toggleActive=id=>setAdminUsers(u=>u.map(x=>x.id===id?{...x,active:!x.active}:x));
  const addUser=()=>{
    if(!newUser.name||!newUser.username||!newUser.password) return;
    setAdminUsers(u=>[...u,{...newUser,id:"admin-"+Date.now()}]);
    setNewUser({name:"",username:"",password:"",role:"office",active:true});
    setAddMode(false);
  };

  return <div>
    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1.1rem"}}>
      <div style={{fontFamily:"DM Mono,monospace",fontSize:".7rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".08em"}}>{adminUsers.length} staff accounts · {adminUsers.filter(u=>u.active).length} active</div>
      <button className="cta" style={{fontSize:".78rem"}} onClick={()=>setAddMode(true)}>+ Add Staff</button>
    </div>

    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden",marginBottom:"1.2rem"}}>
      {adminUsers.map(u=>{
        const role=ADMIN_ROLES.find(r=>r.id===u.role);
        return <div key={u.id} className="staff-row" style={{opacity:u.active?1:.55}}>
          <div className="staff-avatar" style={{background:role?.color||"var(--accent)"}}>{u.name.split(" ").map(w=>w[0]).join("").slice(0,2)}</div>
          <div className="staff-info">
            <div className="staff-name">{u.name} {!u.active&&<span style={{fontSize:".68rem",color:"var(--muted)",fontWeight:400}}>(Inactive)</span>}</div>
            <div className="staff-meta">@{u.username} · <span className="role-badge" style={{background:role?.color+"18",color:role?.color,border:`1px solid ${role?.color}33`}}>{role?.label||u.role}</span></div>
          </div>

          {/* Password */}
          <div style={{display:"flex",gap:".4rem",alignItems:"center",flexWrap:"wrap"}}>
            {editId===u.id
              ? <div style={{display:"flex",gap:".4rem",alignItems:"center"}}>
                  <input className="finput" style={{width:"150px",fontSize:".78rem"}} placeholder="New password" value={newPw} onChange={e=>setNewPw(e.target.value)} onKeyDown={e=>e.key==="Enter"&&savePassword(u.id)}/>
                  <button className="btn-approve" onClick={()=>savePassword(u.id)}>Save</button>
                  <button className="btn-sm" onClick={()=>{setEditId(null);setNewPw("");}}>✕</button>
                </div>
              : <div className="pw-input-wrap">
                  <div className="pw-display">{showPw[u.id]?u.password:"•".repeat(Math.min(u.password.length,10))}</div>
                  <button className="btn-sm" onClick={()=>toggleShow(u.id)}>{showPw[u.id]?"Hide":"Show"}</button>
                  <button className="btn-sm" onClick={()=>{setEditId(u.id);setNewPw("");}}>Change</button>
                </div>}
          </div>

          {/* Active toggle */}
          <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",flexShrink:0}}>
            <input type="checkbox" checked={u.active} onChange={()=>toggleActive(u.id)} style={{width:14,height:14,accentColor:"var(--accent)"}}/>
            <span style={{fontSize:".72rem",color:"var(--muted)"}}>Active</span>
          </label>
        </div>;
      })}
    </div>

    {/* Add new user panel */}
    {addMode&&<div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",padding:"1.2rem",marginBottom:"1rem"}}>
      <div className="fsec-title" style={{marginBottom:".85rem"}}>New Staff Account</div>
      <div className="frow"><div className="fgrp"><label className="flbl">Full Name</label><input className="finput" value={newUser.name} onChange={e=>setNewUser(u=>({...u,name:e.target.value}))}/></div>
      <div className="fgrp"><label className="flbl">Username</label><input className="finput" style={{fontFamily:"DM Mono,monospace"}} value={newUser.username} onChange={e=>setNewUser(u=>({...u,username:e.target.value.toLowerCase().replace(/\s/g,"")}))}/></div></div>
      <div className="frow"><div className="fgrp"><label className="flbl">Password</label><input className="finput" value={newUser.password} onChange={e=>setNewUser(u=>({...u,password:e.target.value}))}/></div>
      <div className="fgrp"><label className="flbl">Role</label><select className="finput fselect" value={newUser.role} onChange={e=>setNewUser(u=>({...u,role:e.target.value}))}>{ADMIN_ROLES.map(r=><option key={r.id} value={r.id}>{r.label}</option>)}</select></div></div>
      <div style={{display:"flex",gap:".6rem"}}>
        <button className="btn-g" onClick={()=>setAddMode(false)}>Cancel</button>
        <button className="btn-p" disabled={!newUser.name||!newUser.username||!newUser.password} onClick={addUser}>Create Account</button>
      </div>
    </div>}
  </div>;
}

// ─── CUSTOMER LOGIN (inline modal version) ────────────────────────────────────
function CustomerLoginInline({onLogin, onRegister, t=k=>k}){
  const [email,setEmail]=useState("");
  const [pass,setPass]=useState("");
  const [err,setErr]=useState("");
  const [loading,setLoading]=useState(false);
  const [showPw,setShowPw]=useState(false);
  const [resetMode,setResetMode]=useState(false);
  const [resetStep,setResetStep]=useState("email"); // email | code | newpw | done
  const [resetEmail,setResetEmail]=useState("");
  const [resetPhone,setResetPhone]=useState("");
  const [resetCode,setResetCode]=useState("");
  const [resetPw,setResetPw]=useState("");
  const [resetPw2,setResetPw2]=useState("");
  const [resetMsg,setResetMsg]=useState("");
  const [resetLoading,setResetLoading]=useState(false);

  const submit=()=>{
    setErr(""); setLoading(true);
    authLogin(email, pass).then(function(result){
      if(result.ok){ authSetCurrent(result.bidder); onLogin(result.bidder); }
      else setErr(result.error||"Email or password incorrect.");
      setLoading(false);
    }).catch(function(){ setErr("Login failed. Please try again."); setLoading(false); });
  };

  // Forgot password: look up phone by email, send SMS code
  var resetLookup = function(){
    setResetMsg(""); setResetLoading(true);
    var em = resetEmail.trim().toLowerCase();
    if(!em){ setResetMsg("Enter your email."); setResetLoading(false); return; }
    fetch("/api/bidder-status-by-email/"+encodeURIComponent(em))
      .then(function(r){return r.json();})
      .then(function(data){
        setResetLoading(false);
        if(!data||!data.found){ setResetMsg("No account found for that email."); return; }
        var ph = (data.phone||"").replace(/\D/g,"");
        if(!ph||ph.length<10){ setResetMsg("No phone number on file. Call (702) 677-0792 for help."); return; }
        setResetPhone(ph);
        // Send verification code
        fetch("/api/sms-verify/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({phone:ph})})
          .then(function(r){return r.json();})
          .then(function(d){
            if(d.success){ setResetStep("code"); setResetMsg("Code sent to ***-***-"+ph.slice(-4)); }
            else setResetMsg("Could not send code. Call (702) 677-0792.");
          }).catch(function(){ setResetMsg("Network error. Try again."); });
      }).catch(function(){ setResetLoading(false); setResetMsg("Network error. Try again."); });
  };

  var resetVerify = function(){
    if(resetCode.length<6){ setResetMsg("Enter the 6-digit code."); return; }
    setResetMsg(""); setResetLoading(true);
    fetch("/api/sms-verify/check",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({phone:resetPhone,code:resetCode})})
      .then(function(r){return r.json();})
      .then(function(d){
        setResetLoading(false);
        if(d.valid){ setResetStep("newpw"); setResetMsg(""); }
        else setResetMsg("Invalid code. Try again.");
      }).catch(function(){ setResetLoading(false); setResetMsg("Network error."); });
  };

  var resetSave = function(){
    if(resetPw.length<6){ setResetMsg("Password must be at least 6 characters."); return; }
    if(resetPw!==resetPw2){ setResetMsg("Passwords don't match."); return; }
    setResetMsg(""); setResetLoading(true);
    var em = resetEmail.trim().toLowerCase();
    fetch("/api/auth/change-password",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:em,newPassword:resetPw})})
      .then(function(r){return r.json();})
      .then(function(){
        setResetLoading(false);
        // Also update localStorage
        authUpdate(em, {password:resetPw});
        setResetStep("done");
      }).catch(function(){ setResetLoading(false); setResetMsg("Failed to save. Try again."); });
  };

  if(resetMode){
    return <div>
      <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",marginBottom:".75rem"}}>Reset Password</div>
      {resetMsg&&<div style={{background:resetStep==="done"?"rgba(21,128,61,.08)":"rgba(220,38,38,.08)",border:"1px solid "+(resetStep==="done"?"rgba(21,128,61,.3)":"rgba(220,38,38,.3)"),borderRadius:6,padding:".6rem .85rem",marginBottom:".85rem",fontSize:".82rem",color:resetStep==="done"?"#15803d":"#dc2626"}}>{resetMsg}</div>}
      {resetStep==="email"&&<>
        <div style={{fontSize:".82rem",color:"var(--muted)",marginBottom:".75rem",lineHeight:1.5}}>Enter the email you registered with. We'll text a verification code to the phone number on file.</div>
        <div className="fgrp" style={{marginBottom:"1rem"}}>
          <label className="flbl">Email</label>
          <input className="finput" type="email" placeholder="you@email.com" value={resetEmail} onChange={function(e){setResetEmail(e.target.value);}} onKeyDown={function(e){if(e.key==="Enter") resetLookup();}}/>
        </div>
        <button className="btn-p" style={{width:"100%",marginBottom:".75rem"}} disabled={resetLoading||!resetEmail.trim()} onClick={resetLookup}>{resetLoading?"Looking up…":"Send Verification Code"}</button>
      </>}
      {resetStep==="code"&&<>
        <div className="fgrp" style={{marginBottom:"1rem"}}>
          <label className="flbl">6-Digit Code</label>
          <input className="finput" type="text" placeholder="000000" maxLength={6} value={resetCode} style={{fontFamily:"DM Mono,monospace",fontSize:"1.1rem",letterSpacing:".3em",textAlign:"center"}} onChange={function(e){setResetCode(e.target.value.replace(/\D/g,""));}} onKeyDown={function(e){if(e.key==="Enter") resetVerify();}}/>
        </div>
        <button className="btn-p" style={{width:"100%",marginBottom:".75rem"}} disabled={resetLoading||resetCode.length<6} onClick={resetVerify}>{resetLoading?"Verifying…":"Verify Code"}</button>
      </>}
      {resetStep==="newpw"&&<>
        <div className="fgrp" style={{marginBottom:".75rem"}}>
          <label className="flbl">New Password</label>
          <input className="finput" type="password" placeholder="At least 6 characters" value={resetPw} onChange={function(e){setResetPw(e.target.value);}}/>
        </div>
        <div className="fgrp" style={{marginBottom:"1rem"}}>
          <label className="flbl">Confirm Password</label>
          <input className="finput" type="password" placeholder="Re-enter password" value={resetPw2} onChange={function(e){setResetPw2(e.target.value);}} onKeyDown={function(e){if(e.key==="Enter") resetSave();}}/>
        </div>
        <button className="btn-p" style={{width:"100%",marginBottom:".75rem"}} disabled={resetLoading} onClick={resetSave}>{resetLoading?"Saving…":"Set New Password"}</button>
      </>}
      {resetStep==="done"&&<>
        <div style={{textAlign:"center",padding:"1.5rem 0"}}>
          <div style={{fontSize:"2.5rem",marginBottom:".5rem"}}>✓</div>
          <div style={{fontSize:".92rem",fontWeight:700,color:"var(--green)",marginBottom:".5rem"}}>Password Reset Successfully</div>
          <div style={{fontSize:".82rem",color:"var(--muted)"}}>You can now sign in with your new password.</div>
        </div>
        <button className="btn-p" style={{width:"100%",marginBottom:".75rem"}} onClick={function(){setResetMode(false);setResetStep("email");setResetCode("");setResetPw("");setResetPw2("");setResetMsg("");setEmail(resetEmail);}}>Back to Sign In</button>
      </>}
      {resetStep!=="done"&&<div style={{textAlign:"center",fontSize:".78rem",color:"var(--muted)"}}>
        <button className="login-link" onClick={function(){setResetMode(false);setResetMsg("");}}>Back to Sign In</button>
      </div>}
    </div>;
  }

  return <div>
    {err&&<div className="login-error" style={{marginBottom:".9rem"}}>{err}</div>}
    <div className="fgrp" style={{marginBottom:".75rem"}}>
      <label className="flbl">Username or Email</label>
      <input className="finput" type="text" placeholder="Your username or email" value={email}
        onChange={e=>setEmail(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
    </div>
    <div className="fgrp" style={{marginBottom:"1.1rem"}}>
      <label className="flbl">Password</label>
      <div style={{position:"relative"}}>
        <input className="finput" style={{paddingRight:"3rem"}} type={showPw?"text":"password"}
          placeholder="••••••••" value={pass}
          onChange={e=>setPass(e.target.value)} onKeyDown={e=>e.key==="Enter"&&submit()}/>
        <button onClick={()=>setShowPw(s=>!s)} style={{position:"absolute",right:".7rem",top:"50%",transform:"translateY(-50%)",background:"none",border:"none",color:"var(--muted)",cursor:"pointer",fontSize:".75rem"}}>
          {showPw?"Hide":"Show"}
        </button>
      </div>
    </div>
    <button className="btn-p" style={{width:"100%",marginBottom:".85rem"}}
      disabled={loading||!email||!pass} onClick={submit}>
      {loading?"Signing in…":"Sign In →"}
    </button>
    <div style={{textAlign:"center",fontSize:".78rem",color:"var(--muted)"}}>
      <button className="login-link" onClick={function(){setResetMode(true);setResetEmail(email);setResetMsg("");}}>Forgot Password?</button>
      {" · "}
      <button className="login-link" onClick={onRegister}>Register &amp; deposit to bid</button>
    </div>
    <div style={{textAlign:"center",fontSize:".72rem",color:"var(--muted)",marginTop:".4rem",fontFamily:"DM Mono,monospace"}}>
      Demo: demo@example.com / demo123
    </div>
  </div>;
}

// ─── EXTRA DEPOSIT SECTION (customer profile) ─────────────────────────────────
// Customer can top up their bidding balance online via Stripe, OR request to
// pay in cash / zelle / at the office (pending admin approval). Entries persist
// on tga_bidders.extra_deposits and show up in admin Bidders tab.
function ExtraDepositSection({customer}){
  var [amount,setAmount]=useState("300");
  var [method,setMethod]=useState("card");
  var [note,setNote]=useState("");
  var [submitting,setSubmitting]=useState(false);
  var [msg,setMsg]=useState(null);
  var list = Array.isArray(customer.extraDeposits) ? customer.extraDeposits
            : Array.isArray(customer.extra_deposits) ? customer.extra_deposits : [];

  var approved = list.filter(function(e){return e.status==="approved";});
  var pending  = list.filter(function(e){return e.status==="pending";});
  var refunded = list.filter(function(e){return e.status==="refunded";});
  var totalApproved = approved.reduce(function(s,e){return s+(+e.amount||0);},0);
  var totalPending  = pending.reduce(function(s,e){return s+(+e.amount||0);},0);

  function submit(){
    var amt = parseFloat(amount);
    if(!amt||amt<=0){ setMsg({err:"Enter a valid amount."}); return; }
    if(amt > 10000){ setMsg({err:"Maximum $10,000 per entry. Please call for larger amounts."}); return; }
    setSubmitting(true); setMsg(null);

    if(method==="card"){
      // Online Stripe payment — redirect to checkout
      fetch("/api/stripe/create-checkout-session",{
        method:"POST",headers:{"Content-Type":"application/json"},
        body:JSON.stringify({email:customer.email||"", bidderNum:customer.bidderNum||"", purpose:"extra-deposit", amount:amt})
      }).then(function(r){return r.json();}).then(function(d){
        if(d.url){ window.location.href = d.url; return; }
        setSubmitting(false);
        setMsg({err:d.error||"Could not start checkout. Try another method."});
      }).catch(function(){
        setSubmitting(false);
        setMsg({err:"Payment service unavailable. Try Zelle, Cash, or arrange in office."});
      });
    } else {
      // Pending request — admin approval required
      fetch("/api/bidders/"+encodeURIComponent(customer.bidderNum)+"/extra-deposit",{
        method:"POST",headers:{"Content-Type":"application/json"},
        body:JSON.stringify({amount:amt, method:method, note:note})
      }).then(function(r){return r.json();}).then(function(d){
        setSubmitting(false);
        if(d.ok){
          var label = method==="zelle"?"Zelle":method==="cash"?"Cash":"Office arrangement";
          setMsg({ok:label+" request submitted. Staff will approve once received."});
          setNote("");
          // Refresh list (we only have local customer object — reload on next open)
          // Optimistic: push entry locally so it shows immediately
          customer.extraDeposits = list.concat([d.entry]);
        } else {
          setMsg({err:d.error||"Could not submit request."});
        }
      }).catch(function(){
        setSubmitting(false);
        setMsg({err:"Network error. Please try again."});
      });
    }
  }

  var methodBtn = function(id, icon, label, sub){
    return React.createElement("button",{
      type:"button",
      onClick:function(){setMethod(id);},
      style:{
        flex:"1 1 140px",
        padding:".7rem .85rem",
        background:method===id?"rgba(0,48,135,.12)":"var(--card)",
        border:"2px solid "+(method===id?"var(--accent)":"var(--border)"),
        borderRadius:8, cursor:"pointer",
        textAlign:"left", transition:"all .15s"
      }
    },
      React.createElement("div",{style:{fontWeight:700,fontSize:".88rem",marginBottom:".15rem"}}, icon+" "+label),
      React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".66rem",color:"var(--muted)"}}, sub)
    );
  };

  var statusBadge = function(e){
    var cfg = e.status==="approved"?{bg:"rgba(21,128,61,.12)",c:"var(--green)",l:"✓ Approved"}
           : e.status==="refunded"?{bg:"rgba(100,116,139,.15)",c:"var(--muted)",l:"↩ Refunded"}
           : {bg:"rgba(217,119,6,.12)",c:"var(--amber)",l:"⏳ Pending approval"};
    return React.createElement("span",{style:{fontFamily:"DM Mono,monospace",fontSize:".65rem",fontWeight:700,color:cfg.c,background:cfg.bg,border:"1px solid "+cfg.c,padding:".15rem .45rem",borderRadius:3}}, cfg.l);
  };

  return React.createElement("div",{style:{marginTop:"1.5rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:8,padding:"1.1rem 1.2rem"}},
    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".75rem"}},"Add Extra Deposit"),
    React.createElement("div",{style:{fontSize:".82rem",color:"var(--muted)",marginBottom:"1rem",lineHeight:1.5}},
      "Increase your bidding power. Extra deposits are refundable if not applied to a winning bid."),

    // Amount row
    React.createElement("div",{style:{display:"flex",gap:".6rem",alignItems:"center",marginBottom:".9rem",flexWrap:"wrap"}},
      React.createElement("div",{style:{flex:"0 0 auto"}},
        React.createElement("div",{style:{fontSize:".7rem",color:"var(--muted)",marginBottom:".2rem",fontFamily:"DM Mono,monospace"}},"Amount (USD)"),
        React.createElement("div",{style:{display:"flex",alignItems:"center",gap:".4rem"}},
          React.createElement("span",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:"var(--accent)"}},"$"),
          React.createElement("input",{
            type:"number", min:"1", step:"50",
            value:amount, onChange:function(e){setAmount(e.target.value);},
            style:{width:120,padding:".45rem .6rem",fontSize:"1.05rem",fontWeight:700,fontFamily:"DM Mono,monospace",background:"var(--card)",border:"1px solid var(--border)",borderRadius:6,color:"var(--text)"}
          })
        )
      ),
      [100,300,500,1000].map(function(v){
        return React.createElement("button",{key:v,type:"button",className:"btn btn-ghost",style:{fontSize:".75rem",padding:".35rem .7rem"},onClick:function(){setAmount(String(v));}},"$"+v);
      })
    ),

    // Method selector
    React.createElement("div",{style:{display:"flex",gap:".5rem",flexWrap:"wrap",marginBottom:".9rem"}},
      methodBtn("card","💳","Pay Online (Card)","Instant · 3.5% processing fee"),
      methodBtn("zelle","💸","Zelle","702-677-0792 · no fee · admin approval"),
      methodBtn("cash","💵","Cash at Office","Bring to 3823 Losee Rd or Henderson"),
      methodBtn("office","🤝","Arrange with Office","Call (702) 677-0792")
    ),

    // Optional note
    (method==="zelle"||method==="cash"||method==="office")&&React.createElement("div",{style:{marginBottom:".9rem"}},
      React.createElement("input",{
        type:"text", placeholder:"Optional note (e.g., Zelle reference, who you spoke to)",
        value:note, onChange:function(e){setNote(e.target.value);},
        style:{width:"100%",padding:".5rem .7rem",fontSize:".85rem",background:"var(--card)",border:"1px solid var(--border)",borderRadius:6,color:"var(--text)"}
      })
    ),

    // Submit
    React.createElement("button",{
      className:"btn btn-primary",
      disabled:submitting||!customer.bidderNum,
      onClick:submit,
      style:{fontSize:".88rem",padding:".6rem 1.3rem"}
    },
      submitting ? "Processing…"
      : method==="card" ? ("💳 Pay $"+(parseFloat(amount)||0).toFixed(2)+" Online →")
      : method==="zelle" ? ("💸 Submit Zelle Request")
      : method==="cash" ? ("💵 Reserve Cash Payment")
      : ("🤝 Request Office Arrangement")
    ),

    msg&&msg.err&&React.createElement("div",{style:{marginTop:".7rem",padding:".55rem .75rem",background:"rgba(220,38,38,.08)",border:"1px solid rgba(220,38,38,.3)",borderRadius:6,color:"var(--red)",fontSize:".82rem"}}, msg.err),
    msg&&msg.ok&&React.createElement("div",{style:{marginTop:".7rem",padding:".55rem .75rem",background:"rgba(21,128,61,.08)",border:"1px solid rgba(21,128,61,.3)",borderRadius:6,color:"var(--green)",fontSize:".82rem"}}, msg.ok),

    // History
    (list.length>0)&&React.createElement("div",{style:{marginTop:"1.2rem",paddingTop:"1rem",borderTop:"1px solid var(--border)"}},
      React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".6rem"}},
        "Your Extra Deposits — "+list.length+" entr"+(list.length===1?"y":"ies")),
      React.createElement("div",{style:{display:"flex",gap:".75rem",flexWrap:"wrap",marginBottom:".65rem",fontFamily:"DM Mono,monospace",fontSize:".72rem"}},
        React.createElement("span",{style:{color:"var(--green)"}},"✓ Approved: $"+totalApproved.toFixed(2)),
        totalPending>0&&React.createElement("span",{style:{color:"var(--amber)"}},"⏳ Pending: $"+totalPending.toFixed(2))
      ),
      list.slice().reverse().map(function(e){
        var methodLbl = ({card:"💳 Card Online","card":"💳 Card","zelle":"💸 Zelle","cash":"💵 Cash","office":"🤝 Office"})[e.method]||e.method;
        var when = e.createdAt?new Date(e.createdAt).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):"";
        return React.createElement("div",{key:e.id,style:{display:"flex",justifyContent:"space-between",alignItems:"center",padding:".55rem .7rem",marginBottom:".35rem",background:"var(--card)",border:"1px solid var(--border)",borderRadius:6,flexWrap:"wrap",gap:".5rem"}},
          React.createElement("div",null,
            React.createElement("div",{style:{fontWeight:600,fontSize:".85rem"}},"$"+(+e.amount).toFixed(2)+" · "+methodLbl),
            React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}, when, e.note?" · "+e.note:"")
          ),
          statusBadge(e)
        );
      })
    )
  );
}

// ─── CUSTOMER ACCOUNT MODAL ───────────────────────────────────────────────────
function CustomerAccountModal({customer, feeSettings, onClose, onLogout, liveBids=[], watchedLots=[], onBid, onAutoBid, canBid}){
  const [tab,setTab]=useState("invoices");
  const [expanded,setExpanded]=useState({});
  const [payModal,setPayModal]=useState(null);
  const [changePw,setChangePw]=useState({old:"",nw:"",confirm:""});
  const [pwMsg,setPwMsg]=useState("");
  // Fetch real invoices (live + all archives) from server, keyed by bidderNum.
  // Falls back to the legacy customer.invoices array if the endpoint fails.
  const [liveInvoices, setLiveInvoices] = useState(null);
  useEffect(function(){
    if(!customer || !customer.bidderNum) return;
    fetch("/api/bidders/"+encodeURIComponent(customer.bidderNum)+"/invoices")
      .then(function(r){return r.json();})
      .then(function(arr){ if(Array.isArray(arr)) setLiveInvoices(arr); })
      .catch(function(){});
  },[customer&&customer.bidderNum]);

  const toggleExpand=id=>setExpanded(e=>({...e,[id]:!e[id]}));

  const calcInv=(inv)=>{
    const adminFee=parseFloat(inv.adminFee)||35.47;
    const keyFee=parseFloat(inv.keyFee)||0;
    const finalBid=parseFloat(inv.finalBid)||0;
    const taxRate=parseFloat(inv.taxRate)||8.375;
    const taxable=finalBid+keyFee+adminFee;
    const tax=inv.taxExempt?0:parseFloat((taxable*taxRate/100).toFixed(2));
    const sameDayDisc=inv.sameDayDiscount?20:0;
    const total=Math.max(0,taxable+tax-sameDayDisc);
    // CC fee from card-method splits
    const splits=Array.isArray(inv.splits)?inv.splits:[];
    const splitTotal=splits.reduce(function(s,p){return s+(+p.amount||0);},0);
    const cardSplits=splits.filter(function(p){return p.method==="card"||p.method==="website";}).reduce(function(s,p){return s+(+p.amount||0);},0);
    const ccFee=parseFloat((cardSplits*0.035).toFixed(2));
    const totalWithFees=total+ccFee;
    // CC fee is pass-through: added AND collected, net = 0
    const balance=Math.max(0,total-splitTotal);
    const paid=splitTotal>=total||(inv.paymentStatus==="paid");
    return {tax,total:total,totalWithFees:totalWithFees,balance:balance,splitTotal:splitTotal,splits:splits,sameDayDisc:sameDayDisc,ccFee:ccFee,adminFee:adminFee,keyFee:keyFee,finalBid:finalBid,paid:paid};
  };

  const invoices = liveInvoices || customer.invoices || [];
  const unpaidInvoices=invoices.filter(function(i){
    if(i.forfeit) return false;
    if(i.paymentStatus==="paid") return false;
    var c=calcInv(i);
    if(c.balance<=0) return false;
    return true;
  });
  const unpaidCount=unpaidInvoices.length;
  const totalOwed=unpaidInvoices.reduce(function(s,i){return s+calcInv(i).balance;},0);

  const submitPw=()=>{
    if(changePw.old!==customer.password){setPwMsg("Current password incorrect.");return;}
    if(changePw.nw.length<6){setPwMsg("New password must be at least 6 characters.");return;}
    if(changePw.nw!==changePw.confirm){setPwMsg("Passwords don't match.");return;}
    authUpdate(customer.email, {password:changePw.nw});
    authSetCurrent({...customer, password:changePw.nw});
    setPwMsg("✓ Password updated successfully.");
    setChangePw({old:"",nw:"",confirm:""});
  };

  return <>
    <div className="acct-bg" onClick={e=>{if(e.target===e.currentTarget)onClose();}}>
      <div className="acct-drawer">

        {/* Header */}
        <div className="acct-hd">
          <div>
            <div className="acct-hd-title">My Account</div>
            <div className="acct-hd-meta">{customer.bidderNum} · {customer.email}</div>
          </div>
          <div style={{display:"flex",gap:".5rem",alignItems:"center"}}>
            {unpaidCount>0&&<span className="chip chip-red">{unpaidCount} unpaid</span>}
            <button className="acct-close" onClick={onClose}>×</button>
          </div>
        </div>

        {/* Tabs */}
        <div className="acct-tabs" style={{display:"flex",flexWrap:"wrap",gap:".25rem",overflowX:"auto",WebkitOverflowScrolling:"touch"}}>
          {[["invoices","📄 Invoices"],["deposit","💰 Deposit"],["credits","💳 Credits"],["livebids","🔴 Live Bids"],["watchlist","🔖 Watchlist"],["profile","👤 Profile"],["security","🔒 Password"]].map(([id,lbl])=>
            <div key={id} className={`acct-tab${tab===id?" active":""}`} style={{whiteSpace:"nowrap",flexShrink:0}} onClick={()=>setTab(id)}>{lbl}</div>)}
        </div>

        <div className="acct-body">

          {/* ── INVOICES TAB ── */}
          {tab==="invoices"&&<>
            {/* Summary row */}
            <div style={{display:"flex",gap:".55rem",marginBottom:"1.1rem",flexWrap:"wrap"}}>
              <span className="chip chip-blue">{invoices.length} Total</span>
              <span className="chip chip-green">{invoices.filter(function(i){return i.paymentStatus==="paid"||i.forfeit||calcInv(i).balance<=0;}).length} Settled</span>
              {unpaidCount>0&&<span className="chip chip-red">{fmtCurrency(totalOwed)} Outstanding</span>}
            </div>

            {invoices.length===0
              ? <div style={{textAlign:"center",padding:"3rem 1rem",color:"var(--muted)"}}>
                  <div style={{fontSize:"2.5rem",opacity:.35,marginBottom:".75rem"}}>🏷️</div>
                  <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"var(--sub)",marginBottom:".4rem"}}>No Invoices Yet</div>
                  <div style={{fontSize:".82rem"}}>Your winning bids will appear here.</div>
                </div>
              : (function(){
                  // Group by auction source — matches admin "Full Bidding History" format
                  var groups = {};
                  invoices.forEach(function(inv){
                    var key = inv.source||"live";
                    if(!groups[key]) groups[key]={label:key,lots:[]};
                    groups[key].lots.push(inv);
                  });
                  var groupKeys = Object.keys(groups).reverse();
                  return React.createElement("div",null,
                    groupKeys.map(function(key){
                      var g = groups[key];
                      return React.createElement("div",{key:key,style:{marginBottom:".75rem"}},
                        groupKeys.length>1&&React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)",textTransform:"uppercase",letterSpacing:".08em",padding:".35rem 0",borderBottom:"1px solid var(--border)",marginBottom:".35rem",fontWeight:700}},"📦 "+g.label),
                        g.lots.map(function(inv){
                          var c=calcInv(inv);
                          var open=!!expanded[inv.id];
                          return React.createElement("div",{key:inv.id,className:"drw-card"},
                            React.createElement("div",{className:"drw-card-hd",onClick:function(){toggleExpand(inv.id);}},
                              React.createElement("div",{style:{flex:1,minWidth:0}},
                                React.createElement("div",{className:"drw-card-title"},inv.year+" "+inv.make+" "+inv.model),
                                React.createElement("div",{className:"drw-card-meta"},inv.lot+" · "+inv.date)
                              ),
                              React.createElement("div",{style:{display:"flex",alignItems:"center",gap:".5rem",flexShrink:0}},
                                inv.forfeit
                                  ? React.createElement("span",{style:{fontSize:".72rem",fontWeight:700,fontFamily:"DM Mono,monospace",color:"#d97706",background:"rgba(217,119,6,.1)",border:"1px solid rgba(217,119,6,.3)",padding:".15rem .45rem",borderRadius:4}},"⚠ Forfeited")
                                  : (inv.paymentStatus==="paid"||c.balance<=0)
                                    ? React.createElement("span",{className:"chip chip-green"},"✓ Paid")
                                    : React.createElement("span",{className:"chip chip-red"},"Due: "+fmtCurrency(c.balance)),
                                React.createElement("span",{style:{color:"var(--muted)",fontSize:".85rem"}},open?"▲":"▼")
                              )
                            ),
                            open&&React.createElement("div",{className:"drw-card-body"},
                              React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)",marginBottom:".6rem",textTransform:"uppercase",letterSpacing:".08em"}},"Invoice #"+inv.id),
                              React.createElement("div",{className:"drw-fee"},React.createElement("span",null,"Winning Bid"),React.createElement("span",null,React.createElement("strong",null,fmtCurrency(c.finalBid)))),
                              c.keyFee>0&&React.createElement("div",{className:"drw-fee"},React.createElement("span",null,"Key Fee"),React.createElement("span",null,fmtCurrency(c.keyFee))),
                              React.createElement("div",{className:"drw-fee"},React.createElement("span",null,"Admin Fee"),React.createElement("span",null,fmtCurrency(c.adminFee))),
                              React.createElement("div",{className:"drw-fee"},
                                React.createElement("span",null,"Sales Tax "+(inv.taxExempt?"(EXEMPT)":"("+inv.taxRate+"%)")),
                                React.createElement("span",{style:inv.taxExempt?{color:"var(--green)",fontWeight:700}:{}},inv.taxExempt?"$0.00 — Tax Exempt":fmtCurrency(c.tax))
                              ),
                              c.sameDayDisc>0&&React.createElement("div",{className:"drw-fee green"},React.createElement("span",null,"Same-Day Payment Discount"),React.createElement("span",null,"−"+fmtCurrency(c.sameDayDisc))),
                              c.ccFee>0&&React.createElement("div",{className:"drw-fee",style:{color:"var(--amber)"}},React.createElement("span",null,"Credit Card Fee (3.5%)"),React.createElement("span",null,"+"+fmtCurrency(c.ccFee))),
                              c.splits&&c.splits.length>0&&c.splits.map(function(sp,j){
                                var mNames={cash:"💵 Cash",card:"💳 Card",zelle:"💸 Zelle",credit:"💳 Credit",balance:"💰 Balance","balance-applied":"💰 Balance"};
                                return React.createElement("div",{key:j,className:"drw-fee green"},
                                  React.createElement("span",null,"Payment — "+(mNames[sp.method]||sp.method)),
                                  React.createElement("span",null,"−"+fmtCurrency(+sp.amount||0)));
                              }),
                              React.createElement("div",{className:"drw-fee balance"},
                                React.createElement("span",null,inv.paymentStatus==="paid"?"Total Paid":"Balance Due"),
                                React.createElement("span",null,inv.paymentStatus==="paid"?fmtCurrency(c.total):fmtCurrency(c.balance))
                              ),
                              inv.paymentStatus==="unpaid"&&React.createElement("div",{style:{marginTop:".7rem"}},
                                React.createElement("button",{className:"drw-pay-btn",style:{width:"100%",marginTop:0},onClick:function(){setPayModal(inv);}},"Pay "+fmtCurrency(c.balance)+" →"))
                            )
                          );
                        })
                      );
                    })
                  );
                })()}
          </>}

          {/* ── DEPOSIT TAB ── */}
          {tab==="deposit"&&<div>
            {(function(){
              var mainDep = customer.depositAmount||0;
              var xd = Array.isArray(customer.extraDeposits)?customer.extraDeposits:[];
              var extraApproved = xd.filter(function(e){return e.status==="approved";}).reduce(function(s,e){return s+(+e.amount||0);},0);
              var creds = Array.isArray(customer.credits)?customer.credits:[];
              var creditRem = creds.reduce(function(s,c){return s+(c.remaining||0);},0);
              var refs = Array.isArray(customer.refundHistory)?customer.refundHistory:[];
              var totalOut = refs.reduce(function(s,r){return s+(+r.amount||0);},0);
              var balance = mainDep + extraApproved + creditRem - totalOut;
              var isApproved = customer.whitelist || balance >= 300;
              return React.createElement("div",{style:{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:8,padding:"1.1rem 1.2rem",marginBottom:"1rem"}},
                React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)",marginBottom:".75rem"}},"Deposit Status"),
                React.createElement("div",{style:{display:"flex",alignItems:"center",gap:"1rem",flexWrap:"wrap"}},
                  React.createElement("div",{style:{flex:1}},
                    React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.8rem",color:isApproved?"var(--green)":balance>0?"var(--amber)":"var(--red)"}},
                      isApproved?"✓ Approved to Bid":balance>0?"⚠ Balance Below $300":"✗ No Deposit on File"),
                    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"var(--muted)",marginTop:".2rem"}},
                      isApproved?"Your balance covers the minimum $300 deposit. You are approved to bid."
                      :balance>0?"Your balance is below the $300 minimum. Add a deposit to bid."
                      :"You need to make a $300 deposit to participate in the auction. Call (702) 677-0792 or pay online.")
                  ),
                  React.createElement("div",{style:{textAlign:"right",flexShrink:0}},
                    React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:balance>=300?"var(--green)":balance>0?"var(--amber)":"var(--red)"}},
                      fmtCurrency(balance)),
                    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}},"Available Balance")
                  )
                )
              );
            })()}
            {[
              {lbl:"Payment Method", val:({"card":"💳 Credit Card (Online)","card-office":"🏢 Credit Card (Office)","zelle":"💸 Zelle","cash":"💵 Cash","arrange":"🤝 Staff Arrangements","none":"🏷 No Deposit"}[customer.depositMethod])||customer.depositMethod||"—"},
              customer.depositMethod!=="arrange"&&customer.depositMethod!=="none"?{lbl:"Keep on File", val:customer.keepOnFile?"Yes — rolls to next auction":"No — refunded if I don't win"}:null,
              {lbl:"Bidder #", val:customer.bidderNum||"—"},
              {lbl:"Username", val:customer.username?"@"+customer.username:"—"},
              {lbl:"Registered", val:customer.registeredAt||"—"},
            ].filter(Boolean).map(row=>
              React.createElement("div",{key:row.lbl,style:{display:"flex",justifyContent:"space-between",padding:".65rem 0",borderBottom:"1px solid var(--border)",fontSize:".85rem"}},
                React.createElement("span",{style:{color:"var(--muted)"}}," "+row.lbl),
                React.createElement("span",{style:{fontWeight:600,fontFamily:"DM Mono,monospace",fontSize:".82rem"}},row.val)
              )
            )}
            <div className="notice" style={{marginTop:"1rem"}}>
              <strong>Refund policy:</strong> Deposits are fully refunded within 3–5 business days if you don't win any lots. To request a refund, call (702) 677-0792.
            </div>

            {/* ── DEPOSIT TRANSACTIONS ── */}
            {(function(){
              var xd = customer.extraDeposits || customer.extra_deposits || [];
              if(!Array.isArray(xd)) xd = [];
              // Build transaction list: main deposit + extra deposits
              var txns = [];
              // Main deposit — show if ever confirmed
              if(customer.depositAmount > 0 || customer.depositConfirmedAt || customer.depositAppliedTo){
                var mainDepAmt = customer.depositAmount || 300;
                var mLabel = ({"card":"💳 Credit Card","card-office":"🏢 CC Office","zelle":"💸 Zelle","cash":"💵 Cash","website":"💳 Card Online","arrange":"🤝 Arranged","none":"🏷 No Deposit"})[customer.depositMethod]||customer.depositMethod||"—";
                txns.push({
                  type:"Main Deposit",
                  amount:mainDepAmt,
                  method:mLabel,
                  status:customer.depositStatus||"confirmed",
                  date:customer.depositConfirmedAt||customer.registeredAt||"—"
                });
              }
              // Extra deposits
              xd.forEach(function(e){
                var eLbl = ({"card":"💳 Credit Card","zelle":"💸 Zelle","cash":"💵 Cash","office":"🤝 Office"})[e.method]||e.method||"—";
                txns.push({
                  type:"Extra Deposit",
                  amount:+e.amount||0,
                  method:eLbl,
                  status:e.status||"pending",
                  date:e.createdAt?new Date(e.createdAt).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):"—",
                  note:e.note||""
                });
              });
              // Credit Memos
              var creditsList = Array.isArray(customer.credits) ? customer.credits : [];
              creditsList.forEach(function(c){
                var remaining = +c.remaining||0;
                var used = (+c.amount||0) - remaining;
                txns.push({
                  type:"Credit Memo",
                  amount:+c.amount||0,
                  method:"💳 Store Credit"+(used>0?" ("+fmtCurrency(remaining)+" remaining)":""),
                  status:remaining>0?"approved":"applied",
                  date:c.createdAt||"—",
                  note:c.reason||"",
                  remaining:remaining,
                  isCredit:true
                });
                if(Array.isArray(c.appliedTo)){
                  c.appliedTo.forEach(function(a){
                    txns.push({type:"Credit Applied",amount:-(+a.amount||0),method:"💳 Applied to "+(a.lotLabel||"lot"),
                      status:"applied",date:a.date||"—",note:"",isRefund:true,isCreditApplied:true});
                  });
                }
              });
              // Refunds + Forfeits — all as line items
              var refundsList = Array.isArray(customer.refundHistory) ? customer.refundHistory : [];
              refundsList.forEach(function(r){
                var isForfeit = r.method==="forfeit";
                var rLbl = isForfeit?"⚠ Deposit kept as penalty":({"zelle":"💸 Zelle","check":"🧾 Check","cash":"💵 Cash","card":"💳 Card"})[r.method]||r.method||"—";
                txns.push({
                  type:isForfeit?"Forfeit — Deposit Applied":"Refund",
                  amount:-(+r.amount||0),
                  method:rLbl,
                  status:isForfeit?"applied":"refunded",
                  date:r.date||"—",
                  note:isForfeit?"":r.note||"",
                  isRefund:true
                });
              });
              // Same formula as Deposit Status box above
              var _md = customer.depositAmount||0;
              var _ea = (Array.isArray(customer.extraDeposits)?customer.extraDeposits:[]).filter(function(e){return e.status==="approved";}).reduce(function(s,e){return s+(+e.amount||0);},0);
              var _cr = creditsList.reduce(function(s,c){return s+(c.remaining||0);},0);
              var _ro = refundsList.reduce(function(s,r){return s+(+r.amount||0);},0);
              var totalOnFile = _md + _ea + _cr - _ro;

              if(txns.length===0) return null;
              return React.createElement("div",{style:{marginTop:"1.2rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:8,padding:"1.1rem 1.2rem"}},
                React.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:".75rem"}},
                  React.createElement("div",null,
                    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--accent)"}},"Deposit Transactions ("+txns.length+")"),
                    _cr>0&&React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--amber)",marginTop:2}},fmtCurrency(_cr)+" store credit available")
                  ),
                  React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"var(--green)"}},fmtCurrency(totalOnFile)+" on file")
                ),
                txns.map(function(t,i){
                  var stColor = (t.status==="approved"||t.status==="confirmed"||t.status==="applied")?"var(--green)":t.status==="refunded"?"var(--muted)":"var(--amber)";
                  var stLabel = (t.status==="approved"||t.status==="confirmed"||t.status==="applied")?"✓ Confirmed":t.status==="refunded"?"↩ Refunded":"⏳ Pending";
                  return React.createElement("div",{key:i,style:{padding:".65rem 0",borderBottom:i<txns.length-1?"1px solid var(--border)":"none"}},
                    React.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:2}},
                      React.createElement("span",{style:{fontWeight:700,fontSize:".88rem"}},t.type+" — "+fmtCurrency(t.amount)),
                      React.createElement("span",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",fontWeight:700,color:stColor,background:stColor==="var(--green)"?"rgba(21,128,61,.12)":stColor==="var(--amber)"?"rgba(217,119,6,.12)":"rgba(100,116,139,.12)",border:"1px solid "+stColor,padding:".12rem .4rem",borderRadius:3}},stLabel)
                    ),
                    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}},
                      t.method+" · "+t.date+(t.note?" · "+t.note:""))
                  );
                })
              );
            })()}

            {/* ── ADD EXTRA DEPOSIT ── */}
            <ExtraDepositSection customer={customer}/>
          </div>}

          {/* ── CREDITS TAB ── */}
          {tab==="credits"&&<div>
            {(()=>{
              var credits = customer.credits || [];
              var totalAvail = credits.reduce(function(s,c){return s+(c.remaining||0);},0);
              var totalIssued = credits.reduce(function(s,c){return s+(c.amount||0);},0);
              if(credits.length===0) return React.createElement("div",{style:{textAlign:"center",padding:"3rem 1rem",color:"var(--muted)"}},
                React.createElement("div",{style:{fontSize:"2.5rem",opacity:.35,marginBottom:".75rem"}},"💳"),
                React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)",marginBottom:".4rem"}},"No Credit Memos"),
                React.createElement("div",{style:{fontSize:".82rem"}},"Store credits issued by our staff will appear here.")
              );
              return React.createElement("div",null,
                // Summary
                React.createElement("div",{style:{background:"rgba(245,158,11,.08)",border:"1.5px solid rgba(245,158,11,.35)",borderRadius:8,padding:"1.1rem 1.3rem",marginBottom:"1rem",display:"flex",justifyContent:"space-between",alignItems:"center",flexWrap:"wrap",gap:".5rem"}},
                  React.createElement("div",null,
                    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--amber)",marginBottom:".35rem"}},"Available Store Credit"),
                    React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"2rem",color:"var(--amber)",lineHeight:1}},fmtCurrency(totalAvail))
                  ),
                  React.createElement("div",{style:{textAlign:"right"}},
                    React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)"}},"Total Issued"),
                    React.createElement("div",{style:{fontWeight:600}},fmtCurrency(totalIssued))
                  )
                ),
                // Each credit
                credits.map(function(c){
                  var fullyUsed = (c.remaining||0)<=0;
                  return React.createElement("div",{key:c.id,style:{background:"var(--card)",border:"1px solid "+(fullyUsed?"var(--border)":"rgba(245,158,11,.3)"),borderRadius:8,padding:"1rem 1.2rem",marginBottom:".75rem",opacity:fullyUsed?.6:1}},
                    React.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:".5rem",flexWrap:"wrap",gap:".5rem"}},
                      React.createElement("div",{style:{flex:1,minWidth:0}},
                        React.createElement("div",{style:{fontWeight:700,fontSize:".95rem"}},c.reason||"Store credit"),
                        React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)",marginTop:".2rem"}},"Issued: "+c.createdAt)
                      ),
                      React.createElement("div",{style:{textAlign:"right",flexShrink:0}},
                        React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".58rem",color:"var(--muted)",textTransform:"uppercase"}},fullyUsed?"Used":"Remaining"),
                        React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",color:fullyUsed?"var(--muted)":"var(--amber)"}},fmtCurrency(c.remaining||0)),
                        React.createElement("div",{style:{fontSize:".62rem",color:"var(--muted)",fontFamily:"DM Mono,monospace"}},"of "+fmtCurrency(c.amount||0))
                      )
                    ),
                    c.appliedTo&&c.appliedTo.length>0&&React.createElement("div",{style:{borderTop:"1px solid var(--border)",paddingTop:".5rem",marginTop:".4rem"}},
                      React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".58rem",textTransform:"uppercase",color:"var(--muted)",marginBottom:".3rem"}},"Applied to:"),
                      c.appliedTo.map(function(a,i){return React.createElement("div",{key:i,style:{display:"flex",justifyContent:"space-between",fontSize:".75rem",padding:".15rem 0"}},
                        React.createElement("span",null,a.lotLabel+" · "+a.date),
                        React.createElement("span",{style:{color:"var(--green)",fontFamily:"DM Mono,monospace"}},"−"+fmtCurrency(a.amount))
                      );})
                    )
                  );
                })
              );
            })()}
          </div>}

          {/* ── LIVE BIDS TAB ── */}
          {tab==="livebids"&&<div>
            {(!liveBids||liveBids.length===0)
              ? React.createElement("div",{style:{textAlign:"center",padding:"3rem 1rem",color:"var(--muted)"}},
                  React.createElement("div",{style:{fontSize:"2.5rem",opacity:.35,marginBottom:".75rem"}},"🏎"),
                  React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)",marginBottom:".4rem"}},"No Active Bids"),
                  React.createElement("div",{style:{fontSize:".82rem"}},"Lots you've bid on will appear here.")
                )
              : liveBids.map(lot=>{
                  var myNum = customer.bidderNum;
                  var leader = lot.winner || lot.leader;
                  var isLeading = leader === myNum;
                  var myLastBid = (lot.bidHistory||[]).filter(h=>h.bidderNum===myNum).slice(-1)[0];
                  var auctionEnded = lot.sold || (lot.closeTime && lot.closeTime < Date.now());
                  var statusColor, statusBg, statusTextColor, statusLabel;
                  if(auctionEnded){
                    if(isLeading){
                      statusColor="rgba(21,128,61,.25)";statusBg="rgba(21,128,61,.12)";statusTextColor="var(--green)";statusLabel="🏆 YOU WON";
                    } else {
                      statusColor="rgba(100,116,139,.3)";statusBg="rgba(100,116,139,.08)";statusTextColor="var(--muted)";statusLabel="⏹ CLOSED — DID NOT WIN";
                    }
                  } else if(isLeading){
                    statusColor="rgba(21,128,61,.25)";statusBg="rgba(21,128,61,.12)";statusTextColor="var(--green)";statusLabel="✓ YOU'RE LEADING";
                  } else {
                    statusColor="rgba(220,38,38,.25)";statusBg="rgba(220,38,38,.1)";statusTextColor="var(--red)";statusLabel="⚠ OUTBID";
                  }
                  return React.createElement("div",{key:lot.id,style:{background:"var(--navy-light)",border:"1.5px solid "+statusColor,borderRadius:8,padding:"1rem",marginBottom:".65rem"}},
                    React.createElement("div",{style:{display:"flex",gap:".75rem",alignItems:"flex-start",flexWrap:"wrap"}},
                      lot.photos&&lot.photos[0]
                        ? React.createElement("img",{src:lot.photos[0],alt:"",style:{width:70,height:50,objectFit:"cover",borderRadius:5,flexShrink:0}})
                        : React.createElement("div",{style:{width:70,height:50,background:"#1a2540",borderRadius:5,flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center",opacity:.4}},"📷"),
                      React.createElement("div",{style:{flex:1,minWidth:0}},
                        React.createElement("div",{style:{fontWeight:700,fontSize:".92rem"}},lot.year+" "+lot.make+" "+lot.model),
                        React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:2}},lot.lot+" · VIN: "+((lot.vin||"").slice(-8)||"—")),
                        myLastBid&&React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:2}},"Your last bid: $"+myLastBid.amount+(myLastBid.isAutoBid?" (auto)":""))
                      ),
                      React.createElement("div",{style:{textAlign:"right",flexShrink:0}},
                        React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".58rem",color:"var(--muted)",textTransform:"uppercase"}},"Current Bid"),
                        React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"var(--accent)"}},"$"+(lot.currentBid||lot.minBid).toLocaleString()),
                        React.createElement("span",{style:{background:statusBg,color:statusTextColor,border:"1px solid "+statusColor,borderRadius:12,padding:".15rem .6rem",fontSize:".65rem",fontFamily:"DM Mono,monospace",fontWeight:700,marginTop:4,display:"inline-block"}},statusLabel)
                      )
                    ),
                    // Bid buttons — only show if auction is still active
                    !auctionEnded&&canBid&&!isLeading&&onBid&&React.createElement("div",{style:{display:"flex",gap:".5rem",marginTop:".6rem",flexWrap:"wrap"}},
                      React.createElement("button",{
                        className:"btn-p",
                        style:{flex:1,fontSize:".82rem",padding:".45rem .85rem"},
                        onClick:function(){onBid(lot);}
                      },"Place Bid →"),
                      onAutoBid&&React.createElement("button",{
                        className:"btn-p",
                        style:{flex:1,fontSize:".82rem",padding:".45rem .85rem",background:"#1d4ed8"},
                        onClick:function(){onAutoBid(lot);}
                      },"🤖 Auto-Bid")
                    ),
                    !auctionEnded&&canBid&&isLeading&&React.createElement("div",{style:{marginTop:".6rem",fontSize:".72rem",color:"var(--green)",fontFamily:"DM Mono,monospace",textAlign:"center"}},"You're winning — no action needed"),
                    auctionEnded&&React.createElement("div",{style:{marginTop:".6rem",fontSize:".72rem",color:"var(--muted)",fontFamily:"DM Mono,monospace",textAlign:"center"}},"Auction closed — no more bids accepted")
                  );
                })
            }
          </div>}

          {/* ── WATCHLIST TAB ── */}
          {tab==="watchlist"&&<div>
            {(!watchedLots||watchedLots.length===0)
              ? React.createElement("div",{style:{textAlign:"center",padding:"3rem 1rem",color:"var(--muted)"}},
                  React.createElement("div",{style:{fontSize:"2.5rem",opacity:.35,marginBottom:".75rem"}},"🔖"),
                  React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)",marginBottom:".4rem"}},"Watchlist Empty"),
                  React.createElement("div",{style:{fontSize:".82rem"}},"Tap the bookmark icon on any vehicle to add it here.")
                )
              : watchedLots.map(lot=>{
                  var myNum = customer.bidderNum;
                  var leader = lot.winner||lot.leader;
                  var isLeading = myNum && leader===myNum && !lot.sold;
                  return React.createElement("div",{key:lot.id,style:{background:"var(--card)",border:"1px solid "+(isLeading?"rgba(21,128,61,.3)":"var(--border)"),borderRadius:8,padding:"1rem",marginBottom:".65rem",display:"flex",alignItems:"center",gap:"1rem",flexWrap:"wrap"}},
                    React.createElement("div",{style:{flex:1}},
                      React.createElement("div",{style:{fontWeight:700,fontSize:".9rem"}},lot.year+" "+lot.make+" "+lot.model),
                      React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:2}},lot.lot+" · "+((lot.vin||"").slice(-8)||"No VIN"))
                    ),
                    React.createElement("div",{style:{textAlign:"right"}},
                      React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--accent)"}},"$"+(lot.currentBid||lot.minBid).toLocaleString()),
                      lot.sold
                        ? React.createElement("span",{style:{color:"var(--muted)",fontSize:".72rem",fontFamily:"DM Mono,monospace"}},"Auction ended")
                        : isLeading
                          ? React.createElement("span",{style:{background:"rgba(21,128,61,.12)",color:"var(--green)",border:"1px solid rgba(21,128,61,.3)",borderRadius:12,padding:".15rem .6rem",fontSize:".65rem",fontFamily:"DM Mono,monospace",fontWeight:700,display:"inline-block",marginTop:2}},"✓ HIGHEST BID")
                          : React.createElement("span",{style:{color:"var(--blue)",fontSize:".72rem",fontFamily:"DM Mono,monospace"}},"Active")
                    )
                  );
                })
            }
          </div>}

          {/* ── PROFILE TAB ── */}
          {tab==="profile"&&<>
            <div style={{textAlign:"center",marginBottom:"1rem"}}>
              <div className="prof-avatar">{customer.first?(customer.first[0]+(customer.last||"")[0]):"👤"}</div>
              <div className="prof-name">{customer.first?(customer.first+" "+(customer.last||"")):customer.username||customer.email||"Bidder"}</div>
              <div className="prof-meta">{customer.bidderNum||"—"}{customer.username?(" · @"+customer.username):""}</div>
            </div>
            <div className="prof-grid">
              <div className="prof-field">
                <div className="prof-lbl">First Name</div>
                <div className="prof-val">{customer.first||"—"}</div>
              </div>
              <div className="prof-field">
                <div className="prof-lbl">Last Name</div>
                <div className="prof-val">{customer.last||"—"}</div>
              </div>
              <div className="prof-field full">
                <div className="prof-lbl">Email</div>
                <div className="prof-val">{customer.email||"—"}</div>
              </div>
              <div className="prof-field">
                <div className="prof-lbl">Phone</div>
                <div className="prof-val">{customer.phone||"—"}</div>
              </div>
              <div className="prof-field">
                <div className="prof-lbl">Driver's License</div>
                <div className="prof-val" style={{fontFamily:"DM Mono,monospace",fontSize:".82rem"}}>{customer.dl||"—"}</div>
              </div>
              <div className="prof-field full">
                <div className="prof-lbl">Address</div>
                <div className="prof-val">{customer.address||"—"}</div>
              </div>
              <div className="prof-field">
                <div className="prof-lbl">City</div>
                <div className="prof-val">{customer.city||"—"}</div>
              </div>
              <div className="prof-field">
                <div className="prof-lbl">State / Zip</div>
                <div className="prof-val">{(customer.state||"")}{customer.state&&customer.zip?" ":""}{customer.zip||""||"—"}</div>
              </div>
              <div className="prof-field full">
                <div className="prof-lbl">Bidder Number</div>
                <div className="prof-val" style={{fontFamily:"DM Mono,monospace",color:"var(--accent)"}}>{customer.bidderNum}</div>
              </div>
              <div className="prof-field full">
                <div className="prof-lbl">Deposit Status</div>
                <div style={{display:"flex",alignItems:"center",gap:".5rem",marginTop:".25rem"}}>
                  <div style={{width:8,height:8,borderRadius:"50%",background:customer.depositStatus==="confirmed"||customer.depositStatus==="applied"?"var(--green)":"var(--amber)"}}/>
                  <span style={{fontSize:".85rem",color:customer.depositStatus==="confirmed"||customer.depositStatus==="applied"?"var(--green)":"var(--amber)",fontWeight:600}}>{customer.depositStatus==="confirmed"||customer.depositStatus==="applied"?"Deposit on file — Approved to bid":"Deposit pending"}</span>
                </div>
              </div>
              {(customer.depositStatus==="confirmed"||customer.depositStatus==="applied")&&<div className="prof-field full">
                <div className="prof-lbl">Bidding Limit</div>
                <div style={{marginTop:".35rem",background:"rgba(0,48,135,.04)",border:"1px solid var(--border)",borderRadius:6,padding:".75rem 1rem"}}>
                  <div style={{display:"flex",alignItems:"center",gap:".5rem",marginBottom:".35rem"}}>
                    <span style={{fontSize:"1.1rem",fontFamily:"Bebas Neue,sans-serif",color:"var(--accent)"}}>{fmtCurrency(customer.creditThreshold||DEPOSIT_THRESHOLD)}</span>
                    <span style={{fontSize:".78rem",color:"var(--green)",fontWeight:600}}>Total Bidding Approved</span>
                  </div>
                  <div style={{fontSize:".78rem",color:"var(--muted)",lineHeight:1.55}}>
                    You are approved for up to <strong style={{color:"var(--accent)"}}>{fmtCurrency(customer.creditThreshold||DEPOSIT_THRESHOLD)}</strong> in combined bids. If you need to bid more, please call the office at <strong>(702) 677-0792</strong> to make arrangements, or place an additional fully refundable $300 deposit.
                  </div>
                </div>
              </div>}
            </div>
            <div style={{fontSize:".75rem",color:"var(--muted)",textAlign:"center",marginTop:"1rem",fontStyle:"italic"}}>To update your contact info, please call (702) 677-0792</div>
            <button className="btn-g" style={{width:"100%",marginTop:".8rem",color:"var(--red)",borderColor:"rgba(220,38,38,.3)"}} onClick={function(){onLogout();onClose();}}>
              Sign Out
            </button>
          </>}

          {/* ── PASSWORD TAB ── */}
          {tab==="security"&&<>
            <div style={{marginBottom:"1.1rem"}}>
              <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",marginBottom:".35rem"}}>Change Password</div>
              <div style={{fontSize:".78rem",color:"var(--muted)",lineHeight:1.55}}>Choose a strong password. Use at least 8 characters with a mix of letters, numbers, and symbols.</div>
            </div>
            {pwMsg&&<div className={`notice ${pwMsg.startsWith("✓")?"ok":"warn"}`} style={{marginBottom:".85rem"}}>{pwMsg}</div>}
            <div className="fgrp" style={{marginBottom:".75rem"}}>
              <label className="flbl">Current Password</label>
              <input className="finput" type="password" value={changePw.old} placeholder="••••••••"
                onChange={e=>setChangePw(p=>({...p,old:e.target.value}))}/>
            </div>
            <div className="fgrp" style={{marginBottom:".75rem"}}>
              <label className="flbl">New Password</label>
              <input className="finput" type="password" value={changePw.nw} placeholder="Min. 6 characters"
                onChange={e=>setChangePw(p=>({...p,nw:e.target.value}))}/>
            </div>
            <div className="fgrp" style={{marginBottom:"1.1rem"}}>
              <label className="flbl">Confirm New Password</label>
              <input className="finput" type="password" value={changePw.confirm} placeholder="Repeat new password"
                onChange={e=>setChangePw(p=>({...p,confirm:e.target.value}))}/>
            </div>
            <button className="btn-p" style={{width:"100%"}}
              disabled={!changePw.old||!changePw.nw||!changePw.confirm}
              onClick={submitPw}>
              Update Password
            </button>
          </>}

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

    {/* Pay modal */}
    {payModal&&<div className="modal-bg" style={{zIndex:400}}><div className="modal">
      <div className="mhd"><div><div className="mtitle">Pay Balance</div><div className="msub">{payModal.year} {payModal.make} {payModal.model}</div></div><button className="mclose" onClick={()=>setPayModal(null)}>×</button></div>
      <div className="mbody">
        <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:"1rem",marginBottom:"1rem",textAlign:"center"}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--muted)",marginBottom:".3rem"}}>Amount Due</div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"2.5rem",color:"var(--accent)"}}>{fmtCurrency(calcInv(payModal).balance)}</div>
          <div style={{fontSize:".72rem",color:"var(--muted)",marginTop:".2rem"}}>Invoice #{payModal.id}</div>
        </div>
        <div className="fsec-title" style={{marginBottom:".6rem"}}>Card Details</div>
        <div className="frow s"><div className="fgrp"><label className="flbl">Name on Card</label><input className="finput" placeholder="John Smith"/></div></div>
        <div className="frow s"><div className="fgrp"><label className="flbl">Card Number</label><input className="finput" placeholder="•••• •••• •••• ••••"/></div></div>
        <div className="frow">
          <div className="fgrp"><label className="flbl">Expiry</label><input className="finput" placeholder="MM/YY"/></div>
          <div className="fgrp"><label className="flbl">CVV</label><input className="finput" placeholder="•••"/></div>
        </div>
        <div className="notice ok" style={{marginBottom:0}}>Processed securely via Stripe.</div>
      </div>
      <div className="mfoot">
        <button className="btn-g" onClick={()=>setPayModal(null)}>Cancel</button>
        <button className="btn-p" onClick={()=>setPayModal(null)}>Pay {fmtCurrency(calcInv(payModal).balance)} →</button>
      </div>
    </div></div>}
  </>;
}

// ─── CONTACT PAGE ─────────────────────────────────────────────────────────────
// ─── TERMS & CONDITIONS PAGE ──────────────────────────────────────────────────
const DEFAULT_TERMS_PUBLIC = [
  { id:1,  text:"You must have a bidder account to bid. Bidders are required to pay a $300 deposit which is refundable if you do not purchase a vehicle. All refunds will not be given until AFTER the auction. Deposits may be paid via Zelle to the number: 702-677-0792 (Name is Mai Niv Enterprise). Zelle deposits will be refunded per request, and must include the phone number and name of the account. You may request the Zelle refund via text to 702-677-0792." },
  { id:2,  text:"You must pay a deposit of $300 or 20% of the winning bid price (whichever is greater) after your win at the auction. If the vehicle sells for under $300 you must pay for it in full after the lien sale. All sales will include a key fee, tax and administration fee." },
  { id:3,  text:"When you buy more than one car you must put a deposit on each one. A $300 additional deposit will be collected, on the spot, for each additional bid." },
  { id:4,  text:"We will accept a credit card from the cardholder only, ID required. A 3% credit card fee is added to each processed transaction. Credit card transactions are limited to $4000." },
  { id:5,  text:"When viewing the cars, you may not open the hoods or doors. This is for ALL customers, if we see you under the hood without permission, we will ask you to leave." },
  { id:6,  text:"We are not responsible for any damage to or theft from the auction vehicles after close of business on the day of the auction. We highly recommend that you take your purchased vehicle off the lot the day of sale." },
  { id:7,  text:"Don't bid on a car unless you want it! If you win a bid and change your mind, you will lose your deposit." },
  { id:8,  text:"We DO NOT give any warranties, refunds or exchanges." },
  { id:9,  text:"Know what you are bidding on before you bid! Don't get caught up in the bidding and pay more than you want to. Once you win the bid, that is your vehicle. (please read #8)" },
  { id:10, text:"Winning the bid does not guarantee the vehicle is yours. The paperwork will go under one more verification for its validity, you will have to pay the fees in full and provide a name and address to send the paperwork to the DMV." },
  { id:11, text:"We cannot guarantee that the vehicle will start, run or drive after the auction." },
  { id:12, text:"All vehicles and vessels sold in the lien sale auction are sold AS IS." },
  { id:13, text:"We do not do a safety inspection on these vehicles and do not give any guarantee of its road worthiness." },
  { id:14, text:"The Auctioneer has the final call on who gets the bid." },
  { id:15, text:"Don't try to jump in at the last minute. You might not be seen and might not get the bid. We are not perfect and may miss people, so make sure you are seen! Getting your account approved in advance is way better than last minute." },
  { id:16, text:"You must pay the remainder after the deposit no later than 5pm the following business day after the auction or risk forfeiting the vehicle." },
  { id:17, text:"Failure to follow these simple rules may result in you being banned from bidding at any of our lien sales." },
  { id:18, text:"Every vehicle sold with a key will have a key fee added to the charges, new or used. Please check the Auction list for the rates on key fees." },
  { id:19, text:"Keys are only guaranteed to work in the ignition." },
  { id:20, text:"An administration fee of $35.47 will be added to each transaction." },
  { id:21, text:"IF YOU DO NOT PICK UP YOUR VEHICLE BY THE FOLLOWING BUSINESS DAY BY 5PM AFTER THE AUCTION YOU WILL LOSE THE VEHICLE AND YOUR DEPOSIT. Please contact the Main Office to make payment arrangements and schedule pickup at (702) 677-0792." },
  { id:22, text:"If the vehicle title returns as salvage, the buyer agrees to sign a Salvage Affidavit and complete the process to obtain a Rebuilt Title as required by state law. We try our best to spot and advertise those in advance, but sometimes the DMV will post it only very close to the sale, before or after, making it almost impossible to detect." },
  { id:23, text:"We advise you to have any/all vehicles that you win towed. Drive at your own risk." },
  { id:24, text:"If we need to tow your winning bid vehicle it will be $175 for the first 10 miles." },
];

const DEFAULT_REG_PUBLIC = {
  newUsers: [
    "You register an account for the website (one time-only).",
    "You will be receiving an email to activate your account. If you don't receive it, please check your spam folder.",
    "Once the account is activated, you will need to register as a bidder for each individual auction/event you are interested in.",
    "Once you complete the registration for the auction, we will ask you to pay a deposit.",
    "You can pay the deposit via Zelle at Tow Guys 702-677-0792, or by cash by coming down to our location on 3823 Losee Rd, N. Las Vegas, NV 89030.",
    "Once a deposit has been made, your username will be activated and enabled to bid.",
  ],
  returningUsers: [
    "You will be registering for each individual auction/event.",
    "Once you complete the registration for the auction, we will ask you to pay a deposit.",
    "You can pay the deposit via Zelle at Tow Guys 702-677-0792, or by cash by coming down to our location on 3823 Losee Rd, N. Las Vegas, NV 89030.",
    "Once a deposit has been made, your username will be activated and enabled to bid.",
  ],
  contact:{phone:"(702) 677-0792",zelle:"702-677-0792",address:"3823 Losee Rd, N. Las Vegas, NV 89030",lotOpen:"8:00 AM",biddingStart:"10:00 AM",pickupDeadline:"Following business day by 5:00 PM"}
};

function loadPublicTerms(){ try{ const s=localStorage.getItem("tga_terms_v1"); return s?JSON.parse(s):DEFAULT_TERMS_PUBLIC; }catch{ return DEFAULT_TERMS_PUBLIC; } }
function loadPublicReg(){ try{ const s=localStorage.getItem("tga_reg_v1"); return s?JSON.parse(s):DEFAULT_REG_PUBLIC; }catch{ return DEFAULT_REG_PUBLIC; } }

function TermsPage({t, onRegister, lang}){
  const [terms, setTerms] = useState(loadPublicTerms);
  // Load latest from server
  useEffect(function(){
    fetch("/api/settings").then(function(r){return r.json();}).then(function(data){
      if(data && data.terms && Array.isArray(data.terms)){
        setTerms(data.terms);
        try{ localStorage.setItem("tga_terms_v1",JSON.stringify(data.terms)); }catch(e){}
      }
    }).catch(function(){});
  },[]);
  const isAllCaps = txt => txt===txt.toUpperCase() && txt.replace(/[^A-Z ]/g,"").trim().length > 8;

  // Spanish translations of each term
  const ES_TERMS = [
    "Debe tener una cuenta de postor para pujar. Los postores deben pagar un depósito de $300 que es reembolsable si no compra un vehículo. Todos los reembolsos se darán DESPUÉS de la subasta. Los depósitos se pueden pagar por Zelle al número: 702-677-0792 (Nombre: Mai Niv Enterprise). Los depósitos de Zelle se reembolsarán previa solicitud, e incluir el número de teléfono y nombre de la cuenta. Puede solicitar el reembolso de Zelle por mensaje de texto al 702-677-0792.",
    "Debe pagar un depósito de $300 o el 20% del precio ganador (lo que sea mayor) después de ganar en la subasta. Si el vehículo se vende por menos de $300, debe pagarlo en su totalidad después de la venta. Todas las ventas incluirán una tarifa de llave, impuestos y tarifa administrativa.",
    "Cuando compre más de un auto, debe poner un depósito en cada uno. Se cobrará un depósito adicional de $300, en el momento, por cada oferta adicional.",
    "Aceptamos tarjeta de crédito solo del titular, se requiere identificación. Se agrega un cargo del 3% por tarjeta de crédito a cada transacción procesada. Las transacciones con tarjeta de crédito están limitadas a $4,000.",
    "Al ver los autos, no puede abrir los cofres ni las puertas. Esto aplica a TODOS los clientes. Si lo vemos bajo el cofre sin permiso, le pediremos que se retire.",
    "No somos responsables de daños ni robos de los vehículos en subasta después del cierre del día de la subasta. Recomendamos llevar su vehículo comprado el mismo día de la venta.",
    "¡No puje en un auto a menos que lo quiera! Si gana una puja y cambia de opinión, perderá su depósito.",
    "NO ofrecemos garantías, reembolsos ni cambios.",
    "¡Sepa en qué está pujando antes de pujar! No se deje llevar por la emoción y pague más de lo que quiere. Una vez que gana la puja, ese es su vehículo. (por favor lea el #8)",
    "Ganar la puja no garantiza que el vehículo sea suyo. La documentación pasará por una verificación más de validez; deberá pagar las tarifas en su totalidad y proporcionar nombre y dirección para enviar la documentación al DMV.",
    "No podemos garantizar que el vehículo arranque, funcione o conduzca después de la subasta.",
    "Todos los vehículos y embarcaciones vendidos en la subasta de embargo se venden TAL COMO ESTÁN.",
    "No realizamos inspección de seguridad en estos vehículos y no ofrecemos garantía de su aptitud para circular.",
    "El Subastador tiene la decisión final sobre quién obtiene la puja.",
    "No intente entrar al último momento. Es posible que no lo vean y no obtenga la puja. No somos perfectos y podemos perdernos a personas, ¡asegúrese de ser visto! Obtener la aprobación de su cuenta con anticipación es mucho mejor que esperar al último momento.",
    "Debe pagar el resto después del depósito a más tardar a las 5pm del siguiente día hábil después de la subasta o arriesga perder el vehículo.",
    "No cumplir con estas reglas puede resultar en que sea prohibido de pujar en cualquiera de nuestras ventas de embargo.",
    "Cada vehículo vendido con llave tendrá una tarifa de llave agregada a los cargos, nueva o usada. Por favor revise la lista de subasta para las tarifas de llaves.",
    "Las llaves solo tienen garantía de funcionar en la ignición.",
    "Se agregará una tarifa administrativa de $35.47 a cada transacción.",
    "SI NO RECOGE SU VEHÍCULO ANTES DE LAS 5PM DEL SIGUIENTE DÍA HÁBIL DESPUÉS DE LA SUBASTA, PERDERÁ EL VEHÍCULO Y SU DEPÓSITO. Por favor comuníquese con la Oficina Principal para hacer arreglos de pago y programar recogida al (702) 677-0792.",
    "Si el título del vehículo aparece como 'salvage' (salvamento), el comprador acepta firmar una Declaración Jurada de Salvamento y completar el proceso para obtener un Título Reconstruido según lo requiere la ley estatal.",
    "Le aconsejamos remolcar todos los vehículos que gane. Conduzca bajo su propio riesgo.",
    "Si necesitamos remolcar el vehículo que ganó, el costo será de $175 por las primeras 10 millas.",
  ];

  const getText = (term, idx) => lang==="es" && ES_TERMS[idx] ? ES_TERMS[idx] : term.text;

  return <div style={{maxWidth:820,margin:"0 auto",padding:"2rem 1.5rem"}}>
    <div style={{background:"var(--accent)",borderRadius:10,padding:"2rem 2.2rem",marginBottom:"2rem",color:"#fff"}}>
      <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"2rem",letterSpacing:".04em",marginBottom:".35rem"}}>{t("terms_title")}</div>
      <div style={{fontSize:".88rem",opacity:.75,fontFamily:"DM Mono,monospace"}}>{t("terms_sub")}</div>
    </div>
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:8,overflow:"hidden",marginBottom:"1.5rem"}}>
      {terms.map((term,idx)=>{
        const txt = getText(term, idx);
        const hi = isAllCaps(term.text); // always check English for caps detection
        return <div key={term.id} style={{display:"flex",gap:"1rem",padding:".85rem 1.2rem",borderBottom:"1px solid var(--border)",background:hi?"rgba(220,38,38,.04)":idx%2===0?"#fff":"var(--navy-light)"}}>
          <div style={{flexShrink:0,width:28,height:28,borderRadius:"50%",background:hi?"var(--red)":"var(--accent)",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontFamily:"Bebas Neue,sans-serif",fontSize:".95rem",fontWeight:700,marginTop:2}}>{idx+1}</div>
          <div style={{flex:1,fontSize:".88rem",lineHeight:1.7,fontWeight:hi?700:400,color:hi?"var(--red)":"var(--text)"}}>{txt}</div>
        </div>;
      })}
    </div>
    <div style={{background:"var(--accent)",borderRadius:8,padding:"1.4rem 1.6rem",display:"flex",alignItems:"center",gap:"1.2rem",flexWrap:"wrap"}}>
      <div style={{color:"#fff",flex:1}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",letterSpacing:".04em",marginBottom:".2rem"}}>{t("terms_cta_title")}</div>
        <div style={{fontSize:".82rem",opacity:.8}}>{t("terms_cta_sub")}</div>
      </div>
      <button className="cta" style={{background:"#fff",color:"var(--accent)",border:"none"}} onClick={onRegister}>{t("terms_cta_btn")}</button>
    </div>
  </div>;
}

function RegistrationPage({t, onRegister, lang}){
  const [reg, setReg] = useState(loadPublicReg);
  useEffect(function(){
    fetch("/api/settings").then(function(r){return r.json();}).then(function(data){
      if(data && data.registration && typeof data.registration==="object"){
        setReg(data.registration);
        try{ localStorage.setItem("tga_reg_v1",JSON.stringify(data.registration));}catch(e){}
      }
    }).catch(function(){});
  },[]);

  const ES_NEW = [
    "Registre una cuenta en el sitio web (solo una vez).",
    "Recibirá un correo electrónico para activar su cuenta. Si no lo recibe, revise su carpeta de spam.",
    "Una vez activada la cuenta, deberá registrarse como postor para cada subasta o evento individual que le interese.",
    "Una vez que complete el registro para la subasta, le pediremos que pague un depósito.",
    "Puede pagar el depósito por Zelle a Tow Guys al 702-677-0792, o en efectivo visitando nuestra ubicación en 3823 Losee Rd, N. Las Vegas, NV 89030.",
    "Una vez realizado el depósito, su nombre de usuario será activado y podrá pujar.",
  ];
  const ES_RETURNING = [
    "Se registrará para cada subasta o evento individual.",
    "Una vez que complete el registro para la subasta, le pediremos que pague un depósito.",
    "Puede pagar el depósito por Zelle a Tow Guys al 702-677-0792, o en efectivo visitando nuestra ubicación en 3823 Losee Rd, N. Las Vegas, NV 89030.",
    "Una vez realizado el depósito, su nombre de usuario será activado y podrá pujar.",
  ];

  const newSteps = lang==="es" ? ES_NEW : reg.newUsers;
  const retSteps = lang==="es" ? ES_RETURNING : reg.returningUsers;

  const Step = ({num, text}) => <div style={{display:"flex",gap:"1rem",alignItems:"flex-start",padding:".75rem 1rem",borderBottom:"1px solid var(--border)"}}>
    <div style={{flexShrink:0,width:30,height:30,borderRadius:"50%",background:"var(--accent)",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",fontWeight:700}}>{num}</div>
    <div style={{flex:1,fontSize:".88rem",lineHeight:1.7,paddingTop:4}}>{text}</div>
  </div>;

  const hoursVal = (t("reg_hours_val")||"Lot open {open} · Viewing from {start}")
    .replace("{open}", reg.contact.lotOpen)
    .replace("{start}", reg.contact.biddingStart);

  return <div style={{maxWidth:760,margin:"0 auto",padding:"2rem 1.5rem"}}>
    <div style={{background:"var(--accent)",borderRadius:10,padding:"2rem 2.2rem",marginBottom:"2rem",color:"#fff"}}>
      <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"2rem",letterSpacing:".04em",marginBottom:".35rem"}}>{t("reg_title")}</div>
      <div style={{fontSize:".88rem",opacity:.75,fontFamily:"DM Mono,monospace"}}>{t("reg_sub")}</div>
    </div>

    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:8,overflow:"hidden",marginBottom:"1.2rem"}}>
      <div style={{padding:".85rem 1.2rem",background:"var(--navy-light)",borderBottom:"1px solid var(--border)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",letterSpacing:".04em"}}>{t("reg_new_users")}</div>
      {newSteps.map((step,i)=><Step key={i} num={i+1} text={step}/>)}
    </div>

    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:8,overflow:"hidden",marginBottom:"1.5rem"}}>
      <div style={{padding:".85rem 1.2rem",background:"var(--navy-light)",borderBottom:"1px solid var(--border)",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",letterSpacing:".04em"}}>{t("reg_returning")}</div>
      {retSteps.map((step,i)=><Step key={i} num={i+1} text={step}/>)}
    </div>

    <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"1rem",marginBottom:"1.5rem"}}>
      {[
        [t("reg_location")||"Location", reg.contact.address],
        [t("reg_phone")||"Phone", reg.contact.phone],
        [t("reg_zelle")||"Zelle", (t("reg_zelle_val")||"Send to: ")+reg.contact.zelle],
        [t("reg_hours")||"Hours", hoursVal],
        [t("reg_pickup")||"Pickup Deadline", reg.contact.pickupDeadline],
        [t("reg_deposit")||"Deposit", t("reg_deposit_val")||"$300 refundable deposit required"],
      ].map(([label,val])=><div key={label} style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:7,padding:".85rem 1rem"}}>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".08em",color:"var(--muted)",marginBottom:".3rem"}}>{label}</div>
        <div style={{fontWeight:600,fontSize:".88rem"}}>{val}</div>
      </div>)}
    </div>

    <div style={{background:"var(--accent)",borderRadius:8,padding:"1.4rem 1.6rem",display:"flex",alignItems:"center",gap:"1.2rem",flexWrap:"wrap"}}>
      <div style={{color:"#fff",flex:1}}>
        <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",letterSpacing:".04em",marginBottom:".2rem"}}>{t("reg_cta_title")}</div>
        <div style={{fontSize:".82rem",opacity:.8}}>{t("reg_cta_sub")}</div>
      </div>
      <button className="cta" style={{background:"#fff",color:"var(--accent)",border:"none"}} onClick={onRegister}>{t("reg_cta_btn")}</button>
    </div>
  </div>;
}

// ─── RELEASE OF LIABILITY CHECK-IN ────────────────────────────────────────────
function ReleaseLiabilityPage(){
  var rs1 = useState(""); var name = rs1[0]; var setName = rs1[1];
  var rs2 = useState(""); var phone = rs2[0]; var setPhone = rs2[1];
  var rs3 = useState(""); var username = rs3[0]; var setUsername = rs3[1];
  var rs4 = useState(null); var result = rs4[0]; var setResult = rs4[1];
  var rs5 = useState(false); var checking = rs5[0]; var setChecking = rs5[1];
  var rs6 = useState(""); var err = rs6[0]; var setErr = rs6[1];
  var rs7 = useState(false); var signed = rs7[0]; var setSigned = rs7[1];
  var rs8 = useState(false); var drawing = rs8[0]; var setDrawing = rs8[1];
  var canvasRef = useRef(null);

  var rs9 = useState(""); var auctionName = rs9[0]; var setAuctionName = rs9[1];
  useEffect(function(){
    fetch("/api/settings").then(function(r){return r.json();}).then(function(d){
      var auc = d&&d.auction; if(auc&&typeof auc==="object"&&auc.value) auc=auc.value;
      if(auc&&auc.label) setAuctionName(auc.label);
      else if(auc&&auc.date) setAuctionName(auc.date);
    }).catch(function(){});
  },[]);

  var handleCheck = function(){
    if(!name.trim() && !phone.trim() && !username.trim()){
      setErr("Please enter your name, phone, or username."); return;
    }
    setErr(""); setChecking(true); setResult(null); setSigned(false);
    fetch("/api/bidders").then(function(r){return r.json();}).then(function(bidders){
      if(!Array.isArray(bidders)){setErr("Could not reach server.");setChecking(false);return;}
      var match = bidders.find(function(b){
        var fullName = ((b.first||"")+" "+(b.last||"")).trim().toLowerCase();
        var ph = (b.phone||"").replace(/\D/g,"");
        var inputPh = phone.replace(/\D/g,"");
        var uname = (b.username||"").toLowerCase();
        if(name.trim() && fullName.includes(name.trim().toLowerCase())) return true;
        if(inputPh.length>=7 && ph.includes(inputPh)) return true;
        if(username.trim() && uname===username.trim().toLowerCase()) return true;
        return false;
      });
      setChecking(false);
      if(match){
        var bal = (parseFloat(match.depositAmount)||0) +
          (Array.isArray(match.extraDeposits)?match.extraDeposits.filter(function(e){return e.status==="approved";}).reduce(function(s,e){return s+(+e.amount||0);},0):0) +
          (Array.isArray(match.credits)?match.credits.reduce(function(s,c){return s+(c.remaining||0);},0):0) -
          (Array.isArray(match.refundHistory)?match.refundHistory.reduce(function(s,r){return s+(+r.amount||0);},0):0);
        var isApproved = match.whitelist || match.depositStatus==="confirmed" || match.depositStatus==="applied" || bal >= 300;
        setResult({found:true, approved:isApproved, bidder:match});
        // Log visitor check-in
        fetch("/api/sms/send",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({phone:"log-only",message:"VISITOR_LOG"})}).catch(function(){});
        fetch("/api/visitor-checkin",{method:"POST",headers:{"Content-Type":"application/json"},
          body:JSON.stringify({bidderNum:match.bidderNum,name:(match.first||"")+" "+(match.last||""),phone:match.phone||"",email:match.email||"",status:isApproved?"approved":"pending",auction:auctionName,ts:new Date().toISOString()})
        }).catch(function(){});
      } else {
        setResult({found:false});
        fetch("/api/visitor-checkin",{method:"POST",headers:{"Content-Type":"application/json"},
          body:JSON.stringify({bidderNum:"",name:name.trim(),phone:phone,email:"",status:"not-registered",auction:auctionName,ts:new Date().toISOString()})
        }).catch(function(){});
      }
    }).catch(function(){setChecking(false);setErr("Network error. Try again.");});
  };

  // Signature pad
  var getPos = function(e,canvas){
    var rect = canvas.getBoundingClientRect();
    var x = (e.touches?e.touches[0].clientX:e.clientX)-rect.left;
    var y = (e.touches?e.touches[0].clientY:e.clientY)-rect.top;
    // Scale for high-DPI
    x = x * (canvas.width / rect.width);
    y = y * (canvas.height / rect.height);
    return {x:x,y:y};
  };
  var startDraw = function(e){
    var canvas = canvasRef.current; if(!canvas) return;
    setDrawing(true);
    var ctx = canvas.getContext("2d");
    var pos = getPos(e, canvas);
    ctx.beginPath(); ctx.moveTo(pos.x, pos.y);
  };
  var draw = function(e){
    if(!drawing) return;
    var canvas = canvasRef.current; if(!canvas) return;
    var ctx = canvas.getContext("2d");
    var pos = getPos(e, canvas);
    ctx.lineWidth = 2.5; ctx.lineCap = "round"; ctx.strokeStyle = "#000";
    ctx.lineTo(pos.x, pos.y); ctx.stroke();
    if(e.preventDefault) e.preventDefault();
  };
  var endDraw = function(){ setDrawing(false); };
  var clearSig = function(){
    var canvas = canvasRef.current; if(!canvas) return;
    canvas.getContext("2d").clearRect(0,0,canvas.width,canvas.height);
  };
  var isCanvasEmpty = function(){
    var canvas = canvasRef.current; if(!canvas) return true;
    var data = canvas.getContext("2d").getImageData(0,0,canvas.width,canvas.height).data;
    for(var i=3;i<data.length;i+=4){ if(data[i]>0) return false; }
    return true;
  };
  var submitSignature = function(){
    if(isCanvasEmpty()){ setErr("Please sign above before submitting."); return; }
    setErr("");
    var sigData = canvasRef.current.toDataURL("image/png");
    var bidder = result.bidder;
    var entry = {
      type:"release-signed",
      ts:new Date().toISOString(),
      date:new Date().toLocaleString("en-US",{month:"short",day:"numeric",year:"numeric",hour:"numeric",minute:"2-digit",timeZone:"America/Los_Angeles"}),
      text:"Release of Liability signed at check-in",
      signature:sigData
    };
    fetch("/api/bidders/"+encodeURIComponent(bidder.bidderNum)+"/comments",{
      method:"PUT",headers:{"Content-Type":"application/json"},
      body:JSON.stringify({comments:[entry].concat(bidder.staffComments||[])})
    }).catch(function(){});
    setSigned(true);
  };

  // After signing
  if(signed && result && result.bidder){
    return React.createElement("div",{style:{minHeight:"100vh",background:"linear-gradient(135deg,#001845 0%,#002366 50%,#001233 100%)",display:"flex",alignItems:"center",justifyContent:"center",padding:"1.5rem"}},
      React.createElement("div",{style:{background:"#fff",borderRadius:12,maxWidth:480,width:"100%",boxShadow:"0 20px 60px rgba(0,0,0,.3)",overflow:"hidden",textAlign:"center",padding:"2.5rem 1.5rem"}},
        React.createElement("div",{style:{fontSize:"3.5rem",marginBottom:".5rem"}},"✅"),
        React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.6rem",color:"#15803d",marginBottom:".3rem"}},"Release Signed"),
        React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".92rem",color:"#333",marginBottom:".2rem"}},(result.bidder.first||"")+" "+(result.bidder.last||"")),
        React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".75rem",color:"#888",marginBottom:"1rem"}},result.bidder.bidderNum),
        React.createElement("div",{style:{fontSize:".82rem",color:"#666",lineHeight:1.6,marginBottom:"1.5rem"}},"You are checked in and approved to bid. Good luck!"),
        React.createElement("button",{style:{padding:".6rem 2rem",background:"var(--accent)",color:"#fff",border:"none",borderRadius:6,fontSize:".9rem",fontWeight:700,cursor:"pointer",fontFamily:"Bebas Neue,sans-serif"},onClick:function(){
          setResult(null);setSigned(false);setName("");setPhone("");setUsername("");clearSig();
        }},"Next Bidder →")
      )
    );
  }

  var inputStyle = {width:"100%",padding:".55rem .75rem",border:"1.5px solid #ddd",borderRadius:6,fontSize:"16px",fontFamily:"DM Sans,sans-serif",outline:"none",boxSizing:"border-box"};
  var labelStyle = {fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".08em",color:"#999",display:"block",marginBottom:".25rem"};

  return React.createElement("div",{style:{minHeight:"100vh",background:"linear-gradient(135deg,#001845 0%,#002366 50%,#001233 100%)",display:"flex",alignItems:"center",justifyContent:"center",padding:"1.5rem"}},
    React.createElement("div",{style:{background:"#fff",borderRadius:12,maxWidth:480,width:"100%",boxShadow:"0 20px 60px rgba(0,0,0,.3)",overflow:"hidden"}},

      // Header
      React.createElement("div",{style:{background:"var(--accent)",padding:"1.5rem 1.5rem 1.2rem",textAlign:"center",position:"relative"}},
        React.createElement("button",{style:{position:"absolute",top:".75rem",right:".75rem",background:"rgba(255,255,255,.2)",border:"none",color:"#fff",fontSize:"1.1rem",width:30,height:30,borderRadius:"50%",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"},onClick:function(){window.location.href="/";}},"×"),
        React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.6rem",color:"#fff",letterSpacing:".06em"}},"Tow Guys Auto Auction"),
        React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"rgba(255,255,255,.8)",marginTop:".2rem"}},"Release of Liability")
      ),

      React.createElement("div",{style:{padding:"1.5rem"}},

        // Step 1: Verify
        !result&&React.createElement("div",null,
          React.createElement("div",{style:{fontSize:".85rem",color:"#666",lineHeight:1.6,marginBottom:"1.2rem"}},"Enter your information to verify your bidder account."),
          React.createElement("div",{style:{marginBottom:".75rem"}},
            React.createElement("label",{style:labelStyle},"Full Name"),
            React.createElement("input",{style:inputStyle,placeholder:"First Last",value:name,onChange:function(e){setName(e.target.value);}})
          ),
          React.createElement("div",{style:{marginBottom:".75rem"}},
            React.createElement("label",{style:labelStyle},"Phone Number"),
            React.createElement("input",{style:inputStyle,type:"tel",placeholder:"(702) 555-1234",value:phone,onChange:function(e){setPhone(e.target.value);}})
          ),
          React.createElement("div",{style:{marginBottom:"1rem"}},
            React.createElement("label",{style:labelStyle},"Username (optional)"),
            React.createElement("input",{style:inputStyle,placeholder:"@username",value:username,onChange:function(e){setUsername(e.target.value);}})
          ),
          err&&React.createElement("div",{style:{background:"rgba(220,38,38,.08)",border:"1px solid rgba(220,38,38,.3)",borderRadius:6,padding:".6rem .85rem",marginBottom:"1rem",fontSize:".82rem",color:"#dc2626"}},err),
          React.createElement("button",{style:{width:"100%",padding:".7rem",background:"var(--accent)",color:"#fff",border:"none",borderRadius:6,fontSize:"1rem",fontWeight:700,fontFamily:"Bebas Neue,sans-serif",letterSpacing:".04em",cursor:"pointer"},disabled:checking,onClick:handleCheck},checking?"Checking…":"Verify Bidder")
        ),

        // Not found
        result&&!result.found&&React.createElement("div",{style:{textAlign:"center"}},
          React.createElement("div",{style:{fontSize:"2.5rem",marginBottom:".5rem"}},"❌"),
          React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"#dc2626",marginBottom:".5rem"}},"NOT REGISTERED"),
          React.createElement("div",{style:{fontSize:".82rem",color:"#666",lineHeight:1.5,marginBottom:"1rem"}},"No matching bidder account found. You must register and place a $300 refundable deposit before you can bid."),
          React.createElement("div",{style:{display:"flex",gap:".5rem"}},
            React.createElement("button",{style:{flex:1,padding:".55rem",background:"#eee",color:"#333",border:"none",borderRadius:6,fontSize:".85rem",fontWeight:600,cursor:"pointer"},onClick:function(){setResult(null);}},"← Try Again"),
            React.createElement("button",{style:{flex:1,padding:".55rem",background:"var(--accent)",color:"#fff",border:"none",borderRadius:6,fontSize:".85rem",fontWeight:700,cursor:"pointer",fontFamily:"Bebas Neue,sans-serif"},onClick:function(){window.location.href="/";}},"Register Now →")
          )
        ),

        // Deposit pending
        result&&result.found&&!result.approved&&React.createElement("div",{style:{textAlign:"center"}},
          React.createElement("div",{style:{fontSize:"2.5rem",marginBottom:".5rem"}},"⚠️"),
          React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"#d97706",marginBottom:".5rem"}},"DEPOSIT PENDING"),
          React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".85rem",color:"#333"}},(result.bidder.first||"")+" "+(result.bidder.last||"")),
          React.createElement("div",{style:{fontSize:".82rem",color:"#666",lineHeight:1.5,marginTop:".5rem",marginBottom:"1rem"}},"Your account exists but your deposit hasn't been confirmed yet. Please see office staff or pay your $300 deposit."),
          React.createElement("button",{style:{width:"100%",padding:".55rem",background:"#eee",color:"#333",border:"none",borderRadius:6,fontSize:".85rem",fontWeight:600,cursor:"pointer"},onClick:function(){setResult(null);}},"← Back")
        ),

        // Approved — release text + signature
        result&&result.found&&result.approved&&React.createElement("div",null,
          React.createElement("div",{style:{background:"rgba(21,128,61,.06)",border:"1px solid rgba(21,128,61,.3)",borderRadius:8,padding:"1rem",marginBottom:"1rem"}},
            React.createElement("div",{style:{display:"flex",alignItems:"center",gap:".5rem",marginBottom:".5rem"}},
              React.createElement("span",{style:{fontSize:"1.3rem"}},"✅"),
              React.createElement("span",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"#15803d"}},"VERIFIED")
            ),
            React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".85rem",color:"#333"}},(result.bidder.first||"")+" "+(result.bidder.last||"")),
            React.createElement("div",{style:{fontFamily:"DM Mono,monospace",fontSize:".72rem",color:"#888",marginTop:".15rem"}},result.bidder.bidderNum+" · "+(result.bidder.phone||""))
          ),
          React.createElement("div",{style:{fontSize:".78rem",color:"#444",lineHeight:1.7,marginBottom:"1rem",padding:".75rem",background:"#f9f9f9",border:"1px solid #eee",borderRadius:6}},
            React.createElement("strong",null,"RELEASE OF LIABILITY"),React.createElement("br"),React.createElement("br"),
            "I, "+(result.bidder.first||"")+" "+(result.bidder.last||"")+", acknowledge that all vehicles sold by Tow Guys Auto Auction are sold AS-IS, WHERE-IS, with NO WARRANTY of any kind, expressed or implied.",React.createElement("br"),React.createElement("br"),
            "I accept full responsibility for any vehicle I purchase at auction. I understand that:",React.createElement("br"),
            "\u2022 All sales are final \u2014 no refunds or exchanges",React.createElement("br"),
            "\u2022 Vehicles must be picked up within 3 business days",React.createElement("br"),
            "\u2022 I am responsible for all DMV title transfer and registration fees",React.createElement("br"),
            "\u2022 Auction staff makes no guarantees about vehicle condition, mileage, or title status",React.createElement("br"),React.createElement("br"),
            "Date: "+new Date().toLocaleDateString("en-US",{month:"long",day:"numeric",year:"numeric",timeZone:"America/Los_Angeles"})
          ),
          React.createElement("div",{style:{marginBottom:"1rem"}},
            React.createElement("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:".35rem"}},
              React.createElement("label",{style:labelStyle},"Sign Below"),
              React.createElement("button",{style:{background:"none",border:"none",color:"var(--accent)",fontSize:".75rem",cursor:"pointer",fontFamily:"DM Mono,monospace"},onClick:clearSig},"Clear")
            ),
            React.createElement("canvas",{ref:canvasRef,width:400,height:120,
              style:{width:"100%",height:120,border:"1.5px solid #ccc",borderRadius:6,cursor:"crosshair",touchAction:"none",background:"#fff"},
              onMouseDown:startDraw,onMouseMove:draw,onMouseUp:endDraw,onMouseLeave:endDraw,
              onTouchStart:startDraw,onTouchMove:draw,onTouchEnd:endDraw})
          ),
          err&&React.createElement("div",{style:{background:"rgba(220,38,38,.08)",border:"1px solid rgba(220,38,38,.3)",borderRadius:6,padding:".6rem .85rem",marginBottom:"1rem",fontSize:".82rem",color:"#dc2626"}},err),
          React.createElement("div",{style:{display:"flex",gap:".5rem"}},
            React.createElement("button",{style:{flex:1,padding:".55rem",background:"#eee",color:"#333",border:"none",borderRadius:6,fontSize:".85rem",fontWeight:600,cursor:"pointer"},onClick:function(){setResult(null);}},"← Back"),
            React.createElement("button",{style:{flex:2,padding:".6rem",background:"#15803d",color:"#fff",border:"none",borderRadius:6,fontSize:"1rem",fontWeight:700,cursor:"pointer",fontFamily:"Bebas Neue,sans-serif",letterSpacing:".04em"},onClick:submitSignature},"Submit Signature \u2713")
          )
        ),

        React.createElement("div",{style:{marginTop:"1.5rem",paddingTop:"1rem",borderTop:"1px solid #eee",textAlign:"center",fontSize:".72rem",color:"#999",lineHeight:1.5}},
          "Tow Guys Auto Auction \u00b7 (702) 677-0792",React.createElement("br"),
          "250 W Warm Springs Rd, Henderson, NV 89011"
        )
      )
    )
  );
}

function ContactPage({t}){
  const [form,setForm]=useState({name:"",email:"",subject:"",message:""});
  const [sent,setSent]=useState(false);
  const [sending,setSending]=useState(false);
  const set=k=>e=>setForm(f=>({...f,[k]:e.target.value}));
  const handleSend=()=>{
    if(!form.name||!form.email||!form.message) return;
    setSending(true);
    var msg = "📩 CONTACT FORM\nFrom: "+form.name+"\nEmail: "+form.email+"\nSubject: "+(form.subject||"General Inquiry")+"\n\n"+form.message;
    fetch("/api/sms/send",{
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body:JSON.stringify({phone:"7026770792", message:msg})
    }).then(function(){
      setSending(false); setSent(true);
    }).catch(function(){
      setSending(false); setSent(true);
    });
  };

  return <div className="contact-wrap">
    {/* Hero */}
    <div className="contact-hero">
      <div className="contact-hero-title">{t("contact_title")}</div>
      <div className="contact-hero-sub">{t("contact_sub")}</div>
    </div>

    <div className="contact-grid">
      {/* Info card */}
      <div className="contact-info-card">
        <div className="contact-info-title">📍 {t("contact_address")}</div>

        <div className="contact-info-row">
          <div>
            <div className="contact-location-badge">
              <span className="contact-location-day">TUE</span>
              250 W Warm Springs Rd, Henderson, NV 89011
            </div>
            <div className="contact-location-badge">
              <span className="contact-location-day">FRI</span>
              3823 Losee Rd, North Las Vegas, NV 89030
            </div>
            <div className="contact-map-placeholder">🗺 Map — Google Maps integration available</div>
          </div>
        </div>

        <div style={{marginTop:"1.1rem",borderTop:"1px solid var(--border)",paddingTop:"1rem"}}>
          <div className="contact-info-row">
            <div className="contact-info-icon">📞</div>
            <div>
              <div className="contact-info-lbl">{t("contact_phone")}</div>
              <div className="contact-info-val"><a href="tel:7026770792">(702) 677-0792</a></div>
            </div>
          </div>
          <div className="contact-info-row">
            <div className="contact-info-icon">✉️</div>
            <div>
              <div className="contact-info-lbl">{t("contact_email")}</div>
              <div className="contact-info-val"><a href="mailto:csrtowguysautoauction@gmail.com">csrtowguysautoauction@gmail.com</a></div>
            </div>
          </div>
          <div className="contact-info-row">
            <div className="contact-info-icon">🕐</div>
            <div>
              <div className="contact-info-lbl">{t("contact_hours")}</div>
              <div className="contact-info-val" style={{fontSize:".82rem",lineHeight:1.7}}>
                Tuesday: 9:00 AM – 2:00 PM (Auction Day)<br/>
                Friday: 9:00 AM – 2:00 PM (Auction Day)<br/>
                <span style={{color:"var(--muted)"}}>Mon–Fri: 8:00 AM – 5:00 PM (Office)</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      {/* Contact form */}
      <div className="contact-form-card">
        <div className="contact-form-title">💬 {t("contact_form_title")}</div>
        {sent
          ? <div className="contact-sent-box">
              <div className="contact-sent-icon">✅</div>
              <div className="contact-sent-title">{t("contact_sent")}</div>
              <div className="contact-sent-sub">{t("contact_sent_sub")}</div>
              <button className="btn-p" style={{marginTop:"1.2rem"}} onClick={()=>{setSent(false);setForm({name:"",email:"",subject:"",message:""});}}>
                {t("contact_send_another")}
              </button>
            </div>
          : <>
              <div className="frow">
                <div className="fgrp"><label className="flbl">{t("contact_name")}</label><input className="finput" value={form.name} onChange={set("name")} placeholder="John Smith"/></div>
                <div className="fgrp"><label className="flbl">{t("contact_email_field")}</label><input className="finput" type="email" value={form.email} onChange={set("email")} placeholder="you@email.com"/></div>
              </div>
              <div className="fgrp" style={{marginBottom:".75rem"}}>
                <label className="flbl">{t("contact_subject")}</label>
                <select className="finput fselect" value={form.subject} onChange={set("subject")}>
                  <option value="">Select a topic…</option>
                  <option>General Inquiry</option>
                  <option>Vehicle / Lot Question</option>
                  <option>Deposit / Payment</option>
                  <option>Registration Help</option>
                  <option>Pickup / Title</option>
                  <option>Other</option>
                </select>
              </div>
              <div className="fgrp" style={{marginBottom:"1.1rem"}}>
                <label className="flbl">{t("contact_message")}</label>
                <textarea className="finput" rows={5} style={{resize:"vertical"}} value={form.message} onChange={set("message")} placeholder="How can we help you?"/>
              </div>
              <button className="btn-p" style={{width:"100%"}} disabled={sending||!form.name||!form.email||!form.message} onClick={handleSend}>
                {sending?"Sending…":t("contact_send")}
              </button>
            </>}
      </div>
    </div>
  </div>;
}

// ─── NOTIFICATION SYSTEM ──────────────────────────────────────────────────────
function useNotifications(){
  const [notifications, setNotifications] = useState([
    {id:"n0", type:"outbid", icon:"⚠️", title:"You've been outbid!", msg:"LOT 001 · 2018 Honda Accord — new bid: $4,500", ts:"9:15 AM", read:false},
    {id:"n1", type:"won", icon:"🏆", title:"You're winning!", msg:"LOT 003 · 2020 Toyota Camry — your bid of $7,100 is leading", ts:"9:08 AM", read:true},
  ]);
  const [toasts, setToasts] = useState([]);

  const addNotification = (notif) => {
    const id = "n"+Date.now();
    const full = {id, ...notif, ts:new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"}), read:false};
    setNotifications(prev=>[full,...prev]);
    setToasts(prev=>[...prev, full]);
    setTimeout(()=>setToasts(prev=>prev.filter(t=>t.id!==id)), 5000);
  };

  const markAllRead = () => setNotifications(prev=>prev.map(n=>({...n,read:true})));
  const dismissToast = (id) => setToasts(prev=>prev.filter(t=>t.id!==id));
  const unreadCount = notifications.filter(n=>!n.read).length;

  return {notifications, toasts, addNotification, markAllRead, dismissToast, unreadCount};
}

function NotifToastStack({toasts, onDismiss}){
  if(!toasts.length) return null;
  return <div className="notif-toast-stack">
    {toasts.map(t=><div key={t.id} className={`notif-toast ${t.type}`}>
      <div className="notif-toast-icon">{t.icon}</div>
      <div style={{flex:1,minWidth:0}}>
        <div className="notif-toast-title">{t.title}</div>
        <div className="notif-toast-body">{t.msg}</div>
        <div className="notif-toast-time">{t.ts}</div>
      </div>
      <button className="notif-toast-close" onClick={()=>onDismiss(t.id)}>×</button>
    </div>)}
  </div>;
}

function NotifBell({notifications, unreadCount, markAllRead}){
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(()=>{
    const handler = e=>{ if(ref.current&&!ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown",handler);
    return ()=>document.removeEventListener("mousedown",handler);
  },[]);

  return <div className="notif-bell-wrap" ref={ref}>
    <button className="notif-bell-btn" onClick={()=>{ setOpen(o=>!o); if(!open) markAllRead(); }}>
      🔔
      {unreadCount>0&&<span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",fontWeight:700}}>{unreadCount}</span>}
    </button>
    {unreadCount>0&&!open&&<div className="notif-badge">{unreadCount}</div>}
    {open&&<div className="notif-inbox">
      <div className="notif-inbox-hd">
        <div className="notif-inbox-title">Notifications</div>
        <span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{notifications.length} total</span>
      </div>
      {notifications.length===0&&<div className="notif-empty">No notifications yet</div>}
      {notifications.map(n=><div key={n.id} className={`notif-item${n.read?"":" unread"}`}>
        <div className="notif-item-icon">{n.icon}</div>
        <div className="notif-item-body">
          <div className="notif-item-title">{n.title}</div>
          <div className="notif-item-msg">{n.msg}</div>
          <div className="notif-item-ts">{n.ts}</div>
        </div>
        {!n.read&&<div className="notif-item-dot"/>}
      </div>)}
    </div>}
  </div>;
}

// ─── MAKE OFFER MODAL ─────────────────────────────────────────────────────────
function MakeOfferModal({auction, onClose, onSubmit, customer=null}){
  const [amount, setAmount] = useState("");
  const [note, setNote] = useState("");
  const custName = customer ? ((customer.first||"")+" "+(customer.last||"")).trim() : "";
  const [name, setName] = useState(custName);
  const [email, setEmail] = useState(customer?(customer.email||""):"");
  const [phone, setPhone] = useState(customer?(customer.phone||""):"");
  const [step, setStep] = useState("form"); // form | verify | sending | done
  const [smsCode, setSmsCode] = useState("");
  const [smsError, setSmsError] = useState("");
  const [smsSending, setSmsSending] = useState(false);
  const isLoggedIn = !!customer && !!custName;

  const cleanPhone = (p) => (p||"").replace(/\D/g,"");

  // Step 1: Send SMS verification code
  const sendCode = () => {
    const p = cleanPhone(phone);
    if(p.length<10){ setSmsError("Enter a valid phone number"); return; }
    if(!amount||+amount<=0) return;
    setSmsSending(true);
    setSmsError("");
    fetch("/api/sms-verify/send",{
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body:JSON.stringify({phone:p})
    })
    .then(r=>r.json())
    .then(data=>{
      setSmsSending(false);
      if(data.success) setStep("verify");
      else setSmsError(data.error||"Failed to send code. Try again.");
    })
    .catch(()=>{ setSmsSending(false); setSmsError("Network error. Try again."); });
  };

  // Step 2: Verify code and submit offer
  const verifyAndSubmit = () => {
    const p = cleanPhone(phone);
    if(smsCode.length<6){ setSmsError("Enter the 6-digit code"); return; }
    setSmsSending(true);
    setSmsError("");
    fetch("/api/sms-verify/check",{
      method:"POST",
      headers:{"Content-Type":"application/json"},
      body:JSON.stringify({phone:p, code:smsCode})
    })
    .then(r=>r.json())
    .then(data=>{
      setSmsSending(false);
      if(data.valid){
        setStep("done");
        onSubmit({amount:+amount, note, name, phone, email});
        setTimeout(()=>onClose(), 2500);
      } else {
        setSmsError("Invalid code. Please try again.");
      }
    })
    .catch(()=>{ setSmsSending(false); setSmsError("Network error. Try again."); });
  };

  return <div className="modal-bg"><div className="modal">
    <div className="mhd">
      <div><div className="mtitle">Make an Offer</div><div className="msub">{auction.lot} · {auction.year} {auction.make} {auction.model}</div></div>
      <button className="mclose" onClick={onClose}>×</button>
    </div>
    <div className="mbody">
      {/* Vehicle info card — always visible across all steps */}
      <div style={{display:"flex",gap:".85rem",padding:".75rem",background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:8,marginBottom:"1rem",alignItems:"center"}}>
        {auction.photos&&auction.photos[0]
          ? <img src={auction.photos[0]} alt="" style={{width:110,height:80,objectFit:"cover",borderRadius:6,flexShrink:0,border:"1px solid var(--navy-mid)"}}/>
          : <div style={{width:110,height:80,background:"#1a2540",borderRadius:6,flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center",fontSize:"1.5rem",opacity:.4}}>📷</div>}
        <div style={{flex:1,minWidth:0}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--accent)",fontWeight:700,letterSpacing:".05em"}}>{auction.lot||"LOT"}</div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.15rem",lineHeight:1.1,marginTop:2}}>{auction.year} {auction.make} {auction.model}</div>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)",marginTop:3}}>
            {auction.vin?"VIN: "+auction.vin.slice(-8):"No VIN"}
            {auction.mileage?" · "+Number(auction.mileage).toLocaleString()+" mi":""}
            {auction.condition?" · "+(auction.condition==="runs"?"✓ Runs":"✗ No Start"):""}
          </div>
        </div>
      </div>

      {step==="done"
        ? <div style={{textAlign:"center",padding:"1.5rem"}}>
            <div style={{fontSize:"2.5rem",marginBottom:".65rem"}}>✅</div>
            <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"var(--green)",marginBottom:".35rem"}}>Offer Submitted!</div>
            <div style={{fontSize:".83rem",color:"var(--muted)",lineHeight:1.6}}>Your offer of <strong>{fmtCurrency(+amount)}</strong> has been verified and sent to our team. We'll respond within 1 business hour via text message.</div>
          </div>
        : step==="verify"
        ? <div>
            <div style={{textAlign:"center",marginBottom:"1.2rem"}}>
              <div style={{fontSize:"2rem",marginBottom:".5rem"}}>📱</div>
              <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--accent)",marginBottom:".25rem"}}>Verification Code Sent</div>
              <div style={{fontSize:".82rem",color:"var(--muted)"}}>We sent a 6-digit code to <strong>{phone}</strong></div>
            </div>
            <div className="fgrp" style={{marginBottom:".75rem"}}>
              <label className="flbl">Enter 6-Digit Code *</label>
              <input className="finput" type="text" maxLength={6} placeholder="000000" value={smsCode}
                style={{textAlign:"center",fontFamily:"DM Mono,monospace",fontSize:"1.5rem",letterSpacing:".5rem"}}
                onChange={e=>setSmsCode(e.target.value.replace(/\D/g,""))}
                onKeyDown={e=>e.key==="Enter"&&verifyAndSubmit()}/>
            </div>
            {smsError&&<div style={{color:"var(--red)",fontSize:".8rem",marginBottom:".75rem",textAlign:"center"}}>{smsError}</div>}
            <div style={{display:"flex",gap:".5rem",justifyContent:"center",fontSize:".75rem",color:"var(--muted)",marginBottom:".5rem"}}>
              <span>Didn't get the code?</span>
              <button style={{background:"none",border:"none",color:"var(--blue)",cursor:"pointer",fontSize:".75rem",textDecoration:"underline"}} onClick={()=>{setSmsCode("");setSmsError("");sendCode();}}>Resend</button>
            </div>
          </div>
        : <>
            <div style={{background:"var(--navy-light)",border:"1px solid var(--navy-mid)",borderRadius:"6px",padding:".85rem 1rem",marginBottom:"1rem",fontSize:".83rem"}}>
              <div style={{display:"flex",justifyContent:"space-between",marginBottom:".25rem"}}>
                <span style={{color:"var(--muted)"}}>Current Bid</span>
                <span style={{fontWeight:600,color:"var(--accent)"}}>{fmtCurrency(auction.currentBid||auction.minBid)}</span>
              </div>
              {/* Buy Now removed */}
              <div style={{display:"flex",justifyContent:"space-between"}}>
                <span style={{color:"var(--muted)"}}>Min Bid</span>
                <span style={{fontWeight:600}}>{fmtCurrency(auction.minBid)}</span>
              </div>
            </div>

            <div className="fgrp" style={{marginBottom:".75rem"}}>
              <label className="flbl">Your Offer Amount ($) *</label>
              <div className="bid-in-row"><div className="bid-in-pre">$</div><input className="finput bid-in" type="number" placeholder="0" value={amount} min={1} onChange={e=>setAmount(e.target.value)}/></div>
            </div>
            <div className="frow">
              <div className="fgrp"><label className="flbl">Your Name *</label><input className="finput" placeholder="John Smith" value={name} onChange={e=>!isLoggedIn&&setName(e.target.value)} readOnly={isLoggedIn} style={{background:isLoggedIn?"var(--navy-light)":""}}/></div>
              <div className="fgrp"><label className="flbl">Phone Number *</label><input className="finput" type="tel" placeholder="(702) 555-0100" value={phone} onChange={e=>!isLoggedIn&&setPhone(e.target.value)} readOnly={isLoggedIn} style={{background:isLoggedIn?"var(--navy-light)":""}}/></div>
            </div>
            <div className="frow">
              <div className="fgrp"><label className="flbl">Email</label><input className="finput" type="email" placeholder="you@email.com" value={email} onChange={e=>!isLoggedIn&&setEmail(e.target.value)} readOnly={isLoggedIn} style={{background:isLoggedIn?"var(--navy-light)":""}}/></div>
            </div>
            {isLoggedIn&&<div style={{fontSize:".72rem",color:"var(--green)",fontFamily:"DM Mono,monospace",marginTop:"-.5rem",marginBottom:".5rem"}}>✓ Using your account info — we'll text you at this number when we respond.</div>}
            <div className="fgrp" style={{marginBottom:"1rem"}}>
              <label className="flbl">Note to Staff (optional)</label>
              <input className="finput" placeholder="e.g. Cash offer, can pick up same day" value={note} onChange={e=>setNote(e.target.value)}/>
            </div>
            {smsError&&<div style={{color:"var(--red)",fontSize:".8rem",marginBottom:".75rem"}}>{smsError}</div>}
            <div className="notice" style={{marginBottom:0}}>
              We'll send a verification code to your phone to confirm your offer. Offers are not binding until confirmed by staff.
            </div>
          </>}
    </div>
    {step==="form"&&<div className="mfoot">
      <button className="btn-g" onClick={onClose}>Cancel</button>
      <button className="btn-p" disabled={!amount||+amount<=0||!phone||!name||smsSending} onClick={sendCode}>
        {smsSending?"Sending Code…":`Verify Phone & Submit — ${amount?fmtCurrency(+amount):"$0"}`}
      </button>
    </div>}
    {step==="verify"&&<div className="mfoot">
      <button className="btn-g" onClick={()=>{setStep("form");setSmsCode("");setSmsError("");}}>← Back</button>
      <button className="btn-p" disabled={smsCode.length<6||smsSending} onClick={verifyAndSubmit}>
        {smsSending?"Verifying…":"Confirm & Submit Offer"}
      </button>
    </div>}
  </div></div>;
}

// ─── OFFERS INBOX (admin tab) ─────────────────────────────────────────────────
function OffersInbox({auctions, setAuctions}){
  const allOffers = auctions.flatMap(a=>(a.offers||[]).map(o=>({...o, auction:a})));
  const pending = allOffers.filter(o=>o.status==="pending");

  const respond = (auctionId, offerId, status) => {
    setAuctions(prev=>prev.map(a=>a.id!==auctionId?a:{
      ...a,
      offers:(a.offers||[]).map(o=>o.id!==offerId?o:{...o,status})
    }));
  };

  return <div>
    {pending.length>0&&<div className="notice warn" style={{marginBottom:"1rem"}}>
      <strong>{pending.length} pending offer{pending.length!==1?"s":" "} awaiting response</strong>
    </div>}
    {allOffers.length===0&&<div style={{textAlign:"center",padding:"3rem",color:"var(--muted)",background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px"}}>
      <div style={{fontSize:"2rem",opacity:.3,marginBottom:".5rem"}}>📬</div>
      <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)"}}>No Offers Yet</div>
      <div style={{fontSize:".82rem",marginTop:".3rem"}}>Offers from bidders appear here when Buy Now or Make Offer is used.</div>
    </div>}
    {allOffers.map(o=><div key={o.id} className="offer-card">
      <div className="offer-card-hd">
        <div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:".95rem",color:"var(--accent)"}}>{o.auction.lot} — {o.auction.year} {o.auction.make} {o.auction.model}</div>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)",marginTop:"2px"}}>{o.auction.vin} · Bidder: {o.bidderNum} · {o.ts}</div>
        </div>
        <span className={`offer-status ${o.status}`}>{o.status.charAt(0).toUpperCase()+o.status.slice(1)}</span>
      </div>
      <div className="offer-card-body">
        <div style={{flex:1}}>
          <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",color:"var(--muted)",marginBottom:".2rem"}}>Offer Amount</div>
          <div className="offer-amount">{fmtCurrency(o.amount)}</div>
          {o.note&&<div style={{fontSize:".78rem",color:"var(--sub)",fontStyle:"italic",marginTop:".3rem"}}>"{o.note}"</div>}
        </div>
        <div style={{fontSize:".78rem",color:"var(--muted)"}}>
          <div>Current bid: <strong>{fmtCurrency(o.auction.currentBid||o.auction.minBid)}</strong></div>
          {o.auction.buyNow&&<div>Buy Now: <strong>{fmtCurrency(o.auction.buyNow)}</strong></div>}
        </div>
        {o.status==="pending"&&<div style={{display:"flex",gap:".5rem",flexShrink:0}}>
          <button className="btn-approve" onClick={()=>respond(o.auction.id,o.id,"accepted")}>✓ Accept</button>
          <button className="btn-danger" onClick={()=>respond(o.auction.id,o.id,"declined")}>✕ Decline</button>
        </div>}
      </div>
    </div>)}
  </div>;
}

// ─── FAQ PAGE ──────────────────────────────────────────────────────────────────
const FAQ_DATA = [
  { cat:"registration", label:"Registration & Deposit", faqs:[
    { q:"How do I register to bid?",
      a:"Create an account on this site, then click Register & Deposit on any auction page. Complete the form with your personal info and driver's license. A refundable $300 deposit is required to activate your bidding account." },
    { q:"How do I pay my deposit?",
      a:"Three options: Credit/Debit Card (instant, auto-approved), Zelle to (702) 677-0792 with your name in the memo (approved within 1 hour), or Cash at our Henderson or North Las Vegas location on auction day." },
    { q:"Is the $300 deposit refundable?",
      a:"Yes, fully. If you don't win any lots, your deposit is returned within 3–5 business days. If you win, the $300 is applied toward your balance. You can also keep it on file for future auctions." },
    { q:"Do I need a dealer's license?",
      a:"No. All auctions are open to the general public. No dealer's license or special credentials are required — just a valid government-issued photo ID and driver's license." },
    { q:"I registered but can't bid yet — why?",
      a:"If you paid by Zelle or cash, your account requires manual approval by our staff. This typically takes less than 1 business hour during auction hours. If you've been waiting longer than 24 hours, call us at (702) 677-0792." },
  ]},
  { cat:"bidding", label:"Bidding", faqs:[
    { q:"How does the bidding work?",
      a:"Auctions are timed — each lot has a countdown clock. Place your bid before the clock hits zero. If someone bids in the final minute, the timer extends by 1 minute (overtime) so no one gets sniped at the last second." },
    { q:"What is auto-bid / proxy bidding?",
      a:"When you place a bid, you can set a maximum amount. The system will automatically bid on your behalf up to your maximum if someone outbids you — so you don't have to watch the auction constantly. Your max is never shown to other bidders." },
    { q:"What does Runs vs No Start mean?",
      a:"Runs means the engine starts and runs — you can inspect in person. No Start means the engine does not start and there may be mechanical issues — tow or transport will be required. All vehicles are sold as-is regardless of condition." },
    { q:"Can I inspect vehicles before bidding?",
      a:"Yes. Our lot is open for viewing starting at 8:00 AM on auction day. We strongly recommend inspecting in person. All vehicles are sold as-is." },
    { q:"What is a reserve price?",
      a:"Some lots have a hidden reserve — a minimum price the seller will accept. If bidding doesn't reach the reserve, the lot may be marked No Sale. The reserve is not disclosed, but a progress bar shows how close the current bid is." },
    { q:"What is Make an Offer?",
      a:"On eligible lots, you can submit a cash offer outside the auction. Offers are reviewed by staff and are not binding until confirmed. The auction continues while your offer is under review." },
  ]},
  { cat:"payment", label:"Payment & Pickup", faqs:[
    { q:"I won — what happens next?",
      a:"You'll receive an invoice by email with your balance (winning bid + admin fee + sales tax minus your deposit). Payment is due within 48 hours. Vehicle must be picked up within 3 business days." },
    { q:"What payment methods do you accept for the balance?",
      a:"Credit/Debit card, Zelle to csrtowguysautoauction@gmail.com, or cash. You can set your preferred payment method at registration — it can differ from your deposit method." },
    { q:"What is the admin fee?",
      a:"A flat administrative fee is added to every winning invoice. It covers title processing and auction administration. The exact amount is shown in the fee breakdown on your invoice." },
    { q:"How do I pick up my vehicle?",
      a:"Contact us at (702) 677-0792 to schedule pickup within 3 business days. Bring payment confirmation and a valid ID. Title documents are released upon full payment." },
  ]},
  { cat:"titles", label:"Titles & Lien Sales", faqs:[
    { q:"What is a lien sale?",
      a:"A government-regulated auction under Nevada law (NRS Chapter 108). When a vehicle owner fails to pay towing and storage fees, the towing company is authorized to sell the vehicle. The sale is publicly advertised and follows strict Nevada DMV rules." },
    { q:"What title will I receive?",
      a:"Title type is disclosed on every lot before bidding: Lien Sale (you receive a lien certificate; DMV transfer is your responsibility), Clean Title (standard clear title), Salvage (salvage title application required before re-registration), or Rebuilt (previously salvage, repaired and re-certified by DMV)." },
    { q:"What if the DMV reclassifies my vehicle as salvage after I bought it?",
      a:"This sometimes happens when the DMV receives a salvage report after a lien sale completes — through no fault of the buyer or Tow Guys. You have 3 options: (1) Keep it + 20% refund, and complete a salvage application at our office. (2) Return the vehicle for a full credit toward any future auction purchase, valid 12 months. (3) Return for a full refund, provided no more than 10 miles were added since pickup — verified against our pickup odometer record. You must notify us within 10 business days of receiving DMV notice." },
    { q:"Do I need a smog check?",
      a:"Nevada requires smog inspection for most vehicles at registration. This is the buyer's responsibility. Salvage and rebuilt title vehicles have separate DMV inspection requirements." },
  ]},
  { cat:"general", label:"General", faqs:[
    { q:"When and where are auctions held?",
      a:"Tuesday: 250 W Warm Springs Rd, Henderson, NV 89011, closes 2:00 PM. Friday: 3823 Losee Rd, North Las Vegas, NV 89030, closes 2:00 PM. Lot open for viewing from 8:00 AM." },
    { q:"How do I get notified about new auctions?",
      a:"Sign up for our Auction List (the button on this page or in the header). We'll email you before each auction with the vehicle roster." },
    { q:"Can I sell my vehicle through your auction?",
      a:"Our auctions are exclusively for lien sale vehicles recovered through our towing operations. We do not accept consignment or private-party vehicles at this time." },
    { q:"Who do I contact with questions?",
      a:"Phone: (702) 677-0792 — Email: csrtowguysautoauction@gmail.com — Office hours: Mon–Fri 8:00 AM – 5:00 PM, auction days until 2:00 PM." },
  ]},
];

const FAQ_DATA_ES = [
  { cat:"registration", label:"Registro y Dep\u00f3sito", faqs:[
    { q:"\u00bfC\u00f3mo me registro para pujar?", a:"Cree una cuenta en este sitio, luego haga clic en Registrarse y Dep\u00f3sito en cualquier p\u00e1gina de subasta. Complete el formulario con su informaci\u00f3n personal y licencia de conducir. Se requiere un dep\u00f3sito reembolsable de $300 para activar su cuenta." },
    { q:"\u00bfC\u00f3mo pago mi dep\u00f3sito?", a:"Tres opciones: Tarjeta de cr\u00e9dito/d\u00e9bito (instant\u00e1neo), Zelle al (702) 677-0792 con su nombre en el memo (aprobado en 1 hora), o efectivo en nuestra oficina en Henderson o North Las Vegas." },
    { q:"\u00bfEl dep\u00f3sito de $300 es reembolsable?", a:"S\u00ed, completamente. Si no gana ning\u00fan lote, su dep\u00f3sito se devuelve en 3-5 d\u00edas h\u00e1biles. Si gana, los $300 se aplican a su saldo. Tambi\u00e9n puede mantenerlo en archivo para futuras subastas." },
    { q:"\u00bfNecesito licencia de distribuidor?", a:"No. Todas las subastas est\u00e1n abiertas al p\u00fablico en general. No se requiere licencia de distribuidor ni credenciales especiales." },
    { q:"Me registr\u00e9 pero no puedo pujar \u2014 \u00bfpor qu\u00e9?", a:"Si pag\u00f3 con Zelle o efectivo, su cuenta requiere aprobaci\u00f3n manual. Esto tarda menos de 1 hora durante horario de subasta. Si ha esperado m\u00e1s de 24 horas, ll\u00e1menos al (702) 677-0792." },
  ]},
  { cat:"bidding", label:"Pujas", faqs:[
    { q:"\u00bfC\u00f3mo funciona la subasta?", a:"Las subastas son cronometradas \u2014 cada lote tiene un reloj de cuenta regresiva. Haga su puja antes de que el reloj llegue a cero. Si alguien puja en el \u00faltimo minuto, el temporizador se extiende 1 minuto." },
    { q:"\u00bfQu\u00e9 es la puja autom\u00e1tica / proxy?", a:"Cuando puja, puede establecer un monto m\u00e1ximo. El sistema pujar\u00e1 autom\u00e1ticamente en su nombre hasta su m\u00e1ximo si alguien le supera. Su m\u00e1ximo nunca se muestra a otros postores." },
    { q:"\u00bfQu\u00e9 significa Funciona vs No Arranca?", a:"Funciona significa que el motor arranca y funciona. No Arranca significa que el motor no arranca y puede haber problemas mec\u00e1nicos. Todos los veh\u00edculos se venden tal cual." },
    { q:"\u00bfPuedo inspeccionar veh\u00edculos antes de pujar?", a:"S\u00ed. Nuestro lote est\u00e1 abierto para ver desde las 8:00 AM el d\u00eda de la subasta. Recomendamos fuertemente inspeccionar en persona." },
    { q:"\u00bfQu\u00e9 es Hacer una Oferta?", a:"En lotes elegibles, puede enviar una oferta en efectivo fuera de la subasta. Las ofertas son revisadas por el personal y no son vinculantes hasta ser confirmadas." },
  ]},
  { cat:"payment", label:"Pago y Recogida", faqs:[
    { q:"Gan\u00e9 \u2014 \u00bfqu\u00e9 pasa ahora?", a:"Recibir\u00e1 una factura por correo electr\u00f3nico con su saldo. El pago debe realizarse dentro de 48 horas. El veh\u00edculo debe recogerse dentro de 3 d\u00edas h\u00e1biles." },
    { q:"\u00bfQu\u00e9 m\u00e9todos de pago aceptan?", a:"Tarjeta de cr\u00e9dito/d\u00e9bito, Zelle a csrtowguysautoauction@gmail.com, o efectivo." },
    { q:"\u00bfC\u00f3mo recojo mi veh\u00edculo?", a:"Cont\u00e1ctenos al (702) 677-0792 para programar la recogida dentro de 3 d\u00edas h\u00e1biles. Traiga confirmaci\u00f3n de pago e identificaci\u00f3n v\u00e1lida." },
  ]},
  { cat:"titles", label:"T\u00edtulos y Ventas por Gravamen", faqs:[
    { q:"\u00bfQu\u00e9 es una venta por gravamen?", a:"Una subasta regulada por el gobierno bajo la ley de Nevada (NRS Cap\u00edtulo 108). Cuando un propietario no paga los cargos de remolque y almacenamiento, la empresa de remolque est\u00e1 autorizada a vender el veh\u00edculo." },
    { q:"\u00bfQu\u00e9 t\u00edtulo recibir\u00e9?", a:"El tipo de t\u00edtulo se indica en cada lote: Venta por Gravamen (certificado de gravamen), T\u00edtulo Limpio (t\u00edtulo est\u00e1ndar), Salvamento (se requiere solicitud de t\u00edtulo de salvamento), o Reconstruido." },
  ]},
  { cat:"general", label:"General", faqs:[
    { q:"\u00bfCu\u00e1ndo y d\u00f3nde son las subastas?", a:"Martes: 250 W Warm Springs Rd, Henderson, NV 89011, cierra 2:00 PM. Viernes: 3823 Losee Rd, North Las Vegas, NV 89030, cierra 2:00 PM. Lote abierto desde las 8:00 AM." },
    { q:"\u00bfC\u00f3mo me notifico sobre nuevas subastas?", a:"Reg\u00edstrese en nuestra Lista de Subastas (el bot\u00f3n en esta p\u00e1gina). Le enviaremos un correo antes de cada subasta." },
    { q:"\u00bfA qui\u00e9n contacto con preguntas?", a:"Tel\u00e9fono: (702) 677-0792 \u2014 Email: csrtowguysautoauction@gmail.com \u2014 Horario: Lun-Vie 8:00 AM \u2013 5:00 PM." },
  ]},
];

function FAQPage({t, onSignup}){
  const [cat,setCat]=useState("all");
  const [open,setOpen]=useState({});
  const toggle=key=>setOpen(o=>({...o,[key]:!o[key]}));
  const faqSource = t("nav_faq")==="Preguntas" ? FAQ_DATA_ES : FAQ_DATA;
  const shown=cat==="all"?faqSource:faqSource.filter(c=>c.cat===cat);
  return <div className="faq-wrap">
    <div className="faq-hero">
      <div className="faq-hero-title">Frequently Asked Questions</div>
      <div className="faq-hero-sub">Everything you need to know about bidding at Tow Guys Auto Auction</div>
    </div>
    <div className="faq-cat-tabs">
      <button className={`faq-cat-btn${cat==="all"?" active":""}`} onClick={()=>setCat("all")}>All Questions</button>
      {FAQ_DATA.map(c=><button key={c.cat} className={`faq-cat-btn${cat===c.cat?" active":""}`} onClick={()=>setCat(c.cat)}>{c.label}</button>)}
    </div>
    {shown.map(section=><div key={section.cat} style={{marginBottom:"1.5rem"}}>
      {cat==="all"&&<div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",textTransform:"uppercase",letterSpacing:".12em",color:"var(--accent)",marginBottom:".65rem"}}>{section.label}</div>}
      {section.faqs.map((faq,fi)=>{
        const key=`${section.cat}-${fi}`;
        const isOpen=!!open[key];
        return <div key={key} className={`faq-item${isOpen?" open":""}`}>
          <div className="faq-q" onClick={()=>toggle(key)}><div className="faq-q-text">{faq.q}</div><span className="faq-chevron">▼</span></div>
          {isOpen&&<div className="faq-a">{faq.a}</div>}
        </div>;
      })}
    </div>)}
    <div className="faq-signup-strip">
      <div className="faq-signup-strip-text"><div className="faq-signup-strip-title">🔔 Auction Alerts</div><div className="faq-signup-strip-sub">Get notified by email or text when a new auction is published.</div></div>
      <AuctionListSignupInline onSuccess={()=>{}} compact/>
    </div>
  </div>;
}

// ─── AUCTION LIST SIGNUP ───────────────────────────────────────────────────────
function AuctionListSignupInline({onSuccess, compact=false}){
  const [email,setEmail]=useState("");
  const [phone,setPhone]=useState("");
  const [wantText,setWantText]=useState(false);
  const [done,setDone]=useState(false);
  const [err,setErr]=useState("");
  const submit=()=>{
    if(!email.includes("@")&&!phone.trim()){setErr("Enter an email or phone number");return;}
    if(wantText&&phone.replace(/\D/g,"").length<10){setErr("Enter a valid phone number for text alerts");return;}
    // Save to server
    fetch("/api/signups",{method:"POST",headers:{"Content-Type":"application/json"},
      body:JSON.stringify({email:email.trim(),phone:wantText?phone.replace(/\D/g,""):"",wantText:wantText})
    }).catch(function(){});
    setDone(true); onSuccess?.(email);
  };
  if(done) return <div style={{display:"flex",alignItems:"center",gap:".5rem",color:compact?"#fff":"var(--green)",fontSize:".85rem",fontWeight:600}}>✓ You're on the list!</div>;
  return <div style={{display:"flex",flexDirection:"column",gap:".4rem"}}>
    <div style={{display:"flex",gap:".45rem",flexWrap:"wrap",alignItems:"center"}}>
      <input style={{flex:1,minWidth:compact?130:180,padding:".45rem .75rem",borderRadius:"5px",border:compact?"none":"1px solid var(--border)",fontSize:"16px",outline:"none",fontFamily:"DM Sans,sans-serif"}}
        type="email" placeholder="your@email.com" value={email} onChange={e=>{setEmail(e.target.value);setErr("");}} onKeyDown={e=>e.key==="Enter"&&submit()}/>
      <button onClick={submit} style={{background:compact?"#fff":"var(--accent)",color:compact?"var(--accent)":"#fff",border:"none",borderRadius:"5px",padding:".45rem 1.1rem",fontWeight:700,fontSize:".85rem",cursor:"pointer",whiteSpace:"nowrap",fontFamily:"DM Sans,sans-serif"}}>Get Notified</button>
    </div>
    <label style={{display:"flex",alignItems:"center",gap:".4rem",cursor:"pointer",fontSize:".78rem",color:compact?"rgba(255,255,255,.8)":"var(--muted)"}}>
      <input type="checkbox" checked={wantText} onChange={function(){setWantText(function(v){return !v;});}} style={{width:15,height:15,accentColor:compact?"#fff":"var(--accent)"}}/>
      Text me when a new auction is published
    </label>
    {wantText&&<input style={{padding:".4rem .75rem",borderRadius:"5px",border:compact?"none":"1px solid var(--border)",fontSize:"16px",outline:"none",fontFamily:"DM Sans,sans-serif",width:compact?"100%":"auto",maxWidth:200}}
      type="tel" placeholder="(702) 555-1234" value={phone} onChange={e=>{setPhone(e.target.value);setErr("");}}/>}
    {err&&<div style={{fontSize:".75rem",color:compact?"#ffcccc":"var(--red)"}}>{err}</div>}
  </div>;
}

function AuctionListSignupFloat({onDismiss, onSignup}){
  const [done,setDone]=useState(false);
  return <div className="signup-float">
    <div className="signup-card">
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:".6rem"}}>
        <div><div style={{display:"flex",alignItems:"center",gap:".4rem",marginBottom:".2rem"}}><span className="signup-pulse"/><div className="signup-card-title">Auction Alerts</div></div><div className="signup-card-sub">Get notified by email or text when a new auction is published. Free, no spam.</div></div>
        <button className="signup-dismiss" onClick={onDismiss}>×</button>
      </div>
      {done?<div style={{textAlign:"center",padding:".5rem",color:"var(--green)",fontWeight:600}}>✓ You're on the list!</div>
        :<AuctionListSignupInline onSuccess={e=>{setDone(true);onSignup?.(e);}}/>}
    </div>
  </div>;
}

function AuctionListAdmin({signups, setSignups}){
  const [filterQ,setFilterQ]=useState("");
  const shown=signups.filter(s=>s.toLowerCase().includes(filterQ.toLowerCase()));
  return <div style={{maxWidth:600}}>
    <div style={{display:"flex",alignItems:"center",gap:".75rem",marginBottom:"1rem",flexWrap:"wrap"}}>
      <div style={{background:"var(--accent)",color:"#fff",borderRadius:"7px",padding:".65rem 1rem",fontFamily:"Bebas Neue,sans-serif",fontSize:"1.4rem",lineHeight:1}}>{signups.length}</div>
      <div><div style={{fontWeight:600}}>Auction List Subscribers</div><div style={{fontFamily:"DM Mono,monospace",fontSize:".68rem",color:"var(--muted)"}}>People who signed up to be notified before auctions</div></div>
    </div>
    <div className="search-wrap" style={{marginBottom:"1rem"}}><span className="search-icon">🔍</span><input className="search-input" placeholder="Search emails…" value={filterQ} onChange={e=>setFilterQ(e.target.value)}/></div>
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden",marginBottom:"1rem"}}>
      {shown.length===0&&<div style={{padding:"1.5rem",textAlign:"center",color:"var(--muted)",fontSize:".83rem"}}>No subscribers yet. Share the auction page — the signup form appears automatically.</div>}
      {shown.map((email,i)=><div key={email} style={{display:"flex",alignItems:"center",justifyContent:"space-between",padding:".65rem 1rem",borderBottom:i<shown.length-1?"1px solid var(--border)":"none",fontSize:".85rem"}}>
        <span style={{fontFamily:"DM Mono,monospace",fontSize:".82rem"}}>{email}</span>
        <button className="btn-sm" style={{color:"var(--red)",borderColor:"rgba(220,38,38,.25)",fontSize:".72rem"}} onClick={()=>setSignups(s=>s.filter(x=>x!==email))}>Remove</button>
      </div>)}
    </div>
    <button className="btn-p" style={{fontSize:".82rem"}} onClick={()=>{const mailto=`mailto:?bcc=${signups.join(",")}&subject=Tow Guys Auto Auction — New Lots Available&body=New vehicles are ready for bidding. View the auction at towguysautoauction.com`;window.open(mailto,"_blank");}} disabled={signups.length===0}>
      📧 Email All {signups.length} Subscriber{signups.length!==1?"s":""}
    </button>
  </div>;
}

// ─── WATCHLIST ─────────────────────────────────────────────────────────────────
function WatchButton({auction, watching, onToggle}){
  return <button className={`watch-btn${watching?" watching":""}`} onClick={e=>{e.stopPropagation();onToggle(auction.id);}}>
    {watching?"🔖 Watching":"🔖 Watch"}
  </button>;
}

function WatchlistModal({auctions, watchlist, onToggle, onClose, onBid, onOffer, canBid}){
  const watched=auctions.filter(a=>watchlist.has(a.id));
  return <div className="modal-bg"><div className="modal wide">
    <div className="mhd"><div><div className="mtitle">My Watchlist</div><div className="msub">{watched.length} lot{watched.length!==1?"s":""} saved</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      {watched.length===0&&<div style={{textAlign:"center",padding:"2.5rem",color:"var(--muted)"}}><div style={{fontSize:"2rem",marginBottom:".5rem"}}>🔖</div><div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.2rem",color:"var(--sub)"}}>No Saved Lots</div><div style={{fontSize:".83rem",marginTop:".3rem"}}>Click 🔖 Watch on any lot to save it here.</div></div>}
      {watched.map(a=><div key={a.id} className="watchlist-modal-item">
        <div style={{display:"flex",gap:".75rem",alignItems:"center",flex:1}}>
          {a.photos&&a.photos[0]
            ?<img src={a.photos[0]} alt="" style={{width:70,height:50,objectFit:"cover",borderRadius:5,flexShrink:0}}/>
            :<div style={{width:70,height:50,background:"#1a2540",borderRadius:5,flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center",opacity:.4}}>📷</div>}
          <div style={{flex:1,minWidth:0}}>
            <div style={{fontWeight:700,fontSize:".9rem"}}>{a.lot} — {a.year} {a.make} {a.model}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:"2px"}}>{a.vin||"No VIN"}</div>
            <div style={{display:"flex",gap:".5rem",marginTop:".35rem",alignItems:"center",flexWrap:"wrap"}}>
              <span style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1rem",color:"var(--accent)"}}>{fmtCurrency(a.currentBid||a.minBid)}</span>
              <span style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)"}}>{a.bids||0} bid{(a.bids||0)!==1?"s":""}</span>
              <TitleBadge type={a.titleType||"lien"}/>
            </div>
          </div>
        </div>
        <div style={{display:"flex",gap:".5rem",flexShrink:0}}>
          {canBid&&!a.sold&&<button className="btn-sm" style={{color:"var(--accent)"}} onClick={()=>{onClose();onBid(a);}}>Bid →</button>}
          {!a.sold&&<button className="btn-sm" style={{color:"var(--blue)",borderColor:"rgba(29,78,216,.25)"}} onClick={()=>{onClose();onOffer(a);}}>Offer</button>}
          <button className="btn-sm" style={{color:"var(--red)",borderColor:"rgba(220,38,38,.25)"}} onClick={()=>onToggle(a.id)}>✕</button>
        </div>
      </div>)}
    </div>
    <div className="mfoot"><button className="btn-g" onClick={onClose}>Close</button></div>
  </div></div>;
}

// ─── BIDDER RATING ─────────────────────────────────────────────────────────────
function StarRating({value, onChange, readonly=false}){
  const [hover,setHover]=useState(0);
  return <div className="rating-stars">{[1,2,3,4,5].map(n=><span key={n} className={`star ${n<=(hover||value)?"filled":"empty"}`} onClick={()=>!readonly&&onChange?.(n)} onMouseEnter={()=>!readonly&&setHover(n)} onMouseLeave={()=>!readonly&&setHover(0)}>★</span>)}</div>;
}

function RateBidderModal({bidder, onSave, onClose}){
  const [rating,setRating]=useState(0);
  const [cats,setCats]=useState({payment:0,pickup:0,communication:0});
  const [note,setNote]=useState("");
  return <div className="modal-bg"><div className="modal">
    <div className="mhd"><div><div className="mtitle">Rate Bidder</div><div className="msub">{bidder.first} {bidder.last} · {bidder.bidderNum}</div></div><button className="mclose" onClick={onClose}>×</button></div>
    <div className="mbody">
      <div style={{textAlign:"center",marginBottom:"1.2rem"}}>
        <div style={{fontFamily:"DM Mono,monospace",fontSize:".62rem",textTransform:"uppercase",letterSpacing:".1em",color:"var(--muted)",marginBottom:".55rem"}}>Overall Rating *</div>
        <div style={{transform:"scale(1.4)",transformOrigin:"center",margin:".5rem 0"}}><StarRating value={rating} onChange={setRating}/></div>
        {rating>0&&<div style={{marginTop:".65rem",fontFamily:"DM Mono,monospace",fontSize:".78rem",color:"var(--accent)"}}>{["","⭐ Poor","⭐⭐ Fair","⭐⭐⭐ Good","⭐⭐⭐⭐ Great","⭐⭐⭐⭐⭐ Excellent"][rating]}</div>}
      </div>
      <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:".65rem",marginBottom:"1rem"}}>
        {[["payment","Payment","💳"],["pickup","Pickup","🚗"],["communication","Comms","💬"]].map(([k,lbl,icon])=>
          <div key={k} style={{background:"var(--navy-light)",border:"1px solid var(--border)",borderRadius:"6px",padding:".6rem .7rem",textAlign:"center"}}>
            <div style={{fontSize:".85rem",marginBottom:".3rem"}}>{icon}</div>
            <div style={{fontFamily:"DM Mono,monospace",fontSize:".6rem",color:"var(--muted)",textTransform:"uppercase",marginBottom:".4rem"}}>{lbl}</div>
            <StarRating value={cats[k]} onChange={v=>setCats(c=>({...c,[k]:v}))}/>
          </div>)}
      </div>
      <div className="fgrp"><label className="flbl">Staff Note (internal only)</label><textarea className="finput" rows={3} style={{resize:"vertical",fontSize:".83rem"}} value={note} onChange={e=>setNote(e.target.value)} placeholder="e.g. Paid on time, picked up same day. Would approve again."/></div>
    </div>
    <div className="mfoot">
      <button className="btn-g" onClick={onClose}>Cancel</button>
      <button className="btn-p" disabled={!rating} onClick={()=>onSave({overall:rating,...cats,note,ts:new Date().toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})})}>Save Rating</button>
    </div>
  </div></div>;
}

// ─── SCHEDULED LOT PUBLISHING ──────────────────────────────────────────────────
function ScheduledPublishingPanel({auctions, setAuctions}){
  const [editId,setEditId]=useState(null);
  const [schedDate,setSchedDate]=useState("");
  const [schedTime,setSchedTime]=useState("08:00");
  useEffect(()=>{
    const t=setInterval(()=>{
      const now=Date.now();
      setAuctions(prev=>prev.map(a=>a.publishStatus==="scheduled"&&a.publishAt&&a.publishAt<=now?{...a,publishStatus:"live",published:true}:a));
    },5000);
    return ()=>clearInterval(t);
  },[]);
  const saveSchedule=id=>{
    if(!schedDate) return;
    const publishAt=new Date(`${schedDate}T${schedTime}`).getTime();
    setAuctions(prev=>prev.map(a=>a.id!==id?a:{...a,publishStatus:"scheduled",publishAt,published:false}));
    setEditId(null);
  };
  const publishNow=id=>setAuctions(prev=>prev.map(a=>a.id!==id?a:{...a,publishStatus:"live",publishAt:Date.now(),published:true}));
  const unpublish=id=>setAuctions(prev=>prev.map(a=>a.id!==id?a:{...a,publishStatus:"draft",publishAt:null,published:false}));
  const clearSched=id=>setAuctions(prev=>prev.map(a=>a.id!==id?a:{...a,publishStatus:"draft",publishAt:null}));
  const fmtSched=ts=>{
    if(!ts) return "—";
    const d=new Date(ts), diff=ts-Date.now();
    if(diff<=0) return "Publishing now…";
    const h=Math.floor(diff/3600000), m=Math.floor((diff%3600000)/60000);
    return `${d.toLocaleDateString("en-US",{month:"short",day:"numeric"})} ${d.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"})} (in ${h>0?`${h}h `:""}${m}m)`;
  };
  return <div>
    <div className="notice info" style={{marginBottom:"1rem"}}>Set a future date/time for any lot to go live. Scheduled lots are hidden from bidders until then — the system publishes them automatically every 5 seconds.</div>
    <div style={{background:"var(--card)",border:"1px solid var(--border)",borderRadius:"8px",overflow:"hidden"}}>
      {auctions.map((a,i)=>{
        const status=a.publishStatus||"live";
        const isEditing=editId===a.id;
        return <div key={a.id} style={{borderBottom:i<auctions.length-1?"1px solid var(--border)":"none"}}>
          <div style={{display:"flex",alignItems:"center",gap:".85rem",padding:".75rem 1.1rem",flexWrap:"wrap"}}>
            <div style={{flex:1,minWidth:0}}>
              <div style={{fontWeight:600,fontSize:".88rem"}}>{a.lot} — {a.year} {a.make} {a.model}</div>
              <div style={{fontFamily:"DM Mono,monospace",fontSize:".65rem",color:"var(--muted)",marginTop:"2px"}}>{status==="scheduled"?`⏰ ${fmtSched(a.publishAt)}`:status==="draft"?"Draft — hidden from public":"Live — visible to bidders"}</div>
            </div>
            <span className={`sched-badge ${status}`}>{status==="live"?"● LIVE":status==="scheduled"?"⏰ SCHEDULED":"○ DRAFT"}</span>
            <div style={{display:"flex",gap:".4rem",flexShrink:0,flexWrap:"wrap"}}>
              {status!=="live"&&<button className="btn-approve" onClick={()=>publishNow(a.id)}>Publish Now</button>}
              {status==="live"&&<button className="btn-sm" style={{color:"var(--muted)"}} onClick={()=>unpublish(a.id)}>Unpublish</button>}
              {status==="scheduled"&&<button className="btn-sm" style={{color:"var(--red)",borderColor:"rgba(220,38,38,.25)"}} onClick={()=>clearSched(a.id)}>Clear</button>}
              {status!=="scheduled"&&<button className="btn-sm" onClick={()=>{setEditId(a.id);setSchedDate(new Date().toISOString().slice(0,10));setSchedTime("08:00");}}>⏰ Schedule</button>}
            </div>
          </div>
          {isEditing&&<div style={{padding:".75rem 1.1rem",borderTop:"1px solid var(--border)",background:"var(--navy-light)",display:"flex",gap:".75rem",alignItems:"flex-end",flexWrap:"wrap"}}>
            <div className="fgrp" style={{marginBottom:0}}><label className="flbl">Date</label><input className="finput" type="date" value={schedDate} onChange={e=>setSchedDate(e.target.value)} style={{width:155}}/></div>
            <div className="fgrp" style={{marginBottom:0}}><label className="flbl">Time</label><input className="finput" type="time" value={schedTime} onChange={e=>setSchedTime(e.target.value)} style={{width:115}}/></div>
            <button className="btn-approve" onClick={()=>saveSchedule(a.id)} disabled={!schedDate}>Set Schedule</button>
            <button className="btn-g" onClick={()=>setEditId(null)}>Cancel</button>
          </div>}
        </div>;
      })}
    </div>
  </div>;
}

// ─── MAIN APP ─────────────────────────────────────────────────────────────────
function App(){
  const [auctions,setAuctions]=useState([]);
  const [stagger,setStagger]=useState(STAGGER_SECONDS);

  // Normalize lots from DB: push stale closeTimes into the future for unsold lots
  var normalizeLots = function(data){
    var now = Date.now();
    // Filter out: draft/removed lots. Sold/closed lots STAY visible with a CLOSED
    // badge until admin clicks Archive (which deletes them from tga_lots).
    // STRICT rule: only lots with publishStatus === "live" are public.
    return data
      .filter(function(l){
        if(l.publishStatus !== "live") return false;
        return true;
      })
      .map(function(l){
        // Strip autoBids from public view — bidders should never see other bidders' max bids
        return Object.assign({}, l, {autoBids: undefined, offerAmount: undefined, offerWinner: undefined, offerAccepted: undefined});
      });
  };

  // Load lots from DB on mount — NO mock fallback (production)
  // Track previous winners so we can detect outbid transitions between polls.
  // Map: lotId → winnerBidderNum (snapshot from last successful fetch).
  const prevWinnersRef = useRef({});

  useEffect(()=>{
    fetch("/api/lots").then(function(r){return r.json();}).then(function(data){
      var lots = Array.isArray(data) ? normalizeLots(data) : [];
      // Seed the winners map so the first poll doesn't falsely trigger outbid alerts
      prevWinnersRef.current = {};
      lots.forEach(function(l){ prevWinnersRef.current[l.id] = l.winner||null; });
      setAuctions(lots);
    }).catch(function(){
      setAuctions([]);
    });
    // Refresh every 5 seconds to pick up bids/edits from other browsers in near-real-time
    var refreshTimer = setInterval(function(){
      fetch("/api/lots").then(function(r){return r.json();}).then(function(data){
        var lots = Array.isArray(data) ? normalizeLots(data) : [];
        // Detect outbid: if I was the previous winner on a lot and am no longer the winner
        try {
          var me = (typeof authGetCurrent==="function") ? authGetCurrent() : null;
          var myNum = me && me.bidderNum;
          if (myNum) {
            lots.forEach(function(l){
              var prev = prevWinnersRef.current[l.id];
              if (prev === myNum && l.winner && l.winner !== myNum && !l.sold) {
                addNotification({
                  type:"outbid",
                  icon:"⚠",
                  title:(l.lot||"")+" — You were outbid! / Te superaron la oferta!",
                  msg:(l.year||"")+" "+(l.make||"")+" "+(l.model||"")+" — "+fmtCurrency(l.currentBid||0)
                });
              }
            });
          }
        } catch(e){}
        // Refresh the snapshot
        var m = {};
        lots.forEach(function(l){ m[l.id] = l.winner||null; });
        prevWinnersRef.current = m;
        setAuctions(lots);
      }).catch(function(){});
    }, 5000);
    return function(){ clearInterval(refreshTimer); };
  },[]);

  const times=useCountdowns(auctions);
  // view: "public" | "adminLogin" | "admin" | "release"
  const [view,setView]=useState(function(){
    try{ if(window.location.pathname==="/release") return "release"; }catch(e){}
    return "public";
  });
  const [lang,setLang]=useState("en");
  const t=key=>TRANSLATIONS[lang]?.[key]||TRANSLATIONS.en[key]||key;
  // Compute bidder status from a customer object
  const computeStatus = function(c){
    if(!c) return null;
    // 1. Whitelisted — always approved
    if(c.whitelist) return "approved";
    // 2. Calculate total balance
    var mainDep = c.depositAmount||0;
    var xd = Array.isArray(c.extraDeposits)?c.extraDeposits:[];
    var extraApproved = xd.filter(function(e){return e.status==="approved";}).reduce(function(s,e){return s+(+e.amount||0);},0);
    var creditsList = Array.isArray(c.credits)?c.credits:[];
    var creditRemaining = creditsList.reduce(function(s,cr){return s+(cr.remaining||0);},0);
    var refundsList = Array.isArray(c.refundHistory)?c.refundHistory:[];
    var totalOut = refundsList.reduce(function(s,r){return s+(+r.amount||0);},0);
    var totalBalance = mainDep + extraApproved + creditRemaining - totalOut;
    // 3. Balance >= $300 → approved
    if(totalBalance >= 300) return "approved";
    // 4. Under $300 — only approved if admin manually set auctionApproved
    if(c.auctionApproved) return "approved";
    // 5. Everything else → pending (needs deposit or manual approval)
    return "pending";
  };
  const [bidderStatus,setBidderStatus]=useState(function(){return computeStatus(authGetCurrent());});
  const [currentCustomer,setCurrentCustomer]=useState(()=>authGetCurrent());
  const [showAuctionRegModal,setShowAuctionRegModal]=useState(false);
  const [auctionRegAgree,setAuctionRegAgree]=useState(false);

  // Poll bidder status every 3 seconds — admin approval reflects within 3s
  useEffect(function(){
    if(!currentCustomer || !currentCustomer.bidderNum) return;
    var refresh = function(){
      fetch("/api/bidder-status/"+currentCustomer.bidderNum)
        .then(function(r){return r.json();})
        .then(function(data){
          if(!data || !data.found) return;
          // Merge fresh DB fields into current customer (preserve password locally)
          var fresh = Object.assign({}, currentCustomer, data);
          var newStatus = computeStatus(fresh);
          // Always update — deposit amount, method, extra deposits, or approval can change
          setCurrentCustomer(fresh);
          setBidderStatus(newStatus);
          authSetCurrent(fresh);
        }).catch(function(){});
    };
    refresh(); // immediate refresh
    var t = setInterval(refresh, 3000);
    return function(){ clearInterval(t); };
  },[currentCustomer && currentCustomer.bidderNum]);
  const [showAccountModal,setShowAccountModal]=useState(false);
  const [showLoginModal,setShowLoginModal]=useState(false);
  const [currentAdmin,setCurrentAdmin]=useState(null);
  const [adminUsers,setAdminUsers]=useState(INIT_ADMIN_USERS);
  const [showDeposit,setShowDeposit]=useState(()=>{
    try{ return typeof window!=="undefined"&&new URLSearchParams(window.location.search).get("register")==="1"; }catch{ return false; }
  });
  const [watchlist,setWatchlist]=useState(function(){
    // Load from currentCustomer if available, else localStorage fallback
    var cust = authGetCurrent();
    if(cust && cust.watchlist && Array.isArray(cust.watchlist)) return new Set(cust.watchlist);
    try{ var s=localStorage.getItem("tga_watchlist"); return s?new Set(JSON.parse(s)):new Set(); }catch(e){ return new Set(); }
  });
  const [showWatchlist,setShowWatchlist]=useState(false);
  const [signups,setSignups]=useState([]);
  const [showSignupFloat,setShowSignupFloat]=useState(false);
  const toggleWatch=function(id){
    setWatchlist(function(w){
      var n=new Set(w); n.has(id)?n.delete(id):n.add(id);
      var arr = Array.from(n);
      // Save to DB if logged in
      var cust = authGetCurrent();
      if(cust && cust.bidderNum){
        fetch("/api/watchlist/"+cust.bidderNum,{
          method:"PUT",
          headers:{"Content-Type":"application/json"},
          body:JSON.stringify({watchlist:arr})
        }).catch(function(){});
        // Also update local session cache
        try{
          cust.watchlist = arr;
          authSetCurrent(cust);
        }catch(e){}
      }
      // localStorage fallback for non-logged-in users
      try{ localStorage.setItem("tga_watchlist",JSON.stringify(arr)); }catch(e){}
      return n;
    });
  };

  // Handle Stripe deposit return
  useEffect(()=>{
    const params = new URLSearchParams(window.location.search);
    const depositStatus = params.get("deposit");
    if(depositStatus==="success"){
      // Update local session to confirmed
      const cur = authGetCurrent();
      if(cur){
        const updated = {...cur, depositStatus:"confirmed", depositAmount:300};
        authSetCurrent(updated);
        authUpdate(cur.email, {depositStatus:"confirmed", depositAmount:300});
        setCurrentCustomer(updated);
      }
      // Clean URL
      window.history.replaceState({}, "", window.location.pathname);
    } else if(depositStatus==="cancelled"){
      window.history.replaceState({}, "", window.location.pathname);
    }
    // Extra deposit return — refresh the current customer from the server so
    // the new entry in extra_deposits appears in the profile Deposit tab.
    const extraStatus = params.get("extra_deposit");
    if(extraStatus==="success"){
      const cur = authGetCurrent();
      if(cur && cur.bidderNum){
        fetch("/api/bidders").then(function(r){return r.json();}).then(function(all){
          const me = Array.isArray(all) ? all.find(function(b){return b.bidderNum===cur.bidderNum;}) : null;
          if(me){
            const merged = Object.assign({}, cur, {extraDeposits: me.extraDeposits||me.extra_deposits||[]});
            authSetCurrent(merged);
            setCurrentCustomer(merged);
          }
        }).catch(function(){});
      }
      window.history.replaceState({}, "", window.location.pathname);
    }
  },[]);

  // Show signup float after 15 seconds if not registered
  useEffect(()=>{
    if(bidderStatus) return;
    const t=setTimeout(()=>setShowSignupFloat(true),15000);
    return ()=>clearTimeout(t);
  },[bidderStatus]);

  // SEO: Dynamic document title + Open Graph meta tags
  useEffect(()=>{
    const base = "Tow Guys Auto Auction";
    const suffix = "Nevada Lien Sale Vehicles — Bid Online";
    document.title = `${base} — ${suffix}`;
    const setMeta = (prop, content, attr="property") => {
      let el = document.querySelector(`meta[${attr}="${prop}"]`);
      if(!el){ el=document.createElement("meta"); el.setAttribute(attr,prop); document.head.appendChild(el); }
      el.setAttribute("content",content);
    };
    setMeta("og:title",`${base} — ${suffix}`);
    setMeta("og:description","Government-regulated lien sale vehicles. Bid online — closes 2:00 PM. $300 refundable deposit. Henderson & North Las Vegas, NV.");
    setMeta("og:url","https://towguysautoauction.com");
    setMeta("og:type","website");
    setMeta("og:site_name","Tow Guys Auto Auction");
    setMeta("description","Government-regulated lien sale vehicles. Bid online — closes 2:00 PM. $300 refundable deposit. Henderson & North Las Vegas, NV.","name");
    setMeta("keywords","tow guys auto auction, nevada lien sale, lien sale vehicles las vegas, repo car auction henderson nv, government auction vehicles nevada","name");
    // Inject JSON-LD structured data if not already present
    if(!document.querySelector("#tga-jsonld")){
      const script = document.createElement("script");
      script.id = "tga-jsonld";
      script.type = "application/ld+json";
      script.text = JSON.stringify({
        "@context":"https://schema.org",
        "@type":"AuctionEvent",
        "name":"Tow Guys Auto Auction — Nevada Lien Sale",
        "description":"Government-regulated lien sale vehicles. Bid online.",
        "url":"https://towguysautoauction.com",
        "organizer":{"@type":"Organization","name":"Tow Guys Auto Auction","telephone":"(702) 677-0792"},
        "location":[
          {"@type":"Place","name":"Henderson","address":"250 W Warm Springs Rd, Henderson, NV 89011"},
          {"@type":"Place","name":"North Las Vegas","address":"3823 Losee Rd, North Las Vegas, NV 89030"}
        ]
      });
      document.head.appendChild(script);
    }
  },[]);

  // SEO: Lot deep-link — ?lot=A001 opens that lot's detail modal directly
  useEffect(()=>{
    try{
      const lotId = new URLSearchParams(window.location.search).get("lot");
      if(lotId){
        // Wait for auctions to be available then open the lot
        const idx = auctions.findIndex(a=>a.id===lotId||a.lot.replace(" ","").toLowerCase()===lotId.toLowerCase());
        if(idx>=0){
          setAuctions(prev=>prev.map((a,i)=>i===idx?{...a,views:(a.views||0)+1}:a));
          setDetailLot({auction:auctions[idx],idx});
          // Update OG tags for this specific lot
          const a=auctions[idx];
          const setMeta=(prop,content,attr="property")=>{let el=document.querySelector(`meta[${attr}="${prop}"]`);if(!el){el=document.createElement("meta");el.setAttribute(attr,prop);document.head.appendChild(el);}el.setAttribute("content",content);};
          document.title=`${a.year} ${a.make} ${a.model} — ${a.lot} | Tow Guys Auto Auction`;
          setMeta("og:title",`${a.year} ${a.make} ${a.model} — Min Bid ${fmtCurrency(a.minBid)}`);
          setMeta("og:description",`${a.lot}: ${a.year} ${a.make} ${a.model}, VIN ${a.vin}, ${(a.mileage||0).toLocaleString()} mi. Nevada lien sale — bid at towguysautoauction.com`);
          setMeta("og:url",`https://towguysautoauction.com?lot=${a.id}`);
        }
      }
    }catch(e){}
  },[auctions.length]);

  const [bidModal,setBidModal]=useState(null);
  const [autoBidModal,setAutoBidModal]=useState(null);
  const [bidDone,setBidDone]=useState(null);
  const [fCond,setFCond]=useState("");
  const [feeSettings]=useState({adminFee:DEFAULT_ADMIN_FEE,taxRate:DEFAULT_TAX_RATE});
  const [auctionBanner, setAuctionBanner]=useState("");
  const [searchQ,setSearchQ]=useState("");
  const [detailLot,setDetailLot]=useState(null);
  const [showTerms,setShowTerms]=useState(false);
  const [thresholdAlert,setThresholdAlert]=useState(null); // {totalExposure, threshold, leadingLots}
  const [pendingBid,setPendingBid]=useState(null);           // bid held while waiting for threshold approval
  const [additionalDeposits,setAdditionalDeposits]=useState(0); // count of extra $300 deposits approved
  const {notifications, toasts, addNotification, markAllRead, dismissToast, unreadCount} = useNotifications();
  const [offerModal, setOfferModal] = useState(null);
  const [myProxies, setMyProxies] = useState({});
  const OVERTIME_DEFAULT = 1;
  const [overtime] = useState(OVERTIME_DEFAULT);
  // Load auction banner from settings
  useEffect(function(){
    fetch("/api/settings").then(function(r){return r.json();}).then(function(data){
      if(data && data.auction && data.auction.banner) setAuctionBanner(data.auction.banner);
    }).catch(function(){});
  },[]);

  // Secret logo tap: 5 taps within 3 seconds → admin login
  const tapCount=useRef(0);
  const tapTimer=useRef(null);
  const handleLogoClick=()=>{
    if(view==="admin"||view==="adminLogin"){ setView("public"); return; }
    tapCount.current+=1;
    clearTimeout(tapTimer.current);
    if(tapCount.current>=3){ tapCount.current=0; setView("adminLogin"); return; }
    tapTimer.current=setTimeout(()=>{ tapCount.current=0; },4000);
  };

  const q=searchQ.toLowerCase();
  const shown=auctions.filter(a=>
    (!fCond||a.condition===fCond)&&
    (!q||`${a.year} ${a.make} ${a.model} ${a.vin}`.toLowerCase().includes(q))
  );
  const active=times.filter(t=>!t.done).length;

  const handleCustomerLogin=(acc)=>{
    setCurrentCustomer(acc);
    // Determine approval: whitelist, confirmed unused deposit, or keepOnFile
    var status = "pending";
    if(acc.whitelist) status = "approved";
    else if((acc.depositStatus==="confirmed"||acc.depositStatus==="applied") && acc.depositAppliedTo==null) status = "approved";
    else if(acc.keepOnFile && acc.depositStatus==="confirmed") status = "approved";
    setBidderStatus(status);
    // Load watchlist from DB
    if(acc.watchlist && Array.isArray(acc.watchlist)){
      setWatchlist(new Set(acc.watchlist));
    } else if(acc.bidderNum){
      fetch("/api/watchlist/"+acc.bidderNum).then(function(r){return r.json();}).then(function(data){
        if(data.watchlist && data.watchlist.length>0) setWatchlist(new Set(data.watchlist));
      }).catch(function(){});
    }
    setShowLoginModal(false);
    setShowAccountModal(true);
  };
  const handleCustomerLogout=()=>{
    authClearCurrent();
    setCurrentCustomer(null);
    setBidderStatus(null);
    setShowAccountModal(false);
    setShowLoginModal(false);
    // Clear cached data
    try{ localStorage.removeItem("tga_current_user"); localStorage.removeItem("tga_watchlist"); }catch(e){}
  };
  const [lotViews, setLotViews] = useState({});

  const openLotDetail = (auction, idx) => {
    // Increment view count
    setAuctions(prev=>prev.map(a=>a.id!==auction.id?a:{...a,views:(a.views||0)+1}));
    setDetailLot({auction,idx});
  };

  const handleLotShare = (lotId, platform) => {
    setAuctions(prev=>prev.map(a=>a.id!==lotId?a:{...a,shares:(a.shares||0)+1}));
  };

  const handleBuyNow = (auction) => {
    var price = auction.buyNow;
    var bidderNum = (currentCustomer && currentCustomer.bidderNum) || "DEMO";
    var bidderLabel = currentCustomer ? ((currentCustomer.first||"")+" "+(currentCustomer.last||"")+" (Buy Now)").trim() : "You (Buy Now)";
    var nowStr = new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});
    setAuctions(function(prev){
      return prev.map(function(a){
        if(a.id!==auction.id) return a;
        var updated = Object.assign({}, a, {
          currentBid: price,
          sold: true,
          winner: bidderNum,
          bids: (a.bids||0)+1,
          bidHistory: [...(a.bidHistory||[]), {bidder:bidderLabel, bidderNum:bidderNum, amount:price, ts:nowStr, tsMs:Date.now(), type:"buy-now"}]
        });
        // Persist to server immediately
        fetch("/api/lots/"+a.id, {
          method:"PUT",
          headers:{"Content-Type":"application/json"},
          body:JSON.stringify(updated)
        }).catch(function(err){ console.error("[BuyNow] Save failed:", err); });
        return updated;
      });
    });
    addNotification({type:"buynow", icon:"💰", title:"Buy Now Confirmed!", msg:auction.lot+" · "+auction.year+" "+auction.make+" "+auction.model+" — "+fmtCurrency(price)});
    setBidDone({auction:auction, amt:price});
  };

  const handleMakeOffer = (auction) => setOfferModal(auction);

  const handleOfferSubmit = (auction, offer) => {
    var newOffer = {
      id:"o"+Date.now(),
      bidderNum:currentCustomer?currentCustomer.bidderNum:"GUEST",
      bidderName:offer.name||(currentCustomer?((currentCustomer.first||"")+" "+(currentCustomer.last||"")).trim()||currentCustomer.username||"Bidder":"Guest"),
      bidderPhone:offer.phone||(currentCustomer?currentCustomer.phone:"")||"",
      bidderEmail:offer.email||(currentCustomer?currentCustomer.email:"")||"",
      amount:offer.amount,
      note:offer.note||"",
      ts:new Date().toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"}),
      status:"pending"
    };
    // Update local state AND send full updated lot to server (NOT just offers — that wipes the rest)
    setAuctions(function(prev){
      return prev.map(function(a){
        if(a.id!==auction.id) return a;
        var updatedLot = Object.assign({}, a, {
          offers: [...(a.offers||[]), newOffer]
        });
        // Persist FULL lot object so DB doesn't lose other fields
        fetch("/api/lots/"+a.id, {
          method:"PUT",
          headers:{"Content-Type":"application/json"},
          body:JSON.stringify(updatedLot)
        }).catch(function(err){ console.error("[Offer] Save failed:", err); });
        return updatedLot;
      });
    });
    addNotification({type:"offer", icon:"📨", title:"Offer Submitted", msg:auction.lot+" · "+fmtCurrency(offer.amount)+" — staff will review within 1 hour"});
    // Text the admin number so staff see it immediately
    var adminMsg = "📨 NEW OFFER\n"+
      (auction.lot||"")+" · "+(auction.year||"")+" "+(auction.make||"")+" "+(auction.model||"")+"\n"+
      "Amount: "+fmtCurrency(newOffer.amount)+"\n"+
      "From: "+newOffer.bidderName+" · "+newOffer.bidderPhone+"\n"+
      (newOffer.note?"Note: "+newOffer.note+"\n":"")+
      "Review in admin → Offers tab.";
    fetch("/api/sms/send",{method:"POST",headers:{"Content-Type":"application/json"},
      body:JSON.stringify({phone:"7026770792", message:adminMsg})}).catch(function(){});
  };
  const handleAdminLogout=()=>{ setCurrentAdmin(null); setView("public"); };
  const handleRegSuccess=()=>{ setBidderStatus("approved"); setShowDeposit(false); setShowAccountModal(false); setShowLoginModal(false); setView("public"); };

  return <>
    <style>{CSS}</style>
    <header className="header">
      <div className="logo" style={{cursor:"pointer",userSelect:"none"}} onClick={handleLogoClick}>
        Tow Guys <span>Auto Auction</span>
      </div>
      <div className="header-right">
        {/* Language toggle — always visible */}
        <div className="lang-toggle">
          <button className={`lang-btn${lang==="en"?" active":""}`} onClick={()=>setLang("en")}>EN</button>
          <button className={`lang-btn${lang==="es"?" active":""}`} onClick={()=>setLang("es")}>ES</button>
        </div>

        {view==="admin"
          ? <>
              <div style={{display:"flex",alignItems:"center",gap:".5rem",background:"rgba(255,255,255,.1)",border:"1px solid rgba(255,255,255,.2)",borderRadius:"4px",padding:".3rem .8rem"}}>
                <div style={{width:22,height:22,borderRadius:"50%",background:"rgba(255,255,255,.2)",display:"flex",alignItems:"center",justifyContent:"center",fontSize:".65rem",fontWeight:700,color:"#fff",fontFamily:"DM Mono,monospace"}}>{currentAdmin?.name.split(" ").map(w=>w[0]).join("").slice(0,2)||"AD"}</div>
                <span style={{fontSize:".73rem",color:"rgba(255,255,255,.9)",fontFamily:"DM Mono,monospace"}}>{currentAdmin?.name||"Admin"}</span>
                <span style={{fontSize:".62rem",color:"rgba(255,255,255,.5)",fontFamily:"DM Mono,monospace",borderLeft:"1px solid rgba(255,255,255,.2)",paddingLeft:".5rem"}}>{ADMIN_ROLES.find(r=>r.id===currentAdmin?.role)?.label||"Staff"}</span>
              </div>
              <button className="nav-badge" onClick={handleAdminLogout}>Sign Out</button>
            </>
          : <>
              <button className={`nav-badge${view==="public"?" active":""}`} onClick={()=>setView("public")}>{t("nav_auction")}</button>
              <button className={`nav-badge${view==="contact"?" active":""}`} onClick={()=>setView("contact")}>{t("nav_contact")}</button>
              {currentCustomer
                ? <button className="nav-badge active" onClick={()=>setShowAccountModal(true)}>
                    <span style={{display:"flex",alignItems:"center",gap:".4rem"}}>
                      {currentCustomer.first
                        ?<span style={{width:18,height:18,borderRadius:"50%",background:"rgba(255,255,255,.3)",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:".6rem",fontWeight:700}}>{currentCustomer.first[0]}{(currentCustomer.last||"")[0]}</span>
                        :<span style={{fontSize:".8rem"}}>👤</span>}
                      {currentCustomer.first||currentCustomer.username||currentCustomer.email||"My Account"}
                    </span>
                  </button>
                : <button className="nav-badge" onClick={()=>setShowLoginModal(true)}>{t("nav_signin")}</button>
              }
              {bidderStatus==="approved"&&<NotifBell notifications={notifications} unreadCount={unreadCount} markAllRead={markAllRead}/>}
              {currentCustomer&&<button className="nav-badge" onClick={()=>setShowWatchlist(true)}>🔖{watchlist.size>0?` ${watchlist.size}`:""}</button>}
              <button className="signup-nav-btn" onClick={()=>setView("faq")} style={view==="faq"?{background:"rgba(255,255,255,.25)"}:{}}>{t("nav_faq")||"FAQ"}</button>
              <button className="signup-nav-btn" onClick={()=>setView("terms")} style={view==="terms"?{background:"rgba(255,255,255,.25)"}:{}}>{t("nav_terms")||"Terms"}</button>
              <button className="signup-nav-btn" onClick={()=>setView("howto")} style={view==="howto"?{background:"rgba(255,255,255,.25)"}:{}}>{t("nav_howto")||"How to Bid"}</button>
              {!bidderStatus&&<button className="cta" style={{fontSize:".82rem"}} onClick={()=>setShowDeposit(true)}>{t("nav_register")}</button>}
              {bidderStatus==="pending"&&currentCustomer&&<button className="cta" style={{fontSize:".82rem",background:"#fbbf24",color:"#000"}} onClick={()=>setShowDeposit(true)}>💰 Pay Deposit / Register for Today's Auction</button>}
              {bidderStatus==="approved"&&!currentCustomer&&<div style={{display:"flex",alignItems:"center",gap:".4rem",background:"rgba(255,255,255,.12)",border:"1px solid rgba(255,255,255,.22)",borderRadius:"4px",padding:".3rem .75rem"}}><div style={{width:8,height:8,borderRadius:"50%",background:"var(--green)"}}/><span style={{fontSize:".73rem",color:"rgba(255,255,255,.9)",fontFamily:"DM Mono,monospace"}}>{t("nav_approved")}</span></div>}
              {bidderStatus==="pending"&&!currentCustomer&&<div style={{display:"flex",alignItems:"center",gap:".4rem",background:"rgba(255,255,255,.08)",border:"1px solid rgba(255,255,255,.2)",borderRadius:"4px",padding:".3rem .75rem"}}><div style={{width:8,height:8,borderRadius:"50%",background:"#fbbf24"}}/><span style={{fontSize:".73rem",color:"rgba(255,255,255,.8)",fontFamily:"DM Mono,monospace"}}>{t("nav_pending")}</span></div>}
            </>}
        {/* Sign Out — far right */}
        {currentCustomer&&<button onClick={handleCustomerLogout} style={{background:"none",border:"1px solid rgba(255,255,255,.2)",color:"rgba(255,255,255,.7)",fontSize:".72rem",padding:".35rem .75rem",borderRadius:4,cursor:"pointer",flexShrink:0,marginLeft:"auto",fontFamily:"DM Sans,sans-serif"}}>Sign Out</button>}
      </div>
    </header>

    {view==="adminLogin" && <AdminLogin adminUsers={adminUsers} onLogin={handleAdminLogin} onCancel={()=>setView("public")}/>}
    {view==="admin" && <AdminPanel auctions={auctions} setAuctions={setAuctions} stagger={stagger} setStagger={setStagger} adminUsers={adminUsers} setAdminUsers={setAdminUsers} currentAdmin={currentAdmin} signups={signups} setSignups={setSignups}/>}
    {view==="release" && <ReleaseLiabilityPage/>}
    {view==="contact" && <ContactPage t={t}/>}
    {view==="faq" && <FAQPage t={t} onSignup={e=>setSignups(s=>s.includes(e)?s:[...s,e])}/>}
    {view==="terms" && <TermsPage t={t} lang={lang} onRegister={()=>setShowDeposit(true)}/>}
    {view==="howto" && <RegistrationPage t={t} lang={lang} onRegister={()=>setShowDeposit(true)}/>}

    {showWatchlist&&<WatchlistModal auctions={auctions} watchlist={watchlist} onToggle={toggleWatch} onClose={()=>setShowWatchlist(false)} onBid={a=>setBidModal(a)} onOffer={a=>setOfferModal(a)} canBid={bidderStatus==="approved"}/>}
    {showSignupFloat&&!bidderStatus&&<AuctionListSignupFloat onDismiss={()=>setShowSignupFloat(false)} onSignup={e=>{setSignups(s=>s.includes(e)?s:[...s,e]);setShowSignupFloat(false);}}/>}

    {view==="public" && <>
      <div className="banner"><div className="banner-inner">
        {auctionBanner&&(auctionBanner||"").replace(/\s*\[LIVE[:\w\s]*\]/g,"").trim()&&<div style={{background:"rgba(255,255,255,.12)",border:"1px solid rgba(255,255,255,.2)",borderRadius:6,padding:".6rem 1.2rem",marginBottom:"1rem",textAlign:"center"}}>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.6rem",letterSpacing:".06em",color:"#fff",lineHeight:1.2}}>{(auctionBanner||"").replace(/\s*\[LIVE[:\w\s]*\]/g,"")}</div>
        </div>}
        <div className="banner-eyebrow">{t("banner_eyebrow")}</div>
        <div className="banner-title">{t("banner_title_1")}<br/><span>{t("banner_title_2")}</span></div>
        <div className="banner-sub">{t("banner_sub")}</div>
        <div style={{display:"flex",gap:".9rem",marginTop:"1.8rem",flexWrap:"wrap"}}>
          {Object.values(AUCTION_EVENTS).map(ev=>{
            // Go Live checked → Tuesday highlighted. Not checked → Friday highlighted.
            // Only show LIVE NOW if there are active published lots.
            const hasActiveLots = auctions.length > 0;
            const tuesdayTagged = auctionBanner && auctionBanner.indexOf("[LIVE:Tuesday Auction]")>=0;
            const fridayTagged = auctionBanner && auctionBanner.indexOf("[LIVE:Friday Auction]")>=0;
            const live = hasActiveLots && (
              (tuesdayTagged && ev.label==="Tuesday Auction") ||
              (fridayTagged && ev.label==="Friday Auction")
            );
            return <div key={ev.label} className={`event-card ${live?"live":"upcoming"}`} style={live?{border:"2px solid rgba(255,255,255,.5)",boxShadow:"0 0 20px rgba(255,255,255,.15)"}:{}}>
              {live&&<div style={{display:"inline-block",background:"#dc2626",color:"#fff",padding:".15rem .55rem",borderRadius:3,fontSize:".6rem",fontWeight:800,fontFamily:"DM Mono,monospace",letterSpacing:".08em",marginBottom:".35rem",animation:"pulse 1.5s ease-in-out infinite"}}>🔴 LIVE NOW</div>}
              <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.15rem",marginBottom:".18rem",color:"#fff"}}>{ev.label}</div>
              <div style={{fontSize:".76rem",color:"rgba(255,255,255,.65)",lineHeight:1.5}}>
                {t("banner_closes")} <strong style={{color:"#fff"}}>2:00 PM</strong><br/>
                {ev.address}
              </div>
              <div style={{fontSize:".7rem",color:"rgba(255,255,255,.5)",marginTop:".4rem",fontFamily:"DM Mono,monospace"}}>
                👀 Viewing: {ev.viewing}
              </div>
            </div>;
          })}
        </div>
        <div className="banner-stats">
          <div><div className="stat-val">{auctions.length}</div><div className="stat-lbl">{t("banner_total_lots")}</div></div>
          <div><div className="stat-val">{active}</div><div className="stat-lbl">{t("banner_active")}</div></div>
        </div>
      </div></div>

      <div className="toolbar">
        <span className="tlbl">{t("filter_label")}</span>
        <button className={`filter-btn${!fCond?" active":""}`} onClick={()=>setFCond("")}>{t("filter_all")}</button>
        <button className={`filter-btn${fCond==="runs"?" active":""}`} onClick={()=>setFCond("runs")}>{t("filter_runs")}</button>
        <button className={`filter-btn${fCond==="no-start"?" active":""}`} onClick={()=>setFCond("no-start")}>{t("filter_no_start")}</button>
        <div className="search-wrap">
          <span className="search-icon">🔍</span>
          <input className="search-input" placeholder={t("search_placeholder")} value={searchQ} onChange={e=>setSearchQ(e.target.value)}/>
          {searchQ&&<button className="search-clear" onClick={()=>setSearchQ("")}>×</button>}
        </div>
        <button className="filter-btn no-print" style={{marginLeft:"auto",fontSize:".75rem",color:"var(--muted)"}} onClick={()=>setShowTerms(true)}>{t("terms_link")}</button>
        <div className="toolbar-right" style={{marginLeft:0}}>
          {bidderStatus==="pending"&&<span style={{fontSize:".78rem",color:"var(--accent)",fontFamily:"DM Mono,monospace"}}>⏳ {t("nav_pending")}</span>}
          {bidderStatus==="approved"&&<div style={{display:"flex",alignItems:"center",gap:".5rem",background:"rgba(21,128,61,.08)",border:"1px solid rgba(21,128,61,.2)",borderRadius:"5px",padding:".4rem .8rem"}}>
            <div style={{width:8,height:8,borderRadius:"50%",background:"var(--green)"}}/>
            <span style={{fontSize:".78rem",color:"var(--green)",fontWeight:600}}>{t("nav_approved")}</span>
          </div>}
        </div>
      </div>

      <div className="grid">
        {shown.length===0&&<div className="no-results" style={{gridColumn:"1/-1"}}>
          <div className="no-results-icon">🔍</div>
          <div style={{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.3rem",color:"var(--sub)",marginBottom:".4rem"}}>{t("no_results_title")}</div>
          <div style={{fontSize:".82rem"}}>{t("no_results_sub")}</div>
        </div>}
        {shown.map(a=>{const i=auctions.indexOf(a);return <div key={a.id} onClick={()=>openLotDetail(a,i)} style={{cursor:"pointer"}}><AuctionCard auction={a} time={times[i]} bidderStatus={bidderStatus} myProxy={myProxies[a.id]||null} watching={watchlist.has(a.id)} t={t} onRegister={()=>setShowDeposit(true)} onBid={e=>{e?.stopPropagation?.();if(e&&e.autoBid){setAutoBidModal(a);}else{setBidModal(a);}}} onBuyNow={e=>{e?.stopPropagation?.();handleBuyNow(a);}} onMakeOffer={e=>{e?.stopPropagation?.();setOfferModal(a);}} onWatch={e=>{e?.stopPropagation?.();toggleWatch(a.id);}}/></div>;} )}
      </div>
    </>}

    {/* Customer login modal */}
    {showLoginModal&&<div className="modal-bg"><div className="modal">
      <div className="mhd"><div><div className="mtitle">{t("login_title")}</div><div className="msub">{t("login_sub")}</div></div><button className="mclose" onClick={()=>setShowLoginModal(false)}>×</button></div>
      <div className="mbody">
        <CustomerLoginInline onLogin={handleCustomerLogin} onRegister={()=>{setShowLoginModal(false);setShowDeposit(true);}} t={t}/>
      </div>
    </div></div>}

    {/* Customer account drawer */}
    {showAccountModal&&currentCustomer&&
      <CustomerAccountModal
        customer={currentCustomer}
        feeSettings={feeSettings}
        onClose={()=>setShowAccountModal(false)}
        onLogout={handleCustomerLogout}
        liveBids={!currentCustomer?[]:auctions.filter(a=>{
          if(a.sold) return false;
          var myNum = currentCustomer.bidderNum;
          // Currently leading
          if((a.winner||a.leader)===myNum) return true;
          // Previously bid on this lot (from bid history)
          if((a.bidHistory||[]).some(h=>h.bidderNum===myNum)) return true;
          // Has an active auto-bid
          if((a.autoBids||[]).some(ab=>ab.bidderNum===myNum)) return true;
          return false;
        })}
        watchedLots={auctions.filter(a=>watchlist.has(a.id))}
        onBid={function(lot){setBidModal(lot);}}
        onAutoBid={function(lot){setAutoBidModal(lot);}}
        canBid={bidderStatus==="approved"}
      />}

    <NotifToastStack toasts={toasts} onDismiss={dismissToast}/>
    {offerModal&&<MakeOfferModal auction={offerModal} onClose={()=>setOfferModal(null)} onSubmit={o=>handleOfferSubmit(offerModal,o)} customer={currentCustomer}/>}
    {showDeposit&&<DepositModal existingCustomer={currentCustomer} onClose={()=>setShowDeposit(false)} onSuccess={handleRegSuccess}/>}

    {showAuctionRegModal&&currentCustomer&&(function(){
      return React.createElement("div",{className:"modal-bg"},
        React.createElement("div",{className:"modal",style:{maxWidth:500}},
          React.createElement("div",{className:"mhd"},
            React.createElement("div",null,
              React.createElement("div",{className:"mtitle"},"Register for This Auction"),
              React.createElement("div",{className:"msub"},"Your deposit is on file — just confirm to start bidding")
            ),
            React.createElement("button",{className:"mclose",onClick:function(){setShowAuctionRegModal(false);}},"×")
          ),
          React.createElement("div",{className:"mbody"},
            React.createElement("div",{style:{background:"rgba(21,128,61,.08)",border:"1px solid rgba(21,128,61,.25)",borderRadius:6,padding:".85rem 1rem",marginBottom:"1rem"}},
              React.createElement("div",{style:{fontFamily:"Bebas Neue,sans-serif",fontSize:"1.1rem",color:"var(--green)",marginBottom:".3rem"}},"✓ Deposit on File — "+fmtCurrency(currentCustomer.depositAmount||300)),
              React.createElement("div",{style:{fontSize:".82rem",color:"var(--muted)"}},"Your deposit carries over. No additional payment required.")
            ),
            React.createElement("div",{style:{maxHeight:200,overflowY:"auto",border:"1px solid var(--border)",borderRadius:6,padding:".75rem",marginBottom:"1rem",fontSize:".78rem",color:"var(--muted)",lineHeight:1.6}},
              "By registering for this auction, I confirm that I have read and agree to the Terms & Conditions of Tow Guys Auto Auction. All sales are final, as-is. I understand my deposit will be applied to winning bids. Vehicles must be picked up within 3 business days of auction close."
            ),
            React.createElement("label",{style:{display:"flex",alignItems:"center",gap:".5rem",cursor:"pointer",marginBottom:"1rem",fontSize:".88rem"}},
              React.createElement("input",{type:"checkbox",checked:auctionRegAgree,style:{width:18,height:18,accentColor:"var(--accent)"},onChange:function(e){setAuctionRegAgree(e.target.checked);}}),
              React.createElement("span",null,"I agree to the Terms & Conditions")
            )
          ),
          React.createElement("div",{className:"mfoot"},
            React.createElement("button",{className:"btn-g",onClick:function(){setShowAuctionRegModal(false);setAuctionRegAgree(false);}},"Cancel"),
            React.createElement("button",{className:"btn-p",onClick:function(){
              if(!auctionRegAgree){window.alert("Please agree to the Terms & Conditions.");return;}
              fetch("/api/bidders/"+encodeURIComponent(currentCustomer.bidderNum)+"/register-auction",{
                method:"POST",headers:{"Content-Type":"application/json"}
              }).then(function(r){return r.json();}).then(function(d){
                if(d.ok){
                  var updated = Object.assign({},currentCustomer,{registeredForAuction:true});
                  setCurrentCustomer(updated);
                  setBidderStatus("approved");
                  authSetCurrent(updated);
                  setShowAuctionRegModal(false);
                  setAuctionRegAgree(false);
                } else { window.alert("Registration failed: "+(d.error||"unknown")); }
              }).catch(function(){window.alert("Network error.");});
            }},"✓ Register & Start Bidding")
          )
        )
      );
    })()}
    {autoBidModal&&<AutoBidModal auction={autoBidModal} onClose={()=>setAutoBidModal(null)} onSubmit={(amt,maxBid)=>{
      var ab = autoBidModal;
      setAutoBidModal(null);
      var bidderNum = (currentCustomer && currentCustomer.bidderNum) || "BIDDER";
      var bidderLabel = currentCustomer ? ((currentCustomer.first||"")+" "+(currentCustomer.last||"")).trim()||currentCustomer.username||"Bidder" : "You";

      // ── THRESHOLD CHECK ──
      var myBidderNum2 = (currentCustomer && currentCustomer.bidderNum) || null;
      var leading2 = myBidderNum2 ? auctions.filter(function(a){return (a.winner||a.leader)===myBidderNum2&&!a.sold&&a.id!==ab.id;}) : [];
      var existExp2 = leading2.reduce(function(s,a){return s+(a.currentBid||0);},0);
      var worstCase2 = maxBid && +maxBid > +amt ? +maxBid : +amt;
      var thresh2 = currentCustomer&&currentCustomer.creditThreshold!=null ? currentCustomer.creditThreshold : DEPOSIT_THRESHOLD;
      var effThresh2 = thresh2 + (additionalDeposits * 5000);
      var actualExp2 = existExp2 + amt;
      var fullExp2 = existExp2 + worstCase2;

      if(actualExp2 >= effThresh2){
        setPendingBid({auction:ab, amt:amt});
        setThresholdAlert({totalExposure:fullExp2, leadingLots:leading2.length+1, threshold:effThresh2});
        return;
      }

      var finalMax2 = maxBid;
      if(finalMax2 && fullExp2 >= effThresh2){
        var maxAllow2 = effThresh2 - existExp2;
        finalMax2 = maxAllow2;
        window.alert("Your auto-bid max has been capped at "+fmtCurrency(maxAllow2)+" to stay within your "+fmtCurrency(effThresh2)+" bidding limit.\n\nTo increase your limit, place an additional $300 deposit or call (702) 677-0792.");
      }

      fetch("/api/bid",{
        method:"POST",
        headers:{"Content-Type":"application/json"},
        body:JSON.stringify({lotId:ab.id, bidderNum:bidderNum, bidderLabel:bidderLabel, amount:amt, maxBid:finalMax2})
      }).then(function(r){return r.json();}).then(function(data){
        if(data.error){ window.alert("Bid failed: "+data.error); return; }
        setAuctions(function(prev){return prev.map(function(a){return a.id===ab.id?Object.assign({},a,{currentBid:data.currentBid, leader:data.leader, winner:data.leader, bids:(a.bids||0)+1, closeTime:data.closeTime||a.closeTime}):a;});});
        setMyProxies(function(p){return Object.assign({},p,{[ab.id]:finalMax2});});
        setBidDone({auction:ab,amt:data.currentBid,maxBid:finalMax2});
      }).catch(function(){ window.alert("Network error placing auto-bid."); });
    }}/>}
    {bidModal&&<BidModal auction={bidModal} time={times[auctions.findIndex(a=>a.id===bidModal.id)]} defaultMax={!!bidModal._autoBid} onClose={()=>setBidModal(null)} onSubmit={(amt, maxBid)=>{
      var bidderNum = (currentCustomer && currentCustomer.bidderNum) || "BIDDER";
      var bidderLabel = currentCustomer ? ((currentCustomer.first||"")+" "+(currentCustomer.last||"")).trim()||currentCustomer.username||"Bidder" : "You";

      // ── THRESHOLD CHECK FIRST ──────────────────────────────────────────
      var myBidderNum = (currentCustomer && currentCustomer.bidderNum) || null;
      var currentLeading = myBidderNum ? auctions.filter(function(a){return (a.winner||a.leader)===myBidderNum&&!a.sold&&a.id!==bidModal.id;}) : [];
      var existingExposure = currentLeading.reduce(function(s,a){return s+(a.currentBid||0);},0);
      var worstCase = maxBid && +maxBid > +amt ? +maxBid : +amt;
      var bidderThreshold = currentCustomer&&currentCustomer.creditThreshold!=null ? currentCustomer.creditThreshold : DEPOSIT_THRESHOLD;
      var effectiveThreshold = bidderThreshold + (additionalDeposits * 5000);
      var actualExposure = existingExposure + amt;
      var fullExposure = existingExposure + worstCase;

      if(actualExposure >= effectiveThreshold){
        // Base bid exceeds threshold — block entirely, ask for deposit
        var leadingLotCount = currentLeading.length + 1;
        setPendingBid({auction:bidModal, amt:amt});
        setThresholdAlert({totalExposure:fullExposure, leadingLots:leadingLotCount, threshold:effectiveThreshold});
        setBidModal(null);
        // Notify admin via SMS + log request
        var custName = currentCustomer?((currentCustomer.first||"")+" "+(currentCustomer.last||"")).trim():"Bidder";
        fetch("/api/threshold-request",{method:"POST",headers:{"Content-Type":"application/json"},
          body:JSON.stringify({bidderNum:myBidderNum,name:custName,phone:currentCustomer?currentCustomer.phone:"",email:currentCustomer?currentCustomer.email:"",currentExposure:actualExposure,requestedThreshold:effectiveThreshold+5000})
        }).catch(function(){});
        fetch("/api/sms/send",{method:"POST",headers:{"Content-Type":"application/json"},
          body:JSON.stringify({phone:"7026770792",message:"⚡ THRESHOLD ALERT\n"+custName+" ("+myBidderNum+") hit their "+fmtCurrency(effectiveThreshold)+" limit.\nExposure: "+fmtCurrency(actualExposure)+"\nNeeds approval to continue bidding.\n\nApprove in Admin → Threshold Requests tab."})
        }).catch(function(){});
        return;
      }

      // Cap maxBid to threshold if it exceeds
      var finalMaxBid = maxBid||null;
      if(finalMaxBid && fullExposure >= effectiveThreshold){
        var maxAllowed = effectiveThreshold - existingExposure;
        finalMaxBid = maxAllowed;
        window.alert("Your auto-bid max has been capped at "+fmtCurrency(maxAllowed)+" to stay within your "+fmtCurrency(effectiveThreshold)+" bidding limit.\n\nTo increase your limit, place an additional $300 deposit or call (702) 677-0792.");
      }

      // Place the bid
      fetch("/api/bid",{
        method:"POST",
        headers:{"Content-Type":"application/json"},
        body:JSON.stringify({lotId:bidModal.id, bidderNum:bidderNum, bidderLabel:bidderLabel, amount:amt, maxBid:finalMaxBid})
      }).then(function(r){return r.json();}).then(function(data){
        if(data.error){ window.alert("Bid failed: "+data.error); return; }
        setAuctions(function(prev){return prev.map(function(a){return a.id===bidModal.id?Object.assign({},a,{currentBid:data.currentBid, leader:data.leader, winner:data.leader, bids:(a.bids||0)+1, closeTime:data.closeTime||a.closeTime}):a;});});
        if(finalMaxBid && +finalMaxBid > +amt) setMyProxies(function(p){return Object.assign({},p,{[bidModal.id]:finalMaxBid});});
      }).catch(function(){ window.alert("Network error placing bid."); });

      setBidDone({auction:bidModal,amt:amt});
      setBidModal(null);
    }}/>}
    {thresholdAlert&&<ThresholdDepositModal
      bidder={currentCustomer ? {...currentCustomer, payMethod:"card", cardLast4:"4242"} : {payMethod:"card", cardLast4:"4242", leadingLots:thresholdAlert.leadingLots}}
      totalExposure={thresholdAlert.totalExposure}
      threshold={thresholdAlert.threshold||DEPOSIT_THRESHOLD}
      nextThreshold={(thresholdAlert.threshold||DEPOSIT_THRESHOLD) + 5000}
      onApprove={()=>{
        // Count the deposit, then release the pending bid
        setAdditionalDeposits(n=>n+1);
        if(pendingBid){
          var pBidderNum = (currentCustomer && currentCustomer.bidderNum) || "BIDDER";
          setAuctions(prev=>prev.map(a=>a.id===pendingBid.auction.id?{...a,currentBid:pendingBid.amt,leader:pBidderNum,winner:pBidderNum}:a));
          setBidDone({auction:pendingBid.auction, amt:pendingBid.amt});
          setPendingBid(null);
        }
        setThresholdAlert(null);
      }}
      onDismiss={()=>{
        // Cancel the held bid entirely
        setPendingBid(null);
        setThresholdAlert(null);
      }}
    />}
    {detailLot&&<VehicleDetailModal auction={detailLot.auction} time={times[detailLot.idx]} feeSettings={feeSettings} bidderStatus={bidderStatus} onBid={a=>{setBidModal(a);}} onShare={handleLotShare} onClose={()=>setDetailLot(null)}/>}
    {showTerms&&<TermsModal onClose={()=>setShowTerms(false)}/>}
    {bidDone&&<div className="modal-bg"><div className="modal"><div className="mbody" style={{padding:"2.5rem",textAlign:"center"}}>
      <div className="succ-icon">🏁</div>
      <div className="succ-title">{t("bid_done_title")}</div>
      <p style={{color:"var(--muted)",fontSize:".83rem",marginBottom:"1.3rem",lineHeight:1.6}}>{t("bid_done_body").replace("{{amount}}",fmtCurrency(bidDone.amt)).replace("{{vehicle}}",`${bidDone.auction.year} ${bidDone.auction.make} ${bidDone.auction.model}`)}</p>
      <div style={{display:"flex",gap:".7rem"}}>
        <button className="btn-g" style={{flex:1}} onClick={()=>setBidDone(null)}>{t("bid_keep")}</button>
        <button className="btn-p" style={{flex:1}} onClick={()=>setBidDone(null)}>{t("bid_done_btn")}</button>
      </div>
    </div></div></div>}
  </>;
}

// ─── MOUNT ────────────────────────────────────────────────────────────────────
ReactDOM.createRoot(document.getElementById("root")).render(React.createElement(App));
