/* Shared mock data, icon helper, and formatters for the 1Threshold quoting-tool UI kit. */

// ── Icon helper (lucide UMD → React SVG) ──────────────────────────────
function Icon({ name, size = 20, stroke = 2, color = "currentColor", style, ...rest }) {
  const node = (window.lucide && (window.lucide.icons?.[name] || window.lucide[name]));
  if (!node) return null;
  const children = Array.isArray(node) ? node : (node.default || []);
  return React.createElement(
    "svg",
    { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: color, strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round", style, ...rest },
    children.map(([tag, attrs], i) => React.createElement(tag, { key: i, ...attrs }))
  );
}

// ── Formatters ────────────────────────────────────────────────────────
const fmt = (n) => "$" + Number(n).toLocaleString("en-US", { maximumFractionDigits: 0 });
const fmtD = (n) => "$" + Number(n).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

// ── Mock data ─────────────────────────────────────────────────────────
// Sales reps (the people payroll pays).
const REPS = [
  { id: "marco",  name: "Marco Reyes",   initials: "MR", role: "Senior Design Consultant", draw: 1200 },
  { id: "priya",  name: "Priya Nair",    initials: "PN", role: "Design Consultant",        draw: 1000 },
  { id: "devon",  name: "Devon White",   initials: "DW", role: "Design Consultant",        draw: 1000 },
  { id: "sofia",  name: "Sofia Marquez", initials: "SM", role: "Junior Consultant",        draw: 800  },
];

// Quotes. Sold quotes carry the margin + commission the engine produced at close.
// (rate from the commission tier table: ≥82%→13.7, ≥80%→12.7, ≥65%→9.7, ≥60%→5.7, ≥57%→3.3, else 3.0)
// Build a full calculator state from interior line-items so a demo quote
// presents/contracts with its real computed total (not the $1,200 default).
// Styles/cores/heights below are real catalog rows. `barn` adds a sliding-barn
// line via customItems. `cc` toggles a custom (non-factory) paint color.
const _qOpts = { paint: true, install: true, hardwareInstall: true, disposal: true, freight: true, measure3d: true, customColor: false, barn: false, casingSides: 0 };
const _qDisc = { bogo: false, volume: true, military: false, hundredOff: false, freeInstall: false, wholeHome99: false, thirtyOff: false, freeHardware: false };
const qState = (interior, opts) => ({
  interior,
  exterior: [],
  customItems: (opts && opts.customItems) || [],
  options: Object.assign({}, _qOpts, opts && opts.options),
  discounts: Object.assign({}, _qDisc, opts && opts.discounts),
});
// Convenience line builders (Cape Cod - M Series is the house standard).
const cc68 = (qty) => ({ style: "Cape Cod - M Series", core: "Solid", height: "6/8", qty });
const cc80 = (qty) => ({ style: "Cape Cod - M Series", core: "Solid", height: "8/0", qty });
const flat68 = (qty) => ({ style: "Flat Flush", core: "Solid", height: "6/8", qty });
const pine68 = (qty) => ({ style: "6-Panel Pine", core: "Solid", height: "6/8", qty });
const barnLine = { label: "Classic Barn Door Painted (7/0)", qty: 1, price: 2683.8 };

const QUOTES = [
  { id: "Q-1042", customer: "Marguerite Olsen",       address: "118 Cibolo Ridge, San Antonio TX", rep: "marco", date: "Jun 14", period: "2026-06B", total: 13244.21, margin: 0.71, rate: 0.097, commission: 1284.69, status: "sold", installed: false, state: qState([cc68(8), cc80(2)]) },
  { id: "Q-1041", customer: "The Castillo Residence",  address: "9042 Stone Oak Pkwy",              rep: "priya", date: "Jun 14", period: "2026-06B", total: 8650.00,  margin: 0.63, rate: 0.057, commission: 0,       status: "pending", state: qState([flat68(6)]) },
  { id: "Q-1039", customer: "Dwight & Ana Reyes",      address: "204 Alamo Heights Blvd",          rep: "marco", date: "Jun 13", period: "2026-06B", total: 21300.00, margin: 0.74, rate: 0.097, commission: 0,       status: "pending", state: qState([cc68(12), cc80(2)], { options: { barn: true }, customItems: [barnLine] }) },
  { id: "Q-1036", customer: "Beverly Tran",            address: "77 Shavano Park Dr",              rep: "devon", date: "Jun 12", period: "2026-06B", total: 5980.00,  margin: 0.58, rate: 0.033, commission: 0,       status: "lost", state: qState([flat68(5)]) },
  { id: "Q-1034", customer: "Holloway Family",         address: "1450 Boerne Stage Rd",            rep: "priya", date: "Jun 11", period: "2026-06B", total: 16740.00, margin: 0.81, rate: 0.127, commission: 2125.98, status: "sold", installed: false, state: qState([cc68(12)]) },
  { id: "Q-1031", customer: "Sandra & Phil Becker",    address: "62 Terrell Hills Ct",             rep: "devon", date: "Jun 10", period: "2026-06B", total: 9420.00,  margin: 0.66, rate: 0.097, commission: 913.74,  status: "sold", installed: true, state: qState([cc68(7)]) },
  { id: "Q-1029", customer: "The Fernandez Group",     address: "330 Olmos Dr",                    rep: "marco", date: "Jun 09", period: "2026-06A", total: 24880.00, margin: 0.83, rate: 0.137, commission: 3408.56, status: "sold", installed: true, state: qState([cc68(12), cc80(2)], { options: { barn: true }, customItems: [barnLine] }) },
  { id: "Q-1025", customer: "Karen Whitfield",         address: "12 Dominion Crest",               rep: "sofia", date: "Jun 06", period: "2026-06A", total: 7310.00,  margin: 0.62, rate: 0.057, commission: 416.67,  status: "sold", installed: false, state: qState([flat68(6)]) },
  { id: "Q-1022", customer: "Liang Residence",         address: "885 Encino Rio",                  rep: "priya", date: "Jun 05", period: "2026-06A", total: 11050.00, margin: 0.69, rate: 0.097, commission: 1071.85, status: "sold", installed: true, state: qState([cc68(8)]) },
  { id: "Q-1018", customer: "Otto & June Sandoval",    address: "47 Bluff Creek",                  rep: "devon", date: "Jun 03", period: "2026-06A", total: 13990.00, margin: 0.59, rate: 0.033, commission: 461.67,  status: "sold", installed: true, state: qState([cc68(9), pine68(1)]) },
  { id: "Q-1015", customer: "The Achebe Family",       address: "209 Vance Jackson",               rep: "marco", date: "Jun 02", period: "2026-06A", total: 18420.00, margin: 0.80, rate: 0.127, commission: 2339.34, status: "sold", installed: false, state: qState([cc68(13)]) },
  { id: "Q-1011", customer: "Greta Lindqvist",         address: "5 Champions Run",                 rep: "sofia", date: "Jun 02", period: "2026-06A", total: 6240.00,  margin: 0.57, rate: 0.033, commission: 205.92,  status: "sold", installed: true, state: qState([flat68(5)]) },
];

// Pay periods (semi-monthly). The current one is open.
const PAY_PERIODS = [
  { id: "2026-06B", label: "Jun 16 – 30, 2026", payDate: "Jul 05", status: "open" },
  { id: "2026-06A", label: "Jun 01 – 15, 2026", payDate: "Jun 20", status: "processing" },
  { id: "2026-05B", label: "May 16 – 31, 2026", payDate: "Jun 05", status: "paid" },
];

const INTERIOR_LINES = [
  { id: 1, style: "Shaker 2-Panel", qty: 6, unit: 420 },
  { id: 2, style: "Flat Modern Slab", qty: 2, unit: 510 },
];
const EXTERIOR_LINES = [
  { id: 3, location: "Front Entry", style: "Craftsman 3/4 Lite", cost: 2400, install: 780 },
];

// Pricing ladder figures
const PRICING = { retail: 18900, advertised: 15400, today: 12480 };

const FINANCING = [
  { id: "12", label: "12 mo · 0% Interest", monthly: 1040 },
  { id: "36", label: "36 mo · 7.99% APR", monthly: 391 },
  { id: "60", label: "60 mo · 5.99% APR", monthly: 241 },
];

const VALUE_FEATURES = [
  { icon: "Crosshair", title: "3D Imaging Accuracy", desc: "Custom 3D imaging accurate to 1/1000th of an inch — precise hinge and backset locations every time." },
  { icon: "Zap", title: "Done in One Day", desc: "One team, one visit. We complete your entire door project in a single day." },
  { icon: "ShieldCheck", title: "Worry-Free Guarantee", desc: "Our Absolutely, Positively, Worry-Free Guarantee covers labor and materials." },
  { icon: "Sparkles", title: "Premium Finish", desc: "Thermally fused, double baked-on eggshell finish over cap-stocked engineered lumber." },
  { icon: "Trash2", title: "Full Debris Removal", desc: "All job-related debris removed upon completion. We leave your home spotless." },
  { icon: "Store", title: "Coast-to-Coast Stores", desc: "National presence with local expertise — here for you long after installation." },
];

// ── Brand lockup (One Day Doors & Closets of San Antonio) ──────────────
// "1Threshold" is the internal software name only; every visible surface
// carries the customer-facing One Day brand artwork.
function BrandMark({ height = 34, onDark = false, variant = "lockup" }) {
  // variant "lockup" = full horizontal mark with "Love What Doors Do";
  //         "stacked" = compact square mark.
  const src = variant === "stacked" ? window.__OD_LOGO_STACKED : window.__OD_LOGO_LOCKUP;
  const ratio = variant === "stacked" ? (663 / 207) : (903 / 175);
  return (
    <img src={src} alt="One Day Doors & Closets of San Antonio"
      style={{ height, width: height * ratio, objectFit: "contain", display: "block", filter: onDark ? "brightness(0) invert(1)" : "none" }} />
  );
}

// ── Press / "As seen in" logos ─────────────────────────────────────────
// Real logo files drop into window.__OD_PRESS[key] (set in assets/press.data.js).
// Until then, an elegant editorial wordmark stands in.
const PRESS = [
  { key: "good-housekeeping", name: "Good Housekeeping" },
  { key: "hgtv",              name: "HGTV" },
  { key: "the-spruce",        name: "The Spruce" },
  { key: "magnolia",          name: "Magnolia Network" },
];
function PressLogo({ item, height = 28 }) {
  const src = (window.__OD_PRESS || {})[item.key];
  if (src) {
    return <img src={src} alt={item.name} title={item.name} style={{ height, width: "auto", maxWidth: 150, objectFit: "contain", filter: "grayscale(1)", opacity: 0.7 }} />;
  }
  return (
    <span title={item.name} style={{ display: "inline-flex", alignItems: "center", height, padding: "0 4px", fontFamily: "var(--font-signature)", fontSize: 16, fontWeight: 600, letterSpacing: "0.01em", color: "var(--text-faint)", whiteSpace: "nowrap" }}>{item.name}</span>
  );
}

const repName = (id) => (REPS.find((r) => r.id === id) || {}).name || id;

// ── Sorting helpers (shared by every table) ───────────────────────────
function sortList(arr, key, dir, get) {
  const g = get || ((o) => o[key]);
  const s = [...arr].sort((a, b) => {
    let x = g(a), y = g(b);
    if (typeof x === "string" && typeof y === "string") { x = x.toLowerCase(); y = y.toLowerCase(); }
    if (x == null) x = -Infinity; if (y == null) y = -Infinity;
    return x < y ? -1 : x > y ? 1 : 0;
  });
  return dir === "desc" ? s.reverse() : s;
}
// Clickable sortable column header. `sort` = {key,dir}; `setSort` toggles.
function SortHeader({ label, k, sort, setSort, align }) {
  const active = sort.key === k;
  return (
    <button
      onClick={() => setSort(active ? { key: k, dir: sort.dir === "asc" ? "desc" : "asc" } : { key: k, dir: "asc" })}
      style={{ display: "flex", alignItems: "center", gap: 4, width: "100%", border: "none", background: "transparent", cursor: "pointer", padding: 0,
        justifyContent: align === "right" ? "flex-end" : "flex-start",
        fontFamily: "var(--font-sans)", fontSize: "var(--text-2xs)", fontWeight: 600, letterSpacing: "var(--tracking-widest)", textTransform: "uppercase",
        color: active ? "var(--color-primary-deep)" : "var(--text-faint)" }}>
      {label}
      <span style={{ fontSize: 9, lineHeight: 1, opacity: active ? 1 : 0.35 }}>{active ? (sort.dir === "asc" ? "▲" : "▼") : "⇅"}</span>
    </button>
  );
}

Object.assign(window, { Icon, fmt, fmtD, BrandMark, PRESS, PressLogo, repName, sortList, SortHeader, QUOTES, REPS, PAY_PERIODS, INTERIOR_LINES, EXTERIOR_LINES, PRICING, FINANCING, VALUE_FEATURES });

// Shared default quote seed so the Calculator and Presentation show identical real numbers.
const DEFAULT_QUOTE_STATE = {
  interior: [
    { style: "Cape Cod - M Series", core: "Solid", height: "6/8", qty: 6 },
    { style: "Cape Cod - M Series", core: "Solid", height: "8/0", qty: 2 },
  ],
  exterior: [],
  customItems: [],
  options: { paint: true, install: true, hardwareInstall: true, disposal: true, freight: true, measure3d: true, customColor: false, barn: false, casingSides: 0 },
  discounts: { bogo: false, volume: true, military: false, hundredOff: false, freeInstall: false, wholeHome99: false, thirtyOff: false, freeHardware: false },
};
window.DEFAULT_QUOTE_STATE = DEFAULT_QUOTE_STATE;

// Shared customer record (pre-fills the calculator, presentation, and contract).
const CUSTOMER = {
  name: "Marguerite Olsen",
  address: "118 Cibolo Ridge, San Antonio, TX 78258",
  email: "m.olsen@example.com",
  phone: "(210) 555-0182",
  invoice: "SA-10428",
  rep: "Marco Reyes",
};
window.CUSTOMER = CUSTOMER;

// ── Sherwin-Williams color chart (curated) — code → {name, hex} ──────────────
// Whites/off-whites: exactly 4 are factory-standard (std); the rest are popular custom colors.
window.SW_COLORS = [
  {"code":"SW 7006","name":"Extra White","hex":"#EFF0EC","std":true},
  {"code":"SW 7005","name":"Pure White","hex":"#EEEDE7","std":true},
  {"code":"SW 7008","name":"Alabaster","hex":"#EEEBE1","std":true},
  {"code":"SW 7009","name":"Pearly White","hex":"#E7E4D9","std":true},
  {"code":"SW 7004","name":"Snowbound","hex":"#EEEBE5"},
  {"code":"SW 7757","name":"High Reflective White","hex":"#F7F7F1"},
  {"code":"SW 9132","name":"Acacia Haze","hex":"#969C92"},
  {"code":"SW 7036","name":"Accessible Beige","hex":"#D1C9B8"},
  {"code":"SW 7035","name":"Aesthetic White","hex":"#E4DFD4"},
  {"code":"SW 7029","name":"Agreeable Gray","hex":"#D2CDC2"},
  {"code":"SW 6241","name":"Aleutian","hex":"#9CAABA"},
  {"code":"SW 7044","name":"Amazing Gray","hex":"#BFB8AA"},
  {"code":"SW 7051","name":"Analytical Gray","hex":"#BDB7A6"},
  {"code":"SW 7030","name":"Anew Gray","hex":"#BFB8AB"},
  {"code":"SW 6119","name":"Antique White","hex":"#E7DEC7"},
  {"code":"SW 7065","name":"Argos","hex":"#B9BBB6"},
  {"code":"SW 6179","name":"Artichoke","hex":"#7E8769"},
  {"code":"SW 6505","name":"Atmospheric","hex":"#C5D9E2"},
  {"code":"SW 7037","name":"Balanced Beige","hex":"#BFB3A1"},
  {"code":"SW 6194","name":"Basil","hex":"#617262"},
  {"code":"SW 6120","name":"Believable Buff","hex":"#D9CAA8"},
  {"code":"SW 7648","name":"Big Chill","hex":"#D0CFCA"},
  {"code":"SW 7020","name":"Black Fox","hex":"#4E4841"},
  {"code":"SW 6991","name":"Black Magic","hex":"#333232"},
  {"code":"SW 6122","name":"Camelback","hex":"#C3AF86"},
  {"code":"SW 6054","name":"Canyon Clay","hex":"#895D50"},
  {"code":"SW 7701","name":"Cavern Clay","hex":"#AE6F5A"},
  {"code":"SW 6990","name":"Caviar","hex":"#302E2F"},
  {"code":"SW 6178","name":"Clary Sage","hex":"#AAB097"},
  {"code":"SW 6192","name":"Coastal Plain","hex":"#9DA894"},
  {"code":"SW 7641","name":"Colonnade Gray","hex":"#C5BFB6"},
  {"code":"SW 6191","name":"Contented","hex":"#BDC2B4"},
  {"code":"SW 7012","name":"Creamy","hex":"#EEEADC"},
  {"code":"SW 7076","name":"Cyberspace","hex":"#44484D"},
  {"code":"SW 6901","name":"Daffodil","hex":"#F6DF77"},
  {"code":"SW 6243","name":"Distance","hex":"#626E82"},
  {"code":"SW 6079","name":"Diverse Beige","hex":"#C4B7A8"},
  {"code":"SW 6989","name":"Domino","hex":"#343136"},
  {"code":"SW 7017","name":"Dorian Gray","hex":"#ACA99F"},
  {"code":"SW 6385","name":"Dover White","hex":"#EFECDD"},
  {"code":"SW 6186","name":"Dried Thyme","hex":"#7B8372"},
  {"code":"SW 6958","name":"Dynamic Blue","hex":"#198BCB"},
  {"code":"SW 7014","name":"Eider White","hex":"#E2DED8"},
  {"code":"SW 7650","name":"Ellie Gray","hex":"#AAAAA4"},
  {"code":"SW 9130","name":"Evergreen Fog","hex":"#95978A"},
  {"code":"SW 6867","name":"Fireworks","hex":"#D73930"},
  {"code":"SW 7514","name":"Foothills","hex":"#837568"},
  {"code":"SW 7736","name":"Garden Sage","hex":"#B2A787"},
  {"code":"SW 7019","name":"Gauntlet Gray","hex":"#78746E"},
  {"code":"SW 6257","name":"Gibraltar","hex":"#656B73"},
  {"code":"SW 7066","name":"Gray Matters","hex":"#A4A7A2"},
  {"code":"SW 7071","name":"Gray Screen","hex":"#C8CBCB"},
  {"code":"SW 7551","name":"Greek Villa","hex":"#EFECE3"},
  {"code":"SW 7068","name":"Grizzle Gray","hex":"#636562"},
  {"code":"SW 6520","name":"Honest Blue","hex":"#B5C5D5"},
  {"code":"SW 9178","name":"In the Navy","hex":"#283849"},
  {"code":"SW 7602","name":"Indigo Batik","hex":"#4D5C6D"},
  {"code":"SW 6992","name":"Inkwell","hex":"#2F3338"},
  {"code":"SW 7069","name":"Iron Ore","hex":"#444543"},
  {"code":"SW 7013","name":"Ivory Lace","hex":"#E8E4D8"},
  {"code":"SW 7533","name":"Khaki Shade","hex":"#C1B19A"},
  {"code":"SW 6106","name":"Kilim Beige","hex":"#D7C9B0"},
  {"code":"SW 6885","name":"Knockout Orange","hex":"#E56F38"},
  {"code":"SW 6108","name":"Latte","hex":"#BAA587"},
  {"code":"SW 6909","name":"Lemon Twist","hex":"#F9E257"},
  {"code":"SW 0055","name":"Light French Gray","hex":"#C2C1BB"},
  {"code":"SW 6142","name":"Macadamia","hex":"#CBBB9C"},
  {"code":"SW 7001","name":"Marshmallow","hex":"#EFEAE1"},
  {"code":"SW 7031","name":"Mega Greige","hex":"#ADA497"},
  {"code":"SW 7016","name":"Mindful Gray","hex":"#BCB8AE"},
  {"code":"SW 7652","name":"Mineral Deposit","hex":"#ACB0AF"},
  {"code":"SW 6232","name":"Misty","hex":"#CDD1D2"},
  {"code":"SW 7632","name":"Modern Gray","hex":"#D7CFC6"},
  {"code":"SW 9142","name":"Moscow Midnight","hex":"#204652"},
  {"code":"SW 7011","name":"Natural Choice","hex":"#E3DED0"},
  {"code":"SW 9109","name":"Natural Linen","hex":"#DFD3C3"},
  {"code":"SW 6244","name":"Naval","hex":"#303A4C"},
  {"code":"SW 7073","name":"Network Gray","hex":"#A1A7A8"},
  {"code":"SW 9137","name":"Niebla Azul","hex":"#B6C3C4"},
  {"code":"SW 6107","name":"Nomadic Desert","hex":"#C6B498"},
  {"code":"SW 6496","name":"Oceanside","hex":"#005370"},
  {"code":"SW 7072","name":"Online","hex":"#B1B6B7"},
  {"code":"SW 6491","name":"Open Air","hex":"#C9DEE1"},
  {"code":"SW 7636","name":"Origami White","hex":"#E6E2DB"},
  {"code":"SW 7064","name":"Passive","hex":"#CCCDC9"},
  {"code":"SW 7642","name":"Pavestone","hex":"#A29C93"},
  {"code":"SW 7674","name":"Peppercorn","hex":"#636364"},
  {"code":"SW 6073","name":"Perfect Greige","hex":"#B5AB9E"},
  {"code":"SW 6208","name":"Pewter Green","hex":"#5F645A"},
  {"code":"SW 6193","name":"Privilege Green","hex":"#7A8B79"},
  {"code":"SW 6212","name":"Quietude","hex":"#ABBBB4"},
  {"code":"SW 6230","name":"Rainstorm","hex":"#2B4656"},
  {"code":"SW 6868","name":"Real Red","hex":"#C6222F"},
  {"code":"SW 7015","name":"Repose Gray","hex":"#CDCAC2"},
  {"code":"SW 6207","name":"Retreat","hex":"#7C8379"},
  {"code":"SW 6209","name":"Ripe Olive","hex":"#474C42"},
  {"code":"SW 6222","name":"Riverway","hex":"#607477"},
  {"code":"SW 2802","name":"Rookwood Red","hex":"#652F2A"},
  {"code":"SW 6187","name":"Rosemary","hex":"#646D5E"},
  {"code":"SW 2839","name":"Roycroft Copper Red","hex":"#7B311E"},
  {"code":"SW 9177","name":"Salty Dog","hex":"#234058"},
  {"code":"SW 6204","name":"Sea Salt","hex":"#CDD3CA"},
  {"code":"SW 7615","name":"Sea Serpent","hex":"#4C5860"},
  {"code":"SW 7042","name":"Shoji White","hex":"#E6E0D3"},
  {"code":"SW 7588","name":"Show Stopper","hex":"#A73C41"},
  {"code":"SW 6225","name":"Sleepy Blue","hex":"#BCCBCF"},
  {"code":"SW 6177","name":"Softened Green","hex":"#BABFA8"},
  {"code":"SW 7074","name":"Software","hex":"#7F8486"},
  {"code":"SW 9138","name":"Stardew","hex":"#A6B2B5"},
  {"code":"SW 7585","name":"Sundried Tomato","hex":"#713F3E"},
  {"code":"SW 6164","name":"Svelte Sage","hex":"#B1B097"},
  {"code":"SW 7038","name":"Tony Taupe","hex":"#B1A491"},
  {"code":"SW 6217","name":"Topsail","hex":"#DAE3E0"},
  {"code":"SW 6218","name":"Tradewind","hex":"#C2D0D1"},
  {"code":"SW 6258","name":"Tricorn Black","hex":"#2D2D2E"},
  {"code":"SW 6239","name":"Upward","hex":"#C1C9D1"},
  {"code":"SW 7048","name":"Urbane Bronze","hex":"#535049"},
  {"code":"SW 7050","name":"Useful Gray","hex":"#CFCBBD"},
  {"code":"SW 6478","name":"Watery","hex":"#B4CCCA"},
  {"code":"SW 7075","name":"Web Gray","hex":"#62676A"},
  {"code":"SW 7566","name":"Westhighland White","hex":"#F2EEE4"},
  {"code":"SW 7043","name":"Worldly Gray","hex":"#CEC8BB"}
];
// Normalize a typed code ("6258", "sw6258", "SW 6258") and resolve to a chart entry.
window.swLookup = function (raw) {
  if (!raw) return null;
  const digits = String(raw).replace(/[^0-9]/g, "");
  if (!digits) return null;
  const norm = "SW " + digits.padStart(4, "0");
  return window.SW_COLORS.find((c) => c.code.replace(/[^0-9]/g, "") === digits) || { code: norm, name: "Custom (SW " + digits + ")", hex: null };
};

