"use client";

import { resumoDaMedida } from "@/lib/orders/quantidade-do-item";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import { getSupabaseClient } from "@/lib/supabase";
import { getCompanyContext } from "@/lib/company-context";
import { useConferenciaDoEstoque, useEstoqueV2Ligado } from "@/lib/use-estoque-da-venda";
import { ArrowDown, ArrowLeft, ArrowUp, ChevronDown, Copy, Lock, Plus, Save, Send, Trash2, Unlock, X } from "lucide-react";
import { CamposDoFormulario, type ValoresEmEdicao } from "@/components/campos-proprios/campos-do-formulario";
import { useCamposProprios } from "@/components/campos-proprios/use-campos-proprios";
import { conferirValores } from "@/lib/campos-proprios";
import { InfoTooltip } from "@/components/ui/info-tooltip";
import { CustomSelect } from "@/components/ui/custom-select";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Switch } from "@/components/ui/switch";
import { formatMoneyInput, parseMoneyInput, formatMeasureInput, parseMeasureInput, formatPercentInput, parsePercentInput } from "@/utils/formatters";
import { ShippingCalculator, ShippingOption } from "@/components/shipping-calculator";
import { calculateEffectiveQuantity, checkSaleQuantityLimits, type ProductPriceTier } from "@/lib/price-tiers";
import { precoDaLinha, somarAdicionais, SEM_ADICIONAIS, valorMinimoDoItem, COLUNAS_DO_VALOR_MINIMO, type OpcaoComPreco, type ResultadoDaLinha } from "@/lib/adicionais";
import { AvisoDoMinimo } from "@/components/quotes/aviso-do-minimo";
import { ClientFormModal } from "@/components/clients/client-form-modal";
import CargaDoDia from "@/components/agenda/carga-do-dia";
import {
  BlocoListaDePreco,
  BotaoAdicionarItem,
  CARTAO_EM_ETAPAS,
  CORPO_DO_ITEM_EM_ETAPAS,
  CabecalhoDoCartao,
  CabecalhoDoItem,
  Chip,
  ContaDoItem,
  EtapaFinanceiro,
  Etapas,
  NavegacaoDasEtapas,
  OPCOES_DE_STATUS,
  RodapeDoItem,
  SeletorDeModelo,
  classesDoItemEmEtapas,
  descreverQuantidade,
  etapaDoErro,
  nomeDaUnidade,
  useItemAberto,
  useModeloDeOrcamento,
} from "@/components/quotes/orcamento-em-etapas";
import { ChaveDasCondicoes, InterruptorDasCondicoes, CondicoesComerciaisEditor } from "@/components/quotes/condicoes-comerciais";
import {
  erroDasCondicoes,
  padraoDasCondicoes,
  resumirCondicoes,
  type CondicoesComerciais,
} from "@/lib/condicoes-comerciais";
import { condicoesDoPadrao, lerModelos, type ModeloDeCondicoes } from "@/lib/modelos-de-condicoes";

type QuoteStatus = "draft" | "sent" | "approved" | "rejected" | "production" | "delivered";

interface ClientOption {
  id: string;
  user_id: string;
  name: string;
  company_name: string | null;
  whatsapp: string | null;
  address_zip: string | null;
  is_deleted?: boolean | null;
}

interface ProductOption {
  id: string;
  name: string;
  price: number;
  cost_total: number;
  stock?: number | null;
  unit_type: string | null;
  image_url: string | null;
  price_on_request?: boolean | null;
  use_variation_price_only?: boolean | null;
  product_price_tiers?: ProductPriceTier[] | null;
  min_sale_qty_enabled?: boolean | null;
  min_sale_qty?: number | null;
  max_sale_qty_enabled?: boolean | null;
  max_sale_qty?: number | null;
  allowed_sale_qty_enabled?: boolean | null;
  allowed_sale_quantities?: number[] | null;
  inventory_scope?: "product" | "option" | "variant" | null;
  inventory_attribute_name?: string | null;
  allow_negative_stock?: boolean | null;
  track_inventory?: boolean | null;
  product_attributes?: ProductAttributeValue[] | null;
  product_variations?: ProductVariationValue[] | null;
  valor_minimo_item?: number | null;
  valor_minimo_orcamentos?: boolean | null;
  valor_minimo_loja?: boolean | null;
  valor_minimo_pdv?: boolean | null;
}

interface ProductAttributeOptionValue {
  id?: string | null;
  label: string;
  price?: number;
  price_applies_per_quantity?: boolean | null;
  price_unit?: string | null;
  stock?: number;
  is_required?: boolean;
  position?: number;
}

interface ProductAttributeValue {
  id?: string | null;
  name: string;
  allow_multiple?: boolean | null;
  is_required?: boolean | null;
  position?: number | null;
  options: Array<string | ProductAttributeOptionValue>;
}

interface ProductVariationValue {
  id?: string | null;
  combination?: Record<string, string> | null;
  stock?: number | null;
}

interface SellerOption {
  user_id: string;
  email: string;
  role: string;
}

interface SellerAllocationDraft {
  id: string;
  seller_user_id: string;
  allocation_percent: string;
}

interface QuoteItemDraft {
  id: string;
  product_id: string;
  title: string;
  description: string;
  unit_type: string;
  width_m: string;
  height_m: string;
  length_m: string;
  quantity: number;
  unit_price: string;
  unit_cost: string;
  unit_price_locked: boolean;
  selected_options?: Record<string, unknown> | null;
  /** O valor mínimo do item pegou nesta linha: a linha vale `minimo`. */
  minimo?: { minimo: number; semMinimo: number; precoPorMedida: number } | null;
}

/** O que a linha vale: o mínimo do item quando pegou; senão quantidade × preço. */
function totalDaLinhaDoRascunho(it: QuoteItemDraft, quantidadeEfetiva: number): number {
  if (it.minimo && !it.unit_price_locked) return it.minimo.minimo;
  return quantidadeEfetiva * parseMoneyInput(it.unit_price);
}

function minimoDoResultado(linha: ResultadoDaLinha): QuoteItemDraft["minimo"] {
  if (linha.minimoAplicado == null) return null;
  return { minimo: linha.minimoAplicado, semMinimo: linha.totalSemMinimo, precoPorMedida: linha.precoPorMedida };
}

interface ArtFileDraft {
  file: File;
  previewUrl: string;
}

interface QuoteItemArtDraft {
  quote_item_id: string;
  title: string;
  notes: string;
  files: ArtFileDraft[];
}

function normalizeDigits(value: string) {
  return value.replace(/\D/g, "");
}

function formatMoney(value: number) {
  return new Intl.NumberFormat("pt-BR", { style: "currency", currency: "BRL" }).format(value || 0);
}

function unitLabel(unitType: string) {
  switch (unitType) {
    case "meter":
      return "Metro";
    case "linear_meter":
      return "Metro Linear";
    case "square_meter":
      return "Metro Quadrado";
    case "box":
      return "Caixa";
    case "ream":
      return "Resma";
    default:
      return "Unidade";
  }
}

function normalizeAttributeOption(option: string | ProductAttributeOptionValue, index: number) {
  if (typeof option === "string") {
    return {
      id: null,
      label: option,
      price: 0,
      price_applies_per_quantity: true,
      price_unit: null,
      stock: null,
      is_required: false,
      position: index,
    };
  }
  return {
    id: option.id ?? null,
    label: option.label,
    price: Number(option.price) || 0,
    price_applies_per_quantity: option.price_applies_per_quantity !== false,
    price_unit: typeof option.price_unit === "string" ? option.price_unit : null,
    stock: Number.isFinite(Number(option.stock)) ? Number(option.stock) : null,
    is_required: Boolean(option.is_required),
    position: typeof option.position === "number" ? option.position : index,
  };
}

function getSortedAttributes(product: ProductOption | null) {
  return (product?.product_attributes || [])
    .filter((attribute) => Boolean(attribute?.name))
    .slice()
    .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
}

function getItemVariationMap(item: QuoteItemDraft) {
  const selectedOptions = item.selected_options as { options?: unknown } | null | undefined;
  const options = Array.isArray(selectedOptions?.options) ? selectedOptions.options : [];
  const map: Record<string, string[]> = {};
  for (const raw of options) {
    if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
    const row = raw as Record<string, unknown>;
    const attributeName = typeof row.attribute_name === "string" ? row.attribute_name : "";
    const label = typeof row.label === "string" ? row.label : "";
    if (!attributeName || !label) continue;
    const list = map[attributeName] || [];
    if (!list.includes(label)) list.push(label);
    map[attributeName] = list;
  }
  return map;
}

function findMatchedVariation(product: ProductOption, selectedMap: Record<string, string[]>) {
  const selectedFlat: Record<string, string> = {};
  for (const [attribute, labels] of Object.entries(selectedMap)) {
    const label = labels[0];
    if (!label) continue;
    selectedFlat[attribute.trim().toLowerCase()] = label.trim().toLowerCase();
  }
  const selectedKeys = Object.keys(selectedFlat).sort();
  if (!selectedKeys.length) return null;

  const variations = (product.product_variations || []).filter((variation) => variation && variation.combination);
  for (const variation of variations) {
    const combinationRaw = variation.combination || {};
    const combination: Record<string, string> = {};
    for (const [attribute, label] of Object.entries(combinationRaw)) {
      combination[attribute.trim().toLowerCase()] = (label || "").trim().toLowerCase();
    }
    const combinationKeys = Object.keys(combination).sort();
    if (combinationKeys.length !== selectedKeys.length) continue;
    const same = selectedKeys.every((key) => combination[key] === selectedFlat[key]);
    if (!same) continue;
    return variation;
  }
  return null;
}

function buildSelectedOptionsPayload(
  product: ProductOption,
  selectionMap: Record<string, string[]>
) {
  const attributes = getSortedAttributes(product);
  const inventoryScope = product.inventory_scope || "product";
  const inventoryAttributeName = (product.inventory_attribute_name || "").trim().toLowerCase();
  const payloadOptions: Array<{
    option_id: string | null;
    attribute_name: string;
    label: string;
    price: number;
    price_applies_per_quantity: boolean;
    price_unit?: string | null;
    affects_stock: boolean;
  }> = [];

  for (const attribute of attributes) {
    const normalizedOptions = (attribute.options || [])
      .map((option, index) => normalizeAttributeOption(option, index))
      .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
    const selectedLabels = selectionMap[attribute.name] || [];
    for (const selectedLabel of selectedLabels) {
      const selectedOption = normalizedOptions.find((option) => option.label === selectedLabel);
      if (!selectedOption) continue;
      payloadOptions.push({
        option_id: selectedOption.id || null,
        attribute_name: attribute.name,
        label: selectedOption.label,
        price: Number(selectedOption.price) || 0,
        price_applies_per_quantity: selectedOption.price_applies_per_quantity !== false,
        price_unit: selectedOption.price_unit ?? null,
        affects_stock:
          inventoryScope === "option" &&
          attribute.name.trim().toLowerCase() === inventoryAttributeName,
      });
    }
  }

  if (!payloadOptions.length) return null;

  return {
    inventory_scope: inventoryScope,
    inventory_attribute_name: inventoryScope === "option" ? product.inventory_attribute_name || null : null,
    options: payloadOptions,
  };
}

function getSelectedOptionsSummary(item: QuoteItemDraft) {
  const map = getItemVariationMap(item);
  const parts = Object.entries(map)
    .filter(([, labels]) => labels.length > 0)
    .map(([attribute, labels]) => `${attribute}: ${labels.join(", ")}`);
  return parts.join(" / ");
}

function getSelectedOptionsPriceBreakdown(item: QuoteItemDraft, product?: ProductOption | null) {
  if (!product) return SEM_ADICIONAIS;
  const selectedMap = getItemVariationMap(item);
  const attributes = getSortedAttributes(product);
  const escolhidas: OpcaoComPreco[] = [];
  for (const attribute of attributes) {
    const selectedLabels = selectedMap[attribute.name] || [];
    if (!selectedLabels.length) continue;
    const normalizedOptions = (attribute.options || [])
      .map((option, index) => normalizeAttributeOption(option, index))
      .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
    for (const selectedLabel of selectedLabels) {
      const selectedOption = normalizedOptions.find((option) => option.label === selectedLabel);
      if (!selectedOption) continue;
      escolhidas.push(selectedOption);
    }
  }
  return somarAdicionais(escolhidas, product.unit_type);
}

function getItemVariationStockMessage(item: QuoteItemDraft, product?: ProductOption | null) {
  if (!product) return null;
  if (product.track_inventory === false) return null;
  const inventoryScope = product.inventory_scope || "product";
  if (inventoryScope === "product") {
    const available = Number(product.stock) || 0;
    const required = effectiveQuantity(item);
    if (available <= 0) {
      return "Sem estoque para o produto selecionado.";
    }
    if (required > available + 0.000001) {
      return `Estoque insuficiente para o produto selecionado. Disponível: ${formatQuantityLimit(available)}.`;
    }
    return null;
  }
  if (inventoryScope === "variant") {
    const selectedMap = getItemVariationMap(item);
    const hasMulti = Object.values(selectedMap).some((labels) => labels.length > 1);
    if (hasMulti) {
      return "Estoque por combinação exige apenas uma opção por atributo.";
    }
    const expectedAttributes = getSortedAttributes(product).filter((attribute) => (attribute.options || []).length > 0);
    const missingAttributes = expectedAttributes.filter((attribute) => !(selectedMap[attribute.name] || [])[0]);
    if (missingAttributes.length > 0) {
      return `Selecione uma combinação completa (${missingAttributes.map((attribute) => attribute.name).join(", ")}).`;
    }
    const variation = findMatchedVariation(product, selectedMap);
    if (!variation) {
      return "A combinação selecionada não existe no cadastro de variações.";
    }
    const available = Number(variation.stock) || 0;
    const required = effectiveQuantity(item);
    if (available <= 0) {
      return "Sem estoque para a combinação selecionada.";
    }
    if (required > available + 0.000001) {
      return `Estoque insuficiente para a combinação selecionada. Disponível: ${formatQuantityLimit(available)}.`;
    }
    return null;
  }
  const inventoryAttributeName = (product.inventory_attribute_name || "").trim();
  if (!inventoryAttributeName) {
    return "Produto configurado com estoque por opção sem atributo de estoque definido.";
  }
  const attributes = getSortedAttributes(product);
  const stockAttribute =
    attributes.find((attribute) => attribute.name.trim().toLowerCase() === inventoryAttributeName.toLowerCase()) || null;
  if (!stockAttribute) {
    return `Atributo de estoque (${inventoryAttributeName}) não encontrado no produto.`;
  }
  const selectedMap = getItemVariationMap(item);
  const selectedEntry =
    Object.entries(selectedMap).find(([name]) => name.trim().toLowerCase() === stockAttribute.name.trim().toLowerCase()) ||
    null;
  const selectedLabels = selectedEntry?.[1] || [];
  if (selectedLabels.length === 0) {
    return `Selecione uma opção de ${stockAttribute.name} para controlar o estoque deste item.`;
  }

  const normalizedOptions = (stockAttribute.options || [])
    .map((option, index) => normalizeAttributeOption(option, index))
    .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
  const selectedOptions = selectedLabels
    .map((label) => normalizedOptions.find((option) => option.label === label) || null)
    .filter((option): option is NonNullable<(typeof normalizedOptions)[number]> => option !== null);
  if (!selectedOptions.length) {
    return `As opções selecionadas de ${stockAttribute.name} não existem mais no cadastro do produto.`;
  }

  const trackedStocks = selectedOptions
    .map((option) => (typeof option.stock === "number" ? option.stock : null))
    .filter((value): value is number => value !== null);
  if (!trackedStocks.length) return null;

  const available = Math.min(...trackedStocks);
  const required = effectiveQuantity(item);
  if (available <= 0) {
    return `Sem estoque para ${stockAttribute.name}: ${selectedLabels.join(", ")}.`;
  }
  if (required > available + 0.000001) {
    return `Estoque insuficiente para ${stockAttribute.name}: ${selectedLabels.join(", ")}. Disponível: ${formatQuantityLimit(available)}.`;
  }
  return null;
}

function effectiveQuantity(item: { quantity: number; unit_type: string; width_m: string | number; height_m: string | number; length_m: string | number }) {
  const w = typeof item.width_m === "string" ? parseMeasureInput(item.width_m) : item.width_m || 0;
  const h = typeof item.height_m === "string" ? parseMeasureInput(item.height_m) : item.height_m || 0;
  const l = typeof item.length_m === "string" ? parseMeasureInput(item.length_m) : item.length_m || 0;
  return calculateEffectiveQuantity({
    quantity: item.quantity || 0,
    unit_type: item.unit_type,
    width_m: w,
    height_m: h,
    length_m: l,
  });
}


function formatQuantityLimit(value: number | null) {
  if (value === null || !Number.isFinite(value)) return "0";
  const rounded = Number(value.toFixed(3));
  return Number.isInteger(rounded)
    ? String(rounded)
    : new Intl.NumberFormat("pt-BR", { minimumFractionDigits: 0, maximumFractionDigits: 3 }).format(rounded);
}

function getMinimumItemQuantity(product?: ProductOption | null) {
  if (!product) return 1;
  const allowedQuantities = getAllowedItemQuantities(product);
  if (Boolean(product.allowed_sale_qty_enabled) && allowedQuantities.length > 0) {
    return Number(allowedQuantities[0].toFixed(3));
  }
  if (Boolean(product.min_sale_qty_enabled)) {
    const minQty = Number(product.min_sale_qty);
    if (Number.isFinite(minQty) && minQty > 0) return Number(minQty.toFixed(3));
  }
  return 1;
}

function getAllowedItemQuantities(product?: ProductOption | null) {
  if (!product) return [] as number[];
  return Array.isArray(product.allowed_sale_quantities)
    ? product.allowed_sale_quantities
        .map((value) => Number(value))
        .filter((value) => Number.isFinite(value) && value > 0)
        .sort((a, b) => a - b)
    : [];
}

function generateDraftId() {
  if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
    return crypto.randomUUID();
  }
  return `draft-${Math.random().toString(16).slice(2)}-${Date.now()}`;
}

function loadImageFromFile(file: File) {
  return new Promise<HTMLImageElement>((resolve, reject) => {
    const url = URL.createObjectURL(file);
    const img = new window.Image();
    img.onload = () => {
      URL.revokeObjectURL(url);
      resolve(img);
    };
    img.onerror = () => {
      URL.revokeObjectURL(url);
      reject(new Error("Falha ao carregar imagem"));
    };
    img.src = url;
  });
}

async function compressToWebp(file: File, maxSize = 2000, quality = 0.82) {
  const img = await loadImageFromFile(file);
  const scale = Math.min(1, maxSize / Math.max(img.width, img.height));
  const width = Math.max(1, Math.round(img.width * scale));
  const height = Math.max(1, Math.round(img.height * scale));
  const canvas = document.createElement("canvas");
  canvas.width = width;
  canvas.height = height;
  const ctx = canvas.getContext("2d");
  if (!ctx) throw new Error("Canvas indisponível");
  ctx.drawImage(img, 0, 0, width, height);
  const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, "image/webp", quality));
  if (!blob) throw new Error("Falha ao converter imagem");
  return new File([blob], file.name.replace(/\.[^.]+$/, ".webp"), { type: "image/webp" });
}

export default function NewQuotePage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const initialItemIdRef = useRef(generateDraftId());
  const pendingItemFocusRef = useRef<string | null>(null);

  // Make the page full-width while on this route
  useEffect(() => {
    const ksPage = document.querySelector('.ks-page') as HTMLElement | null;
    if (ksPage) {
      ksPage.style.maxWidth = 'none';
    }
    return () => {
      if (ksPage) {
        ksPage.style.maxWidth = '';
      }
    };
  }, []);
  const [clients, setClients] = useState<ClientOption[]>([]);
  const [products, setProducts] = useState<ProductOption[]>([]);
  /* O dono da empresa: o estoque é conferido no banco pela empresa. */
  const [donoDaEmpresa, setDonoDaEmpresa] = useState<string | null>(null);
  const [sellers, setSellers] = useState<SellerOption[]>([]);
  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  const [createdQuoteId, setCreatedQuoteId] = useState<string | null>(null);
  const [quoteArtEnabled, setQuoteArtEnabled] = useState(false);
  const [clientModalOpen, setClientModalOpen] = useState(false);

  const [form, setForm] = useState({
    client_id: "",
    title: "",
    status: "draft" as QuoteStatus,
    expires_at: "",
    delivery_date: "",
    notes: "",
    internal_notes: "",
    discount: "0,00",
    shipping: "0,00",
    list_price_mode: false,
  });
  const [sellerMode, setSellerMode] = useState<"single" | "split">("single");
  const [primarySellerUserId, setPrimarySellerUserId] = useState("");
  const [sellerAllocations, setSellerAllocations] = useState<SellerAllocationDraft[]>([
    { id: generateDraftId(), seller_user_id: "", allocation_percent: "100,00" },
  ]);
  const [discountType, setDiscountType] = useState<"value" | "percent">("value");
  /* As condições comerciais: começam no padrão da empresa (ou à vista no
     Pix) e podem ser tiradas da proposta (null). */
  /* Nasce sem condições: quem decide se a proposta leva forma e prazo é a
     pessoa (a chave da aba Financeiro). Só o modelo padrão da empresa, que é
     uma escolha dela, liga a chave sozinho quando carrega. */
  const [condicoes, setCondicoes] = useState<CondicoesComerciais | null>(null);
  /* Campos próprios do orçamento (migration 187). */
  const { definicoes: camposDoOrcamento, ativas: camposAtivosDoOrcamento } = useCamposProprios("orcamento");
  const [camposValores, setCamposValores] = useState<ValoresEmEdicao>({});
  const [camposErros, setCamposErros] = useState<Record<string, string>>({});
  /* O que estava preenchido quando a chave foi desligada: ligar de novo devolve. */
  const condicoesGuardadas = useRef<CondicoesComerciais | null>(null);
  const alternarCondicoes = (ligar: boolean) => {
    if (ligar) {
      setCondicoes(condicoesGuardadas.current ?? condicoesDoPadrao(modelosDaEmpresa) ?? padraoDasCondicoes());
    } else {
      condicoesGuardadas.current = condicoes;
      setCondicoes(null);
    }
  };
  /* Os modelos da empresa; o marcado como padrão é com o que este orçamento
     começa (lib/modelos-de-condicoes.ts). */
  const [modelosDaEmpresa, setModelosDaEmpresa] = useState<ModeloDeCondicoes[]>([]);
  const [ehDonoDaEmpresa, setEhDonoDaEmpresa] = useState(false);

  const [items, setItems] = useState<QuoteItemDraft[]>([
    {
      id: initialItemIdRef.current,
      product_id: "",
      title: "",
      description: "",
      unit_type: "unit",
      width_m: "0,00",
      height_m: "0,00",
      length_m: "0,00",
      quantity: 1,
      unit_price: "0,00",
      unit_cost: "0,00",
      unit_price_locked: false,
    },
  ]);

  /*
    Estoque v2: o orçamento conferido no banco a cada mudança
    (estoque_conferir_itens). Avisa por linha o que falta ("Acabou o estoque
    de "Camiseta lisa (G / Preta)" para "Camisetas": tem 0, o pedido precisa
    de 3."); não trava salvar. Fora do v2 o aviso segue o de sempre.
  */
  const supabaseDoOrcamento = useMemo(() => getSupabaseClient(), []);
  const estoqueV2 = useEstoqueV2Ligado(supabaseDoOrcamento, donoDaEmpresa);
  const linhasParaOEstoque = useMemo(
    () =>
      items.map((it) => ({
        product_id: it.product_id || null,
        quantity: it.quantity,
        selected_options: it.selected_options ?? null,
        width_m: it.width_m || null,
        height_m: it.height_m || null,
        title: it.title,
      })),
    [items]
  );
  const { faltas: faltasDoEstoqueV2 } = useConferenciaDoEstoque({
    supabase: supabaseDoOrcamento,
    dono: donoDaEmpresa,
    linhas: linhasParaOEstoque,
    ativo: estoqueV2 === true,
  });
  const [activeItemId, setActiveItemId] = useState<string | null>(null);
  const [quantityDrafts, setQuantityDrafts] = useState<Record<string, string>>({});
  const [manualProductSubmittingItemId, setManualProductSubmittingItemId] = useState<string | null>(null);
  const [manualProductErrors, setManualProductErrors] = useState<Record<string, string>>({});
  const [itemArts, setItemArts] = useState<Record<string, QuoteItemArtDraft>>({});
  const [itemArtPdfVisibility, setItemArtPdfVisibility] = useState<Record<string, boolean>>({});
  const [artModalOpen, setArtModalOpen] = useState(false);
  const [activeArtItemId, setActiveArtItemId] = useState<string | null>(null);
  const [artDraft, setArtDraft] = useState<QuoteItemArtDraft | null>(null);
  const [artUploading, setArtUploading] = useState(false);
  const [artError, setArtError] = useState("");
  const [previewOpen, setPreviewOpen] = useState(false);
  const [previewImageUrl, setPreviewImageUrl] = useState<string | null>(null);
  const [shippingDetails, setShippingDetails] = useState<ShippingOption | null>(null);
  const preselectedClientId = useMemo(
    () => searchParams.get("client_id") || searchParams.get("clientId") || "",
    [searchParams]
  );
  const clientOptions = useMemo(
    () => [
      { value: "", label: "Selecione..." },
      ...clients.map((c) => ({
        value: c.id,
        label: c.company_name ? `${c.company_name} - ${c.name}` : c.name,
      })),
    ],
    [clients]
  );

  const refreshClients = useCallback(async (preferredClientId?: string) => {
    try {
      const supabase = getSupabaseClient();
      const {
        data: { user },
      } = await supabase.auth.getUser();
      if (!user) return;
      const ctx = await getCompanyContext(supabase, user);
      const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];
      const { data: clientsData } = await supabase
        .from("clients")
        .select("id,user_id,name,company_name,whatsapp,address_zip,is_deleted")
        .in("user_id", tenantIds)
        .or("active.is.null,active.eq.true")
        .not("is_deleted", "is", true)
        .order("company_name", { ascending: true })
        .order("name", { ascending: true });
      const availableClients = ((clientsData as ClientOption[]) || []).filter((client) => !client.is_deleted);
      setClients(availableClients);
      if (preferredClientId && availableClients.some((client) => client.id === preferredClientId)) {
        setForm((prev) => ({ ...prev, client_id: preferredClientId }));
      }
    } catch (err) {
      console.error("Erro ao recarregar clientes:", err);
    }
  }, []);

  useEffect(() => {
    let cancelled = false;
    async function run() {
      try {
        const supabase = getSupabaseClient();
        const {
          data: { user },
        } = await supabase.auth.getUser();
        if (!user) return;
        const ctx = await getCompanyContext(supabase, user);
        const tenantIds = ctx.tenantIds?.length ? ctx.tenantIds : [user.id];

        const sellerOptionsRequest = fetch("/api/company/users?mode=sales-options", {
          method: "GET",
          cache: "no-store",
        }).then(async (response) => {
          const json = (await response.json().catch(() => null)) as
            | { users?: SellerOption[]; currentUserId?: string; error?: string }
            | null;
          if (!response.ok) {
            throw new Error(json?.error || "Falha ao carregar vendedores.");
          }
          return json;
        });

        const [
          { data: clientsData },
          { data: productsData, error: productsError },
          { data: profileData, error: profileError },
          sellersResult,
        ] =
          await Promise.all([
          supabase
            .from("clients")
            .select("id,user_id,name,company_name,whatsapp,address_zip,is_deleted")
            .in("user_id", tenantIds)
            .or("active.is.null,active.eq.true")
            .not("is_deleted", "is", true)
            .order("company_name", { ascending: true })
            .order("name", { ascending: true }),
          supabase
            .from("products")
            .select(`id,name,price,cost_total,unit_type,image_url,price_on_request,use_variation_price_only,min_sale_qty_enabled,min_sale_qty,max_sale_qty_enabled,max_sale_qty,allowed_sale_qty_enabled,allowed_sale_quantities,inventory_scope,inventory_attribute_name,allow_negative_stock,track_inventory,stock,product_attributes(name,allow_multiple,is_required,position,options),product_variations(combination,stock),product_price_tiers(min_qty,max_qty,unit_price,sort_order,active),${COLUNAS_DO_VALOR_MINIMO}`)
            .in("user_id", tenantIds)
            .neq("product_kind", "digital")
            .eq("active", true)
            .order("name", { ascending: true }),
          supabase
            .from("profiles")
            .select("quote_art_registration_enabled,quote_default_payment_terms,quote_payment_terms_templates")
            .eq("id", ctx.ownerId || user.id)
            .maybeSingle(),
          sellerOptionsRequest,
        ]);

        if (cancelled) return;
        setEhDonoDaEmpresa(!ctx.ownerId || ctx.ownerId === user.id);
        setDonoDaEmpresa(ctx.ownerId || user.id);
        let resolvedProductsData = (productsData as ProductOption[] | null) ?? null;
        if (productsError) {
          const message = String((productsError as { message?: unknown } | null)?.message ?? "").toLowerCase();
          if (message.includes("product_price_tiers") || message.includes("product_attributes")) {
            const fallback = await supabase
              .from("products")
              .select("id,name,price,cost_total,unit_type,image_url,price_on_request,use_variation_price_only,min_sale_qty_enabled,min_sale_qty,max_sale_qty_enabled,max_sale_qty,allowed_sale_qty_enabled,allowed_sale_quantities,inventory_scope,inventory_attribute_name,allow_negative_stock,track_inventory,stock,product_attributes(name,allow_multiple,is_required,position,options),product_variations(combination,stock)")
              .in("user_id", tenantIds)
              .neq("product_kind", "digital")
              .eq("active", true)
              .order("name", { ascending: true });
            if (fallback.error) throw fallback.error;
            resolvedProductsData = (fallback.data as ProductOption[] | null) ?? null;
          } else {
            throw productsError;
          }
        }
        const availableClients = ((clientsData as ClientOption[]) || []).filter((client) => !client.is_deleted);
        setClients(availableClients);
        setProducts(resolvedProductsData || []);
        setSellers(sellersResult?.users || []);
        setPrimarySellerUserId((prev) => prev || sellersResult?.currentUserId || "");
        setSellerAllocations((prev) =>
          prev.map((allocation, index) =>
            index === 0 && !allocation.seller_user_id
              ? { ...allocation, seller_user_id: sellersResult?.currentUserId || "" }
              : allocation
          )
        );
        if (!profileError || profileError.code === "PGRST116") {
          setQuoteArtEnabled(Boolean(profileData?.quote_art_registration_enabled));
          const perfilDoDono = profileData as { quote_default_payment_terms?: unknown; quote_payment_terms_templates?: unknown } | null;
          const modelos = lerModelos(perfilDoDono?.quote_payment_terms_templates, perfilDoDono?.quote_default_payment_terms);
          setModelosDaEmpresa(modelos);
          const padraoDaEmpresa = condicoesDoPadrao(modelos);
          if (padraoDaEmpresa) setCondicoes(padraoDaEmpresa);
        } else {
          const message = String((profileError as { message?: unknown } | null)?.message ?? "");
          if (!message.toLowerCase().includes("column")) throw profileError;
        }
      } catch (err) {
        console.error("Erro ao carregar clientes:", err);
      } finally {
        if (!cancelled) setLoading(false);
      }
    }
    run();
    return () => {
      cancelled = true;
    };
  }, []);

  useEffect(() => {
    if (!preselectedClientId || !clients.length) return;
    const existsInTenant = clients.some((client) => client.id === preselectedClientId);
    if (!existsInTenant) return;
    setForm((prev) => (prev.client_id === preselectedClientId ? prev : { ...prev, client_id: preselectedClientId }));
  }, [clients, preselectedClientId]);

  const productsById = useMemo(() => new Map(products.map((product) => [product.id, product])), [products]);
  const sellerSelectOptions = useMemo(
    () =>
      sellers.map((seller) => ({
        value: seller.user_id,
        label: `${seller.email} • ${seller.role}`,
      })),
    [sellers]
  );

  useEffect(() => {
    if (activeItemId && !items.some((item) => item.id === activeItemId)) {
      setActiveItemId(null);
    }
  }, [activeItemId, items]);

  useEffect(() => {
    const targetId = pendingItemFocusRef.current;
    if (!targetId || typeof window === "undefined") return;

    const timer = window.setTimeout(() => {
      const card = document.getElementById(`quote-item-${targetId}`);
      if (!card) return;

      const primaryField = card.querySelector(
        '[data-item-primary-field="true"] input, [data-item-primary-field="true"] button, [data-item-primary-field="true"] [role="combobox"]'
      ) as HTMLElement | null;
      const fallbackField = card.querySelector(
        'input:not([disabled]), textarea:not([disabled]), button:not([disabled]), [role="combobox"]'
      ) as HTMLElement | null;
      const focusTarget = primaryField || fallbackField;

      pendingItemFocusRef.current = null;
      setActiveItemId(targetId);
      if (focusTarget) {
        focusTarget.focus();
        return;
      }
      if (card instanceof HTMLElement) {
        card.focus();
      }
    }, 120);

    return () => window.clearTimeout(timer);
  }, [items]);

  function formatUnitPriceValue(value: number) {
    return new Intl.NumberFormat("pt-BR", { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(value || 0);
  }

  function resolveProductUnitPrice(item: QuoteItemDraft, product: ProductOption) {
    return resolveProductLine(item, product).precoPorMedida;
  }

  function resolveProductLine(item: QuoteItemDraft, product: ProductOption): ResultadoDaLinha {
    /* A mesma conta da loja: faixa pela área total, adicional por m² × área,
       por peça × peças, uma vez no pedido, e por último o valor mínimo do
       item. O preço unitário guardado é por medida, com peça e pedido rateados. */
    return precoDaLinha({
      precoBase: Number(product.price) || 0,
      faixas: product.product_price_tiers || [],
      pecas: Number(item.quantity) || 0,
      quantidadeEfetiva: effectiveQuantity(item),
      adicionais: getSelectedOptionsPriceBreakdown(item, product),
      soVariacao: Boolean(product.use_variation_price_only),
      sobConsulta: Boolean(product.price_on_request),
      valorMinimo: valorMinimoDoItem(product, "orcamentos"),
    });
  }

  function getItemQuantityRuleMessage(item: QuoteItemDraft, product?: ProductOption | null) {
    if (!product) return null;
    const quantityCheck = checkSaleQuantityLimits({
      min_sale_qty_enabled: product.min_sale_qty_enabled,
      min_sale_qty: product.min_sale_qty,
      max_sale_qty_enabled: product.max_sale_qty_enabled,
      max_sale_qty: product.max_sale_qty,
      allowed_sale_qty_enabled: product.allowed_sale_qty_enabled,
      allowed_sale_quantities: product.allowed_sale_quantities,
      effectiveQuantity: effectiveQuantity(item),
    });
    if (quantityCheck.isBelowMin && quantityCheck.minQty !== null) {
      return `Quantidade minima: ${formatQuantityLimit(quantityCheck.minQty)}.`;
    }
    if (quantityCheck.isAboveMax && quantityCheck.maxQty !== null) {
      return `Quantidade maxima: ${formatQuantityLimit(quantityCheck.maxQty)}.`;
    }
    if (quantityCheck.isNotAllowedValue && quantityCheck.allowedQuantities.length > 0) {
      const values = quantityCheck.allowedQuantities.map((value) => formatQuantityLimit(value)).join(", ");
      return `Use uma quantidade permitida: ${values}.`;
    }
    return null;
  }

  const totals = useMemo(() => {
    const normalizedItems = items.filter((i) => i.title.trim() || i.description.trim());
    const subtotal = normalizedItems.reduce((acc, it) => acc + totalDaLinhaDoRascunho(it, effectiveQuantity(it)), 0);
    const discountBase = Math.max(
      0,
      discountType === "percent" ? parsePercentInput(form.discount) : parseMoneyInput(form.discount)
    );
    const discount = discountType === "percent" ? (subtotal * discountBase) / 100 : discountBase;
    const shipping = parseMoneyInput(form.shipping);
    const total = Math.max(0, subtotal - discount + shipping);
    const cost = normalizedItems.reduce((acc, it) => acc + effectiveQuantity(it) * parseMoneyInput(it.unit_cost), 0);
    const margin = total - cost;
    const marginPct = total > 0 ? (margin / total) * 100 : 0;
    return { subtotal, discount, shipping, total, cost, margin, marginPct };
  }, [items, form.discount, form.shipping, discountType]);

  /* A contribuição do orçamento (MC) e o IRG — quantos % do custo fixo do
     mês esta venda paga. A MC é a do padrão do ramo: total menos
     MATÉRIA-PRIMA menos os variáveis da venda; a mão de obra fica dentro,
     porque é custo fixo sendo recuperado. O custo de cada item é dividido
     pela proporção da ficha do produto; item sem produto (ou sem ficha) é
     tratado como matéria-prima inteira — o lado conservador. */
  const [precificacao, setPrecificacao] = useState<{ variaveisPct: number; fixoMensal: number } | null>(null);
  const [fichasDosProdutos, setFichasDosProdutos] = useState<Record<string, { materiais: number; processos: number }>>({});
  const fichasPedidas = useRef<Set<string>>(new Set());

  useEffect(() => {
    fetch("/api/precificacao/preparo", { cache: "no-store" })
      .then((r) => r.json())
      .then((j) => setPrecificacao({
        variaveisPct: Number(j?.custosVariaveis?.totalPct ?? 0),
        fixoMensal: Number(j?.custosFixos?.total_mensal ?? 0),
      }))
      .catch(() => {});
  }, []);

  useEffect(() => {
    const faltando = [...new Set(items.map((i) => i.product_id).filter(Boolean))]
      .filter((id) => !fichasPedidas.current.has(id));
    if (faltando.length === 0) return;
    faltando.forEach((id) => fichasPedidas.current.add(id));
    fetch(`/api/precificacao/fichas?ids=${faltando.join(",")}`, { cache: "no-store" })
      .then((r) => r.json())
      .then((j) => {
        if (j?.fichas) setFichasDosProdutos((atual) => ({ ...atual, ...j.fichas }));
      })
      .catch(() => {});
  }, [items]);

  const contribuicao = useMemo(() => {
    if (!precificacao) return null;
    const itensValidos = items.filter((i) => i.title.trim() || i.description.trim());
    const materiaPrima = itensValidos.reduce((acc, it) => {
      const custoItem = effectiveQuantity(it) * parseMoneyInput(it.unit_cost);
      if (custoItem <= 0) return acc;
      const ficha = it.product_id ? fichasDosProdutos[it.product_id] : undefined;
      const somaFicha = (ficha?.materiais ?? 0) + (ficha?.processos ?? 0);
      const parteMateriais = somaFicha > 0 ? custoItem * ((ficha?.materiais ?? 0) / somaFicha) : custoItem;
      return acc + parteMateriais;
    }, 0);
    const variaveis = (totals.total * precificacao.variaveisPct) / 100;
    const mc = totals.total - materiaPrima - variaveis;
    const mcPct = totals.total > 0 ? (mc / totals.total) * 100 : 0;
    const irgPct = precificacao.fixoMensal > 0 ? (mc / precificacao.fixoMensal) * 100 : null;
    const maoDeObra = Math.max(0, totals.cost - materiaPrima);
    return {
      mc, mcPct, irgPct, materiaPrima, maoDeObra,
      fixoMensal: precificacao.fixoMensal, variaveisPct: precificacao.variaveisPct,
    };
  }, [items, totals.total, totals.cost, precificacao, fichasDosProdutos]);

  /* A página em etapas: o mesmo formulário e o mesmo salvar, mostrados em
     cinco passos quando a pessoa prefere assim. Os blocos abaixo só ganham
     `hidden={fora(n)}`; nada é desmontado. */
  const paginaEmEtapas = useModeloDeOrcamento();
  const { emEtapas, etapa, fora, irPara } = paginaEmEtapas;
  const { itemAberto, abrirItem, alternarItem } = useItemAberto();
  const [maisIndicadores, setMaisIndicadores] = useState(false);
  const etapasFeitas = useMemo(() => {
    const preenchidos = items.filter((i) => i.title.trim() || i.description.trim());
    return {
      1: Boolean(form.client_id),
      2: preenchidos.length > 0,
      3: condicoes ? erroDasCondicoes(condicoes, totals.total) === null : false,
      4: preenchidos.length > 0 && preenchidos.every((i) => parseMoneyInput(i.unit_cost) > 0),
      5: Boolean(form.delivery_date),
      6: form.internal_notes.trim().length > 0,
    };
  }, [items, form.client_id, form.delivery_date, form.internal_notes, condicoes, totals.total]);
  const ultimoErroLevadoAEtapa = useRef<string | null>(null);
  useEffect(() => {
    if (!error) {
      ultimoErroLevadoAEtapa.current = null;
      return;
    }
    if (!emEtapas || ultimoErroLevadoAEtapa.current === error) return;
    ultimoErroLevadoAEtapa.current = error;
    const destino = etapaDoErro(error);
    if (destino) irPara(destino);
    if (destino === 2) {
      /* A mensagem cita o item pelo nome; ele abre para a pessoa corrigir. */
      const alvo = items.find((i) => {
        const nome = i.title.trim() || productsById.get(i.product_id)?.name || "";
        return nome !== "" && error.includes(nome);
      });
      if (alvo) abrirItem(alvo.id);
    }
  }, [error, emEtapas, irPara, items, productsById, abrirItem]);

  const selectedClient = useMemo(() => clients.find((c) => c.id === form.client_id) || null, [clients, form.client_id]);
  const normalizedSellerAllocations = useMemo(
    () =>
      sellerAllocations
        .map((allocation, index) => ({
          ...allocation,
          allocationPercent: parsePercentInput(allocation.allocation_percent),
          is_primary: index === 0,
        }))
        .filter((allocation) => allocation.seller_user_id && allocation.allocationPercent > 0),
    [sellerAllocations]
  );

  const whatsappLink = useMemo(() => {
    const digits = normalizeDigits(selectedClient?.whatsapp || "");
    if (!digits) return "";
    const condicoesTexto = condicoes ? ` ${resumirCondicoes(condicoes, totals.total)}` : "";
    const message = `Olá! Segue orçamento em rascunho: Total ${formatMoney(totals.total)}.${condicoesTexto}`;
    return `https://wa.me/${digits}?text=${encodeURIComponent(message)}`;
  }, [selectedClient?.whatsapp, totals.total, condicoes]);

  function addSellerAllocation() {
    setSellerAllocations((prev) => [
      ...prev,
      { id: generateDraftId(), seller_user_id: "", allocation_percent: "0,00" },
    ]);
  }

  function updateSellerAllocation(id: string, patch: Partial<SellerAllocationDraft>) {
    setSellerAllocations((prev) => prev.map((allocation) => (allocation.id === id ? { ...allocation, ...patch } : allocation)));
  }

  function removeSellerAllocation(id: string) {
    setSellerAllocations((prev) => (prev.length > 2 ? prev.filter((allocation) => allocation.id !== id) : prev));
  }

  async function handleSave(e: React.FormEvent) {
    e.preventDefault();
    setSaving(true);
    setError("");
    try {
      if (!form.client_id) {
        setError("Selecione um cliente.");
        return;
      }

      if (sellerMode === "single" && !primarySellerUserId) {
        setError("Selecione o vendedor principal do orçamento.");
        return;
      }

      if (sellerMode === "split") {
        if (normalizedSellerAllocations.length < 2) {
          setError("Informe ao menos dois vendedores para o rateio.");
          return;
        }
        const allocationTotal = normalizedSellerAllocations.reduce(
          (sum, allocation) => sum + allocation.allocationPercent,
          0
        );
        if (Math.abs(allocationTotal - 100) > 0.01) {
          setError("O rateio do orçamento deve totalizar exatamente 100%.");
          return;
        }
        const uniqueSellerCount = new Set(normalizedSellerAllocations.map((allocation) => allocation.seller_user_id)).size;
        if (uniqueSellerCount !== normalizedSellerAllocations.length) {
          setError("O mesmo vendedor não pode aparecer mais de uma vez no rateio.");
          return;
        }
      }

      if (condicoes) {
        const erroDasCondicoesComerciais = erroDasCondicoes(condicoes, totals.total);
        if (erroDasCondicoesComerciais) {
          setError(erroDasCondicoesComerciais);
          return;
        }
      }

      for (const item of items) {
        if (!item.product_id) continue;
        const product = productsById.get(item.product_id);
        if (product) {
          const attributes = getSortedAttributes(product);
          if (attributes.length > 0) {
            const selectedMap = getItemVariationMap(item);
            for (const attribute of attributes) {
              if (!attribute.is_required) continue;
              const selectedValues = selectedMap[attribute.name] || [];
              if (!selectedValues.length) {
                setError(`Selecione uma opção obrigatória em ${attribute.name} para o item ${item.title || product.name}.`);
                return;
              }
            }
          }
        }
        const quantityRuleMessage = getItemQuantityRuleMessage(item, product);
        if (quantityRuleMessage) {
          const itemLabel = item.title.trim() || product?.name || "Item";
          setError(`${itemLabel}: ${quantityRuleMessage}`);
          return;
        }
      }

      const meaningfulItems = items
        .map((it) => {
          const w = parseMeasureInput(it.width_m);
          const h = parseMeasureInput(it.height_m);
          const l = parseMeasureInput(it.length_m);
          return {
            id: it.id,
            product_id: it.product_id || null,
            unit_type: it.unit_type || "unit",
            width_m: w > 0 ? w : null,
            height_m: h > 0 ? h : null,
            length_m: l > 0 ? l : null,
            title: it.title.trim(),
            description: it.description.trim() || null,
            quantity: Math.max(1, it.quantity || 1),
            // Com o mínimo, o preço por medida vai inteiro (70 / 0,24 m²) e a
            // linha é gravada no valor exato do mínimo.
            unit_price: it.minimo && !it.unit_price_locked
              ? Math.round(it.minimo.precoPorMedida * 1e6) / 1e6
              : Math.max(0, parseMoneyInput(it.unit_price)),
            unit_cost: Math.max(0, parseMoneyInput(it.unit_cost)),
            selected_options: it.selected_options && typeof it.selected_options === "object" ? it.selected_options : null,
            valor_minimo_aplicado: it.minimo && !it.unit_price_locked ? it.minimo.minimo : null,
            valor_sem_minimo: it.minimo && !it.unit_price_locked ? Math.round(it.minimo.semMinimo * 100) / 100 : null,
          };
        })
        .filter((it) => it.title || it.description);

      if (meaningfulItems.length === 0) {
        setError("Adicione ao menos 1 item no orçamento.");
        return;
      }

      let camposProprios: Record<string, unknown> | null = null;
      if (camposAtivosDoOrcamento.length > 0) {
        const novos: Record<string, unknown> = {};
        for (const def of camposAtivosDoOrcamento) novos[def.chave] = camposValores[def.chave] ?? null;
        const conferido = conferirValores(camposDoOrcamento, novos, { exigirObrigatorios: true });
        if (!conferido.ok) {
          setCamposErros(conferido.erros);
          setError(`Confira as informações extras: ${Object.values(conferido.erros)[0]}`);
          return;
        }
        if (Object.keys(conferido.valores).length > 0) camposProprios = conferido.valores;
      }
      let createdId = createdQuoteId;
      if (!createdId) {
        const res = await fetch("/api/quotes", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({
            client_id: form.client_id,
            status: form.status,
            title: form.title.trim() || null,
            expires_at: form.expires_at || null,
            delivery_date: form.delivery_date || null,
            notes: form.notes.trim() || null,
            internal_notes: form.internal_notes.trim() || null,
            discount: totals.discount,
            shipping: totals.shipping,
            shipping_details: shippingDetails,
            list_price_mode: form.list_price_mode,
            payment_terms: condicoes,
            seller_mode: sellerMode,
            primary_seller_user_id: sellerMode === "single" ? primarySellerUserId : normalizedSellerAllocations[0]?.seller_user_id,
            allocations:
              sellerMode === "split"
                ? normalizedSellerAllocations.map((allocation) => ({
                    seller_user_id: allocation.seller_user_id,
                    allocation_percent: allocation.allocationPercent,
                    is_primary: allocation.is_primary,
                  }))
                : [
                    {
                      seller_user_id: primarySellerUserId,
                      allocation_percent: 100,
                      is_primary: true,
                    },
                  ],
            items: meaningfulItems,
          }),
        });

        const json = (await res.json().catch(() => null)) as { quoteId?: string; error?: string } | null;
        if (!res.ok) {
          setError(json?.error || "Erro ao salvar orçamento.");
          return;
        }

        createdId = json?.quoteId || "";
        if (!createdId) {
          setError("Erro ao salvar orçamento.");
          return;
        }
        setCreatedQuoteId(createdId);
      }

      /* O orçamento nasce pela API; os campos próprios vão logo em seguida,
         pela sessão de quem está no painel. */
      if (camposProprios) {
        const { error: erroDosCampos } = await getSupabaseClient().from("quotes").update({ campos_proprios: camposProprios }).eq("id", createdId);
        if (erroDosCampos) throw new Error("o orçamento foi criado, mas as informações extras não foram salvas. Abra o orçamento e salve de novo.");
      }

      const artsPayload = quoteArtEnabled
        ? Object.values(itemArts)
            .filter((art) => meaningfulItems.some((it) => it.id === art.quote_item_id))
            .map((art) => ({
              quote_item_id: art.quote_item_id,
              title: art.title.trim(),
              notes: art.notes.trim(),
              files: art.files,
            }))
            .filter((art) => art.title || art.notes || art.files.length > 0)
        : [];

      if (quoteArtEnabled && artsPayload.length > 0) {
        setArtUploading(true);
        const supabase = getSupabaseClient();
        const {
          data: { user },
        } = await supabase.auth.getUser();
        const { data: quoteRow, error: quoteErr } = await supabase
          .from("quotes")
          .select("id,user_id")
          .eq("id", createdId)
          .maybeSingle();
        if (quoteErr) throw quoteErr;
        const ownerId = (quoteRow as { user_id?: string } | null)?.user_id || user?.id;
        if (!ownerId) throw new Error("Usuário não autenticado");

        const artsToInsert = [];
        for (const art of artsPayload) {
          const uploadedUrls: string[] = [];
          for (const fileDraft of art.files) {
            const webp = await compressToWebp(fileDraft.file);
            const path = `${ownerId}/quotes/${createdId}/items/${art.quote_item_id}/${crypto.randomUUID()}.webp`;
            const { error: uploadError } = await supabase.storage.from("quote-arts").upload(path, webp, {
              contentType: "image/webp",
            });
            if (uploadError) throw uploadError;
            const { data } = supabase.storage.from("quote-arts").getPublicUrl(path);
            if (data.publicUrl) uploadedUrls.push(data.publicUrl);
          }

          artsToInsert.push({
            quote_id: createdId,
            quote_item_id: art.quote_item_id,
            title: art.title || null,
            notes: art.notes || null,
            image_urls: uploadedUrls,
          });
        }

      if (quoteArtEnabled && artsToInsert.length > 0) {
          const { error: insertErr } = await supabase.from("quote_item_arts").insert(artsToInsert);
          if (insertErr) throw insertErr;
        }
        setArtUploading(false);
      }

      router.push(`/dashboard/quotes/${createdId}`);
    } catch (err) {
      console.error("Erro ao salvar orçamento:", err);
      const msg = err instanceof Error ? err.message : JSON.stringify(err);
      const normalized = msg.toLowerCase();
      if (normalized.includes("quote-arts") || normalized.includes("bucket") || normalized.includes("storage")) {
        setError("Falha ao enviar artes. Verifique o bucket quote-arts e as políticas no Supabase.");
      } else {
        setError(`Erro ao salvar orçamento: ${msg}`);
      }
      setArtUploading(false);
    } finally {
      setSaving(false);
    }
  }

  function updateItem(
    index: number,
    patch: Partial<QuoteItemDraft>,
    options?: { manualPrice?: boolean; recalculatePrice?: boolean }
  ) {
    setItems((prev) =>
      prev.map((it, i) => {
        if (i !== index) return it;
        let next: QuoteItemDraft = { ...it, ...patch };
        if (options?.manualPrice) {
          next = { ...next, unit_price_locked: true };
        }
        const shouldRecalculate =
          options?.recalculatePrice === true ||
          Object.prototype.hasOwnProperty.call(patch, "product_id") ||
          Object.prototype.hasOwnProperty.call(patch, "unit_type") ||
          Object.prototype.hasOwnProperty.call(patch, "quantity") ||
          Object.prototype.hasOwnProperty.call(patch, "width_m") ||
          Object.prototype.hasOwnProperty.call(patch, "height_m") ||
          Object.prototype.hasOwnProperty.call(patch, "length_m") ||
          Object.prototype.hasOwnProperty.call(patch, "selected_options") ||
          Object.prototype.hasOwnProperty.call(patch, "unit_price_locked");

        // Preço travado à mão não leva o mínimo do item.
        if (!next.product_id || next.unit_price_locked) return next.minimo ? { ...next, minimo: null } : next;
        if (!shouldRecalculate) return next;

        const product = productsById.get(next.product_id);
        if (!product) return next;

        const linha = resolveProductLine(next, product);
        return { ...next, unit_price: formatUnitPriceValue(linha.precoPorMedida), minimo: minimoDoResultado(linha) };
      })
    );
  }

  function handleQuantityDraftChange(index: number, itemId: string, rawValue: string, minQty: number) {
    setQuantityDrafts((prev) => ({ ...prev, [itemId]: rawValue }));
    if (!rawValue.trim()) return;
    const parsed = Number(rawValue.replace(",", "."));
    if (!Number.isFinite(parsed)) return;
    updateItem(index, { quantity: Math.max(minQty, parsed) });
  }

  function commitQuantityDraft(index: number, itemId: string, minQty: number) {
    const draftValue = quantityDrafts[itemId];
    if (draftValue === undefined) return;
    const parsed = Number(draftValue.replace(",", "."));
    const nextQty = Number.isFinite(parsed) && parsed > 0 ? Math.max(minQty, parsed) : minQty;
    updateItem(index, { quantity: nextQty });
    setQuantityDrafts((prev) => {
      const next = { ...prev };
      delete next[itemId];
      return next;
    });
  }

  function canRegisterManualItem(item: QuoteItemDraft) {
    const hasName = item.title.trim().length > 0;
    const hasUnitType = Boolean(item.unit_type?.trim());
    const hasPrice = parseMoneyInput(item.unit_price) > 0;
    return hasName && hasUnitType && hasPrice;
  }

  async function registerManualItemAsProduct(itemId: string) {
    if (manualProductSubmittingItemId) return;
    const index = items.findIndex((entry) => entry.id === itemId);
    if (index < 0) return;
    const item = items[index];
    const name = item.title.trim();
    if (!canRegisterManualItem(item)) {
      setManualProductErrors((prev) => ({ ...prev, [item.id]: "Preencha nome, unidade e valor." }));
      return;
    }
    if (!name) return;

    setManualProductSubmittingItemId(item.id);
    setManualProductErrors((prev) => ({ ...prev, [item.id]: "" }));
    try {
      const unitPrice = Math.max(0, parseMoneyInput(item.unit_price));
      const unitCost = Math.max(0, parseMoneyInput(item.unit_cost));
      const response = await fetch("/api/products", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          name,
          description: item.description || "",
          price: unitPrice,
          price_on_request: false,
          use_variation_price_only: false,
          estimated_base_cost: unitCost,
          stock: 0,
          unit_type: item.unit_type || "unit",
          active: true,
          category_id: null,
          image_url: null,
          images: [],
          show_in_catalog: false,
          catalog_color: "#4F46E5",
          is_catalog_exclusive: false,
          min_sale_qty_enabled: false,
          min_sale_qty: null,
          max_sale_qty_enabled: false,
          max_sale_qty: null,
          allowed_sale_qty_enabled: false,
          allowed_sale_quantities: null,
          sku: null,
          barcode: null,
          track_inventory: false,
          inventory_scope: "product",
          inventory_attribute_name: null,
          allow_negative_stock: false,
          materials: [],
          processes: [],
          attributes: [],
          variations: [],
          price_tiers: [],
        }),
      });
      const json = (await response.json().catch(() => null)) as { id?: string; error?: string } | null;
      if (!response.ok || !json?.id) {
        setManualProductErrors((prev) => ({ ...prev, [item.id]: json?.error || "Não foi possível cadastrar o produto." }));
        return;
      }

      const createdProduct: ProductOption = {
        id: json.id,
        name,
        price: unitPrice,
        cost_total: unitCost,
        unit_type: item.unit_type || "unit",
        image_url: null,
        price_on_request: false,
        use_variation_price_only: false,
        product_price_tiers: [],
        min_sale_qty_enabled: false,
        min_sale_qty: null,
        max_sale_qty_enabled: false,
        max_sale_qty: null,
        allowed_sale_qty_enabled: false,
        allowed_sale_quantities: null,
        inventory_scope: "product",
        inventory_attribute_name: null,
        allow_negative_stock: false,
        track_inventory: false,
        product_attributes: [],
        product_variations: [],
      };
      setProducts((prev) =>
        [...prev, createdProduct].sort((a, b) => a.name.localeCompare(b.name, "pt-BR", { sensitivity: "base" }))
      );
      updateItem(index, {
        product_id: createdProduct.id,
        title: createdProduct.name,
        unit_type: createdProduct.unit_type || "unit",
        unit_price: formatUnitPriceValue(unitPrice),
        unit_price_locked: false,
        selected_options: null,
      });
      setManualProductErrors((prev) => ({ ...prev, [item.id]: "" }));
    } catch {
      setManualProductErrors((prev) => ({ ...prev, [item.id]: "Não foi possível cadastrar o produto." }));
    } finally {
      setManualProductSubmittingItemId(null);
    }
  }

  function updateItemVariationSelection(
    index: number,
    product: ProductOption,
    attribute: ProductAttributeValue,
    optionLabel: string
  ) {
    const item = items[index];
    if (!item) return;
    const currentMap = getItemVariationMap(item);
    const currentValues = currentMap[attribute.name] || [];
    const allowMultiple = Boolean(attribute.allow_multiple);
    const nextValues = allowMultiple
      ? (currentValues.includes(optionLabel)
        ? currentValues.filter((value) => value !== optionLabel)
        : [...currentValues, optionLabel])
      : [optionLabel];
    const nextMap = { ...currentMap, [attribute.name]: nextValues };
    const payload = buildSelectedOptionsPayload(product, nextMap);
    updateItem(index, { selected_options: payload }, { recalculatePrice: true });
  }

  function toggleItemPriceLock(index: number) {
    setItems((prev) =>
      prev.map((it, i) => {
        if (i !== index) return it;
        const shouldLock = !it.unit_price_locked;
        if (shouldLock || !it.product_id) return { ...it, unit_price_locked: shouldLock, minimo: null };
        const product = productsById.get(it.product_id);
        if (!product) return { ...it, unit_price_locked: false, minimo: null };
        const linha = resolveProductLine(it, product);
        return {
          ...it,
          unit_price_locked: false,
          unit_price: formatUnitPriceValue(linha.precoPorMedida),
          minimo: minimoDoResultado(linha),
        };
      })
    );
  }

  function scrollToItemCard(itemId: string) {
    if (typeof window === "undefined") return;
    window.setTimeout(() => {
      document.getElementById(`quote-item-${itemId}`)?.scrollIntoView({
        behavior: "smooth",
        block: "center",
      });
    }, 80);
  }

  function setItemInFocus(itemId: string, options?: { focusField?: boolean }) {
    setActiveItemId(itemId);
    scrollToItemCard(itemId);
    if (options?.focusField) {
      pendingItemFocusRef.current = itemId;
    }
  }

  function moveItemToPosition(index: number, targetIndex: number) {
    if (targetIndex < 0 || targetIndex >= items.length || targetIndex === index) return;
    const movedItemId = items[index]?.id;
    setItems((prev) => {
      const next = [...prev];
      const [movedItem] = next.splice(index, 1);
      if (!movedItem) return prev;
      next.splice(targetIndex, 0, movedItem);
      return next;
    });
    if (movedItemId) setItemInFocus(movedItemId);
  }

  function moveItem(index: number, direction: "up" | "down") {
    moveItemToPosition(index, direction === "up" ? index - 1 : index + 1);
  }

  function addItem() {
    const newItem = {
      id: generateDraftId(),
      product_id: "",
      title: "",
      description: "",
      unit_type: "unit",
      width_m: "0,00",
      height_m: "0,00",
      length_m: "0,00",
      quantity: 1,
      unit_price: "0,00",
      unit_cost: "0,00",
      unit_price_locked: false,
    };

    setItems((prev) => [...prev, newItem]);
    setItemInFocus(newItem.id, { focusField: true });
    abrirItem(newItem.id);
  }

  function removeItem(index: number) {
    const removedId = items[index]?.id;
    const fallbackItemId =
      removedId && removedId === activeItemId
        ? items[index + 1]?.id ?? items[index - 1]?.id ?? null
        : activeItemId;
    setItems((prev) => prev.filter((_, i) => i !== index));
    if (removedId) {
      setQuantityDrafts((prev) => {
        const next = { ...prev };
        delete next[removedId];
        return next;
      });
      setManualProductErrors((prev) => {
        const next = { ...prev };
        delete next[removedId];
        return next;
      });
      setItemArts((prev) => {
        const next = { ...prev };
        const art = next[removedId];
        if (art?.files?.length) {
          art.files.forEach((file) => URL.revokeObjectURL(file.previewUrl));
        }
        delete next[removedId];
        return next;
      });
      setItemArtPdfVisibility((prev) => {
        const next = { ...prev };
        delete next[removedId];
        return next;
      });
    }
    if (fallbackItemId) {
      setItemInFocus(fallbackItemId, { focusField: removedId === activeItemId });
    } else {
      setActiveItemId(null);
    }
  }

  function duplicateItem(index: number) {
    const source = items[index];
    if (!source) return;
    const newItem: QuoteItemDraft = {
      ...source,
      id: generateDraftId(),
      selected_options: source.selected_options ? JSON.parse(JSON.stringify(source.selected_options)) : null,
    };
    setItems((prev) => {
      const next = [...prev];
      next.splice(index + 1, 0, newItem);
      return next;
    });
    setItemInFocus(newItem.id, { focusField: true });
    abrirItem(newItem.id);
  }

  function openArtModal(itemId: string) {
    setArtError("");
    setActiveArtItemId(itemId);
    const existing = itemArts[itemId];
    const itemTitle = items.find((it) => it.id === itemId)?.title || "";
    setArtDraft(
      existing
        ? {
            ...existing,
            title: existing.title || itemTitle,
          }
        : {
            quote_item_id: itemId,
            title: itemTitle,
            notes: "",
            files: [],
          }
    );
    setArtModalOpen(true);
  }

  function closeArtModal() {
    setArtModalOpen(false);
    setActiveArtItemId(null);
    setArtDraft(null);
    setArtError("");
    setArtUploading(false);
  }

  function openArtPreview(url: string) {
    setPreviewImageUrl(url);
    setPreviewOpen(true);
  }

  function saveArtDraft() {
    if (!artDraft || !activeArtItemId) return;
    const title = artDraft.title.trim();
    const notes = artDraft.notes.trim();
    const hasContent = title || notes || artDraft.files.length > 0;
    if (!hasContent) {
      setItemArts((prev) => {
        const next = { ...prev };
        delete next[activeArtItemId];
        return next;
      });
      closeArtModal();
      return;
    }
    setItemArts((prev) => ({
      ...prev,
      [activeArtItemId]: {
        ...artDraft,
        title,
        notes,
        quote_item_id: activeArtItemId,
      },
    }));
    closeArtModal();
  }

  function handleArtFiles(files: FileList | null) {
    if (!files?.length) return;
    setArtError("");
    const draftFiles = Array.from(files).map((file) => ({
      file,
      previewUrl: URL.createObjectURL(file),
    }));
    setArtDraft((prev) =>
      prev
        ? {
            ...prev,
            files: [...prev.files, ...draftFiles],
          }
        : prev
    );
  }

  function removeArtImage(previewUrl: string) {
    setArtDraft((prev) => {
      if (!prev) return prev;
      const removed = prev.files.find((file) => file.previewUrl === previewUrl);
      if (removed) URL.revokeObjectURL(removed.previewUrl);
      return {
        ...prev,
        files: prev.files.filter((file) => file.previewUrl !== previewUrl),
      };
    });
  }

  return (
    <div className="relative -mx-5 md:-mx-8 px-5 md:px-8">
      <div className="pointer-events-none absolute inset-x-0 -top-14 h-64 bg-gradient-to-b from-[var(--ks-color-primary-soft)] via-transparent to-transparent blur-2xl opacity-80" />
      {activeItemId && (
        <button
          type="button"
          aria-label="Fechar foco do item"
          onClick={() => setActiveItemId(null)}
          className="fixed inset-0 z-40 bg-slate-950/55 backdrop-blur-[2px]"
        />
      )}
      <div className="space-y-6 relative">
        <div className="bg-white/80 backdrop-blur rounded-3xl border border-[var(--ks-color-border-subtle)] px-5 py-4 flex flex-wrap items-center justify-between gap-4">
          <div className="min-w-0">
            <div className="flex items-center gap-2">
              <Link
                href="/dashboard/quotes"
                className="p-2 rounded-2xl border border-[var(--ks-color-border-subtle)] text-[var(--ks-color-text-primary)] hover:bg-[var(--ks-color-bg-soft)] transition-colors"
                aria-label="Voltar"
              >
                <ArrowLeft size={18} />
              </Link>
              <h1 className="text-2xl font-bold text-[var(--ks-color-text-primary)] truncate">Novo Orçamento</h1>
            </div>
            <p className="text-[var(--ks-color-text-muted)] mt-1">Monte itens, margem e envie para aprovar.</p>
          </div>
          <div className="flex flex-wrap items-center justify-end gap-2">
            {/* Em etapas o status mora aqui, à vista em todas as etapas; na
                página única ele segue no cartão de dados. */}
            {emEtapas && (
              <div className="w-44" title="Status do orçamento">
                <CustomSelect
                  options={OPCOES_DE_STATUS}
                  value={form.status}
                  onChange={(value) => setForm((p) => ({ ...p, status: value as QuoteStatus }))}
                />
              </div>
            )}
            <SeletorDeModelo modelo={paginaEmEtapas.modelo} aoTrocar={paginaEmEtapas.trocarModelo} />
            {whatsappLink && (
              <a
                href={whatsappLink}
                target="_blank"
                rel="noopener noreferrer"
                className={
                  emEtapas
                    ? "inline-flex items-center gap-2 rounded-xl border border-[var(--ks-color-border-subtle)] bg-white px-3.5 py-2 text-sm font-semibold text-[var(--ks-color-status-success)] transition-colors hover:bg-[var(--ks-color-bg-soft)] whitespace-nowrap"
                    : "px-4 py-2 rounded-2xl border border-[var(--ks-color-border-subtle)] text-[var(--ks-color-text-primary)] hover:bg-[var(--ks-color-bg-soft)] transition-colors whitespace-nowrap"
                }
              >
                {emEtapas && <Send size={15} />}
                Abrir WhatsApp
              </a>
            )}
          </div>
        </div>

      {loading ? (
        <div className="text-center py-10 text-[var(--ks-color-text-muted)]">Carregando...</div>
      ) : (
        <form onSubmit={handleSave} className="space-y-6">
          {emEtapas && (
            <Etapas etapa={etapa} feitas={etapasFeitas} aoEscolher={irPara} topoRef={paginaEmEtapas.topoRef} />
          )}
          <div className="grid grid-cols-1 lg:grid-cols-12 gap-6 items-start">
            <div className={`lg:col-span-8 ${emEtapas ? "flex flex-col gap-6" : "space-y-6"} ${paginaEmEtapas.classeDaTransicao}`}>
              <div
                hidden={fora(1, 5)}
                className={
                  emEtapas
                    ? `${CARTAO_EM_ETAPAS} flex flex-col gap-4`
                    : "bg-white rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 shadow-sm space-y-5"
                }
              >
            {emEtapas && (
              <CabecalhoDoCartao
                hidden={fora(1)}
                icone="dados"
                titulo="Dados do Orçamento"
                descricao="Informações principais para identificar e organizar este orçamento."
              />
            )}
            <div hidden={fora(1)} className="grid grid-cols-1 lg:grid-cols-12 gap-5">
              <div className="space-y-1 lg:col-span-6">
                <div className="flex items-center justify-between gap-2">
                  <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">
                    Cliente
                    {emEtapas && <span className="ml-1 text-[var(--ks-color-status-danger)]">*</span>}
                  </label>
                  <button
                    hidden={emEtapas}
                    type="button"
                    onClick={() => setClientModalOpen(true)}
                    className="h-7 w-7 rounded-full border border-[var(--ks-color-border-subtle)] text-[var(--ks-color-primary)] hover:bg-[var(--ks-color-bg-soft)] inline-flex items-center justify-center transition-colors"
                    title="Cadastrar cliente"
                    aria-label="Cadastrar cliente"
                  >
                    <Plus size={14} />
                  </button>
                </div>
                <div className={emEtapas ? "flex gap-2" : undefined}>
                  <div className="min-w-0 flex-1">
                    <CustomSelect
                      options={clientOptions}
                      value={form.client_id}
                      onChange={(value) => setForm((p) => ({ ...p, client_id: value }))}
                      searchable
                    />
                  </div>
                  {/* Em etapas o cadastro rápido fica ao lado do campo, como
                      na proposta; na página única segue junto do rótulo. */}
                  {emEtapas && (
                    <button
                      type="button"
                      onClick={() => setClientModalOpen(true)}
                      className="flex h-11 w-11 shrink-0 items-center justify-center rounded-xl border border-[var(--ks-color-border-subtle)] bg-white text-[var(--ks-color-primary)] transition-colors hover:bg-[var(--ks-color-bg-soft)]"
                      title="Cadastrar cliente"
                      aria-label="Cadastrar cliente"
                    >
                      <Plus size={16} />
                    </button>
                  )}
                </div>
              </div>

              <div className={emEtapas ? "space-y-1 lg:col-span-6" : "space-y-1 lg:col-span-4"}>
                <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Título (opcional)</label>
                <input
                  value={form.title}
                  onChange={(e) => setForm((p) => ({ ...p, title: e.target.value }))}
                  className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                  placeholder="Ex: 500 cartões + 1 banner"
                />
              </div>

              <div hidden={emEtapas} className="space-y-1 lg:col-span-2">
                <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Status</label>
                <CustomSelect
                  options={[
                    { value: "draft", label: "Rascunho" },
                    { value: "sent", label: "Enviado" },
                    { value: "approved", label: "Aprovado" },
                    { value: "rejected", label: "Recusado" },
                    { value: "production", label: "Em produção" },
                    { value: "delivered", label: "Entregue" },
                  ]}
                  value={form.status}
                  onChange={(value) => setForm((p) => ({ ...p, status: value as QuoteStatus }))}
                />
              </div>
            </div>

            {emEtapas && (
              <>
                <div hidden={fora(1)} className="h-px bg-[var(--ks-color-border-subtle)]" />
                <CabecalhoDoCartao
                  hidden={fora(1)}
                  icone="vendedores"
                  titulo="Atribuição comercial"
                  descricao="Quem vendeu, ou como a venda se divide entre vendedores."
                />
              </>
            )}
            <div
              hidden={fora(1)}
              className={`rounded-2xl border p-4 space-y-4 ${
                emEtapas
                  ? "border-[var(--ks-color-primary-soft-strong)] bg-[var(--ks-color-primary-soft)]"
                  : "border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-soft)]"
              }`}
            >
              <div className="flex items-center justify-between gap-3">
                <div>
                  {emEtapas ? (
                    <h3 className="text-[13px] font-bold text-[var(--ks-color-text-primary)]">
                      {sellerMode === "single" ? "Vendedor principal" : "Vendedores e a parte de cada um"}
                    </h3>
                  ) : (
                    <>
                      <h3 className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Atribuição comercial</h3>
                      <p className="text-xs text-[var(--ks-color-text-muted)]">
                        Defina quem será o vendedor do orçamento ou como o rateio será dividido.
                      </p>
                    </>
                  )}
                </div>
                <div className="inline-flex rounded-xl border border-[var(--ks-color-border-subtle)] bg-white p-1">
                  <button
                    type="button"
                    onClick={() => setSellerMode("single")}
                    className={`rounded-lg px-3 py-1.5 text-xs font-semibold transition-colors ${
                      sellerMode === "single"
                        ? "bg-[var(--ks-color-primary)]/10 text-[var(--ks-color-primary)]"
                        : "text-[var(--ks-color-text-muted)]"
                    }`}
                  >
                    Vendedor unico
                  </button>
                  <button
                    type="button"
                    onClick={() => setSellerMode("split")}
                    className={`rounded-lg px-3 py-1.5 text-xs font-semibold transition-colors ${
                      sellerMode === "split"
                        ? "bg-[var(--ks-color-primary)]/10 text-[var(--ks-color-primary)]"
                        : "text-[var(--ks-color-text-muted)]"
                    }`}
                  >
                    Rateio
                  </button>
                </div>
              </div>

              {sellerMode === "single" ? (
                <div className="space-y-1">
                  <label className={emEtapas ? "sr-only" : "text-sm font-medium text-[var(--ks-color-text-primary)]"}>
                    Vendedor principal
                  </label>
                  <CustomSelect
                    options={sellerSelectOptions}
                    value={primarySellerUserId}
                    onChange={setPrimarySellerUserId}
                    searchable
                    placeholder="Selecione o vendedor"
                  />
                </div>
              ) : (
                <div className="space-y-3">
                  {sellerAllocations.map((allocation, index) => (
                    <div
                      key={allocation.id}
                      className={
                        emEtapas
                          ? "grid grid-cols-[minmax(0,1fr)_96px_36px] items-center gap-2"
                          : "grid grid-cols-1 lg:grid-cols-12 gap-3 items-end"
                      }
                    >
                      <div className={emEtapas ? "min-w-0" : "space-y-1 lg:col-span-7"}>
                        <label className={emEtapas ? "sr-only" : "text-sm font-medium text-[var(--ks-color-text-primary)]"}>
                          {index === 0 ? "Vendedor principal" : "Vendedor"}
                        </label>
                        <CustomSelect
                          options={sellerSelectOptions}
                          value={allocation.seller_user_id}
                          onChange={(value) => updateSellerAllocation(allocation.id, { seller_user_id: value })}
                          searchable
                          placeholder="Selecione o vendedor"
                        />
                      </div>
                      <div className={emEtapas ? "relative" : "space-y-1 lg:col-span-3"}>
                        <label className={emEtapas ? "sr-only" : "text-sm font-medium text-[var(--ks-color-text-primary)]"}>
                          % do rateio
                        </label>
                        <input
                          value={allocation.allocation_percent}
                          onChange={(e) =>
                            updateSellerAllocation(allocation.id, {
                              allocation_percent: formatPercentInput(e.target.value),
                            })
                          }
                          className={`w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white ${
                            emEtapas ? "pr-7 text-right" : ""
                          }`}
                          placeholder="0,00"
                        />
                        {emEtapas && (
                          <span
                            aria-hidden="true"
                            className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 text-xs text-[var(--ks-color-text-muted)]"
                          >
                            %
                          </span>
                        )}
                      </div>
                      <div className={emEtapas ? "" : "lg:col-span-2"}>
                        <button
                          type="button"
                          onClick={() => removeSellerAllocation(allocation.id)}
                          disabled={sellerAllocations.length <= 2}
                          className={
                            emEtapas
                              ? "flex h-9 w-9 items-center justify-center rounded-lg text-[var(--ks-color-text-soft)] transition-colors hover:bg-white hover:text-[var(--ks-color-status-danger)] disabled:cursor-not-allowed disabled:opacity-40"
                              : "w-full inline-flex items-center justify-center gap-2 rounded-xl border border-[var(--ks-color-border-subtle)] px-3 py-2.5 text-sm font-medium text-[var(--ks-color-text-muted)] disabled:opacity-50"
                          }
                          aria-label="Remover vendedor"
                          title="Remover vendedor"
                        >
                          <Trash2 size={14} />
                          {!emEtapas && "Remover"}
                        </button>
                      </div>
                    </div>
                  ))}

                  <div className="flex items-center justify-between gap-3">
                    <div className="text-xs text-[var(--ks-color-text-muted)]">
                      Total do rateio: {formatPercentInput(
                        normalizedSellerAllocations.reduce((sum, allocation) => sum + allocation.allocationPercent, 0).toFixed(2)
                      )}%
                    </div>
                    <button
                      type="button"
                      onClick={addSellerAllocation}
                      className={
                        emEtapas
                          ? "inline-flex items-center gap-1.5 text-[13px] font-semibold text-[var(--ks-color-primary)]"
                          : "inline-flex items-center gap-2 rounded-xl border border-[var(--ks-color-border-subtle)] bg-white px-3 py-2 text-xs font-semibold text-[var(--ks-color-primary)]"
                      }
                    >
                      <Plus size={14} />
                      Adicionar vendedor
                    </button>
                  </div>
                </div>
              )}
            </div>

            {emEtapas && (
              <CabecalhoDoCartao
                hidden={fora(5)}
                icone="prazos"
                titulo="Prazos"
                descricao="Até quando o orçamento vale e quando o pedido fica pronto."
              />
            )}
            <div hidden={fora(5)} className="grid grid-cols-1 lg:grid-cols-12 gap-5">
              <div className="space-y-1 lg:col-span-6">
                <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Validade (opcional)</label>
                <input
                  type="date"
                  value={form.expires_at}
                  onChange={(e) => setForm((p) => ({ ...p, expires_at: e.target.value }))}
                  className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                />
              </div>
              <div className="space-y-1 lg:col-span-6">
                <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Data de Entrega</label>
                <input
                  type="date"
                  value={form.delivery_date}
                  onChange={(e) => setForm((p) => ({ ...p, delivery_date: e.target.value }))}
                  className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                />
                <CargaDoDia data={form.delivery_date} />
              </div>
            </div>
          </div>

              <div
                hidden={fora(2)}
                className={
                  emEtapas
                    ? `${CARTAO_EM_ETAPAS} space-y-4`
                    : "bg-white rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 shadow-sm space-y-4"
                }
              >
            {emEtapas ? (
              <CabecalhoDoCartao
                icone="itens"
                titulo="Itens"
                descricao="Detalhe quantidade, preço e custo para margem."
                direita={
                  <Chip tom="marca">
                    {items.length} {items.length === 1 ? "item" : "itens"}
                  </Chip>
                }
              />
            ) : (
              <div className="flex items-start gap-3">
                <div>
                  <h2 className="text-lg font-semibold text-[var(--ks-color-text-primary)]">Itens</h2>
                  <p className="text-sm text-[var(--ks-color-text-muted)]">Detalhe quantidade, preço e custo para margem.</p>
                </div>
              </div>
            )}

            <div className="space-y-3">
              {items.map((it, idx) => {
                const usedQuantity = effectiveQuantity(it);
                const unitPrice = parseMoneyInput(it.unit_price);
                const unitCost = parseMoneyInput(it.unit_cost);
                const lineTotal = totalDaLinhaDoRascunho(it, usedQuantity);
                const minimoDaLinha = it.minimo && !it.unit_price_locked ? it.minimo : null;
                const lineCost = usedQuantity * unitCost;
                const margin = lineTotal - lineCost;
                const marginPct = lineTotal > 0 ? (margin / lineTotal) * 100 : 0;
                const isMarginLow = marginPct < 30; // Alerta se margem < 30%
                const isLoss = margin < 0;
                const selectedProduct = it.product_id ? productsById.get(it.product_id) : null;
                const quantityRuleMessage = getItemQuantityRuleMessage(it, selectedProduct);
                const allowedQuantities = getAllowedItemQuantities(selectedProduct);
                const usesAllowedQuantities = Boolean(selectedProduct?.allowed_sale_qty_enabled) && allowedQuantities.length > 0;
                const selectedAllowedQuantity = usesAllowedQuantities
                  ? allowedQuantities.find((value) => Math.abs(value - Number(it.quantity || 0)) <= 0.000001)
                  : null;
                /* Estoque v2: a falta vem do banco (a mesma conta da loja e do
                   PDV, por combinação e somando por célula). Só aviso: salvar
                   o orçamento nunca trava. */
                const stockRuleMessage =
                  estoqueV2 === true
                    ? (faltasDoEstoqueV2.get(idx) || []).join(" ") || null
                    : getItemVariationStockMessage(it, selectedProduct);
                const artPreviews = itemArts[it.id]?.files?.map((file) => file.previewUrl) ?? [];
                const showArtInPdf = itemArtPdfVisibility[it.id] ?? true;

                const accents = [
                  { bg: '#7c3aed', light: '#ede9fe' }, // violet
                  { bg: '#0284c7', light: '#e0f2fe' }, // sky
                  { bg: '#059669', light: '#d1fae5' }, // emerald
                  { bg: '#d97706', light: '#fef3c7' }, // amber
                  { bg: '#db2777', light: '#fce7f3' }, // pink
                  { bg: '#ea580c', light: '#ffedd5' }, // orange
                  { bg: '#0891b2', light: '#cffafe' }, // cyan
                  { bg: '#a21caf', light: '#fae8ff' }, // fuchsia
                  { bg: '#65a30d', light: '#ecfccb' }, // lime
                  { bg: '#4338ca', light: '#e0e7ff' }, // indigo
                ] as const;
                const accent = isLoss
                  ? { bg: '#e11d48', light: '#ffe4e6' }
                  : accents[idx % 10];
                const isItemActive = activeItemId === it.id;
                /* Em etapas o item é uma linha que abre; o único item da
                   lista já nasce aberto. O foco pelo clique só existe na
                   página única — em etapas ele vem pelo botão "Foco". */
                const itemEstaAberto = emEtapas && (itemAberto ? itemAberto === it.id : items.length === 1);
                const temAtributos = Boolean(selectedProduct && getSortedAttributes(selectedProduct).length > 0);
                const temMedidas = it.unit_type === "square_meter" || it.unit_type === "linear_meter" || it.unit_type === "meter";
                const nomeDoItem = it.title.trim() || selectedProduct?.name || "";
                const resumoDasOpcoes = getSelectedOptionsSummary(it);

                return (
                  <div
                    id={`quote-item-${it.id}`}
                    key={it.id}
                    tabIndex={-1}
                    onMouseDownCapture={emEtapas ? undefined : () => setActiveItemId(it.id)}
                    onMouseLeave={() => {
                      if (activeItemId === it.id) setActiveItemId(null);
                    }}
                    className={
                      emEtapas
                        ? classesDoItemEmEtapas(itemEstaAberto, isItemActive)
                        : `relative rounded-3xl overflow-hidden transition-all duration-200 p-5 ${
                            isItemActive
                              ? "z-50 border border-[var(--ks-color-primary)] bg-white ring-2 ring-[var(--ks-color-primary)]/20 shadow-[0_20px_70px_rgba(15,23,42,0.28)]"
                              : "border border-slate-200/70 bg-white shadow-[0_1px_3px_rgba(0,0,0,0.06),0_6px_24px_rgba(0,0,0,0.05)] hover:shadow-[0_4px_32px_rgba(0,0,0,0.12)] hover:-translate-y-0.5"
                          }`
                    }
                  >
                    {isItemActive && (
                      <div
                        className="pointer-events-none absolute inset-y-3 left-0 w-1 rounded-full"
                        style={{ background: accent.bg }}
                        aria-hidden="true"
                      />
                    )}
                    {emEtapas ? (
                      <CabecalhoDoItem
                        numero={idx + 1}
                        nome={nomeDoItem || "Item sem nome"}
                        semNome={!nomeDoItem}
                        chips={
                          <>
                            <Chip>{nomeDaUnidade(it.unit_type)}</Chip>
                            {resumoDasOpcoes && <Chip>{resumoDasOpcoes}</Chip>}
                            {!it.product_id && <Chip>Item manual</Chip>}
                            {artPreviews.length > 0 && (
                              <Chip tom="marca">
                                {artPreviews.length} {artPreviews.length === 1 ? "arte" : "artes"}
                              </Chip>
                            )}
                          </>
                        }
                        total={formatMoney(lineTotal)}
                        detalhe={
                          minimoDaLinha
                            ? `${descreverQuantidade(usedQuantity, it.unit_type)} · Valor mínimo`
                            : `${descreverQuantidade(usedQuantity, it.unit_type)} × ${formatMoney(unitPrice)}`
                        }
                        aberto={itemEstaAberto}
                        aoAlternar={() => alternarItem(it.id)}
                        aoSubir={() => moveItem(idx, "up")}
                        aoDescer={() => moveItem(idx, "down")}
                        podeSubir={idx > 0}
                        podeDescer={idx < items.length - 1}
                      />
                    ) : (
                    <div className="relative z-10 mb-4 flex items-center justify-between gap-3 border-b border-slate-100 pb-3">
                      <div className="flex items-center gap-2">
                        {/* Colored number badge — the hero color element */}
                        <div
                          className="flex h-8 min-w-[2rem] items-center justify-center rounded-xl px-2 text-sm font-black text-white select-none shadow-sm"
                          style={{ background: accent.bg, boxShadow: `0 2px 8px ${accent.bg}55` }}
                          aria-label={`Item ${idx + 1}`}
                        >
                          {idx + 1}
                        </div>
                        <div className="w-px h-5 bg-slate-200 rounded-full" />
                        <button
                          type="button"
                          onClick={() => moveItem(idx, "up")}
                          disabled={idx === 0}
                          className="inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-200/80 text-slate-400 transition-colors hover:bg-slate-50 hover:text-slate-600 disabled:cursor-not-allowed disabled:opacity-30"
                          aria-label="Mover item para cima"
                        >
                          <ArrowUp size={14} />
                        </button>
                        <button
                          type="button"
                          onClick={() => moveItem(idx, "down")}
                          disabled={idx === items.length - 1}
                          className="inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-200/80 text-slate-400 transition-colors hover:bg-slate-50 hover:text-slate-600 disabled:cursor-not-allowed disabled:opacity-30"
                          aria-label="Mover item para baixo"
                        >
                          <ArrowDown size={14} />
                        </button>
                        <button
                          type="button"
                          onClick={() => duplicateItem(idx)}
                          className="inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-200/80 text-slate-400 transition-colors hover:bg-slate-50 hover:text-slate-600"
                          aria-label="Duplicar item"
                          title="Duplicar item"
                        >
                          <Copy size={14} />
                        </button>
                      </div>
                      {/* Delete — right side */}
                      <button
                        type="button"
                        onClick={() => removeItem(idx)}
                        disabled={items.length === 1}
                        className="inline-flex h-8 w-8 items-center justify-center rounded-xl border border-slate-200/80 text-slate-400 transition-colors hover:bg-red-50 hover:text-red-500 hover:border-red-200 disabled:opacity-30 disabled:cursor-not-allowed"
                        aria-label="Remover item"
                        title="Remover item"
                      >
                        <Trash2 size={14} />
                      </button>
                    </div>
                    )}

                    <div hidden={emEtapas && !itemEstaAberto} className={emEtapas ? CORPO_DO_ITEM_EM_ETAPAS : "relative z-10"}>
                    <div className={emEtapas ? "grid grid-cols-1 sm:grid-cols-2 gap-3.5" : "grid grid-cols-1 lg:grid-cols-12 gap-3"}>
                      <div
                        className={emEtapas ? (temAtributos ? "space-y-1" : "space-y-1 sm:col-span-2") : "lg:col-span-12 space-y-1"}
                        data-item-primary-field="true"
                      >
                        <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Produto</label>
                        <CustomSelect
                          options={[
                            { value: "", label: "Item manual" },
                            ...products
                              .filter((p) => p.id)
                              .map((p) => ({
                                value: p.id,
                                label: `${p.name} (${unitLabel(p.unit_type || "unit")}) - ${p.price_on_request ? "Sob consulta" : formatMoney(p.price || 0)}`,
                                image_url: p.image_url || "https://placehold.co/100x100/f4f4f5/a1a1aa?text=IMG",
                              })),
                          ]}
                          value={it.product_id}
                          onChange={(value) => {
                            if (!value) {
                              updateItem(idx, { product_id: "", unit_price_locked: false, selected_options: null });
                              return;
                            }
                            const selected = productsById.get(value);
                            if (!selected) return;
                            const minQty = getMinimumItemQuantity(selected);
                            const nextDraft: QuoteItemDraft = {
                              ...it,
                              product_id: selected.id,
                              title: selected.name,
                              description: it.description,
                              unit_type: selected.unit_type || "unit",
                              width_m: "0,00",
                              height_m: "0,00",
                              length_m: "0,00",
                              quantity: Math.max(minQty, it.quantity || minQty),
                              unit_price: "0,00",
                              unit_cost: formatUnitPriceValue(selected.cost_total || 0),
                              unit_price_locked: false,
                              selected_options: null,
                            };
                            const tierPrice = resolveProductUnitPrice(nextDraft, selected);
                            updateItem(idx, {
                              product_id: selected.id,
                              title: selected.name,
                              unit_price: formatUnitPriceValue(tierPrice),
                              unit_cost: formatUnitPriceValue(selected.cost_total || 0),
                              unit_type: selected.unit_type || "unit",
                              width_m: "0,00",
                              height_m: "0,00",
                              length_m: "0,00",
                              quantity: Math.max(minQty, it.quantity || minQty),
                              unit_price_locked: false,
                              selected_options: null,
                            });
                          }}
                          searchable
                        />
                      </div>
                      {selectedProduct && getSortedAttributes(selectedProduct).length > 0 && (
                        <div className={emEtapas ? "space-y-1" : "lg:col-span-12 space-y-1"}>
                          <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Variações</label>
                          <div className="rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-soft)] px-3 py-2">
                            <div className="text-xs text-[var(--ks-color-text-muted)]">
                              {getSelectedOptionsSummary(it) || "Nenhuma opção selecionada"}
                            </div>
                          </div>
                        </div>
                      )}
                      {!it.product_id && (
                        <div className={emEtapas ? "space-y-1 sm:col-span-2" : "lg:col-span-12 space-y-1"}>
                          <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Item</label>
                          <input
                            value={it.title}
                            onChange={(e) => updateItem(idx, { title: e.target.value })}
                            className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                            placeholder="Ex: 1000 cartões 4x0"
                          />
                          <button
                            type="button"
                            onClick={() => registerManualItemAsProduct(it.id)}
                            disabled={!canRegisterManualItem(it) || manualProductSubmittingItemId === it.id}
                            className="inline-flex h-6 items-center rounded-md border border-[var(--ks-color-primary-soft-strong)] px-2 text-[11px] font-semibold text-[var(--ks-color-primary)] hover:bg-[rgba(68,37,167,0.08)] disabled:opacity-45 disabled:cursor-not-allowed"
                          >
                            {manualProductSubmittingItemId === it.id ? "Cadastrando..." : "Cadastrar produto"}
                          </button>
                          {manualProductErrors[it.id] ? (
                            <p className="text-[11px] font-medium text-rose-600">{manualProductErrors[it.id]}</p>
                          ) : null}
                        </div>
                      )}
                      <div className={emEtapas ? "space-y-1" : "lg:col-span-6 space-y-1"}>
                        <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Unidade</label>
                        <CustomSelect
                          options={[
                            { value: "unit", label: "Unidade" },
                            { value: "meter", label: "Metro" },
                            { value: "linear_meter", label: "Metro Linear" },
                            { value: "square_meter", label: "Metro Quadrado" },
                            { value: "box", label: "Caixa" },
                            { value: "ream", label: "Resma" },
                          ]}
                          value={it.unit_type}
                          onChange={(value) => updateItem(idx, { unit_type: value })}
                          disabled={!!it.product_id}
                        />
                      </div>
                      <div className={emEtapas ? "space-y-1" : "lg:col-span-6 space-y-1"}>
                          <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Qtd</label>
                          {usesAllowedQuantities ? (
                            <CustomSelect
                              options={allowedQuantities.map((value) => ({
                                value: String(value),
                                label: formatQuantityLimit(value),
                              }))}
                              value={String(selectedAllowedQuantity ?? allowedQuantities[0])}
                              onChange={(value) => {
                                const parsed = Number(value);
                                if (!Number.isFinite(parsed) || parsed <= 0) return;
                                updateItem(idx, { quantity: parsed });
                              }}
                            />
                          ) : (
                            <input
                              value={quantityDrafts[it.id] ?? String(it.quantity)}
                              min={getMinimumItemQuantity(selectedProduct)}
                              onChange={(e) => handleQuantityDraftChange(idx, it.id, e.target.value, getMinimumItemQuantity(selectedProduct))}
                              onBlur={() => commitQuantityDraft(idx, it.id, getMinimumItemQuantity(selectedProduct))}
                              onKeyDown={(e) => {
                                if (e.key === "Enter") {
                                  e.preventDefault();
                                  commitQuantityDraft(idx, it.id, getMinimumItemQuantity(selectedProduct));
                                  (e.currentTarget as HTMLInputElement).blur();
                                }
                              }}
                              className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                              inputMode="decimal"
                            />
                          )}
                      </div>
                      </div>

                      <div className={emEtapas ? "mt-3.5 grid grid-cols-2 items-end gap-3.5 sm:grid-cols-4" : "mt-3 grid grid-cols-1 lg:grid-cols-12 lg:items-end gap-3"}>
                        {it.unit_type === "square_meter" ? (
                          <>
                            <div className={emEtapas ? "space-y-1" : "lg:col-span-2 space-y-1"}>
                              <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Largura (m)</label>
                              <input
                                value={it.width_m}
                                onChange={(e) => updateItem(idx, { width_m: formatMeasureInput(e.target.value) })}
                                className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                                inputMode="decimal"
                              />
                            </div>
                            <div className={emEtapas ? "space-y-1" : "lg:col-span-2 space-y-1"}>
                              <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Altura (m)</label>
                              <input
                                value={it.height_m}
                                onChange={(e) => updateItem(idx, { height_m: formatMeasureInput(e.target.value) })}
                                className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                                inputMode="decimal"
                              />
                            </div>
                          </>
                        ) : it.unit_type === "linear_meter" || it.unit_type === "meter" ? (
                          <div className={emEtapas ? "col-span-2 space-y-1" : "lg:col-span-4 space-y-1"}>
                            <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Comprimento (m)</label>
                            <input
                              value={it.length_m}
                              onChange={(e) => updateItem(idx, { length_m: formatMeasureInput(e.target.value) })}
                              className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                              inputMode="decimal"
                            />
                          </div>
                        ) : (
                          <div hidden={emEtapas} className="lg:col-span-4" />
                        )}

                        <div className={emEtapas ? (temMedidas ? "space-y-1" : "col-span-2 space-y-1") : "lg:col-span-3 space-y-1"}>
                          <div className="flex items-center gap-1">
                            <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Preço Unit.</label>
                            {it.product_id && (
                              <button
                                type="button"
                                onClick={() => toggleItemPriceLock(idx)}
                                className={`inline-flex h-6 w-6 items-center justify-center rounded-full border text-[10px] transition-colors ${
                                  it.unit_price_locked
                                    ? "border-amber-300 bg-amber-50 text-amber-700"
                                    : "border-[var(--ks-color-border-subtle)] text-[var(--ks-color-text-soft)] hover:bg-[var(--ks-color-bg-soft)]"
                                }`}
                                title={it.unit_price_locked ? "Preço travado manualmente" : "Preço automático por faixa"}
                              >
                                {it.unit_price_locked ? <Lock size={12} /> : <Unlock size={12} />}
                              </button>
                            )}
                          </div>
                          <input
                            value={it.unit_price}
                            onChange={(e) => updateItem(idx, { unit_price: formatMoneyInput(e.target.value) }, { manualPrice: true })}
                            className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white text-right font-medium"
                            inputMode="numeric"
                          />
                        </div>
                        <div className={emEtapas ? (temMedidas ? "space-y-1" : "col-span-2 space-y-1") : "lg:col-span-3 space-y-1"}>
                          <div className="flex items-center gap-1">
                            <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">Custo Unit.</label>
                            <InfoTooltip text="Custo total estimado por unidade para cálculo de margem." />
                          </div>
                          <input
                            value={it.unit_cost}
                            onChange={(e) => updateItem(idx, { unit_cost: formatMoneyInput(e.target.value) })}
                            className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-slate-50 text-slate-600 text-right text-sm"
                            inputMode="numeric"
                          />
                        </div>

                        <div hidden={emEtapas} className="lg:col-span-2 flex items-end justify-end">
                          <div className="text-right">
                            <div className="text-xs text-[var(--ks-color-text-soft)]">
                              Total
                              {it.unit_type === "unit" || it.unit_type === "box" || it.unit_type === "ream" ? null : (
                                <div className="whitespace-nowrap">{resumoDaMedida(it)}</div>
                              )}
                            </div>
                            <div className="text-sm font-semibold text-[var(--ks-color-text-primary)]">
                              {formatMoney(lineTotal)}
                            </div>
                            
                            {/* Margem do item */}
                            {(unitPrice > 0 || unitCost > 0) && (
                              <div className={`text-[10px] mt-1 font-medium flex items-center justify-end gap-1 ${
                                isLoss ? "text-rose-600" : isMarginLow ? "text-amber-600" : "text-emerald-600"
                              }`}>
                                {isLoss ? "Prejuízo" : "Margem"}: {marginPct.toFixed(1)}%
                                {isLoss && <ArrowLeft className="rotate-[-45deg]" size={10} />}
                              </div>
                            )}
                          </div>
                        </div>
                    </div>
                    {emEtapas && (
                      <ContaDoItem
                        medida={temMedidas ? resumoDaMedida(it) : "Total do item"}
                        total={formatMoney(lineTotal)}
                        margemPct={marginPct}
                        prejuizo={isLoss}
                        mostrarMargem={unitPrice > 0 || unitCost > 0}
                      />
                    )}
                    {/* Observação individual do item — aparece no PDF e no link público */}
                    <div className="mt-3 space-y-1">
                      <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">
                        Observação do item <span className="text-xs font-normal text-[var(--ks-color-text-muted)]">(opcional — aparece no PDF e no link público)</span>
                      </label>
                      <textarea
                        value={it.description}
                        onChange={(e) => updateItem(idx, { description: e.target.value })}
                        className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white text-sm resize-none min-h-[60px]"
                        placeholder="Ex: Arte aprovada, sangria 3mm, laminação fosca..."
                        rows={2}
                      />
                    </div>
                    {minimoDaLinha && (
                      <AvisoDoMinimo minimo={minimoDaLinha.minimo} semMinimo={minimoDaLinha.semMinimo} />
                    )}
                    {quantityRuleMessage && (

                      <div className="mt-3 rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-xs font-medium text-amber-700">
                        {quantityRuleMessage}
                      </div>
                    )}
                    {stockRuleMessage && (
                      <div className="mt-3 rounded-xl border border-rose-200 bg-rose-50 px-3 py-2 text-xs font-medium text-rose-700">
                        {stockRuleMessage}
                      </div>
                    )}
                    {selectedProduct && getSortedAttributes(selectedProduct).length > 0 && (
                      <div className="mt-3 rounded-2xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-soft)] p-3">
                        <div className="space-y-3">
                          {getSortedAttributes(selectedProduct).map((attribute) => {
                            const selectedMap = getItemVariationMap(it);
                            const selectedValues = selectedMap[attribute.name] || [];
                            const normalizedOptions = (attribute.options || [])
                              .map((option, optionIndex) => normalizeAttributeOption(option, optionIndex))
                              .sort((a, b) => Number(a.position ?? 0) - Number(b.position ?? 0));
                            return (
                              <div key={`${it.id}-${attribute.name}`} className="space-y-2">
                                <div className="flex items-center gap-2">
                                  <span className="text-xs font-semibold text-[var(--ks-color-text-primary)]">{attribute.name}</span>
                                  {attribute.is_required && (
                                    <span className="text-[10px] rounded-full bg-rose-100 px-2 py-0.5 text-rose-700">obrigatório</span>
                                  )}
                                </div>
                                <div className="flex flex-wrap gap-2">
                                  {normalizedOptions.map((option) => {
                                    const active = selectedValues.includes(option.label);
                                    const priceModeSuffix = option.price_applies_per_quantity === false ? " (1x)" : "";
                                    const priceText = option.price > 0 ? ` +${formatMoney(option.price)}${priceModeSuffix}` : "";
                                    return (
                                      <button
                                        type="button"
                                        key={`${it.id}-${attribute.name}-${option.label}`}
                                        onClick={() => updateItemVariationSelection(idx, selectedProduct, attribute, option.label)}
                                        className={`rounded-full border px-3 py-1 text-xs transition-colors ${
                                          active
                                            ? "border-[var(--ks-color-primary)] bg-[var(--ks-color-primary)]/10 text-[var(--ks-color-primary)]"
                                            : "border-[var(--ks-color-border-subtle)] bg-white text-[var(--ks-color-text-muted)] hover:border-[var(--ks-color-primary)]/50"
                                        }`}
                                      >
                                        {option.label}{priceText}
                                      </button>
                                    );
                                  })}
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    )}
                    {quoteArtEnabled && (
                    <div className="mt-4 rounded-2xl border border-[var(--ks-color-border-subtle)] bg-white p-3">
                      <div className="py-0">
                        <div className="flex flex-col gap-3">
                          <div className="flex flex-wrap items-center justify-between gap-2">
                            <div className="flex items-center gap-2 min-w-0">
                              <span className="text-[10px] font-bold tracking-[0.16em] uppercase text-[var(--ks-color-text-soft)]">
                                Arte
                              </span>
                              <span className="text-[10px] text-[var(--ks-color-text-soft)] truncate">
                                {artPreviews.length} imagem(ns)
                              </span>
                            </div>
                            <div className="flex items-center gap-2 flex-wrap justify-end">
                          <button
                            type="button"
                            onClick={() => openArtModal(it.id)}
                            className="h-8 px-3 rounded-full bg-[var(--ks-color-bg-soft)] text-[11px] font-semibold inline-flex items-center justify-center gap-2 border border-[var(--ks-color-border-subtle)] hover:bg-[rgba(68,37,167,0.08)] transition-colors"
                          >
                            <svg
                              viewBox="0 0 24 24"
                              className="h-4 w-4 text-[var(--ks-color-brand-dark)]"
                              fill="currentColor"
                              aria-hidden="true"
                            >
                              <path
                                fillRule="evenodd"
                                clipRule="evenodd"
                                d="M9.29289 1.29289C9.48043 1.10536 9.73478 1 10 1H18C19.6569 1 21 2.34315 21 4V9C21 9.55228 20.5523 10 20 10C19.4477 10 19 9.55228 19 9V4C19 3.44772 18.5523 3 18 3H11V8C11 8.55228 10.5523 9 10 9H5V20C5 20.5523 5.44772 21 6 21H10C10.5523 21 11 21.4477 11 22C11 22.5523 10.5523 23 10 23H6C4.34315 23 3 21.6569 3 20V8C3 7.73478 3.10536 7.48043 3.29289 7.29289L9.29289 1.29289ZM6.41421 7H9V4.41421L6.41421 7ZM11.2929 10.2929C11.63 9.95583 12.1581 9.90353 12.5547 10.1679C12.7377 10.29 13.138 10.4206 13.8692 10.5557C14.2116 10.619 14.5873 10.6773 15.0006 10.7413L15.0159 10.7436C15.42 10.8062 15.8556 10.8736 16.3008 10.9531C18.0592 11.2671 20.2179 11.8037 21.7071 13.2929C22.907 14.4928 23.2701 15.7765 23.1846 16.8892C23.1413 17.4519 22.9841 17.9568 22.7829 18.3687L23 18.5858C23.781 19.3668 23.781 20.6332 23 21.4142L21.4142 23C20.6332 23.781 19.3668 23.781 18.5858 23L18.3687 22.7829C17.9568 22.9841 17.4519 23.1413 16.8892 23.1846C15.7765 23.2701 14.4928 22.907 13.2929 21.7071C11.8037 20.2179 11.2671 18.0592 10.9531 16.3008C10.8736 15.8556 10.8062 15.42 10.7436 15.0159L10.7413 15.0006C10.6773 14.5873 10.619 14.2116 10.5557 13.8692C10.4206 13.138 10.29 12.7377 10.1679 12.5547C9.90353 12.1581 9.95583 11.63 10.2929 11.2929L10.7926 10.7931L10.7929 10.7929L11.2929 10.2929ZM15.0677 16.482L12.6124 14.0266C12.6482 14.2458 12.683 14.47 12.7177 14.6947L12.7186 14.7006L12.7187 14.7007C12.7821 15.1107 12.8465 15.527 12.9219 15.9492C13.2329 17.6908 13.6963 19.2821 14.7071 20.2929C15.5072 21.093 16.2235 21.2299 16.7358 21.1904C17.3109 21.1462 17.7121 20.8737 17.7929 20.7929C18.1834 20.4024 18.8166 20.4024 19.2071 20.7929L20 21.5858L21.5858 20L20.7929 19.2071C20.6054 19.0196 20.5 18.7652 20.5 18.5C20.5 18.2348 20.6054 17.9804 20.7929 17.7929C20.8737 17.7121 21.1462 17.3109 21.1904 16.7358C21.2299 16.2235 21.093 15.5072 20.2929 14.7071C19.2821 13.6963 17.6908 13.2329 15.9492 12.9219C15.527 12.8465 15.1107 12.7821 14.7007 12.7187L14.7006 12.7186L14.6947 12.7177C14.47 12.683 14.2458 12.6482 14.0266 12.6124L16.482 15.0677C16.6472 15.0236 16.8208 15 17 15C18.1046 15 19 15.8954 19 17C19 18.1046 18.1046 19 17 19C15.8954 19 15 18.1046 15 17C15 16.8208 15.0236 16.6472 15.0677 16.482Z"
                              />
                            </svg>
                            <span className="text-[10px] font-semibold text-[var(--ks-color-text-primary)] whitespace-nowrap">
                              Adicionar arte
                            </span>
                          </button>
                          {artPreviews.length > 0 && (
                            <div className="h-8 rounded-full bg-white border border-[var(--ks-color-border-subtle)] flex items-center gap-2 px-3">
                              <span className="text-[10px] font-semibold text-[var(--ks-color-text-primary)]">
                                Mostrar no PDF
                              </span>
                              <Switch
                                checked={showArtInPdf}
                                onCheckedChange={(checked) =>
                                  setItemArtPdfVisibility((prev) => ({ ...prev, [it.id]: checked }))
                                }
                              />
                            </div>
                          )}
                            </div>
                          </div>
                          {artPreviews.length === 0 && (
                            <div className="text-xs text-[var(--ks-color-text-muted)] px-1">
                              Nenhuma arte enviada.
                            </div>
                          )}
                          {artPreviews.length > 0 && (
                            <>
                              <div className="grid grid-cols-[repeat(auto-fill,minmax(56px,1fr))] gap-2 w-full">
                                {artPreviews.map((url, index) => (
                                  <div
                                    key={`${url}-${index}`}
                                  className="group relative aspect-square rounded-xl bg-[var(--ks-color-bg-soft)] overflow-hidden border border-[var(--ks-color-border-subtle)] cursor-pointer"
                                  onClick={() => openArtPreview(url)}
                                  >
                                    <div className="absolute inset-0 bg-gradient-to-br from-white/0 via-white/0 to-white/40 opacity-0 group-hover:opacity-100 transition-opacity" />
                                    <Image
                                      src={url}
                                      alt="Arte"
                                      fill
                                      sizes="56px"
                                      className="object-cover transition-transform duration-300 group-hover:scale-110"
                                      unoptimized
                                    />
                                    <div className="absolute inset-0 rounded-xl ring-1 ring-white/60" />
                                  </div>
                                ))}
                              </div>
                            </>
                          )}
                        </div>
                      </div>
                    </div>
                    )}
                    {emEtapas && (
                      <RodapeDoItem
                        aoFocar={() => setActiveItemId(it.id)}
                        aoDuplicar={() => duplicateItem(idx)}
                        aoRemover={() => removeItem(idx)}
                        podeRemover={items.length > 1}
                      />
                    )}
                  </div>
                  </div>
                );
              })}
            </div>
            {emEtapas ? (
              <BotaoAdicionarItem onClick={addItem} />
            ) : (
            <div className="flex items-center pt-1">
              <button
                type="button"
                onClick={addItem}
                className="w-10 h-10 rounded-2xl bg-[var(--ks-color-brand-dark)] text-white transition-all hover:opacity-90 active:scale-95 inline-flex items-center justify-center shadow-md"
                title="Adicionar item"
                aria-label="Adicionar item"
              >
                <Plus size={18} />
              </button>
            </div>
            )}
          </div>

              {/* A aba Financeiro: as condições comerciais. Em etapas ela é a
                  etapa 3; na página única, um cartão logo depois dos itens. */}
              <div
                hidden={fora(3)}
                className={emEtapas ? undefined : "bg-white rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 shadow-sm space-y-5"}
              >
                {/* Em etapas, com condições, a chave mora no canto do cartão "Formas de
                    pagamento"; desligada (ou na página única), é a linha de título. */}
                {!(emEtapas && condicoes) && (
                  <ChaveDasCondicoes
                    ligada={condicoes !== null}
                    emEtapas={emEtapas}
                    aoMudar={alternarCondicoes}
                  />
                )}
                {condicoes && (
                  <CondicoesComerciaisEditor
                    chave={emEtapas ? <InterruptorDasCondicoes ligada aoMudar={alternarCondicoes} /> : undefined}
                    valor={condicoes}
                    aoMudar={setCondicoes}
                    total={totals.total}
                    dataDeEntrega={form.delivery_date || null}
                    emEtapas={emEtapas}
                    modelos={{
                      lista: modelosDaEmpresa,
                      podeGerenciar: ehDonoDaEmpresa,
                      aoUsar: setCondicoes,
                      aoMudarLista: setModelosDaEmpresa,
                    }}
                  />
                )}
              </div>

              {emEtapas && (
                <EtapaFinanceiro
                  hidden={fora(4)}
                  linhas={items.flatMap((i, idx) => {
                    if (!i.title.trim() && !i.description.trim()) return [];
                    const quantidade = effectiveQuantity(i);
                    const precoUnitario = parseMoneyInput(i.unit_price);
                    return [
                      {
                        id: i.id,
                        nome: i.title.trim() || `Item ${idx + 1}`,
                        detalhe: [getSelectedOptionsSummary(i), `${descreverQuantidade(quantidade, i.unit_type)} × ${formatMoney(precoUnitario)}`]
                          .filter(Boolean)
                          .join(" · "),
                        total: quantidade * precoUnitario,
                        custo: quantidade * parseMoneyInput(i.unit_cost),
                      },
                    ];
                  })}
                  totais={totals}
                  contribuicao={contribuicao}
                  podeVerCustos
                />
              )}

              <div
                hidden={fora(5, 6)}
                className={
                  emEtapas
                    ? `${CARTAO_EM_ETAPAS} order-2 flex flex-col gap-4`
                    : "bg-white rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 shadow-sm"
                }
              >
                {emEtapas && (
                  <>
                    <CabecalhoDoCartao
                      hidden={fora(5)}
                      icone="conversa"
                      titulo="Observações para o cliente"
                      descricao="Saem no PDF e no link público."
                    />
                    <CabecalhoDoCartao
                      hidden={fora(6)}
                      icone="notas"
                      titulo="Configurações"
                      descricao="Notas internas e o que o cliente vê no PDF e no link."
                    />
                  </>
                )}
                <div className={emEtapas ? "grid grid-cols-1 gap-4" : "grid grid-cols-1 lg:grid-cols-2 gap-4"}>
                  <div hidden={fora(5)} className="space-y-1">
                    <label className={emEtapas ? "sr-only" : "text-sm font-medium text-[var(--ks-color-text-primary)]"}>
                      Observações para o cliente (opcional)
                    </label>
                    <textarea
                      value={form.notes}
                      onChange={(e) => setForm((p) => ({ ...p, notes: e.target.value }))}
                      className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] min-h-[110px] bg-white"
                      placeholder="Prazo, condições, arte, prova, pagamento..."
                    />
                  </div>
                  <div hidden={fora(6)} className="space-y-1">
                    <label className="text-sm font-medium text-[var(--ks-color-text-primary)]">
                      Notas internas (opcional)
                    </label>
                    <textarea
                      value={form.internal_notes}
                      onChange={(e) => setForm((p) => ({ ...p, internal_notes: e.target.value }))}
                      className="w-full px-3 py-2.5 rounded-xl border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] min-h-[110px] bg-white"
                      placeholder="Fornecedor, custo, etapa de produção, prioridades..."
                    />
                  </div>
                  {/* Em etapas a Lista de Preço também mora em Configurações.
                      É o mesmo interruptor do resumo, ligado ao mesmo campo. */}
                  {emEtapas && (
                    <div hidden={fora(6)}>
                      <BlocoListaDePreco
                        checked={form.list_price_mode}
                        onCheckedChange={(checked) => setForm((p) => ({ ...p, list_price_mode: checked }))}
                      />
                    </div>
                  )}
                </div>
                {camposAtivosDoOrcamento.length > 0 && (
                  <div hidden={fora(6)} className={emEtapas ? "space-y-3" : "mt-5 space-y-3 border-t border-[var(--ks-color-border-subtle)] pt-5"}>
                    <div>
                      <p className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Informações extras</p>
                      <p className="text-xs text-[var(--ks-color-text-muted)]">Campos criados pela sua empresa. Ficam só no painel; os que existirem também no pedido passam para ele na aprovação.</p>
                    </div>
                    <CamposDoFormulario
                      definicoes={camposDoOrcamento}
                      valores={camposValores}
                      erros={camposErros}
                      prefixo="orcamento-novo-cp"
                      aoMudar={(chave, valor) => {
                        setCamposValores((atual) => ({ ...atual, [chave]: valor }));
                        setCamposErros((atual) => {
                          if (!atual[chave]) return atual;
                          const resto = { ...atual };
                          delete resto[chave];
                          return resto;
                        });
                      }}
                    />
                  </div>
                )}
              </div>
              <div hidden={fora(5)} className={emEtapas ? "order-1" : "mt-6"}>
                <ShippingCalculator
                  initialZip={selectedClient?.address_zip ? selectedClient.address_zip.replace(/\D/g, "").slice(0, 8) : ""}
                  selectedOption={shippingDetails}
                  onSelectShipping={(option) => {
                    if (option) {
                      setForm((p) => ({ ...p, shipping: formatMoneyInput(option.price) }));
                      setShippingDetails(option);
                    } else {
                      setForm((p) => ({ ...p, shipping: "0,00" }));
                      setShippingDetails(null);
                    }
                  }}
                />
              </div>
              {emEtapas && (
                <NavegacaoDasEtapas
                  className="order-3"
                  etapa={etapa}
                  aoVoltar={paginaEmEtapas.anterior}
                  aoAvancar={paginaEmEtapas.proximo}
                  salvar={{ rotulo: saving ? "Salvando..." : "Salvar", ocupado: saving }}
                />
              )}
            </div>

            <div className="lg:col-span-4 space-y-4 lg:sticky lg:top-6">
              <div className={emEtapas ? CARTAO_EM_ETAPAS : "bg-white rounded-3xl border border-[var(--ks-color-border-subtle)] p-6 shadow-sm"}>
                {emEtapas && (
                  <div className="mb-4">
                    <CabecalhoDoCartao icone="resumo" titulo="Resumo do orçamento" descricao="Os valores mudam conforme você preenche." />
                  </div>
                )}
                <div className="flex items-center justify-between text-sm text-[var(--ks-color-text-soft)]">
                  <span>Subtotal</span>
                  <span className="font-semibold text-[var(--ks-color-text-primary)]">{formatMoney(totals.subtotal)}</span>
                </div>
                <div className="flex items-center justify-between text-sm text-[var(--ks-color-text-soft)] mt-2">
                  <span>Desconto</span>
                  <div className="flex items-center gap-2">
                    <div className="flex items-center rounded-lg border border-[var(--ks-color-border-subtle)] bg-white overflow-hidden">
                      <button
                        type="button"
                        onClick={() => {
                          setDiscountType("value");
                          setForm((p) => ({ ...p, discount: formatMoneyInput(p.discount) }));
                        }}
                        className={[
                          "px-2 py-1 text-xs font-semibold transition-colors",
                          discountType === "value"
                            ? "bg-[var(--ks-color-primary-soft)] text-[var(--ks-color-primary-strong)]"
                            : "text-[var(--ks-color-text-soft)] hover:text-[var(--ks-color-text-primary)]",
                        ].join(" ")}
                      >
                        R$
                      </button>
                      <button
                        type="button"
                        onClick={() => {
                          setDiscountType("percent");
                          setForm((p) => ({ ...p, discount: formatPercentInput(p.discount) }));
                        }}
                        className={[
                          "px-2 py-1 text-xs font-semibold transition-colors border-l border-[var(--ks-color-border-subtle)]",
                          discountType === "percent"
                            ? "bg-[var(--ks-color-primary-soft)] text-[var(--ks-color-primary-strong)]"
                            : "text-[var(--ks-color-text-soft)] hover:text-[var(--ks-color-text-primary)]",
                        ].join(" ")}
                      >
                        %
                      </button>
                    </div>
                    <input
                      value={form.discount}
                      onChange={(e) =>
                        setForm((p) => ({
                          ...p,
                          discount:
                            discountType === "percent"
                              ? formatPercentInput(e.target.value)
                              : formatMoneyInput(e.target.value),
                        }))
                      }
                      className="w-32 px-2 py-1 text-right text-sm rounded-lg border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                      inputMode="numeric"
                    />
                  </div>
                </div>
                <div className="flex items-center justify-between text-sm text-[var(--ks-color-text-soft)] mt-2">
                  <span>Frete</span>
                  <input
                    value={form.shipping}
                    onChange={(e) => setForm((p) => ({ ...p, shipping: formatMoneyInput(e.target.value) }))}
                    className="w-32 px-2 py-1 text-right text-sm rounded-lg border border-[var(--ks-color-border-subtle)] focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] bg-white"
                    inputMode="numeric"
                  />
                </div>
                <div className="h-px bg-[var(--ks-color-border-subtle)] my-3" />
                <div className={emEtapas ? "flex items-baseline justify-between" : "flex items-center justify-between"}>
                  <span className={emEtapas ? "text-[17px] font-extrabold text-[var(--ks-color-text-primary)]" : "text-sm font-semibold text-[var(--ks-color-text-primary)]"}>
                    Total
                  </span>
                  <span
                    className={
                      emEtapas
                        ? "text-2xl font-extrabold tracking-tight tabular-nums text-[var(--ks-color-text-primary)]"
                        : "text-lg font-bold text-[var(--ks-color-text-primary)]"
                    }
                  >
                    {formatMoney(totals.total)}
                  </span>
                </div>
                {emEtapas ? (
                  <div className="mt-3">
                    <BlocoListaDePreco
                      checked={form.list_price_mode}
                      onCheckedChange={(checked) => setForm((p) => ({ ...p, list_price_mode: checked }))}
                    />
                  </div>
                ) : (
                <div className="mt-3 rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-soft)] px-3 py-2.5">
                  <div className="flex items-center justify-between gap-3">
                    <div>
                      <div className="text-sm font-semibold text-[var(--ks-color-text-primary)]">Lista de Preço</div>
                      <div className="text-[11px] text-[var(--ks-color-text-muted)]">
                        Oculta o valor total no PDF e no link público.
                      </div>
                    </div>
                    <Switch
                      checked={form.list_price_mode}
                      onCheckedChange={(checked) => setForm((p) => ({ ...p, list_price_mode: checked }))}
                    />
                  </div>
                </div>
                )}
                <div
                  className={
                    emEtapas
                      ? "mt-3 text-[13px] text-[var(--ks-color-text-secondary)] border-t border-[var(--ks-color-border-subtle)] pt-3"
                      : "mt-3 text-xs text-[var(--ks-color-text-muted)] border-t border-[var(--ks-color-border-subtle)] pt-3"
                  }
                >
                  <div className="flex items-center justify-between">
                    <span>Custo estimado</span>
                    <span className="font-semibold text-[var(--ks-color-text-primary)]">{formatMoney(totals.cost)}</span>
                  </div>
                  <div className="flex items-center justify-between mt-1">
                    <span>Lucro Bruto</span>
                    <span className={`font-semibold ${totals.margin >= 0 ? "text-emerald-600" : "text-rose-600"}`}>
                      {formatMoney(totals.margin)}
                    </span>
                  </div>
                  <div className="flex items-center justify-between mt-1">
                    <div className="flex items-center gap-1">
                      <span>Margem Total</span>
                      {totals.marginPct < 30 && totals.total > 0 && <InfoTooltip text="Margem abaixo de 30% pode ser arriscada." />}
                    </div>
                    <span
                      className={`font-bold ${
                        totals.margin < 0 ? "text-rose-700" : totals.marginPct < 30 ? "text-amber-600" : "text-emerald-700"
                      }`}
                    >
                      {totals.marginPct.toFixed(1)}%
                    </span>
                  </div>
                  {contribuicao && totals.total > 0 && (
                    <>
                      {/* Em etapas o resumo fica enxuto: MC, IRG e custos
                          produtivos abrem por aqui, e por inteiro na etapa 3. */}
                      {emEtapas && (
                        <button
                          type="button"
                          onClick={() => setMaisIndicadores((aberto) => !aberto)}
                          aria-expanded={maisIndicadores}
                          className="mt-2 flex w-full items-center justify-between gap-2 text-xs font-semibold text-[var(--ks-color-primary)]"
                        >
                          Mais indicadores
                          <ChevronDown size={14} className={`transition-transform ${maisIndicadores ? "rotate-180" : ""}`} />
                        </button>
                      )}
                      <div hidden={emEtapas && !maisIndicadores}>
                      <div className="flex items-center justify-between mt-2 pt-2 border-t border-[var(--ks-color-border-subtle)]">
                        <div className="flex items-center gap-1">
                          <span>MC — contribuição</span>
                          <InfoTooltip text={`Também chamada de VMC (valor) e ICM (índice): o que este orçamento devolve para pagar as contas da empresa — total menos matéria-prima e menos ${contribuicao.variaveisPct.toFixed(1)}% de impostos e taxas. A mão de obra fica dentro: é custo fixo sendo recuperado.`} />
                        </div>
                        <span className={`font-semibold ${contribuicao.mc >= 0 ? "text-[var(--ks-color-text-primary)]" : "text-rose-600"}`}>
                          {formatMoney(contribuicao.mc)}
                          <span className="font-normal text-[var(--ks-color-text-soft)]"> · {contribuicao.mcPct.toFixed(1)}%</span>
                        </span>
                      </div>
                      {contribuicao.irgPct != null && (
                        <div className="flex items-center justify-between mt-1">
                          <div className="flex items-center gap-1">
                            <span>IRG</span>
                            <InfoTooltip text={`Índice de representatividade geral: aprovando este orçamento, o ponto de equilíbrio do mês avança ${contribuicao.irgPct.toFixed(1)}% — a contribuição dele sobre o custo fixo de ${formatMoney(contribuicao.fixoMensal)}.`} />
                          </div>
                          <span className={`font-bold ${contribuicao.irgPct > 0 ? "text-emerald-700" : "text-rose-700"}`}>
                            {contribuicao.irgPct.toFixed(1)}%
                          </span>
                        </div>
                      )}
                      {totals.cost > 0 && (
                        <div className="mt-2">
                          <div className="flex items-center justify-between text-[11px] text-[var(--ks-color-text-soft)]">
                            <div className="flex items-center gap-1">
                              <span>Custos produtivos</span>
                              <InfoTooltip text="O custo dividido pela ficha dos produtos: matéria-prima × mão de obra e máquina. Tem serviço em que a máquina custa mais que o material — é aqui que isso aparece." />
                            </div>
                          </div>
                          <div className="mt-1 flex h-2 rounded-full overflow-hidden bg-[var(--ks-color-bg-hover)]">
                            <div style={{ width: `${totals.cost > 0 ? (contribuicao.materiaPrima / totals.cost) * 100 : 0}%`, background: "var(--ks-amber)" }} />
                            <div style={{ width: `${totals.cost > 0 ? (contribuicao.maoDeObra / totals.cost) * 100 : 0}%`, background: "var(--ks-sky)" }} />
                          </div>
                          <div className="mt-1 flex items-center justify-between text-[10px] text-[var(--ks-color-text-soft)]">
                            <span className="inline-flex items-center gap-1">
                              <span className="h-2 w-2 rounded-full" style={{ background: "var(--ks-amber)" }} />
                              matéria-prima {formatMoney(contribuicao.materiaPrima)}
                            </span>
                            <span className="inline-flex items-center gap-1">
                              <span className="h-2 w-2 rounded-full" style={{ background: "var(--ks-sky)" }} />
                              mão de obra {formatMoney(contribuicao.maoDeObra)}
                            </span>
                          </div>
                        </div>
                      )}
                      </div>
                    </>
                  )}
                </div>
              </div>

              {error && (
                <div className="bg-red-50 text-red-600 text-sm px-4 py-2 rounded-2xl flex items-center gap-2 border border-red-100">
                  <div className="w-1.5 h-1.5 rounded-full bg-red-600" />
                  {error}
                </div>
              )}

              <div className={emEtapas ? "grid grid-cols-2 gap-2.5" : "flex items-center justify-end gap-2"}>
                <Link
                  href="/dashboard/quotes"
                  className={`px-4 py-2 rounded-2xl border border-[var(--ks-color-border-subtle)] text-[var(--ks-color-text-primary)] hover:bg-[var(--ks-color-bg-soft)] transition-colors ${
                    emEtapas ? "inline-flex items-center justify-center py-2.5 font-semibold" : ""
                  }`}
                >
                  Cancelar
                </Link>
                <button
                  type="submit"
                  disabled={saving}
                  className={`flex items-center gap-2 px-6 py-2.5 bg-[var(--ks-color-primary)] text-white rounded-2xl hover:bg-[var(--ks-color-primary-strong)] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--ks-color-primary)] disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-sm font-medium ${
                    emEtapas ? "justify-center" : ""
                  }`}
                >
                  <Save size={18} />
                  {saving ? "Salvando..." : "Salvar"}
                </button>
              </div>
            </div>
          </div>
        </form>
      )}





      <Dialog open={artModalOpen} onOpenChange={(open) => !open && closeArtModal()}>
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle>Cadastro de arte</DialogTitle>
            <DialogDescription>Envie o croqui e fotos para aprovacao do cliente.</DialogDescription>
          </DialogHeader>
          <div className="space-y-4">
            <div className="space-y-1">
              <label className="text-sm font-medium text-zinc-700">Título</label>
              <input
                value={artDraft?.title || ""}
                onChange={(e) => setArtDraft((prev) => (prev ? { ...prev, title: e.target.value } : prev))}
                className="w-full px-3 py-2.5 rounded-xl border border-zinc-200 focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)]"
                placeholder="Ex: Croqui da fachada"
                disabled={artUploading}
              />
            </div>
            <div className="space-y-1">
              <label className="text-sm font-medium text-zinc-700">Observações (opcional)</label>
              <textarea
                value={artDraft?.notes || ""}
                onChange={(e) => setArtDraft((prev) => (prev ? { ...prev, notes: e.target.value } : prev))}
                className="w-full px-3 py-2.5 rounded-xl border border-zinc-200 focus:outline-none focus:ring-2 focus:ring-[var(--ks-color-primary)]/20 focus:border-[var(--ks-color-primary)] min-h-[90px]"
                disabled={artUploading}
              />
            </div>
            <div className="space-y-1">
              <label className="text-sm font-medium text-zinc-700">Fotos da arte</label>
              <input
                type="file"
                multiple
                accept="image/*"
                onChange={(e) => handleArtFiles(e.target.files)}
                className="block w-full text-sm text-zinc-600 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:bg-[var(--ks-color-primary-soft)] file:text-[var(--ks-color-primary-strong)] file:font-semibold hover:file:bg-[var(--ks-color-primary)] hover:file:text-white"
                disabled={artUploading}
              />
              <div className="text-xs text-zinc-500">Imagens sao convertidas para WebP automaticamente.</div>
            </div>

            {artDraft?.files?.length ? (
              <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
                {artDraft.files.map((file) => (
                  <div key={file.previewUrl} className="relative h-24 rounded-lg border border-zinc-200 overflow-hidden">
                    <Image
                      src={file.previewUrl}
                      alt="Arte"
                      fill
                      sizes="96px"
                      className="object-cover"
                      unoptimized
                    />
                    <button
                      type="button"
                      onClick={() => removeArtImage(file.previewUrl)}
                      className="absolute top-2 right-2 bg-white/90 text-zinc-700 hover:text-red-600 rounded-full p-1 shadow"
                      disabled={artUploading}
                    >
                      <Trash2 size={14} />
                    </button>
                  </div>
                ))}
              </div>
            ) : (
              <div className="text-xs text-zinc-500">Nenhuma imagem enviada.</div>
            )}

            {artError && (
              <div className="text-sm text-red-600 bg-red-50 border border-red-100 rounded-lg px-3 py-2">
                {artError}
              </div>
            )}
          </div>
          <DialogFooter>
            <button
              type="button"
              onClick={closeArtModal}
              className="px-4 py-2 rounded-lg border border-zinc-200 text-zinc-700 hover:bg-zinc-50"
              disabled={artUploading}
            >
              Cancelar
            </button>
            <button
              type="button"
              onClick={saveArtDraft}
              className="px-4 py-2 rounded-lg bg-[var(--ks-color-primary)] text-white hover:bg-[var(--ks-color-primary-strong)]"
              disabled={artUploading}
            >
              Salvar arte
            </button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog
        open={previewOpen}
        onOpenChange={(open) => {
          setPreviewOpen(open);
          if (!open) setPreviewImageUrl(null);
        }}
      >
        <DialogContent className="max-w-[92vw] w-auto border-0 bg-transparent p-0 shadow-none">
          <DialogHeader className="sr-only">
            <DialogTitle>Pré-visualização da arte</DialogTitle>
          </DialogHeader>
          <div className="relative">
            <button
              type="button"
              onClick={() => {
                setPreviewOpen(false);
                setPreviewImageUrl(null);
              }}
              className="absolute -top-10 right-0 h-9 w-9 rounded-full bg-black/70 text-white flex items-center justify-center shadow-lg hover:bg-black/80"
            >
              <X size={18} />
            </button>
            {previewImageUrl && (
              <Image
                src={previewImageUrl}
                alt="Arte ampliada"
                width={1200}
                height={800}
                sizes="90vw"
                className="max-h-[80vh] max-w-[90vw] object-contain shadow-[0_30px_80px_rgba(0,0,0,0.45)]"
                unoptimized
              />
            )}
          </div>
        </DialogContent>
      </Dialog>
      <ClientFormModal
        isOpen={clientModalOpen}
        onClose={() => setClientModalOpen(false)}
        onSuccess={(createdClientId) => {
          void refreshClients(createdClientId);
        }}
      />
    </div>
    </div>
  );
}
