{"product_id":"silk-sleep-set","title":"Silk Sleep Set – Mulberry Silk Pillowcase \u0026 Overnight Curl Set","description":"\u003ch2\u003eA night routine for smoother mornings\u003c\/h2\u003e\n\u003cp\u003eThe Silk Sleep Set pairs a mulberry silk pillowcase with our Overnight Curl Set, so you can set soft waves while you sleep and have less to do in the morning.\u003c\/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cstrong\u003eMulberry silk pillowcase:\u003c\/strong\u003e smooth mulberry silk with a hidden zipper closure.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eNo-heat curls:\u003c\/strong\u003e a padded velvet curling rod with ribbon ties, a satin bonnet, scrunchies and a claw clip.\u003c\/li\u003e\n\u003cli\u003e\n\u003cstrong\u003eBonus:\u003c\/strong\u003e a mulberry silk scrunchie in a matching shade.\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003ch3\u003eWhat's in the set\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003e1 mulberry silk pillowcase, hidden zipper (in the size you choose)\u003c\/li\u003e\n\u003cli\u003e1 padded velvet heatless curling rod with ribbon ties\u003c\/li\u003e\n\u003cli\u003e1 satin sleep bonnet\u003c\/li\u003e\n\u003cli\u003e2 velvet scrunchies\u003c\/li\u003e\n\u003cli\u003e1 claw clip\u003c\/li\u003e\n\u003cli\u003e1 mulberry silk scrunchie\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003ch3\u003ePillowcase sizes\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003eStandard: 20 × 26 in (51 × 66 cm)\u003c\/li\u003e\n\u003cli\u003eQueen: 20 × 30 in (51 × 76 cm)\u003c\/li\u003e\n\u003cli\u003eKing: 20 × 36 in (51 × 91 cm)\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003ch3\u003eCare\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003eHand wash, or machine wash on a delicate cycle in cold water inside a laundry bag, with a mild detergent.\u003c\/li\u003e\n\u003cli\u003eDo not bleach or tumble dry. Air dry away from direct sun; iron on low if needed.\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003ch3\u003eGood to know\u003c\/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe pillowcase and the curl set ship from different warehouses and may arrive in separate packages.\u003c\/li\u003e\n\u003cli\u003eCurl set materials: polyester velvet rod and scrunchies, polyester satin bonnet, plastic claw clip.\u003c\/li\u003e\n\u003cli\u003eNatural silk can show slight shade differences between batches.\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cp\u003eNew to heatless curls? Read our step-by-step guide: \u003ca href=\"\/blogs\/hair-guides\/heatless-curls-overnight\"\u003eHow to Get Heatless Curls Overnight\u003c\/a\u003e.\u003c\/p\u003e\n\u003cp\u003eSee the \u003ca href=\"\/products\/overnight-curl-set\"\u003eOvernight Curl Set\u003c\/a\u003e on its own.\u003c\/p\u003e\n\u003c!-- hv-upsell v2.3 (Havendoa, 2026-10-15): add-ons with variant picker + quantity, quick view, delivery, trust. Remove from the hv-upsell v2.3 start marker to the \/hv-upsell v2.3 end marker to undo. --\u003e\n\u003cdiv class=\"hb\" data-handle=\"silk-sleep-set\" hidden\u003e\u003cdiv class=\"hb-pay\"\u003e\u003c\/div\u003e\u003c\/div\u003e\n\u003cstyle\u003e\n.hb{--g:#7a5534;--line:#e3e3e3;font-size:15px;color:#2b2b2b}\n.hb-pay{display:flex;flex-wrap:wrap;justify-content:center;gap:6px;margin:12px 0 0}\n.hb-pay svg{width:38px;height:24px}\n.hb-add{margin:16px 0 0;border-radius:12px;background:#f5efe8;padding:12px}\n.hb-add-h{font-weight:700;font-size:17px;color:#1d1d1d;margin:0}\n.hb-add-p{font-size:14px;color:#555;margin:3px 0 6px;line-height:1.45}\n.hb-item{display:flex;align-items:center;gap:10px;background:#fff;border-radius:8px;padding:9px 10px;margin-top:7px;cursor:pointer}\n.hb-item input{width:20px;height:20px;accent-color:var(--g);flex:0 0 20px;margin:0}\n.hb-item img{width:54px;height:54px;object-fit:cover;border-radius:6px;flex:0 0 54px}\n.hb-item-t{flex:1;min-width:0;font-size:14px;line-height:1.35}\n.hb-item-t small{display:block;color:#6b6b6b;font-size:13px}\n.hb-item-p{text-align:right;white-space:nowrap;font-weight:700}\n.hb-item-p\u003espan:not(.hb-sr){display:block;font-weight:400;font-size:13px;color:#c0392b}\n.hb-item-p s{color:#8a8a8a;margin-left:4px}\n.hb-ship{text-align:center;margin:16px 0 0;font-size:15px;line-height:1.5}\n.hb-ship b{color:var(--g)}\n.hb-trust{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:14px 0 18px;text-align:center;font-weight:700;font-size:13.5px;color:var(--g)}\n.hb-trust svg{display:block;margin:0 auto 5px;width:32px;height:32px}\n.hb-err{color:#c0392b;text-align:center;font-size:14px;margin-top:6px}\n.hb-item-a{color:inherit;text-decoration:underline;text-underline-offset:2px}\n.hb-item-img{display:block;flex:0 0 54px}\n.hb-ck{text-align:center;margin:0 0 16px;font-size:14px}\n.hb-ck a{color:var(--g);font-weight:600}\n.hq{position:fixed;inset:0;z-index:2147483000;background:rgba(0,0,0,.45);display:flex;align-items:center;justify-content:center;padding:16px}\n.hq[hidden]{display:none}\n.hq-box{background:#fff;border-radius:14px;max-width:780px;width:100%;max-height:90vh;overflow:auto;position:relative;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:28px;padding:30px 26px 24px;color:#1d1d1d;font-size:15px}\n.hq-box\u003ediv{min-width:0}\n.hq-x{position:absolute;top:8px;right:10px;background:none;border:0;font-size:28px;line-height:1;cursor:pointer;color:#444;padding:4px 8px}\n.hq-main{position:relative;aspect-ratio:1\/1;display:flex;align-items:center;justify-content:center}\n.hq-main img{max-width:100%;max-height:100%;object-fit:contain}\n.hq-nav{position:absolute;top:50%;transform:translateY(-50%);background:rgba(255,255,255,.9);border:0;border-radius:50%;width:36px;height:36px;font-size:24px;line-height:1;cursor:pointer;color:#333}\n.hq-prev{left:0}.hq-next{right:0}\n.hq-th{display:flex;gap:10px;overflow-x:auto;margin-top:14px;padding-bottom:4px}\n.hq-th button{flex:0 0 58px;padding:0 0 6px;border:0;border-bottom:2px solid transparent;background:none;cursor:pointer}\n.hq-th button.on{border-bottom-color:#1d1d1d}\n.hq-th img{width:58px;height:52px;object-fit:cover;border-radius:4px;display:block}\n.hq-t{font-size:21px;line-height:1.35;margin:0 30px 8px 0;font-weight:500}\n.hq-v{font-size:13.5px;color:#6b6b6b;margin:0 0 8px}\n.hq-p{font-size:20px;font-weight:700;margin:0 0 4px}\n.hq-p s{font-size:15px;color:#8a8a8a;font-weight:400;margin-left:6px}\n.hq-save{font-size:13.5px;color:#7a5534;margin:0 0 14px}\n.hq-ul{list-style:none;padding:0;margin:0 0 18px;font-size:14.5px;line-height:1.5}\n.hq-ul li{position:relative;padding-left:27px;margin:0 0 6px}\n.hq-ul li:before{content:\"\\2713\";position:absolute;left:0;top:2px;width:19px;height:19px;border-radius:4px;background:#a57549;color:#fff;font-size:13px;font-weight:700;line-height:19px;text-align:center}\n.hq-add{display:block;width:100%;border:0;border-radius:40px;background:#7a5534;color:#fff;font:inherit;font-weight:700;padding:12px;cursor:pointer;margin:0 0 14px}\n.hq-more{display:inline-block;color:#1d1d1d;font-weight:600;text-decoration:none;font-size:15.5px}\nbody.hq-lock{overflow:hidden}\n@media (max-width:640px){.hq-box{grid-template-columns:minmax(0,1fr);gap:14px;padding:42px 16px 18px}.hq-t{font-size:18px;margin-right:0}}\n.hb-ctl{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:6px}\n.hb-sel{-webkit-appearance:menulist;appearance:auto;font:inherit;font-size:13px;line-height:1.2;height:30px;padding:0 4px;flex:1 1 120px;max-width:100%;min-width:0;border:1px solid #8a7f73;border-radius:6px;background:#fff;color:#2b2b2b;cursor:pointer}\n.hb-qty{display:inline-flex;align-items:center;height:30px;border:1px solid #8a7f73;border-radius:6px;background:#fff;overflow:hidden}\n.hb-qty button{border:0;background:none;width:28px;height:28px;padding:0;font:inherit;font-size:17px;line-height:1;color:#2b2b2b;cursor:pointer}\n.hb-qty button[aria-disabled=\"true\"]{color:#c4c4c4;cursor:default}\n.hb-qty button:focus-visible{outline:2px solid #7a5534;outline-offset:-2px}\n.hb-sr{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;margin:0}\n@media (max-width:749px){.hb-sel{font-size:16px;height:36px}.hb-qty{height:36px}.hb-qty button{width:36px;height:34px}}\n.hb-qty output{min-width:20px;text-align:center;font-size:13.5px;font-weight:600}\n.hb-item.on{box-shadow:inset 0 0 0 1.5px var(--g)}\n\u003c\/style\u003e\n\u003cscript\u003e\n(() =\u003e {\n  const cs = document.currentScript;\n  const start = () =\u003e {\n  const root = (cs \u0026\u0026 cs.parentElement.querySelector('.hb')) || document.querySelector('.hb');\n  if (!root || root.dataset.ready) return;\n  root.dataset.ready = 1;\n  \/\/ what to offer under each product (handle -\u003e handles)\n  const PAIR = {\n      'duo-french-twist-set': ['pearl-crystal-flower-hair-pin-set', 'geometric-hair-clips-set-of-2', 'overnight-curl-set'],\n      'tortoiseshell-french-hair-pin': ['geometric-hair-clips-set-of-2', 'pearl-crystal-flower-hair-pin-set', 'overnight-curl-set'],\n      'elegant-claw-clip': ['tortoiseshell-french-hair-pin', 'geometric-hair-clips-set-of-2'],\n      'geometric-hair-clips-set-of-2': ['tortoiseshell-french-hair-pin', 'overnight-curl-set'],\n      'pearl-crystal-flower-hair-pin-set': ['vintage-crystal-hair-pin-set-of-3', 'tortoiseshell-french-hair-pin'],\n      'vintage-crystal-hair-pin-set-of-3': ['pearl-crystal-flower-hair-pin-set', 'tortoiseshell-french-hair-pin'],\n      'heart-pearl-hair-clip': ['pearl-crystal-flower-hair-pin-set', 'vintage-crystal-hair-pin-set-of-3'],\n      'overnight-curl-set': ['tortoiseshell-french-hair-pin', 'geometric-hair-clips-set-of-2'],\n      'silk-sleep-set': ['tortoiseshell-french-hair-pin', 'duo-french-twist-set']\n    };\n  const HEAD = { 'overnight-curl-set': 'Add a day-two style', 'silk-sleep-set': 'Add a day-two style' };\n  \/\/ must match the store's automatic discounts: Buy 2 items 10%, Buy 3+ items 15%\n  const pctFor = n =\u003e n \u003e= 3 ? 15 : n \u003e= 2 ? 10 : 0;\n  const money = c =\u003e '$' + (c \/ 100).toFixed(2);\n  const esc = s =\u003e String(s).replace(\/\u0026\/g, '\u0026amp;').replace(\/\u003c\/g, '\u0026lt;').replace(\/\u003e\/g, '\u0026gt;').replace(\/\"\/g, '\u0026quot;');\n  const MAXQ = 10;\n  const info = document.querySelector('.product__info-container');\n  const form = info \u0026\u0026 info.querySelector('form[action*=\"\/cart\/add\"][data-type=\"add-to-cart-form\"]');\n  if (!info || !form) return;\n  const blockOf = el =\u003e { while (el \u0026\u0026 el.parentElement !== info) el = el.parentElement; return el; };\n  const buyBlock = blockOf(form);\n  const qtyInput = () =\u003e info.querySelector('.product-form__quantity input[name=\"quantity\"]') || document.querySelector('input[name=\"quantity\"]');\n  const mainQty = () =\u003e Math.max(1, parseInt((qtyInput() || {}).value, 10) || 1);\n  buyBlock.after(root);\n  root.hidden = false;\n  const pay = root.querySelector('.hb-pay'), footerPay = document.querySelector('.list-payment');\n  if (!pay.querySelector('svg') \u0026\u0026 footerPay) pay.innerHTML = [...footerPay.querySelectorAll('svg')].map(s =\u003e s.outerHTML).join('');\n  if (!pay.querySelector('svg')) pay.remove();\n  const icon = d =\u003e '\u003csvg aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.7\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e' + d + '\u003c\/svg\u003e';\n  root.insertAdjacentHTML('beforeend',\n    '\u003cdiv class=\"hb-add\" hidden\u003e\u003c\/div\u003e' +\n    '\u003cdiv class=\"hb-ship\"\u003e\u003cb\u003eFree US shipping\u003c\/b\u003e on orders $60+.\u003cbr\u003eTypical delivery: 5–11 days after dispatch.\u003c\/div\u003e' +\n    '\u003cdiv class=\"hb-trust\"\u003e' +\n    '\u003cdiv\u003e' + icon('\u003cpath d=\"M3 7h11v8H3zM14 10h4l3 3v2h-7\"\/\u003e\u003ccircle cx=\"7\" cy=\"17\" r=\"1.6\"\/\u003e\u003ccircle cx=\"17\" cy=\"17\" r=\"1.6\"\/\u003e') + 'Free Shipping $60+\u003c\/div\u003e' +\n    '\u003cdiv\u003e' + icon('\u003cpath d=\"M4 12a8 8 0 1 0 2.4-5.7\"\/\u003e\u003cpath d=\"M4 4v4h4\"\/\u003e') + '30-Day Returns\u003c\/div\u003e' +\n    '\u003cdiv\u003e' + icon('\u003crect x=\"5\" y=\"11\" width=\"14\" height=\"9\" rx=\"2\"\/\u003e\u003cpath d=\"M8 11V8a4 4 0 0 1 8 0v3\"\/\u003e') + 'Secure Checkout\u003c\/div\u003e' +\n    '\u003c\/div\u003e' +\n    (root.dataset.handle === 'elegant-claw-clip' ? '\u003cp class=\"hb-ck\"\u003e\u003ca href=\"\/blogs\/hair-guides\/french-pin-vs-claw-clip\"\u003eClaw clip or French pin? Compare them \u0026rarr;\u003c\/a\u003e\u003c\/p\u003e' : \/french-hair-pin|duo-french\/.test(root.dataset.handle) ? '\u003cp class=\"hb-ck\"\u003e\u003ca href=\"\/blogs\/hair-guides\/how-to-use-a-french-hair-pin\"\u003eNew to French pins? Read our step-by-step guide \u0026rarr;\u003c\/a\u003e\u003c\/p\u003e' : ''));\n  const handles = PAIR[root.dataset.handle] || [];\n  let extras = [];\n  const add = root.querySelector('.hb-add');\n  const cbOf = i =\u003e add.querySelector('input[type=\"checkbox\"][data-x=\"' + i + '\"]');\n  const picks = () =\u003e [...add.querySelectorAll('input[type=\"checkbox\"]:checked')].map(c =\u003e extras[+c.dataset.x]);\n  const paint = () =\u003e {\n    const n = mainQty() + picks().reduce((s, x) =\u003e s + x.q, 0);\n    add.querySelectorAll('.hb-item').forEach(el =\u003e {\n      const e = extras[+el.dataset.x], on = cbOf(el.dataset.x).checked;\n      el.classList.toggle('on', on);\n      el.dataset.q = e.q;\n      const pct = pctFor(on ? n : n + e.q);\n      const unit = e.v.price - Math.floor(e.v.price * pct \/ 100);\n      el.querySelector('.hb-item-p').innerHTML = (pct ? '\u003cspan\u003e-' + pct + '%\u003cs\u003e\u003cspan class=\"hb-sr\"\u003eRegular price \u003c\/span\u003e' + money(e.v.price * e.q) + '\u003c\/s\u003e\u003c\/span\u003e\u003cspan class=\"hb-sr\"\u003eSale price \u003c\/span\u003e' : '') + money(unit * e.q);\n      const q = el.querySelector('.hb-qty');\n      const out = q.querySelector('output'); if (out.textContent !== String(e.q)) out.textContent = e.q;\n      q.querySelector('[data-d=\"-1\"]').setAttribute('aria-disabled', e.q \u003c= 1 ? 'true' : 'false');\n      q.querySelector('[data-d=\"1\"]').setAttribute('aria-disabled', e.q \u003e= MAXQ ? 'true' : 'false');\n    });\n  };\n  const say = t =\u003e { const s = add.querySelector('.hb-sr'); if (s) { s.textContent = ''; setTimeout(() =\u003e { s.textContent = t; }, 50); } };\n  const check = i =\u003e { const cb = cbOf(i); if (!cb.checked) { cb.checked = true; cb.dispatchEvent(new Event('change', { bubbles: true })); say(extras[i].a.title.split(' – ')[0] + ' added to this order'); } else paint(); };\n  const hvP = h =\u003e new Promise(ok =\u003e { const go = () =\u003e ok((window.HVP || {})[h] || null); if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', go); else go(); }).then(p =\u003e p || fetch('\/products\/' + h + '.js').then(r =\u003e r.ok ? r.json() : null));\n  Promise.all(handles.map(h =\u003e hvP(h).catch(() =\u003e null))).then(list =\u003e {\n    extras = list.filter(Boolean).map(a =\u003e { const v = a.variants.find(x =\u003e x.available); return v \u0026\u0026 { a, v, q: 1 }; }).filter(Boolean);\n    if (!extras.length) return;\n    const img = s =\u003e s ? s + (s.includes('?') ? '\u0026' : '?') + 'width=120' : '';\n    const vImg = e =\u003e (e.v.featured_image \u0026\u0026 e.v.featured_image.src) || e.a.featured_image;\n    const link = e =\u003e '\/products\/' + e.a.handle + '?variant=' + e.v.id;\n    const optName = e =\u003e (e.a.options || []).map(o =\u003e typeof o === 'string' ? o : o.name).join(' \/ ') || 'Option';\n    const name = e =\u003e e.a.title.split(' – ')[0];\n    const sel = (e, i) =\u003e e.a.variants.length \u003c 2 ? '' :\n      '\u003cselect class=\"hb-sel\" data-x=\"' + i + '\" aria-label=\"' + esc(name(e) + ': ' + optName(e)) + '\"\u003e' +\n      e.a.variants.map(v =\u003e '\u003coption value=\"' + v.id + '\"' + (v.id === e.v.id ? ' selected' : '') + (v.available ? '' : ' disabled') + '\u003e' + esc(v.title) + (v.available ? '' : ' (sold out)') + '\u003c\/option\u003e').join('') +\n      '\u003c\/select\u003e';\n    const qty = (e, i) =\u003e '\u003cspan class=\"hb-qty\" data-x=\"' + i + '\"\u003e\u003cbutton type=\"button\" data-d=\"-1\" aria-label=\"Decrease quantity of ' + esc(name(e)) + '\"\u003e\u0026minus;\u003c\/button\u003e\u003coutput aria-label=\"Quantity\"\u003e1\u003c\/output\u003e\u003cbutton type=\"button\" data-d=\"1\" aria-label=\"Increase quantity of ' + esc(name(e)) + '\"\u003e+\u003c\/button\u003e\u003c\/span\u003e';\n    add.innerHTML = '\u003cp class=\"hb-add-h\" role=\"heading\" aria-level=\"2\"\u003e' + (HEAD[root.dataset.handle] || 'Complete the look') + '\u003c\/p\u003e\u003cp class=\"hb-sr\" role=\"status\"\u003e\u003c\/p\u003e' +\n      '\u003cp class=\"hb-add-p\"\u003ePick a color or style and quantity to add it to this order, or uncheck to remove it. Buy 2 items, save 10%; buy 3 or more, save 15%, applied automatically at checkout.\u003c\/p\u003e' +\n      extras.map((e, i) =\u003e '\u003cdiv class=\"hb-item\" data-x=\"' + i + '\"\u003e\u003cinput type=\"checkbox\" data-x=\"' + i + '\" aria-label=\"Add ' + esc(name(e)) + ' to this order\"\u003e' +\n        (vImg(e) ? '\u003ca class=\"hb-item-img\" href=\"' + link(e) + '\" tabindex=\"-1\" aria-hidden=\"true\"\u003e\u003cimg src=\"' + img(vImg(e)) + '\" alt=\"\" loading=\"lazy\"\u003e\u003c\/a\u003e' : '') +\n        '\u003cspan class=\"hb-item-t\"\u003e\u003ca class=\"hb-item-a\" href=\"' + link(e) + '\" aria-haspopup=\"dialog\"\u003e' + esc(name(e)) + '\u003c\/a\u003e' +\n        '\u003cspan class=\"hb-ctl\"\u003e' + sel(e, i) + qty(e, i) + '\u003c\/span\u003e\u003c\/span\u003e' +\n        '\u003cspan class=\"hb-item-p\"\u003e\u003c\/span\u003e\u003c\/div\u003e').join('');\n    add.hidden = false;\n    add.addEventListener('click', ev =\u003e {\n      const t = ev.target;\n      const b = t.closest('.hb-qty button');\n      if (b) {\n        ev.preventDefault();\n        if (b.getAttribute('aria-disabled') === 'true') return;\n        const i = +b.closest('.hb-qty').dataset.x, e = extras[i];\n        e.q = Math.min(MAXQ, Math.max(1, e.q + +b.dataset.d));\n        check(i);\n        return;\n      }\n      if (t.closest('.hb-ctl')) return;\n      const a = t.closest('.hb-item-a, .hb-item-img');\n      if (a) {\n        if (!window.hhQV) return;\n        ev.preventDefault();\n        const i = +a.closest('.hb-item').dataset.x, e = extras[i], cb = cbOf(i);\n        window.hhQV({ a: e.a, v: e.v, from: a, note: 'Add it to this order: 2 items save 10%, 3 or more save 15% at checkout.', addLabel: cb.checked ? 'Remove from this order' : 'Add to this order', onAdd: () =\u003e { cb.checked = !cb.checked; cb.dispatchEvent(new Event('change', { bubbles: true })); } });\n        return;\n      }\n      const row = t.closest('.hb-item');\n      if (row \u0026\u0026 t.type !== 'checkbox') { const cb = cbOf(row.dataset.x); cb.checked = !cb.checked; cb.dispatchEvent(new Event('change', { bubbles: true })); }\n    });\n    add.addEventListener('change', ev =\u003e {\n      const s = ev.target.closest('.hb-sel');\n      if (s) {\n        const i = +s.dataset.x, e = extras[i], v = e.a.variants.find(x =\u003e x.id === +s.value);\n        if (v) {\n          e.v = v;\n          const row = s.closest('.hb-item'), im = row.querySelector('.hb-item-img img');\n          if (im \u0026\u0026 vImg(e)) im.src = img(vImg(e));\n          row.querySelectorAll('.hb-item-a, .hb-item-img').forEach(x =\u003e x.href = link(e));\n        }\n        check(i);\n        return;\n      }\n      paint();\n    });\n    document.addEventListener('change', e =\u003e { if (e.target.name === 'quantity') setTimeout(paint, 50); });\n    paint();\n  });\n  \/\/ Add to cart with add-ons is handled by the theme script in the hv_shim block (add-all v2).\n  };\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); else start();\n})();\n\u003c\/script\u003e\n\u003c!-- \/hv-upsell v2.3 --\u003e\n\u003c!-- hv-extra v2.5 (Havendoa, 2026-10-15): shared quick view, single\/duo switch and French Twist Kit with color + quantity pickers. Remove from the hv-extra v2.5 start marker to the \/hv-extra v2.5 end marker to undo. --\u003e\n\u003cdiv class=\"hd\" data-handle=\"silk-sleep-set\" hidden\u003e\u003c\/div\u003e\u003cdiv class=\"hn\" data-handle=\"silk-sleep-set\" hidden\u003e\u003c\/div\u003e\n\u003cstyle\u003e\n.hd{--g:#7a5534;margin:6px 0 18px;border:1px solid #e5d6c6;border-radius:12px;padding:12px;background:#fff;font-size:15px;color:#2b2b2b}\n.hd-h{font-weight:700;font-size:17px;margin:0}\n.hd-p{font-size:14px;color:#555;margin:3px 0 8px;line-height:1.45}\n.hd-card{display:flex;gap:10px;align-items:flex-start;border-top:1px solid #eee;padding:10px 0 4px}\n.hd-card img{width:62px;height:62px;object-fit:cover;border-radius:8px;flex:0 0 62px}\n.hd-b{flex:1;min-width:0;font-size:13.5px;line-height:1.4}\n.hd-b a.hd-t{font-weight:700;color:#1d1d1d;text-decoration:underline;text-underline-offset:2px;font-size:14.5px}\n.hd-img{display:block;flex:0 0 62px}\n.hd-b .hd-in{color:#2f6b52}\n.hd-b .hd-out{color:#8a5a2b}\n.hd-btn{margin-top:6px;border:1.5px solid var(--g);background:#fff;color:var(--g);border-radius:30px;padding:7px 14px;font:inherit;font-weight:700;font-size:13.5px;cursor:pointer}\n.hd-btn:disabled{opacity:.6}\n.hn{--g:#7a5534;margin:6px 0 18px;border:2px solid var(--g);border-radius:14px;padding:14px;background:#f8f2ec;font-size:15px;color:#2b2b2b}\n.hn-k{font-size:13px;letter-spacing:.08em;text-transform:uppercase;font-weight:700;color:#c75b2a;margin:0}\n.hn-h{font-weight:700;font-size:18px;margin:2px 0 4px;color:var(--g)}\n.hn-p{font-size:14px;color:#555;margin:0 0 10px;line-height:1.45}\n.hn-list{display:grid;gap:8px;margin:0 0 10px}\n.hn-row{display:flex;gap:10px;align-items:center;background:#fff;border-radius:10px;padding:8px}\n.hn-row img{width:48px;height:48px;object-fit:cover;border-radius:6px;flex:0 0 48px}\n.hn-row span{flex:1;min-width:0;font-size:13.5px;line-height:1.35}\n.hn-row span small{display:block;color:#6b6b6b}\n.hn-row b{white-space:nowrap;font-size:14px}\n.hn-sum{display:flex;justify-content:space-between;font-size:14px;margin:2px 2px 0}\n.hn-sum.hn-you{font-weight:700;font-size:16px;color:var(--g)}\n.hn-btn{display:block;width:100%;margin-top:10px;border:0;border-radius:40px;background:var(--g);color:#fff;font:inherit;font-weight:700;font-size:16px;padding:13px;cursor:pointer}\n.hn-btn:disabled{opacity:.6}\n.hn-a{color:inherit;text-decoration:underline;text-underline-offset:2px}\n.hn-img{display:block;flex:0 0 48px}\n.hn-note{font-size:13px;color:#6b6b6b;margin:8px 0 0;text-align:center}\n.hd-ctl{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-top:8px}\n.hd-sel{-webkit-appearance:menulist;appearance:auto;font:inherit;font-size:13px;line-height:1.2;height:30px;padding:0 4px;flex:1 1 130px;max-width:100%;min-width:0;border:1px solid #d6cfc6;border-radius:6px;background:#fff;color:#2b2b2b;cursor:pointer}\n.hd-qty{display:inline-flex;align-items:center;height:30px;border:1px solid #d6cfc6;border-radius:6px;background:#fff;overflow:hidden}\n.hd-qty button{border:0;background:none;width:28px;height:28px;padding:0;font:inherit;font-size:17px;line-height:1;color:#2b2b2b;cursor:pointer}\n.hd-qty button:disabled{color:#c4c4c4;cursor:default}\n.hd-qty output{min-width:20px;text-align:center;font-size:13.5px;font-weight:600}\n.hd-pr s{color:#8a8a8a;font-weight:400}\n.hd-sel{border-color:#8a7f73}\n.hd-qty{border-color:#8a7f73}\n.hd-qty button[aria-disabled=\"true\"]{color:#c4c4c4;cursor:default}\n.hd-qty button:focus-visible{outline:2px solid #7a5534;outline-offset:-2px}\n.hn-sel{-webkit-appearance:menulist;appearance:auto;display:block;margin-top:5px;font:inherit;font-size:13px;line-height:1.2;height:30px;padding:0 4px;max-width:100%;border:1px solid #8a7f73;border-radius:6px;background:#fff;color:#2b2b2b;cursor:pointer}\n.hd-err{color:#c0392b;font-size:13.5px;margin:4px 0 0}\n.hd-err:empty{display:none}\n.hv-vh{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n@media (max-width:749px){.hd-sel,.hn-sel{font-size:16px;height:36px}.hd-qty{height:36px}.hd-qty button{width:36px;height:34px}}\n\u003c\/style\u003e\n\u003cscript\u003e\n(() =\u003e {\n  const cs = document.currentScript;\n  if (!window.hhQV) window.hhQV = (() =\u003e {\n    const qv = document.createElement('div');\n    qv.className = 'hq'; qv.hidden = true;\n    document.body.appendChild(qv);\n    const px = (s, w) =\u003e s ? s + (s.includes('?') ? '\u0026' : '?') + 'width=' + w : '';\n    const esc = s =\u003e String(s).replace(\/[\u0026\u003c\u003e\"]\/g, c =\u003e ({ '\u0026': '\u0026amp;', '\u003c': '\u0026lt;', '\u003e': '\u0026gt;', '\"': '\u0026quot;' }[c]));\n    const cash = c =\u003e '$' + (c \/ 100).toFixed(2);\n    const fileOf = s =\u003e String(s || '').split('?')[0].split('\/').pop();\n    const bullets = html =\u003e {\n      const d = new DOMParser().parseFromString(html || '', 'text\/html');\n      d.querySelectorAll('script, style, .hb, .hd, .hn').forEach(x =\u003e x.remove());\n      let li = [...d.querySelectorAll('li')].map(x =\u003e x.textContent.replace(\/\\s+\/g, ' ').trim()).filter(Boolean);\n      if (!li.length) li = [...d.querySelectorAll('p')].map(x =\u003e x.textContent.trim()).filter(Boolean).slice(0, 1);\n      return li.slice(0, 5).map(t =\u003e t.length \u003e 95 ? t.slice(0, 92).replace(\/[\\s,.;:]+\\S*$\/, '') + '…' : t);\n    };\n    let back = null, off = [];\n    const close = () =\u003e { qv.hidden = true; document.body.classList.remove('hq-lock'); off.forEach(el =\u003e { el.inert = false; }); off = []; if (back) back.focus(); };\n    qv.addEventListener('click', ev =\u003e { if (ev.target === qv) close(); });\n    document.addEventListener('keydown', ev =\u003e {\n      if (qv.hidden) return;\n      if (ev.key === 'Escape') close();\n      if (ev.key === 'ArrowLeft') { const b = qv.querySelector('.hq-prev'); if (b) b.click(); }\n      if (ev.key === 'ArrowRight') { const b = qv.querySelector('.hq-next'); if (b) b.click(); }\n    });\n    return o =\u003e {\n      const a = o.a, v = o.v;\n      back = o.from || null;\n      const imgs = (a.images \u0026\u0026 a.images.length) ? a.images : [a.featured_image];\n      let k = v.featured_image ? Math.max(0, imgs.findIndex(s =\u003e fileOf(s) === fileOf(v.featured_image.src))) : 0;\n      qv.innerHTML = '\u003cdiv class=\"hq-box\" role=\"dialog\" aria-modal=\"true\" aria-label=\"' + esc(a.title) + '\"\u003e' +\n        '\u003cbutton type=\"button\" class=\"hq-x\" aria-label=\"Close\"\u003e\u0026times;\u003c\/button\u003e' +\n        '\u003cdiv\u003e\u003cdiv class=\"hq-main\"\u003e\u003cimg alt=\"\"\u003e' +\n        (imgs.length \u003e 1 ? '\u003cbutton type=\"button\" class=\"hq-nav hq-prev\" aria-label=\"Previous image\"\u003e\u0026lsaquo;\u003c\/button\u003e\u003cbutton type=\"button\" class=\"hq-nav hq-next\" aria-label=\"Next image\"\u003e\u0026rsaquo;\u003c\/button\u003e' : '') +\n        '\u003c\/div\u003e' + (imgs.length \u003e 1 ? '\u003cdiv class=\"hq-th\"\u003e' + imgs.map((s, j) =\u003e '\u003cbutton type=\"button\" data-j=\"' + j + '\" aria-label=\"Image ' + (j + 1) + '\"\u003e\u003cimg src=\"' + px(s, 120) + '\" alt=\"\" loading=\"lazy\"\u003e\u003c\/button\u003e').join('') + '\u003c\/div\u003e' : '') + '\u003c\/div\u003e' +\n        '\u003cdiv\u003e\u003ch2 class=\"hq-t\"\u003e' + esc(a.title) + '\u003c\/h2\u003e' +\n        (a.variants.length \u003e 1 ? '\u003cp class=\"hq-v\"\u003e' + esc(v.title.split(' \/ ')[0]) + '\u003c\/p\u003e' : '') +\n        '\u003cp class=\"hq-p\"\u003e' + cash(v.price) + (v.compare_at_price \u003e v.price ? '\u003cs\u003e\u003cspan class=\"hv-vh\"\u003eRegular price \u003c\/span\u003e' + cash(v.compare_at_price) + '\u003c\/s\u003e' : '') + '\u003c\/p\u003e' +\n        (o.note ? '\u003cp class=\"hq-save\"\u003e' + esc(o.note) + '\u003c\/p\u003e' : '') +\n        '\u003cul class=\"hq-ul\"\u003e' + bullets(a.description).map(t =\u003e '\u003cli\u003e' + esc(t) + '\u003c\/li\u003e').join('') + '\u003c\/ul\u003e' +\n        (o.onAdd ? '\u003cbutton type=\"button\" class=\"hq-add\"\u003e' + esc(o.addLabel || 'Add to cart') + '\u003c\/button\u003e' : '') +\n        '\u003ca class=\"hq-more\" href=\"\/products\/' + a.handle + '?variant=' + v.id + '\"\u003eView more details \u003cspan aria-hidden=\"true\"\u003e\u0026rarr;\u003c\/span\u003e\u003c\/a\u003e\u003c\/div\u003e\u003c\/div\u003e';\n      const main = qv.querySelector('.hq-main img'), th = [...qv.querySelectorAll('.hq-th button')];\n      const show = j =\u003e { k = (j + imgs.length) % imgs.length; main.src = px(imgs[k], 800); main.alt = a.title.split(' – ')[0] + ', image ' + (k + 1) + ' of ' + imgs.length; th.forEach((b, x) =\u003e { b.classList.toggle('on', x === k); b.setAttribute('aria-current', x === k ? 'true' : 'false'); }); };\n      th.forEach(b =\u003e b.addEventListener('click', () =\u003e show(+b.dataset.j)));\n      const prev = qv.querySelector('.hq-prev'), next = qv.querySelector('.hq-next');\n      if (prev) prev.addEventListener('click', () =\u003e show(k - 1));\n      if (next) next.addEventListener('click', () =\u003e show(k + 1));\n      qv.querySelector('.hq-x').addEventListener('click', close);\n      const addBtn = qv.querySelector('.hq-add');\n      if (addBtn) addBtn.addEventListener('click', () =\u003e { close(); o.onAdd(); });\n      show(k);\n      qv.hidden = false;\n      off = [...document.body.children].filter(el =\u003e el !== qv \u0026\u0026 !el.inert); off.forEach(el =\u003e { el.inert = true; });\n      document.body.classList.add('hq-lock');\n      qv.querySelector('.hq-x').focus();\n    };\n  })();\n  \/\/ single \u003c-\u003e duo switch, per product page\n  const SWITCH = {\n    'duo-french-twist-set': { h: 'Just need one pin?', p: 'Start with a single pin and add a second one later. Orders under $60 ship for $8.', items: [{ handle: 'tortoiseshell-french-hair-pin', name: 'French Hair Pin', inc: '1 French Hair Pin in the color you choose', out: 'the second pin (the Duo is $65, less than two single pins)' }] },\n    'tortoiseshell-french-hair-pin': { h: 'Want a spare? Get the Duo', p: 'One pin for a simple twist; add a second for a fuller bun on long or thick hair. $65 for two: less than two single pins, even with the 2-item discount.', items: [{ handle: 'duo-french-twist-set', name: 'Duo French Twist Set', inc: '2 French Hair Pins in the color you choose', out: '' }] }\n  };\n  \/\/ French Twist Kit, shown on these pages\n  const KIT_ON = ['duo-french-twist-set', 'tortoiseshell-french-hair-pin'];\n  const SET = [\n    { h: 'duo-french-twist-set', name: 'Duo French Twist Set', note: 'two French pins for the twist' },\n    { h: 'geometric-hair-clips-set-of-2', name: 'Geometric Hair Clips, Set of 2', note: 'side clips for quick half-up days' },\n    { h: 'pearl-crystal-flower-hair-pin-set', name: 'Simulated Pearl \u0026 Crystal Flower Pins', note: 'for weddings and special days' }\n  ];\n  const PCT = 15; \/\/ store's automatic discount for 3+ items\n  const money = c =\u003e '$' + (c \/ 100).toFixed(2);\n  const img = (s, w) =\u003e s ? s + (s.includes('?') ? '\u0026' : '?') + 'width=' + w : '';\n  const esc = s =\u003e String(s).replace(\/\u0026\/g, '\u0026amp;').replace(\/\u003c\/g, '\u0026lt;').replace(\/\u003e\/g, '\u0026gt;').replace(\/\"\/g, '\u0026quot;');\n  const optName = p =\u003e (p.options || []).map(o =\u003e typeof o === 'string' ? o : o.name).join(' \/ ') || 'Option';\n  const vImg = (p, v) =\u003e (v \u0026\u0026 v.featured_image \u0026\u0026 v.featured_image.src) || p.featured_image;\n  const pickColor = () =\u003e { const i = document.querySelector('.product__info-container variant-picker input:checked, variant-picker input:checked, variant-selects input:checked, variant-radios input:checked'); return i ? i.value : null; };\n  const match = p =\u003e { const c = pickColor(); return (c \u0026\u0026 p.variants.find(v =\u003e v.available \u0026\u0026 v.title.split(' \/ ')[0] === c)) || p.variants.find(v =\u003e v.available); };\n  const selHtml = (p, v, cls, i, label) =\u003e p.variants.length \u003c 2 ? '' :\n    '\u003cselect class=\"' + cls + '\" data-i=\"' + i + '\" aria-label=\"' + esc(label + ': ' + optName(p)) + '\"\u003e' +\n    p.variants.map(x =\u003e '\u003coption value=\"' + x.id + '\"' + (x.id === v.id ? ' selected' : '') + (x.available ? '' : ' disabled') + '\u003e' + esc(x.title) + (x.available ? '' : ' (sold out)') + '\u003c\/option\u003e').join('') + '\u003c\/select\u003e';\n  const hvP = h =\u003e new Promise(ok =\u003e { const go = () =\u003e ok((window.HVP || {})[h] || null); if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', go); else go(); }).then(p =\u003e p || fetch('\/products\/' + h + '.js').then(r =\u003e r.ok ? r.json() : null));\n  const go = async items =\u003e { try { const r = await fetch('\/cart\/add.js', { method: 'POST', headers: { 'Content-Type': 'application\/json', Accept: 'application\/json' }, body: JSON.stringify({ items }) }); return r.ok; } catch (e) { return false; } };\n  const start = () =\u003e {\n    const d = (cs \u0026\u0026 cs.parentElement.querySelector('.hd')) || document.querySelector('.hd');\n    const n = (cs \u0026\u0026 cs.parentElement.querySelector('.hn')) || document.querySelector('.hn');\n    if (!d || d.dataset.ready) return;\n    d.dataset.ready = 1;\n    const handle = d.dataset.handle;\n    const anchor = () =\u003e document.querySelector('.hb:not([hidden])') || (document.querySelector('.product__info-container product-form') || {}).parentElement;\n    const sw = SWITCH[handle];\n    if (sw) Promise.all(sw.items.map(o =\u003e hvP(o.handle).catch(() =\u003e null))).then(list =\u003e {\n      const rows = sw.items.map((o, i) =\u003e ({ o, p: list[i] })).filter(x =\u003e x.p \u0026\u0026 x.p.available);\n      if (!rows.length) return;\n      rows.forEach(x =\u003e { x.v = match(x.p); x.q = 1; x.touched = false; });\n      const lk = x =\u003e '\/products\/' + x.o.handle + '?variant=' + x.v.id;\n      d.innerHTML = '\u003cp class=\"hd-h\" role=\"heading\" aria-level=\"2\"\u003e' + sw.h + '\u003c\/p\u003e\u003cp class=\"hd-p\"\u003e' + sw.p + '\u003c\/p\u003e' + rows.map((x, i) =\u003e\n        '\u003cdiv class=\"hd-card\" data-i=\"' + i + '\"\u003e' + (vImg(x.p, x.v) ? '\u003ca class=\"hd-img\" tabindex=\"-1\" aria-hidden=\"true\" href=\"' + lk(x) + '\"\u003e\u003cimg src=\"' + img(vImg(x.p, x.v), 140) + '\" alt=\"\"\u003e\u003c\/a\u003e' : '') +\n        '\u003cdiv class=\"hd-b\"\u003e\u003ca class=\"hd-t\" href=\"' + lk(x) + '\" aria-haspopup=\"dialog\"\u003e' + x.o.name + ' · \u003cspan class=\"hd-pr\"\u003e\u003c\/span\u003e\u003c\/a\u003e\u003cbr\u003e' +\n        '\u003cspan class=\"hd-in\"\u003eIncludes: ' + x.o.inc + '.\u003c\/span\u003e' + (x.o.out ? '\u003cbr\u003e\u003cspan class=\"hd-out\"\u003eNot included: ' + x.o.out + '.\u003c\/span\u003e' : '') +\n        '\u003cdiv class=\"hd-ctl\"\u003e' + selHtml(x.p, x.v, 'hd-sel', i, x.o.name) +\n        '\u003cspan class=\"hd-qty\" data-i=\"' + i + '\"\u003e\u003cbutton type=\"button\" data-d=\"-1\" aria-label=\"Decrease quantity of ' + esc(x.o.name) + '\"\u003e\u0026minus;\u003c\/button\u003e\u003coutput aria-label=\"Quantity\"\u003e1\u003c\/output\u003e\u003cbutton type=\"button\" data-d=\"1\" aria-label=\"Increase quantity of ' + esc(x.o.name) + '\"\u003e+\u003c\/button\u003e\u003c\/span\u003e\u003c\/div\u003e' +\n        '\u003cbutton type=\"button\" class=\"hd-btn\" data-i=\"' + i + '\"\u003e\u003c\/button\u003e\u003cp class=\"hd-err\" role=\"alert\"\u003e\u003c\/p\u003e\u003c\/div\u003e\u003c\/div\u003e').join('');\n      const paint = () =\u003e rows.forEach((x, i) =\u003e {\n        const c = d.querySelector('.hd-card[data-i=\"' + i + '\"]');\n        c.querySelector('.hd-pr').innerHTML = money(x.v.price) + (x.v.compare_at_price \u003e x.v.price ? ' \u003cs\u003e\u003cspan class=\"hv-vh\"\u003eRegular price \u003c\/span\u003e' + money(x.v.compare_at_price) + '\u003c\/s\u003e' : '');\n        c.querySelector('output').textContent = x.q;\n        c.querySelector('[data-d=\"-1\"]').setAttribute('aria-disabled', x.q \u003c= 1 ? 'true' : 'false');\n        c.querySelector('[data-d=\"1\"]').setAttribute('aria-disabled', x.q \u003e= 10 ? 'true' : 'false');\n        const b = c.querySelector('.hd-btn'); if (!b.disabled) { const t = x.v.price * x.q, off = x.q \u003e= 3 ? 15 : x.q \u003e= 2 ? 10 : 0; b.textContent = 'Add to cart — ' + money(t - Math.floor(t * off \/ 100)) + (off ? ' at checkout' : ''); }\n        const s = c.querySelector('.hd-sel'); if (s) s.value = String(x.v.id);\n        const im = c.querySelector('.hd-img img'); if (im \u0026\u0026 vImg(x.p, x.v)) im.src = img(vImg(x.p, x.v), 140);\n        c.querySelectorAll('a.hd-t, a.hd-img').forEach(a =\u003e { a.href = lk(x); });\n      });\n      const a = (handle === 'duo-french-twist-set' \u0026\u0026 n \u0026\u0026 !n.hidden) ? n : anchor(); if (a) a.after(d);\n      d.hidden = false;\n      d.addEventListener('change', ev =\u003e {\n        const s = ev.target.closest('.hd-sel'); if (!s) return;\n        const x = rows[+s.dataset.i], v = x.p.variants.find(v =\u003e v.id === +s.value);\n        if (v) { x.v = v; x.touched = true; paint(); }\n      });\n      d.addEventListener('click', ev =\u003e {\n        const qb = ev.target.closest('.hd-qty button');\n        if (qb) { if (qb.getAttribute('aria-disabled') === 'true') return; const x = rows[+qb.closest('.hd-qty').dataset.i]; x.q = Math.min(10, Math.max(1, x.q + +qb.dataset.d)); paint(); return; }\n        const l = ev.target.closest('a.hd-t, a.hd-img'); if (!l) return; ev.preventDefault();\n        const card = l.closest('.hd-card'), x = rows[+card.dataset.i], b = card.querySelector('.hd-btn');\n        window.hhQV({ a: x.p, v: x.v, from: l, note: 'Includes: ' + x.o.inc + '.', addLabel: b.textContent, onAdd: () =\u003e b.click() });\n      });\n      \/\/ follow the color picked on the page until the shopper picks one here\n      document.addEventListener('change', ev =\u003e { if (d.contains(ev.target)) return; setTimeout(() =\u003e { rows.forEach(x =\u003e { if (!x.touched) x.v = match(x.p); }); paint(); }, 200); });\n      d.querySelectorAll('.hd-btn').forEach(b =\u003e b.addEventListener('click', async () =\u003e {\n        const x = rows[+b.dataset.i], err = b.parentElement.querySelector('.hd-err');\n        b.disabled = true; b.textContent = 'Adding…'; err.textContent = '';\n        if (await go([{ id: x.v.id, quantity: x.q }])) location.href = '\/cart';\n        else { b.disabled = false; paint(); err.textContent = 'Could not add to cart. Please try again.'; }\n      }));\n      window.addEventListener('pageshow', e =\u003e { if (e.persisted) { d.querySelectorAll('.hd-btn').forEach(b =\u003e { b.disabled = false; }); paint(); } });\n      paint();\n    });\n    if (n \u0026\u0026 KIT_ON.includes(handle)) Promise.all(SET.map(s =\u003e hvP(s.h).catch(() =\u003e null))).then(list =\u003e {\n      const rows = SET.map((s, i) =\u003e { const p = list[i]; if (!p || !p.available) return null; const v = s.h === 'duo-french-twist-set' ? match(p) : p.variants.find(v =\u003e v.available); return v ? { s, p, v, touched: false } : null; });\n      if (rows.some(r =\u003e !r)) return;\n      const lk = r =\u003e '\/products\/' + r.s.h + '?variant=' + r.v.id;\n      n.innerHTML = '\u003cp class=\"hn-k\" role=\"heading\" aria-level=\"2\"\u003eThe French Twist Kit\u003c\/p\u003e\u003cp class=\"hn-h\"\u003eThree pieces for twists, half-up days and evenings out.\u003c\/p\u003e' +\n        '\u003cp class=\"hn-p\"\u003eTwo French pins for the twist, a pair of side clips for quick half-up days, and simulated pearl flower pins for special occasions. Pick a color or style for each piece.\u003c\/p\u003e' +\n        '\u003cdiv class=\"hn-list\"\u003e' + rows.map((r, i) =\u003e '\u003cdiv class=\"hn-row\" data-i=\"' + i + '\"\u003e' + (vImg(r.p, r.v) ? '\u003ca class=\"hn-img\" tabindex=\"-1\" aria-hidden=\"true\" href=\"' + lk(r) + '\"\u003e\u003cimg src=\"' + img(vImg(r.p, r.v), 100) + '\" alt=\"\"\u003e\u003c\/a\u003e' : '') +\n          '\u003cspan\u003e\u003ca class=\"hn-a\" href=\"' + lk(r) + '\" aria-haspopup=\"dialog\"\u003e' + r.s.name + '\u003c\/a\u003e\u003csmall\u003e' + r.s.note + '\u003c\/small\u003e' + selHtml(r.p, r.v, 'hn-sel', i, r.s.name) + '\u003c\/span\u003e\u003cb class=\"hn-pr\"\u003e\u003c\/b\u003e\u003c\/div\u003e').join('') + '\u003c\/div\u003e' +\n        '\u003cdiv class=\"hn-sum\"\u003e\u003cspan\u003eBought separately\u003c\/span\u003e\u003cspan class=\"hn-full\"\u003e\u003c\/span\u003e\u003c\/div\u003e' +\n        '\u003cdiv class=\"hn-sum hn-you\"\u003e\u003cspan\u003eWith ' + PCT + '% off 3+ items\u003c\/span\u003e\u003cspan class=\"hn-off\"\u003e\u003c\/span\u003e\u003c\/div\u003e' +\n        '\u003cbutton type=\"button\" class=\"hn-btn\"\u003e\u003c\/button\u003e\u003cp class=\"hd-err\" role=\"alert\"\u003e\u003c\/p\u003e' +\n        '\u003cp class=\"hn-note\"\u003eThe ' + PCT + '% applies automatically at checkout and can’t be combined with other discount codes. Items may arrive in separate parcels, each with its own tracking number.\u003c\/p\u003e';\n      const a = handle === 'duo-french-twist-set' ? anchor() : ((d.hidden ? null : d) || anchor()); if (a) a.after(n);\n      n.hidden = false;\n      const btn = n.querySelector('.hn-btn'), err = n.querySelector('.hd-err');\n      const paint = () =\u003e {\n        rows.forEach((r, i) =\u003e {\n          const row = n.querySelector('.hn-row[data-i=\"' + i + '\"]');\n          row.querySelector('.hn-pr').textContent = money(r.v.price);\n          const s = row.querySelector('.hn-sel'); if (s) s.value = String(r.v.id);\n          const im = row.querySelector('.hn-img img'); if (im \u0026\u0026 vImg(r.p, r.v)) im.src = img(vImg(r.p, r.v), 100);\n          row.querySelectorAll('a.hn-a, a.hn-img').forEach(x =\u003e { x.href = lk(r); });\n        });\n        const sum = rows.reduce((t, r) =\u003e t + r.v.price, 0), you = sum - Math.floor(sum * PCT \/ 100);\n        n.querySelector('.hn-full').textContent = money(sum);\n        n.querySelector('.hn-off').textContent = money(you);\n        if (!btn.disabled) btn.textContent = 'Add all ' + rows.length + ' to cart — ' + money(you) + ' at checkout';\n      };\n      n.addEventListener('change', ev =\u003e {\n        const s = ev.target.closest('.hn-sel'); if (!s) return;\n        const r = rows[+s.dataset.i], v = r.p.variants.find(v =\u003e v.id === +s.value);\n        if (v) { r.v = v; r.touched = true; paint(); }\n      });\n      document.addEventListener('change', ev =\u003e { if (n.contains(ev.target)) return; setTimeout(() =\u003e { rows.forEach(r =\u003e { if (!r.touched \u0026\u0026 r.s.h === 'duo-french-twist-set') r.v = match(r.p); }); paint(); }, 200); });\n      btn.addEventListener('click', async () =\u003e {\n        btn.disabled = true; btn.textContent = 'Adding…'; err.textContent = '';\n        if (await go(rows.map(r =\u003e ({ id: r.v.id, quantity: 1 })))) location.href = '\/cart';\n        else { btn.disabled = false; paint(); err.textContent = 'Could not add to cart. Please try again.'; }\n      });\n      window.addEventListener('pageshow', e =\u003e { if (e.persisted) { btn.disabled = false; paint(); } });\n      n.addEventListener('click', ev =\u003e {\n        const l = ev.target.closest('a.hn-a, a.hn-img'); if (!l) return; ev.preventDefault();\n        const r = rows[+l.closest('.hn-row').dataset.i];\n        window.hhQV({ a: r.p, v: r.v, from: l, note: 'Part of the French Twist Kit: ' + r.s.note + '.', addLabel: btn.textContent, onAdd: () =\u003e btn.click() });\n      });\n      paint();\n    });\n  };\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', () =\u003e setTimeout(start, 50)); else setTimeout(start, 50);\n})();\n\u003c\/script\u003e\n\u003c!-- \/hv-extra v2.5 --\u003e\n\u003c!-- hv-tiers v1.4 (Havendoa, 2026-10-15): \"Buy more, save more\" 1\/2\/3 items, replaces the quantity box. Must match automatic discounts (2 items 10%, 3+ items 15%). Remove from the hv-tiers v1.4 start marker to the \/hv-tiers v1.4 end marker to undo. --\u003e\n\u003cdiv class=\"hv-tiers\" data-handle=\"silk-sleep-set\" hidden\u003e\u003c\/div\u003e\n\u003cstyle\u003e\n.hv-tiers{margin:4px 0 16px;background:#f5efe8;border:1px solid #e5d6c6;border-radius:14px;padding:12px 12px 6px;font-size:15px;color:#2b2b2b}\n.hv-tiers__h{font-weight:700;font-size:16px;margin:0 0 8px;color:#7a5534}\n.hv-tier{display:flex;align-items:center;gap:10px;background:#fff;border:1px solid #eadfd3;border-radius:10px;padding:10px 12px;margin:0 0 8px;cursor:pointer}\n.hv-tier.is-on{box-shadow:0 0 0 2px #7a5534;border-color:#7a5534}\n.hv-tier input{width:20px;height:20px;accent-color:#7a5534;margin:0;flex:0 0 20px}\n.hv-tier__t{flex:1;min-width:0;line-height:1.3}\n.hv-tier__t small{display:block;color:#6b6b6b;font-size:13px}\n.hv-tier__b{display:inline-block;margin-left:6px;background:#7a5534;color:#fff;border-radius:20px;font-size:13px;font-weight:700;padding:1px 8px;vertical-align:middle}\n.hv-tier__p{text-align:right;font-weight:700;white-space:nowrap}\n.hv-tier__p s{display:block;font-weight:400;font-size:13px;color:#8a8a8a}\n.hv-vh{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n.hv-tiers__note{font-size:13px;color:#6b6b6b;margin:0 2px 6px}\n\u003c\/style\u003e\n\u003cscript\u003e\n(() =\u003e {\n  const cs = document.currentScript;\n  const TIERS = [[1, 0, ''], [2, 10, 'Save 10%'], [3, 15, 'Save 15%']];\n  const money = c =\u003e '$' + (c \/ 100).toFixed(2);\n  const pctFor = c =\u003e c \u003e= 3 ? 15 : c \u003e= 2 ? 10 : 0;\n  \/\/ add-ons checked in hv-upsell count toward the same automatic discount\n  const extra = () =\u003e [...document.querySelectorAll('.hb-add input[type=\"checkbox\"]:checked')].reduce((s, c) =\u003e { const it = c.closest('.hb-item'); return s + Math.max(1, parseInt(it \u0026\u0026 it.dataset.q, 10) || 1); }, 0);\n  const esc = s =\u003e String(s).replace(\/\u0026\/g, '\u0026amp;').replace(\/\u003c\/g, '\u0026lt;').replace(\/\u003e\/g, '\u0026gt;').replace(\/\"\/g, '\u0026quot;');\n  const start = () =\u003e {\n    const box = (cs \u0026\u0026 cs.parentElement.querySelector('.hv-tiers')) || document.querySelector('.hv-tiers');\n    if (!box || box.dataset.ready) return;\n    box.dataset.ready = 1;\n    const info = document.querySelector('.product__info-container');\n    const form = info \u0026\u0026 info.querySelector('form[action*=\"\/cart\/add\"][data-type=\"add-to-cart-form\"]');\n    if (!info || !form) return;\n    const blockOf = el =\u003e { while (el \u0026\u0026 el.parentElement !== info) el = el.parentElement; return el; };\n    const qtyBox = info.querySelector('.product-form__quantity');\n    const anchor = qtyBox ? blockOf(qtyBox) : blockOf(form);\n    const qty = () =\u003e info.querySelector('input[name=\"quantity\"]') || document.querySelector('input[name=\"quantity\"]');\n    const hvP = h =\u003e new Promise(ok =\u003e { const go = () =\u003e ok((window.HVP || {})[h] || null); if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', go); else go(); }).then(p =\u003e p || fetch('\/products\/' + h + '.js').then(r =\u003e r.ok ? r.json() : null));\n    hvP(box.dataset.handle).then(p =\u003e {\n      if (!p) return;\n      const cur = () =\u003e {\n        const vals = [...info.querySelectorAll('variant-picker fieldset input:checked, variant-picker select')].map(i =\u003e i.value);\n        const byPick = vals.length ? p.variants.find(v =\u003e v.options.join('|') === vals.join('|')) : null;\n        const id = +(form.querySelector('input[name=\"id\"]') || {}).value;\n        return byPick || p.variants.find(v =\u003e v.id === id) || p.variants.find(v =\u003e v.available) || p.variants[0];\n      };\n      const render = focusN =\u003e {\n        const v = cur(), on = box.querySelector('input:checked'), pick = on ? +on.value : Math.max(1, Math.min(3, parseInt((qty() || {}).value, 10) || 1));\n        box.innerHTML = '\u003cp class=\"hv-tiers__h\" id=\"hv-tiers-h\" role=\"heading\" aria-level=\"2\"\u003eBuy more, save more\u003c\/p\u003e\u003cdiv role=\"radiogroup\" aria-labelledby=\"hv-tiers-h\"\u003e' + TIERS.map(([n]) =\u003e {\n          const pct = pctFor(n + extra()), badge = pct ? 'Save ' + pct + '%' : '';\n          const full = v.price * n, you = full - Math.floor(full * pct \/ 100);\n          return '\u003clabel class=\"hv-tier' + (n === pick ? ' is-on' : '') + '\"\u003e\u003cinput type=\"radio\" name=\"hv-tier\" value=\"' + n + '\"' + (n === pick ? ' checked' : '') + '\u003e' +\n            '\u003cspan class=\"hv-tier__t\"\u003e\u003cb\u003e' + n + (n === 1 ? ' item' : ' items') + '\u003c\/b\u003e' + (badge ? '\u003cspan class=\"hv-tier__b\"\u003e' + badge + '\u003c\/span\u003e' : '') + (p.variants.length \u003e 1 ? '\u003csmall\u003e' + esc(v.title) + (n \u003e 1 ? ' x ' + n : '') + '\u003c\/small\u003e' : '') + '\u003c\/span\u003e' +\n            '\u003cspan class=\"hv-tier__p\"\u003e' + money(you) + (pct ? '\u003cs\u003e\u003cspan class=\"hv-vh\"\u003eRegular price \u003c\/span\u003e' + money(full) + '\u003c\/s\u003e' : '') + '\u003c\/span\u003e\u003c\/label\u003e';\n        }).join('') + '\u003c\/div\u003e' + (p.variants.length \u003e 1 ? '\u003cp class=\"hv-tiers__note\"\u003eWant different colors? Add each one to your cart: the discount counts every item in your order. Applied automatically at checkout; can’t be combined with other discount codes.\u003c\/p\u003e' : '\u003cp class=\"hv-tiers__note\"\u003eApplied automatically at checkout; can’t be combined with other discount codes.\u003c\/p\u003e');\n        if (focusN) { const f = box.querySelector('input[value=\"' + focusN + '\"]'); if (f) f.focus(); }\n      };\n      const setQty = n =\u003e { const q = qty(); if (q \u0026\u0026 q.value !== String(n)) { q.value = n; q.dispatchEvent(new Event('change', { bubbles: true })); } };\n      anchor.before(box);\n      if (qtyBox) { if (anchor.contains(form)) qtyBox.style.display = 'none'; else anchor.style.display = 'none'; }\n      render(); box.hidden = false;\n      box.addEventListener('change', e =\u003e { if (e.target.name !== 'hv-tier') return; setQty(+e.target.value); render(+e.target.value); });\n      const reapply = () =\u003e { const t = box.querySelector('input:checked'); if (t) setQty(+t.value); render(); };\n      document.addEventListener('change', e =\u003e { if (e.target.closest \u0026\u0026 e.target.closest('variant-picker')) { render(); setTimeout(reapply, 400); setTimeout(reapply, 1200); } });\n      document.addEventListener('change', e =\u003e { if (e.target.closest \u0026\u0026 e.target.closest('.hb-add')) setTimeout(() =\u003e render(), 0); });\n      document.addEventListener('click', e =\u003e { if (e.target.closest \u0026\u0026 e.target.closest('.hb-add .hb-qty button')) setTimeout(() =\u003e render(), 0); });\n      \/\/ the theme resets quantity to 1 on every variant change; put the tier back and refresh prices\n      document.addEventListener('change', e =\u003e { if (box.contains(e.target)) return; if (e.target \u0026\u0026 e.target.name === 'id') setTimeout(() =\u003e { const t = box.querySelector('input:checked'); if (t) setQty(+t.value); render(); }, 60); });\n      window.addEventListener('pageshow', () =\u003e setTimeout(() =\u003e { const t = box.querySelector('input:checked'); if (t) setQty(+t.value); }, 0));\n    });\n  };\n  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', start); else start();\n})();\n\u003c\/script\u003e\n\u003c!-- \/hv-tiers v1.4 --\u003e","brand":"Havendoa","offers":[{"title":"Black \/ Standard","offer_id":49339596144823,"sku":"HV-SSS-BLK-STD","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Black \/ Queen","offer_id":49339596177591,"sku":"HV-SSS-BLK-QN","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Black \/ King","offer_id":49339596210359,"sku":"HV-SSS-BLK-KG","price":94.0,"currency_code":"USD","in_stock":true},{"title":"Champagne \/ Standard","offer_id":49339596243127,"sku":"HV-SSS-CHP-STD","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Champagne \/ Queen","offer_id":49339596275895,"sku":"HV-SSS-CHP-QN","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Champagne \/ King","offer_id":49339596308663,"sku":"HV-SSS-CHP-KG","price":94.0,"currency_code":"USD","in_stock":true},{"title":"Silver Gray \/ Standard","offer_id":49339596341431,"sku":"HV-SSS-SLV-STD","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Silver Gray \/ Queen","offer_id":49339596374199,"sku":"HV-SSS-SLV-QN","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Silver Gray \/ King","offer_id":49339596406967,"sku":"HV-SSS-SLV-KG","price":94.0,"currency_code":"USD","in_stock":true},{"title":"Blush Pink \/ Standard","offer_id":49339596439735,"sku":"HV-SSS-BLS-STD","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Blush Pink \/ Queen","offer_id":49339596472503,"sku":"HV-SSS-BLS-QN","price":89.0,"currency_code":"USD","in_stock":true},{"title":"Blush Pink \/ King","offer_id":49339596505271,"sku":"HV-SSS-BLS-KG","price":94.0,"currency_code":"USD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0761\/4998\/1367\/files\/0a9e8172-e135-4b0f-be21-b1013cbdea23.jpg?v=1791940137","url":"https:\/\/havendoa.com\/products\/silk-sleep-set","provider":"Havendoa","version":"1.0","type":"link"}