{
  "version": 3,
  "sources": ["/cdn/shop/t/16/assets/mhv-utils-5.js?bust=1787930925"],
  "sourcesContent": ["// =============================================================================\r\n// MHV UTILS \u2014 Shared utility functions for Memory Hole Vintage\r\n// Extends window.MHV (set up by mhv-config.js). Load AFTER mhv-config.js.\r\n// =============================================================================\r\n\r\n(function() {\r\n  'use strict';\r\n\r\n  var MHV = window.MHV || {};\r\n\r\n  /**\r\n   * Escape HTML entities to prevent XSS.\r\n   * Used across: live page, host page, chat widget, auction hub.\r\n   */\r\n  MHV.escapeHtml = function(text) {\r\n    if (!text) return '';\r\n    var div = document.createElement('div');\r\n    div.textContent = text;\r\n    return div.innerHTML;\r\n  };\r\n\r\n  /**\r\n   * Quote-safe HTML escaper for ATTRIBUTE contexts. Escapes all five significant\r\n   * chars INCLUDING quotes \u2014 unlike escapeHtml (text-context only, leaves \" and '\r\n   * raw). Use this for any value placed inside a quoted attribute (src, href,\r\n   * value, title, data-*). For building whole fragments prefer the MHV.html\r\n   * tagged template; use escapeAttr for one-off attribute interpolation.\r\n   */\r\n  MHV.escapeAttr = function(v) {\r\n    if (v === null || v === undefined) return '';\r\n    return String(v).replace(/[&<>\"']/g, function(c) {\r\n      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c];\r\n    });\r\n  };\r\n\r\n  // Escape all five HTML-significant chars \u2014 safe in BOTH element text and\r\n  // quoted-attribute contexts (escapeHtml above does not escape quotes, so it's\r\n  // unsafe inside attributes). Used internally by MHV.html.\r\n  function escForHtml(v) {\r\n    if (v === null || v === undefined) return '';\r\n    return String(v).replace(/[&<>\"']/g, function(c) {\r\n      return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c];\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Mark a string as already-safe trusted HTML so MHV.html does NOT re-escape it.\r\n   * Use ONLY for HTML you built yourself (e.g. nested MHV.html fragments) \u2014 never\r\n   * for user/server data. This is the explicit, greppable opt-out.\r\n   *   MHV.html`<div>${MHV.raw(trustedRowsHtml)}</div>`\r\n   *\r\n   * Returns a marker object that stringifies to the HTML (so `el.innerHTML = ...`\r\n   * and string concatenation still work), but is recognized by MHV.html so nested\r\n   * results aren't double-escaped.\r\n   */\r\n  MHV.raw = function(html) {\r\n    var s = (html === null || html === undefined) ? '' : String(html);\r\n    return { __mhvRaw: s, toString: function() { return s; } };\r\n  };\r\n\r\n  /**\r\n   * Auto-escaping HTML tagged template \u2014 the safe-by-default way to build markup\r\n   * for innerHTML. Every ${interpolation} is HTML-escaped automatically; you have\r\n   * to go out of your way (MHV.raw) to inject unescaped HTML. This inverts the old\r\n   * model where you had to remember MHV.escapeHtml() around every field.\r\n   *\r\n   *   el.innerHTML = MHV.html`<span class=\"name\">${user.screenName}</span>`;       // escaped\r\n   *   el.innerHTML = MHV.html`<ul>${rows.map(r => MHV.html`<li>${r.name}</li>`)}</ul>`; // arrays + nesting\r\n   *\r\n   * Arrays are joined; MHV.raw(...) values and nested MHV.html results pass through\r\n   * unescaped (they're already safe). Returns an MHV.raw marker \u2014 assign it to\r\n   * innerHTML or nest it directly; call String(result) if you need a plain string.\r\n   */\r\n  MHV.html = function(strings) {\r\n    var values = Array.prototype.slice.call(arguments, 1);\r\n    function render(v) {\r\n      if (v === null || v === undefined) return '';\r\n      if (typeof v === 'object' && v.__mhvRaw !== undefined) return v.__mhvRaw; // trusted (raw / nested html)\r\n      if (Array.isArray(v)) return v.map(render).join('');\r\n      return escForHtml(v);\r\n    }\r\n    var out = strings[0];\r\n    for (var i = 0; i < values.length; i++) {\r\n      out += render(values[i]) + strings[i + 1];\r\n    }\r\n    return MHV.raw(out);\r\n  };\r\n\r\n  /**\r\n   * Determine if a given date falls within US Eastern Daylight Saving Time.\r\n   * DST starts: second Sunday in March at 2:00 AM EST (07:00 UTC)\r\n   * DST ends:   first Sunday in November at 2:00 AM EDT (06:00 UTC)\r\n   */\r\n  MHV.isEasternDST = function(year, month, day) {\r\n    var march = new Date(Date.UTC(year, 2, 1));\r\n    var marchDay = march.getUTCDay();\r\n    var secondSundayMarch = 8 + ((7 - marchDay) % 7);\r\n\r\n    var november = new Date(Date.UTC(year, 10, 1));\r\n    var novemberDay = november.getUTCDay();\r\n    var firstSundayNovember = (novemberDay === 0) ? 1 : (8 - novemberDay);\r\n\r\n    var dstStart = new Date(Date.UTC(year, 2, secondSundayMarch, 7, 0, 0));\r\n    var dstEnd = new Date(Date.UTC(year, 10, firstSundayNovember, 6, 0, 0));\r\n\r\n    var inputDate = new Date(Date.UTC(year, month - 1, day));\r\n    return (inputDate >= dstStart && inputDate < dstEnd);\r\n  };\r\n\r\n  /**\r\n   * Convert Eastern local time (EST/EDT) to a UTC Date object.\r\n   * Automatically handles DST offset (UTC-5 for EST, UTC-4 for EDT).\r\n   *\r\n   * @param {number} year   - 4-digit year\r\n   * @param {number} month  - 1-based month (1=Jan, 12=Dec)\r\n   * @param {number} day    - Day of month\r\n   * @param {number} hour   - Hour (0-23) in Eastern time\r\n   * @param {number} minute - Minute (0-59)\r\n   * @returns {Date} UTC Date object\r\n   */\r\n  MHV.easternToUTC = function(year, month, day, hour, minute) {\r\n    var inDST = MHV.isEasternDST(year, month, day);\r\n    var offset = inDST ? 4 : 5;\r\n    return new Date(Date.UTC(year, month - 1, day, hour + offset, minute, 0));\r\n  };\r\n\r\n  /**\r\n   * Money for DISPLAY. Cents appear only when there ARE cents \u2014 a whole-dollar bid reads\r\n   * \"$25\", not \"$25.00\". Thousands are comma-separated.\r\n   * Accepts a number or an already-formatted string (\"$1,234.00\"), so it is safe to run\r\n   * over a value that has been through another formatter. Returns '-' for non-numbers.\r\n   * NOTE: display only \u2014 never use it to build a value that gets parsed or stored.\r\n   */\r\n  MHV.money = function(value) {\r\n    var n = typeof value === 'number'\r\n      ? value\r\n      : parseFloat(String(value == null ? '' : value).replace(/[$,\\s]/g, ''));\r\n    if (!isFinite(n)) return '-';\r\n    var parts = (n % 1 === 0 ? String(n) : n.toFixed(2)).split('.');\r\n    parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\r\n    return '$' + parts.join('.');\r\n  };\r\n\r\n  /**\r\n   * Format a customer's real name as \"First L.\" (last initial only).\r\n   * Returns '' when no first name is available.\r\n   */\r\n  MHV.realName = function(firstName, lastName) {\r\n    firstName = (firstName || '').trim();\r\n    if (!firstName) return '';\r\n    var last = (lastName || '').trim();\r\n    return last ? firstName + ' ' + last.charAt(0).toUpperCase() + '.' : firstName;\r\n  };\r\n\r\n  /**\r\n   * Resolve how a customer should appear in chat / viewer lists.\r\n   * Model (2026, name-first): the REAL name (First L.) is the PRIMARY label, revealed\r\n   * by default. A set screen name is ALWAYS shown \u2014 as the secondary line under the\r\n   * real name, or AS the primary when the customer hides their real name (hideName).\r\n   * Admins/employees always see the real name.\r\n   *\r\n   * Mirrors the backend lib/display-name.js \u2014 keep the two in sync.\r\n   *\r\n   * @returns {{primary: string, secondary: string, bidderFallback: boolean}}\r\n   *   primary   \u2014 main name line (\"First L.\" \u2192 screen name \u2192 \"Bidder #n\" \u2192 \"Guest\")\r\n   *   secondary \u2014 the screen name shown UNDER the real name when revealed\r\n   */\r\n  MHV.chatDisplayName = function(p) {\r\n    p = p || {};\r\n    var sn = (p.screenName || '').trim();\r\n    var real = MHV.realName(p.firstName, p.lastName);\r\n    var reveal = !!p.isAdminView || !p.hideName;\r\n\r\n    if (reveal && real) return { primary: real, secondary: sn, bidderFallback: false };\r\n    if (sn) return { primary: sn, secondary: '', bidderFallback: false };\r\n    if (p.bidderNumber) return { primary: 'Bidder #' + p.bidderNumber, secondary: '', bidderFallback: true };\r\n    return { primary: 'Guest', secondary: '', bidderFallback: false };\r\n  };\r\n\r\n  /**\r\n   * Canonical, guaranteed-non-empty identity label for a customer \u2014 used as the\r\n   * stable key for lot requests (and matched against viewers for online status).\r\n   * Resolves to screen name \u2192 \"First L.\" \u2192 \"Bidder #n\". Always reveals the real\r\n   * name (admin view) so requesters/viewers resolve consistently host-side.\r\n   * Accepts a customer ({screenName,firstName,lastName,bidderNumber}) or a viewer\r\n   * (whose screen name is in `name`). Commas are stripped (stored comma-joined).\r\n   */\r\n  MHV.requesterLabel = function(c) {\r\n    if (!c) return '';\r\n    var primary = MHV.chatDisplayName({\r\n      screenName: c.screenName != null ? c.screenName : c.name,\r\n      firstName: c.firstName, lastName: c.lastName,\r\n      bidderNumber: c.bidderNumber, isAdminView: true\r\n    }).primary;\r\n    if (primary === 'Guest') return '';\r\n    return primary.replace(/,/g, ' ').trim();\r\n  };\r\n\r\n  // Backdrop-dismiss guard: close a modal/overlay on a click ONLY when the mouse\r\n  // press started on the backdrop itself \u2014 so a text-selection drag that begins in\r\n  // a field and releases on the backdrop doesn't wrongly close the modal. Shared\r\n  // by admin pages; mirrors the local versions in the table-core/scheduler libs.\r\n  MHV.backdropDismiss = function(el, closeFn) {\r\n    if (!el || typeof closeFn !== 'function') return;\r\n    var down = false;\r\n    el.addEventListener('mousedown', function(e) { down = (e.target === el); });\r\n    el.addEventListener('click', function(e) {\r\n      var ok = down; down = false;\r\n      if (ok && e.target === el) closeFn();\r\n    });\r\n  };\r\n\r\n  // Order the \"Coming Up\" lots. PRIMARY: request count DESC (most-wanted lots first).\r\n  // WITHIN a count tier: STAGGER by the lot's primary requester (requesters[0] \u2014 the earliest,\r\n  // who set the lot's request timestamp) so one person can't monopolize the top: group the\r\n  // tier's lots by primary requester, order each requester's lots oldest-first, then round-robin\r\n  // across requesters (rotation ordered by each requester's oldest request). A tier with a single\r\n  // requester is therefore just oldest-first (no change). Lots with NO requests fall to the bottom,\r\n  // ordered by lot number. Pure \u2014 returns a NEW array. The `requests` metafield is\r\n  // \"timestamp;count;requesters\" (see auction-routes lot-request).\r\n  MHV.orderComingUpLots = function(products, opts) {\r\n    opts = opts || {};\r\n    var getRequests = opts.getRequests || function(p) { return (p.metafields && p.metafields['requests']) || ''; };\r\n    var getLot = opts.getLot || function(p) {\r\n      var m = p.metafields || {};\r\n      var lot = (m.custom && m.custom.lot) || m.lot;\r\n      if (lot) return parseInt(lot, 10) || 0;\r\n      var sku = p.variants && p.variants[0] && p.variants[0].sku;\r\n      var mm = sku && String(sku).match(/LOT(\\d+)/);\r\n      if (mm) return parseInt(mm[1], 10) || 0;\r\n      return parseInt(String(p.handle || '').replace(/\\D/g, ''), 10) || 0;\r\n    };\r\n    var items = (products || []).map(function(p) {\r\n      var parts = String(getRequests(p) || '').split(';');\r\n      var reqs = (parts[2] || '').split(',').map(function(s) { return s.trim(); }).filter(Boolean);\r\n      return {\r\n        p: p,\r\n        count: parseInt(parts[1], 10) || 0,\r\n        ts: parts[0] ? (Date.parse(parts[0]) || 0) : 0,   // oldest request time for the lot\r\n        requester: reqs[0] || '',                          // primary (earliest) requester\r\n        lot: getLot(p)\r\n      };\r\n    });\r\n\r\n    // Bucket by count tier, process tiers high\u2192low.\r\n    var tiers = {};\r\n    items.forEach(function(it) { (tiers[it.count] = tiers[it.count] || []).push(it); });\r\n    var counts = Object.keys(tiers).map(Number).sort(function(a, b) { return b - a; });\r\n\r\n    var out = [];\r\n    counts.forEach(function(c) {\r\n      var tier = tiers[c];\r\n      if (c <= 0) {\r\n        // Unrequested lots \u2192 lot-number order, at the bottom.\r\n        tier.sort(function(a, b) { return a.lot - b.lot; });\r\n        tier.forEach(function(it) { out.push(it.p); });\r\n        return;\r\n      }\r\n      // Group by primary requester; oldest-first within each; round-robin across requesters.\r\n      var byReq = {};\r\n      tier.forEach(function(it) { (byReq[it.requester] = byReq[it.requester] || []).push(it); });\r\n      Object.keys(byReq).forEach(function(r) {\r\n        byReq[r].sort(function(a, b) { return (a.ts - b.ts) || (a.lot - b.lot); });\r\n      });\r\n      var reqOrder = Object.keys(byReq).sort(function(a, b) {\r\n        return (byReq[a][0].ts - byReq[b][0].ts) || (byReq[a][0].lot - byReq[b][0].lot);\r\n      });\r\n      var more = true;\r\n      while (more) {\r\n        more = false;\r\n        reqOrder.forEach(function(r) { if (byReq[r].length) { out.push(byReq[r].shift().p); more = true; } });\r\n      }\r\n    });\r\n    return out;\r\n  };\r\n\r\n  // \u2500\u2500 THE \"Lot ### - \" PREFIX \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  //\r\n  // Every catalogue title is composed as \"Lot ### - Title\" (computeTitle in\r\n  // routes/catalogue/helpers.js). Inside a UI that already labels the lot, that\r\n  // prints the number twice and the word for no one; in a bare string that\r\n  // travels alone \u2014 a chat announcement, a receipt line \u2014 it is what makes the\r\n  // string self-describing.\r\n  //\r\n  // So this is a DISPLAY helper, and the rule for using it is: strip where the\r\n  // surface around it already says which lot this is, keep it everywhere else.\r\n  //\r\n  // \u26A0\uFE0F NEVER strip a title that is about to be STORED or SENT. On the host page\r\n  // the displayed title is read back as data (getSellingProductTitle feeds the\r\n  // sold-list entry on both commit and pass), so stripping the element there\r\n  // would strip the record too. See TODO.md #5.\r\n  //\r\n  // Tolerates the hyphen, en dash and em dash, because titles have been written\r\n  // by three different composers over time.\r\n  // Take the \"Lot ### - \" off the front of a composed title, for DISPLAY only.\r\n  //\r\n  // \u26A0\uFE0F THIS WAS BROKEN FROM THE DAY IT WAS WRITTEN and nothing caught it. The\r\n  // pattern read /^s*Lots+S+s*[-\u2013\u2014]s*/i \u2014 every backslash had been eaten by the\r\n  // shell that wrote the file, so it matched the literal text \"s*Lots+S+s*\" and\r\n  // therefore nothing at all. Every caller looked correct, ran, and silently did\r\n  // nothing; the prefix stayed on screen everywhere while the code said it was\r\n  // gone. If you edit this function, edit the FILE \u2014 do not pipe it through a\r\n  // shell.\r\n  //\r\n  // Deliberately conservative. `lot\\b` will not match \"Lottery\", and requiring a\r\n  // real separator means \"Lot of 5 chairs\" \u2014 an actual auction phrase \u2014 is left\r\n  // alone. The app composes `Lot ${padded} - ${title}`; the extra shapes here\r\n  // (#, colon) are for titles typed by hand.\r\n  MHV.stripLotPrefix = function(title) {\r\n    if (title == null) return '';\r\n    return String(title).replace(/^\\s*lot\\b\\s*#?\\s*\\S+\\s*[-\u2013\u2014:]\\s*/i, '');\r\n  };\r\n\r\n\r\n  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n  // MHV.icon(name) \u2014 the house icon set\r\n  // \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n  //\r\n  // SVG, not emoji. An emoji is a different picture on every platform, cannot\r\n  // take a colour, and renders at a size the font decides \u2014 all three matter for\r\n  // a control whose colour IS its state.\r\n  //\r\n  // One 24x24 grid, stroke-based, stroke on currentColor, so an icon inherits\r\n  // the colour of whatever it sits in and every icon has the same visual weight.\r\n  //\r\n  // \u26A0\uFE0F THE PENCIL IS COMPUTED, NOT DRAWN BY HAND. Its outline is generated from\r\n  // an axis, a width and three distances along it, so the two long sides are\r\n  // exactly parallel and exactly equal and the tip sits on the centreline. Ad-hoc\r\n  // pencil paths look subtly wrong at 16px in a way that is hard to name and\r\n  // impossible to fix by nudging numbers: the sides taper, or the point is off\r\n  // the axis. Regenerate it rather than editing the coordinates.\r\n  var MHV_ICONS = {\r\n    // Body outline, the sharpened edge, and the ferrule band.\r\n    pencil: '<path d=\"M4.6 19.4L8.3 18.3L16.4 10.2L13.8 7.6L5.7 15.7Z\"/><path d=\"M8.3 18.3L5.7 15.7\"/><path d=\"M14.1 12.5L11.5 9.9\"/>',\r\n\r\n    // Two arrows chasing each other round a circle \u2014 the universal \"in sync\".\r\n    // Deliberately NOT a tick: a tick is being kept for the second scribe's\r\n    // verification, and one glyph cannot mean both \"the computer sent it\" and\r\n    // \"a person checked it\".\r\n    // \u26A0\uFE0F BOTH ARCS SIT ON ONE CIRCLE \u2014 centre (12,12), r 7.2, each sweeping 140\u00B0\r\n    // with the gaps left for the arrowheads. The first version was two arcs whose\r\n    // endpoints were not equidistant from any centre, which at 16px reads as a\r\n    // wobble you can see but cannot name.\r\n    sync: '<path d=\"M18.8 3.8V9.5h-5.7\"/><path d=\"M5.2 20.2v-5.7h5.7\"/>'\r\n      + '<path d=\"M5.2 9.5a7.2 7.2 0 0 1 13.6 0\"/>'\r\n      + '<path d=\"M18.8 14.5a7.2 7.2 0 0 1 -13.6 0\"/>',\r\n\r\n    // A pennant on a staff. Reads at 16px where a rectangular flag does not.\r\n    flag: '<path d=\"M5.5 14.4s1.3-1 4-1 5 1.9 7.6 1.9c1.4 0 2.4-.4 2.4-.4V4.6s-1 .5-2.4.5c-2.6 0-5-1.9-7.6-1.9s-4 1-4 1z\"/>'\r\n      + '<path d=\"M5.5 21.2V3.2\"/>',\r\n\r\n    check: '<path d=\"M20 6.5 9.2 17.3 4 12.1\"/>',\r\n\r\n    // Two bars. \u26A0\uFE0F Replaces the \u23F8 EMOJI, which sat low against its label and\r\n    // rendered at whatever size and weight the platform font felt like \u2014 the\r\n    // exact three problems an emoji has in a control (see the note above).\r\n    // Drawn as strokes rather than filled rects so it carries the same weight\r\n    // as every other glyph in the set.\r\n    pause: '<path d=\"M9.5 5.5v13\"/><path d=\"M14.5 5.5v13\"/>',\r\n\r\n    // \u2500\u2500 The two COUNT glyphs on a lot: \"3 \u2665  57 \uD83D\uDC41\" (2026-09-13) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n    // A lot's card used to read \"3 Favs | 57 Views\"; the words are gone and the\r\n    // number sits beside a picture. Both are FILLED (currentColor) so they read\r\n    // at 12\u201314px in a line of text, where a stroked outline turns to fuzz.\r\n    // \u26A0\uFE0F The same two shapes are drawn in snippets/mhv-icon.liquid for the\r\n    // Liquid-rendered counts \u2014 keep the paths identical.\r\n    //\r\n    // The favourite control (the clickable icon on the card / product page /\r\n    // locked pill) is this SAME heart, stroke-based, with fill toggled by JS \u2014\r\n    // one shape for \"favourite\" everywhere. Replaced the star.\r\n    heart: '<path fill=\"currentColor\" d=\"M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z\"/>',\r\n\r\n    // The live page's viewer-count eyeball (files/eyeball-s.png), redrawn: an\r\n    // almond outline, a filled iris, a highlight dot cut out (evenodd) at\r\n    // upper-left. The iris is stroke:none or the ring would close the dot at 16px.\r\n    eye: '<path d=\"M1.6 12C5.2 5.4 18.8 5.4 22.4 12 18.8 18.6 5.2 18.6 1.6 12Z\"/>'\r\n      + '<path fill=\"currentColor\" stroke=\"none\" fill-rule=\"evenodd\" d=\"M12 7.3a4.7 4.7 0 1 0 .01 0zM10.2 9.1a1.5 1.5 0 1 0 .01 0z\"/>',\r\n  };\r\n\r\n  // size defaults to 16 \u2014 the size these are used at in the sold list rail.\r\n  // opts.label (\"Favorites\") makes it a MEANINGFUL image rather than decoration:\r\n  // role=img + aria-label + a <title> tooltip, so \"3 \u2665\" reads \"3 Favorites\" to a\r\n  // screen reader and on hover. opts.inline sizes it to the text (1em, baseline-\r\n  // nudged) for use inside a line of copy.\r\n  MHV.icon = function (name, opts) {\r\n    var o = opts || {};\r\n    var body = MHV_ICONS[name];\r\n    if (!body) return '';\r\n    var size = o.inline ? '1em' : (o.size || 16);\r\n    var w = o.strokeWidth || 1.9;\r\n    var label = o.label ? String(o.label).replace(/[&<>\"]/g, function (c) { return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;' }[c]; }) : '';\r\n    return '<svg class=\"mhv-icon mhv-icon-' + name + (o.inline ? ' mhv-icon--inline' : '') + (o.className ? ' ' + o.className : '') + '\"'\r\n      + ' viewBox=\"0 0 24 24\" width=\"' + size + '\" height=\"' + size + '\"'\r\n      + ' fill=\"none\" stroke=\"currentColor\" stroke-width=\"' + w + '\"'\r\n      + ' stroke-linecap=\"round\" stroke-linejoin=\"round\"'\r\n      + (label ? ' role=\"img\" aria-label=\"' + label + '\"' : ' aria-hidden=\"true\"')\r\n      + ' focusable=\"false\"'\r\n      + (o.inline ? ' style=\"display:inline-block;vertical-align:-0.15em;\"' : '') + '>'\r\n      + (label ? '<title>' + label + '</title>' : '')\r\n      + body + '</svg>';\r\n  };\r\n  MHV.iconNames = Object.keys(MHV_ICONS);\r\n\r\n  // \"3 \u2665\" / \"57 \uD83D\uDC41\" \u2014 the count-with-glyph a lot's card prints for favourites and\r\n  // views. One helper so every surface (hub card, lightbox, product page, live\r\n  // page list, home carousel) spells it the same way.\r\n  MHV.countGlyph = function (n, name) {\r\n    var label = name === 'heart' ? 'Favorites' : name === 'eye' ? 'Views' : name;\r\n    return (Number(n) || 0) + '\\u00a0' + MHV.icon(name, { inline: true, label: label });\r\n  };\r\n\r\n  // \u2500\u2500 DOWNLOAD-PDF BRIDGE FOR PRINT POPUPS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  //\r\n  // Every receipt/slip in this app is FETCHED with an auth header and then\r\n  // `document.write`n into a blank popup. That popup is same-origin but has no URL\r\n  // and no credentials, so its \"\u2B07 DOWNLOAD PDF\" button cannot fetch anything \u2014 and\r\n  // embedding the admin key in the markup to fix that would publish it into a\r\n  // window anyone at the desk can View-Source on.\r\n  //\r\n  // So the popup borrows ours. Call this with the SAME headers you used to fetch\r\n  // the document, immediately before `window.open`; the popup then calls\r\n  // `window.opener.MHVReceiptPdf(url, filename)` and we do the authenticated fetch\r\n  // and the save. The credential never leaves this page.\r\n  //\r\n  // \u26A0\uFE0F Install it BEFORE window.open. A popup that loads faster than the line after\r\n  // it finds no bridge and falls back to a plain navigation, which 403s.\r\n  //\r\n  // \u26A0\uFE0F Saved from a BLOB, not by pointing the browser at the URL: a navigation\r\n  // cannot carry the header either. `serveHtmlOrPdf` answers ?download=1 with a\r\n  // real error rather than HTML-labelled-.pdf, so a non-PDF response here is a\r\n  // genuine failure and is reported as one.\r\n  // \u2500\u2500 HOW THE DESK LIKES ITS RECEIPTS ORDERED \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  // Sale time (the default, and what the order's own line order already is) or lot\r\n  // number (how the goods are stacked on the floor, so how a pile gets checked\r\n  // against a list). Remembered, because a desk that wants lot order wants it for\r\n  // all 30 checkouts tonight, not once.\r\n  var RECEIPT_SORT_KEY = 'mhv_receipt_sort';\r\n  MHV.receiptSort = function () {\r\n    try { return localStorage.getItem(RECEIPT_SORT_KEY) === 'lot' ? 'lot' : 'sale'; }\r\n    catch (e) { return 'sale'; }\r\n  };\r\n  // Ready to append to a URL that already has a query string. Empty for the\r\n  // default, so an unchanged preference leaves every existing URL byte-identical.\r\n  MHV.receiptSortParam = function () {\r\n    return MHV.receiptSort() === 'lot' ? '&sort=lot' : '';\r\n  };\r\n\r\n  MHV.receiptDownloadBridge = function (headers) {\r\n    // Re-fetch the SAME document in the other order. Same credential problem as the\r\n    // PDF, same answer: the popup has none, so it asks us. Storing the choice here\r\n    // rather than in the popup is deliberate \u2014 the popup is thrown away, this page\r\n    // is the one that will open the next receipt.\r\n    window.MHVReceiptReload = function (url, nextSort) {\r\n      try { localStorage.setItem(RECEIPT_SORT_KEY, nextSort === 'lot' ? 'lot' : 'sale'); } catch (e) { /* private mode */ }\r\n      return fetch(url, { headers: headers || {}, cache: 'no-store' }).then(function (resp) {\r\n        if (!resp.ok) throw new Error('HTTP ' + resp.status);\r\n        return resp.text();\r\n      });\r\n    };\r\n\r\n    window.MHVReceiptPdf = function (url, filename) {\r\n      return fetch(url, { headers: headers || {}, cache: 'no-store' })\r\n        .then(function (resp) {\r\n          if (!resp.ok) {\r\n            return resp.text().catch(function () { return ''; }).then(function (t) {\r\n              throw new Error((t || ('HTTP ' + resp.status)).slice(0, 160));\r\n            });\r\n          }\r\n          var type = resp.headers.get('content-type') || '';\r\n          if (type.indexOf('application/pdf') === -1) throw new Error('server did not return a PDF');\r\n          return resp.blob();\r\n        })\r\n        .then(function (blob) {\r\n          var href = URL.createObjectURL(blob);\r\n          var a = document.createElement('a');\r\n          a.href = href;\r\n          a.download = filename || 'receipt.pdf';\r\n          document.body.appendChild(a);\r\n          a.click();\r\n          document.body.removeChild(a);\r\n          // Chrome needs the object URL to outlive the click.\r\n          setTimeout(function () { URL.revokeObjectURL(href); }, 60000);\r\n        });\r\n    };\r\n  };\r\n\r\n  // \u2500\u2500 THE \"no photo\" PLACEHOLDER \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n  //\r\n  // \u26A0\uFE0F ONE URL, BECAUSE THERE WERE TWO AND ONE OF THEM WAS DEAD. The sold list\r\n  // and invoices used this file; the Catalogue Manager grid used a different\r\n  // upload that now 404s on every variant \u2014 so every lot without a photo showed\r\n  // a BROKEN image there. A constant nobody has to remember is the fix.\r\n  //\r\n  // \u26A0\uFE0F ALWAYS ASK FOR A SIZE. The source PNG is 2.9 MB; at width=200 the CDN\r\n  // serves 37 KB. A grid of a hundred lots without photos was pulling a third of\r\n  // a gigabyte.\r\n  MHV.NO_IMAGE = 'https://cdn.shopify.com/s/files/1/0073/9101/9067/files/no-image-placeholder.png?v=1756872687';\r\n  MHV.noImage = function (px) {\r\n    var w = parseInt(px, 10);\r\n    return MHV.NO_IMAGE + (w > 0 ? '&width=' + w : '');\r\n  };\r\n\r\n  window.MHV = MHV;\r\n})();\r\n"],
  "mappings": "CAKC,UAAW,CACV,aAEA,IAAI,IAAM,OAAO,KAAO,CAAC,EAMzB,IAAI,WAAa,SAAS,KAAM,CAC9B,GAAI,CAAC,KAAM,MAAO,GAClB,IAAI,IAAM,SAAS,cAAc,KAAK,EACtC,WAAI,YAAc,KACX,IAAI,SACb,EASA,IAAI,WAAa,SAAS,EAAG,CAC3B,OAAI,GAAM,KAAgC,GACnC,OAAO,CAAC,EAAE,QAAQ,WAAY,SAAS,EAAG,CAC/C,MAAO,CAAE,IAAK,QAAS,IAAK,OAAQ,IAAK,OAAQ,IAAK,SAAU,IAAK,OAAQ,EAAE,CAAC,CAClF,CAAC,CACH,EAKA,SAAS,WAAW,EAAG,CACrB,OAAI,GAAM,KAAgC,GACnC,OAAO,CAAC,EAAE,QAAQ,WAAY,SAAS,EAAG,CAC/C,MAAO,CAAE,IAAK,QAAS,IAAK,OAAQ,IAAK,OAAQ,IAAK,SAAU,IAAK,OAAQ,EAAE,CAAC,CAClF,CAAC,CACH,CAYA,IAAI,IAAM,SAAS,KAAM,CACvB,IAAI,EAAK,MAAS,KAA8B,GAAK,OAAO,IAAI,EAChE,MAAO,CAAE,SAAU,EAAG,SAAU,UAAW,CAAE,OAAO,CAAG,CAAE,CAC3D,EAeA,IAAI,KAAO,SAAS,QAAS,CAC3B,IAAI,OAAS,MAAM,UAAU,MAAM,KAAK,UAAW,CAAC,EACpD,SAAS,OAAO,EAAG,CACjB,OAAI,GAAM,KAAgC,GACtC,OAAO,GAAM,UAAY,EAAE,WAAa,OAAkB,EAAE,SAC5D,MAAM,QAAQ,CAAC,EAAU,EAAE,IAAI,MAAM,EAAE,KAAK,EAAE,EAC3C,WAAW,CAAC,CACrB,CAEA,QADI,IAAM,QAAQ,CAAC,EACV,EAAI,EAAG,EAAI,OAAO,OAAQ,IACjC,KAAO,OAAO,OAAO,CAAC,CAAC,EAAI,QAAQ,EAAI,CAAC,EAE1C,OAAO,IAAI,IAAI,GAAG,CACpB,EAOA,IAAI,aAAe,SAAS,KAAM,MAAO,IAAK,CAC5C,IAAI,MAAQ,IAAI,KAAK,KAAK,IAAI,KAAM,EAAG,CAAC,CAAC,EACrC,SAAW,MAAM,UAAU,EAC3B,kBAAoB,GAAM,EAAI,UAAY,EAE1C,SAAW,IAAI,KAAK,KAAK,IAAI,KAAM,GAAI,CAAC,CAAC,EACzC,YAAc,SAAS,UAAU,EACjC,oBAAuB,cAAgB,EAAK,EAAK,EAAI,YAErD,SAAW,IAAI,KAAK,KAAK,IAAI,KAAM,EAAG,kBAAmB,EAAG,EAAG,CAAC,CAAC,EACjE,OAAS,IAAI,KAAK,KAAK,IAAI,KAAM,GAAI,oBAAqB,EAAG,EAAG,CAAC,CAAC,EAElE,UAAY,IAAI,KAAK,KAAK,IAAI,KAAM,MAAQ,EAAG,GAAG,CAAC,EACvD,OAAQ,WAAa,UAAY,UAAY,MAC/C,EAaA,IAAI,aAAe,SAAS,KAAM,MAAO,IAAK,KAAM,OAAQ,CAC1D,IAAI,MAAQ,IAAI,aAAa,KAAM,MAAO,GAAG,EACzC,OAAS,MAAQ,EAAI,EACzB,OAAO,IAAI,KAAK,KAAK,IAAI,KAAM,MAAQ,EAAG,IAAK,KAAO,OAAQ,OAAQ,CAAC,CAAC,CAC1E,EASA,IAAI,MAAQ,SAAS,MAAO,CAC1B,IAAI,EAAI,OAAO,OAAU,SACrB,MACA,WAAW,OAAO,OAAS,KAAO,GAAK,KAAK,EAAE,QAAQ,UAAW,EAAE,CAAC,EACxE,GAAI,CAAC,SAAS,CAAC,EAAG,MAAO,IACzB,IAAI,OAAS,EAAI,IAAM,EAAI,OAAO,CAAC,EAAI,EAAE,QAAQ,CAAC,GAAG,MAAM,GAAG,EAC9D,aAAM,CAAC,EAAI,MAAM,CAAC,EAAE,QAAQ,wBAAyB,GAAG,EACjD,IAAM,MAAM,KAAK,GAAG,CAC7B,EAMA,IAAI,SAAW,SAAS,UAAW,SAAU,CAE3C,GADA,WAAa,WAAa,IAAI,KAAK,EAC/B,CAAC,UAAW,MAAO,GACvB,IAAI,MAAQ,UAAY,IAAI,KAAK,EACjC,OAAO,KAAO,UAAY,IAAM,KAAK,OAAO,CAAC,EAAE,YAAY,EAAI,IAAM,SACvE,EAeA,IAAI,gBAAkB,SAAS,EAAG,CAChC,EAAI,GAAK,CAAC,EACV,IAAI,IAAM,EAAE,YAAc,IAAI,KAAK,EAC/B,KAAO,IAAI,SAAS,EAAE,UAAW,EAAE,QAAQ,EAC3C,OAAS,CAAC,CAAC,EAAE,aAAe,CAAC,EAAE,SAEnC,OAAI,QAAU,KAAa,CAAE,QAAS,KAAM,UAAW,GAAI,eAAgB,EAAM,EAC7E,GAAW,CAAE,QAAS,GAAI,UAAW,GAAI,eAAgB,EAAM,EAC/D,EAAE,aAAqB,CAAE,QAAS,WAAa,EAAE,aAAc,UAAW,GAAI,eAAgB,EAAK,EAChG,CAAE,QAAS,QAAS,UAAW,GAAI,eAAgB,EAAM,CAClE,EAUA,IAAI,eAAiB,SAAS,EAAG,CAC/B,GAAI,CAAC,EAAG,MAAO,GACf,IAAI,QAAU,IAAI,gBAAgB,CAChC,WAAY,EAAE,YAAc,KAAO,EAAE,WAAa,EAAE,KACpD,UAAW,EAAE,UAAW,SAAU,EAAE,SACpC,aAAc,EAAE,aAAc,YAAa,EAC7C,CAAC,EAAE,QACH,OAAI,UAAY,QAAgB,GACzB,QAAQ,QAAQ,KAAM,GAAG,EAAE,KAAK,CACzC,EAMA,IAAI,gBAAkB,SAAS,GAAI,QAAS,CAC1C,GAAI,GAAC,IAAM,OAAO,SAAY,YAC9B,KAAI,KAAO,GACX,GAAG,iBAAiB,YAAa,SAAS,EAAG,CAAE,KAAQ,EAAE,SAAW,EAAK,CAAC,EAC1E,GAAG,iBAAiB,QAAS,SAAS,EAAG,CACvC,IAAI,GAAK,KAAM,KAAO,GAClB,IAAM,EAAE,SAAW,IAAI,QAAQ,CACrC,CAAC,EACH,EAUA,IAAI,kBAAoB,SAAS,SAAU,KAAM,CAC/C,KAAO,MAAQ,CAAC,EAChB,IAAI,YAAc,KAAK,aAAe,SAAS,EAAG,CAAE,OAAQ,EAAE,YAAc,EAAE,WAAW,UAAgB,EAAI,EACzG,OAAS,KAAK,QAAU,SAAS,EAAG,CACtC,IAAI,EAAI,EAAE,YAAc,CAAC,EACrB,IAAO,EAAE,QAAU,EAAE,OAAO,KAAQ,EAAE,IAC1C,GAAI,IAAK,OAAO,SAAS,IAAK,EAAE,GAAK,EACrC,IAAI,IAAM,EAAE,UAAY,EAAE,SAAS,CAAC,GAAK,EAAE,SAAS,CAAC,EAAE,IACnD,GAAK,KAAO,OAAO,GAAG,EAAE,MAAM,UAAU,EAC5C,OAAI,GAAW,SAAS,GAAG,CAAC,EAAG,EAAE,GAAK,EAC/B,SAAS,OAAO,EAAE,QAAU,EAAE,EAAE,QAAQ,MAAO,EAAE,EAAG,EAAE,GAAK,CACpE,EACI,OAAS,UAAY,CAAC,GAAG,IAAI,SAAS,EAAG,CAC3C,IAAI,MAAQ,OAAO,YAAY,CAAC,GAAK,EAAE,EAAE,MAAM,GAAG,EAC9C,MAAQ,MAAM,CAAC,GAAK,IAAI,MAAM,GAAG,EAAE,IAAI,SAAS,EAAG,CAAE,OAAO,EAAE,KAAK,CAAG,CAAC,EAAE,OAAO,OAAO,EAC3F,MAAO,CACL,EAAG,EACH,MAAO,SAAS,MAAM,CAAC,EAAG,EAAE,GAAK,EACjC,GAAI,MAAM,CAAC,GAAK,KAAK,MAAM,MAAM,CAAC,CAAC,GAAK,EACxC,UAAW,KAAK,CAAC,GAAK,GACtB,IAAK,OAAO,CAAC,CACf,CACF,CAAC,EAGG,MAAQ,CAAC,EACb,MAAM,QAAQ,SAAS,GAAI,EAAG,MAAM,GAAG,KAAK,EAAI,MAAM,GAAG,KAAK,GAAK,CAAC,GAAG,KAAK,EAAE,CAAG,CAAC,EAClF,IAAI,OAAS,OAAO,KAAK,KAAK,EAAE,IAAI,MAAM,EAAE,KAAK,SAAS,EAAG,EAAG,CAAE,OAAO,EAAI,CAAG,CAAC,EAE7E,IAAM,CAAC,EACX,cAAO,QAAQ,SAAS,EAAG,CACzB,IAAI,KAAO,MAAM,CAAC,EAClB,GAAI,GAAK,EAAG,CAEV,KAAK,KAAK,SAAS,EAAG,EAAG,CAAE,OAAO,EAAE,IAAM,EAAE,GAAK,CAAC,EAClD,KAAK,QAAQ,SAAS,GAAI,CAAE,IAAI,KAAK,GAAG,CAAC,CAAG,CAAC,EAC7C,MACF,CAEA,IAAI,MAAQ,CAAC,EACb,KAAK,QAAQ,SAAS,GAAI,EAAG,MAAM,GAAG,SAAS,EAAI,MAAM,GAAG,SAAS,GAAK,CAAC,GAAG,KAAK,EAAE,CAAG,CAAC,EACzF,OAAO,KAAK,KAAK,EAAE,QAAQ,SAAS,EAAG,CACrC,MAAM,CAAC,EAAE,KAAK,SAAS,EAAG,EAAG,CAAE,OAAQ,EAAE,GAAK,EAAE,IAAQ,EAAE,IAAM,EAAE,GAAM,CAAC,CAC3E,CAAC,EAKD,QAJI,SAAW,OAAO,KAAK,KAAK,EAAE,KAAK,SAAS,EAAG,EAAG,CACpD,OAAQ,MAAM,CAAC,EAAE,CAAC,EAAE,GAAK,MAAM,CAAC,EAAE,CAAC,EAAE,IAAQ,MAAM,CAAC,EAAE,CAAC,EAAE,IAAM,MAAM,CAAC,EAAE,CAAC,EAAE,GAC7E,CAAC,EACG,KAAO,GACJ,MACL,KAAO,GACP,SAAS,QAAQ,SAAS,EAAG,CAAM,MAAM,CAAC,EAAE,SAAU,IAAI,KAAK,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,EAAG,KAAO,GAAQ,CAAC,CAExG,CAAC,EACM,GACT,EAkCA,IAAI,eAAiB,SAAS,MAAO,CACnC,OAAI,OAAS,KAAa,GACnB,OAAO,KAAK,EAAE,QAAQ,oCAAqC,EAAE,CACtE,EAoBA,IAAI,UAAY,CAEd,OAAQ,2HAUR,KAAM,oJAKN,KAAM,4IAGN,MAAO,sCAOP,MAAO,kDAYP,MAAO,2KAKP,IAAK,qMAEP,EAOA,IAAI,KAAO,SAAU,KAAM,KAAM,CAC/B,IAAI,EAAI,MAAQ,CAAC,EACb,KAAO,UAAU,IAAI,EACzB,GAAI,CAAC,KAAM,MAAO,GAClB,IAAI,KAAO,EAAE,OAAS,MAAS,EAAE,MAAQ,GACrC,EAAI,EAAE,aAAe,IACrB,MAAQ,EAAE,MAAQ,OAAO,EAAE,KAAK,EAAE,QAAQ,UAAW,SAAU,EAAG,CAAE,MAAO,CAAE,IAAK,QAAS,IAAK,OAAQ,IAAK,OAAQ,IAAK,QAAS,EAAE,CAAC,CAAG,CAAC,EAAI,GAClJ,MAAO,iCAAmC,MAAQ,EAAE,OAAS,oBAAsB,KAAO,EAAE,UAAY,IAAM,EAAE,UAAY,IAAM,gCAC7F,KAAO,aAAe,KAAO,qDACR,EAAI,oDAEzD,MAAQ,2BAA6B,MAAQ,IAAM,uBACpD,sBACC,EAAE,OAAS,wDAA0D,IAAM,KAC3E,MAAQ,UAAY,MAAQ,WAAa,IAC1C,KAAO,QACb,EACA,IAAI,UAAY,OAAO,KAAK,SAAS,EAKrC,IAAI,WAAa,SAAU,EAAG,KAAM,CAClC,IAAI,MAAQ,OAAS,QAAU,YAAc,OAAS,MAAQ,QAAU,KACxE,OAAQ,OAAO,CAAC,GAAK,GAAK,OAAW,IAAI,KAAK,KAAM,CAAE,OAAQ,GAAM,MAAO,KAAM,CAAC,CACpF,EA2BA,IAAI,iBAAmB,mBACvB,IAAI,YAAc,UAAY,CAC5B,GAAI,CAAE,OAAO,aAAa,QAAQ,gBAAgB,IAAM,MAAQ,MAAQ,MAAQ,OACzE,EAAG,CAAE,MAAO,MAAQ,CAC7B,EAGA,IAAI,iBAAmB,UAAY,CACjC,OAAO,IAAI,YAAY,IAAM,MAAQ,YAAc,EACrD,EAEA,IAAI,sBAAwB,SAAU,QAAS,CAK7C,OAAO,iBAAmB,SAAU,IAAK,SAAU,CACjD,GAAI,CAAE,aAAa,QAAQ,iBAAkB,WAAa,MAAQ,MAAQ,MAAM,CAAG,OAAS,EAAG,CAAqB,CACpH,OAAO,MAAM,IAAK,CAAE,QAAS,SAAW,CAAC,EAAG,MAAO,UAAW,CAAC,EAAE,KAAK,SAAU,KAAM,CACpF,GAAI,CAAC,KAAK,GAAI,MAAM,IAAI,MAAM,QAAU,KAAK,MAAM,EACnD,OAAO,KAAK,KAAK,CACnB,CAAC,CACH,EAEA,OAAO,cAAgB,SAAU,IAAK,SAAU,CAC9C,OAAO,MAAM,IAAK,CAAE,QAAS,SAAW,CAAC,EAAG,MAAO,UAAW,CAAC,EAC5D,KAAK,SAAU,KAAM,CACpB,GAAI,CAAC,KAAK,GACR,OAAO,KAAK,KAAK,EAAE,MAAM,UAAY,CAAE,MAAO,EAAI,CAAC,EAAE,KAAK,SAAU,EAAG,CACrE,MAAM,IAAI,OAAO,GAAM,QAAU,KAAK,QAAS,MAAM,EAAG,GAAG,CAAC,CAC9D,CAAC,EAEH,IAAI,KAAO,KAAK,QAAQ,IAAI,cAAc,GAAK,GAC/C,GAAI,KAAK,QAAQ,iBAAiB,IAAM,GAAI,MAAM,IAAI,MAAM,6BAA6B,EACzF,OAAO,KAAK,KAAK,CACnB,CAAC,EACA,KAAK,SAAU,KAAM,CACpB,IAAI,KAAO,IAAI,gBAAgB,IAAI,EAC/B,EAAI,SAAS,cAAc,GAAG,EAClC,EAAE,KAAO,KACT,EAAE,SAAW,UAAY,cACzB,SAAS,KAAK,YAAY,CAAC,EAC3B,EAAE,MAAM,EACR,SAAS,KAAK,YAAY,CAAC,EAE3B,WAAW,UAAY,CAAE,IAAI,gBAAgB,IAAI,CAAG,EAAG,GAAK,CAC9D,CAAC,CACL,CACF,EAYA,IAAI,SAAW,+FACf,IAAI,QAAU,SAAU,GAAI,CAC1B,IAAI,EAAI,SAAS,GAAI,EAAE,EACvB,OAAO,IAAI,UAAY,EAAI,EAAI,UAAY,EAAI,GACjD,EAEA,OAAO,IAAM,GACf,GAAG",
  "names": []
}
