{"product_id":"curtain-helpers-playful-elf-tiebacks-in-3-charming-styles","title":"🎄 Christmas Elf Curtain Tiebacks | Christmas Curtain Helpers in 3 Styles","description":"\u003cstyle\u003e\n  #aj-curtain-helpers {\n    --cream: #fff8ed;\n    --pine: #223f35;\n    --berry: #7f3043;\n    --gold: #f2ce91;\n    --ink: #29382f;\n    --muted: #526056;\n    --line: #e6d8c5;\n    width: 100%;\n    max-width: 1080px;\n    margin: 24px auto;\n    color: var(--ink);\n    font: 16px\/1.6 system-ui, sans-serif;\n  }\n\n  #aj-curtain-helpers * { box-sizing: border-box; }\n  #aj-curtain-helpers [hidden] { display: none !important; }\n\n  #aj-curtain-helpers :is(h2, h3, p, figure, ol) {\n    margin: 0;\n    padding: 0;\n    letter-spacing: normal;\n    text-transform: none;\n  }\n\n  #aj-curtain-helpers :is(h2, h3) {\n    color: inherit;\n    font-family: Georgia, serif;\n    font-weight: 700;\n    line-height: 1.12;\n    text-wrap: balance;\n  }\n\n  #aj-curtain-helpers h2 { font-size: clamp(31px, 5vw, 58px); }\n  #aj-curtain-helpers h3 { font-size: clamp(23px, 3vw, 36px); }\n  #aj-curtain-helpers :is(h2, h3) + p { margin-top: 12px; }\n\n  .ajch-shell {\n    overflow: hidden;\n    border: 1px solid var(--line);\n    border-radius: 18px;\n    background: var(--cream);\n    container-type: inline-size;\n  }\n\n  .ajch-row {\n    display: grid;\n    grid-template-columns: minmax(0, 1fr);\n    align-items: center;\n  }\n\n  .ajch-hero {\n    background: var(--pine);\n    color: var(--cream);\n  }\n\n  .ajch-intro { padding: clamp(21px, 5cqi, 48px); }\n\n  #aj-curtain-helpers .ajch-kicker {\n    margin-bottom: 10px;\n    color: var(--gold);\n    font-size: 12px;\n    font-weight: 750;\n    letter-spacing: .09em;\n    text-transform: uppercase;\n  }\n\n  .ajch-photo {\n    min-width: 0;\n    overflow: hidden;\n    background: #f1e7d8;\n  }\n\n  .ajch-photo img {\n    display: block;\n    width: 100%;\n    height: auto;\n    aspect-ratio: 1;\n    object-fit: contain;\n  }\n\n  #aj-curtain-helpers .ajch-strip {\n    padding: 11px 18px;\n    background: #f0dfc6;\n    text-align: center;\n    font-size: 14px;\n    font-weight: 700;\n  }\n\n  .ajch-body {\n    display: grid;\n    gap: clamp(25px, 5cqi, 46px);\n    padding: clamp(17px, 4cqi, 42px);\n  }\n\n  .ajch-body p { color: var(--muted); }\n  .ajch-story { gap: 16px 28px; }\n  .ajch-body .ajch-photo { border-radius: 12px; }\n\n  .ajch-guide, .ajch-faq {\n    padding: clamp(16px, 3.5cqi, 28px);\n    border: 1px solid var(--line);\n    border-radius: 13px;\n    background: #fffdf8;\n  }\n\n  #aj-curtain-helpers .ajch-guide ol {\n    margin-top: 12px;\n    padding-left: 22px;\n  }\n\n  .ajch-guide li + li { margin-top: 7px; }\n\n  .ajch-grid {\n    display: grid;\n    grid-template-columns: repeat(2, minmax(0, 1fr));\n    gap: 10px;\n    margin-top: 13px;\n  }\n\n  .ajch-grid \u003e :only-child { grid-column: 1 \/ -1; }\n  .ajch-faq h3 { margin-bottom: 10px !important; }\n  .ajch-faq details { border-top: 1px solid var(--line); }\n  .ajch-faq summary { padding: 11px 0; font-weight: 700; cursor: pointer; }\n  .ajch-faq details p { padding-bottom: 12px; }\n\n  .ajch-footer {\n    padding: 26px 18px 18px;\n    background: var(--berry);\n    color: var(--cream);\n    text-align: center;\n  }\n\n  .ajch-cta {\n    display: inline-flex;\n    align-items: center;\n    min-height: 46px;\n    margin-top: 15px;\n    padding: 9px 22px;\n    border-radius: 999px;\n    background: var(--gold);\n    color: #34271b;\n    font-weight: 750;\n    text-decoration: none;\n  }\n\n  .ajch-control {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 8px;\n    min-height: 44px;\n    margin-top: 6px;\n    font-size: 13px;\n    cursor: pointer;\n  }\n\n  .ajch-control input { accent-color: #dfab62; }\n\n  #aj-curtain-helpers :is(a, input, summary):focus-visible {\n    outline: 2px solid #b78038;\n    outline-offset: 4px;\n  }\n\n  @container (min-width: 700px) {\n    .ajch-row.ajch-has-image {\n      grid-template-columns: repeat(2, minmax(0, 1fr));\n    }\n\n    .ajch-reverse figure { order: 2; }\n    .ajch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }\n  }\n\n  .ajch-effects {\n    position: fixed;\n    inset: 0;\n    z-index: 12;\n    overflow: hidden;\n    pointer-events: none;\n  }\n\n  .ajch-effects * { pointer-events: none; }\n\n  .ajch-wing {\n    position: absolute;\n    left: 0;\n    top: 22%;\n    width: clamp(34px, 9vw, 114px);\n    height: 47%;\n    opacity: 0;\n    animation: ajch-appear 14s ease-in-out infinite;\n  }\n\n  .ajch-wing-right {\n    left: auto;\n    right: 0;\n    transform: scaleX(-1);\n  }\n\n  .ajch-drape {\n    position: absolute;\n    inset: 0;\n    transform-origin: left center;\n    background: repeating-linear-gradient(\n      93deg, #4c1527 0%, #a34356 17%, #701e33 32%\n    );\n    clip-path: polygon(0 0, 100% 0, 83% 30%, 62% 50%, 79% 79%, 100% 100%, 0 100%);\n    animation: ajch-gather 14s ease-in-out infinite;\n  }\n\n  .ajch-clasp {\n    position: absolute;\n    top: 48%;\n    left: 0;\n    width: 49%;\n    height: clamp(7px, 1vw, 13px);\n    border: 1px solid #a56d32;\n    border-radius: 0 12px 12px 0;\n    background: linear-gradient(#fff1b8, #d89b50);\n    box-shadow: 0 0 10px #ffd78788;\n    opacity: 0;\n    animation: ajch-clasp 14s ease-out infinite;\n  }\n\n  .ajch-glow {\n    position: absolute;\n    inset: 0;\n    opacity: 0;\n    background:\n      radial-gradient(ellipse at left 44%, #ffca7170, transparent 29%),\n      radial-gradient(ellipse at right 44%, #ffca7170, transparent 29%);\n    animation: ajch-glow 14s ease-in-out infinite;\n  }\n\n  #aj-curtain-helpers:has(.ajch-off:checked) .ajch-effects { display: none; }\n\n  @keyframes ajch-appear {\n    0%, 6%, 47%, 100% { opacity: 0; }\n    13%, 36% { opacity: .96; }\n  }\n\n  @keyframes ajch-gather {\n    0%, 13% { transform: scaleX(1); }\n    24%, 48%, 100% { transform: scaleX(.69); }\n  }\n\n  @keyframes ajch-clasp {\n    0%, 16%, 46%, 100% { opacity: 0; transform: translateY(7px) rotate(-9deg); }\n    24%, 37% { opacity: 1; transform: translateY(0) rotate(0); }\n  }\n\n  @keyframes ajch-glow {\n    0%, 22%, 47%, 100% { opacity: 0; }\n    31%, 36% { opacity: 1; }\n  }\n\n  @media (max-width: 600px) {\n    .ajch-wing { top: 28%; width: clamp(24px, 7vw, 42px); height: 31%; }\n  }\n\n  @media (prefers-reduced-motion: reduce) {\n    #aj-curtain-helpers :is(.ajch-effects, .ajch-control) { display: none; }\n  }\n\u003c\/style\u003e\n\n\u003csection id=\"aj-curtain-helpers\" aria-labelledby=\"ajch-title\"\u003e\n  \u003cdiv class=\"ajch-shell\"\u003e\n    \u003cheader class=\"ajch-hero ajch-row\"\u003e\n      \u003cfigure class=\"ajch-photo\" data-ajch-photo hidden\u003e\u003c\/figure\u003e\n      \u003cdiv class=\"ajch-intro\"\u003e\n        \u003cp class=\"ajch-kicker\"\u003eChristmas Elf Curtain Tiebacks\u003c\/p\u003e\n        \u003ch2 id=\"ajch-title\"\u003eGive the Curtains a Christmas Hug.\u003c\/h2\u003e\n        \u003cp\u003eGather the fabric to one side and give a little elf the job of holding it there. It’s a playful way to dress the window beside your tree, over the breakfast nook, or in the room where holiday guests will stay.\u003c\/p\u003e\n      \u003c\/div\u003e\n    \u003c\/header\u003e\n\n    \u003cp class=\"ajch-strip\"\u003eDecorative curtain tiebacks · Three elf styles to choose from\u003c\/p\u003e\n\n    \u003cdiv class=\"ajch-body\"\u003e\n      \u003carticle class=\"ajch-row ajch-story\"\u003e\n        \u003cfigure class=\"ajch-photo\" data-ajch-photo hidden\u003e\u003c\/figure\u003e\n        \u003cdiv\u003e\n          \u003ch3\u003eThe Detail You’ll Notice from Across the Room\u003c\/h3\u003e\n          \u003cp\u003ePlace the elf where the folds come together and turn its face toward the room. When the drapes are open, the character sits right at the gather, where it’s easy to see.\u003c\/p\u003e\n        \u003c\/div\u003e\n      \u003c\/article\u003e\n\n      \u003carticle class=\"ajch-row ajch-story ajch-reverse\"\u003e\n        \u003cfigure class=\"ajch-photo\" data-ajch-photo hidden\u003e\u003c\/figure\u003e\n        \u003cdiv\u003e\n          \u003ch3\u003eMatch the Window or Mix the Elves\u003c\/h3\u003e\n          \u003cp\u003eUse the same design on two panels for a coordinated look, or give each side a different elf. For a smaller holiday touch, start with the curtain by a reading chair or the window guests see when they walk in.\u003c\/p\u003e\n        \u003c\/div\u003e\n      \u003c\/article\u003e\n\n      \u003csection class=\"ajch-guide\"\u003e\n        \u003ch3\u003eThree Steps to Dress the Window\u003c\/h3\u003e\n        \u003col\u003e\n          \u003cli\u003eGather the curtain panel at the height you want.\u003c\/li\u003e\n          \u003cli\u003ePosition the tieback around the gathered fabric.\u003c\/li\u003e\n          \u003cli\u003eTurn the elf toward the room and adjust the folds around it.\u003c\/li\u003e\n        \u003c\/ol\u003e\n      \u003c\/section\u003e\n\n      \u003csection data-ajch-gallery hidden\u003e\n        \u003ch3\u003eA Closer Look at the Curtain Crew\u003c\/h3\u003e\n        \u003cdiv class=\"ajch-grid\" data-ajch-grid\u003e\u003c\/div\u003e\n      \u003c\/section\u003e\n\n      \u003csection class=\"ajch-faq\"\u003e\n        \u003ch3\u003eBefore You Choose an Elf\u003c\/h3\u003e\n        \u003cdetails\u003e\n          \u003csummary\u003eAre all three styles included?\u003c\/summary\u003e\n          \u003cp\u003eThere are three designs to choose from. Check the option and quantity shown in the purchase area before ordering.\u003c\/p\u003e\n        \u003c\/details\u003e\n        \u003cdetails\u003e\n          \u003csummary\u003eWill it fit thick curtains?\u003c\/summary\u003e\n          \u003cp\u003eGather the curtain where you want the elf to sit. Compare that bundle with any tieback measurements shown for the option you select. Lined drapes usually make a fuller bundle than sheers.\u003c\/p\u003e\n        \u003c\/details\u003e\n        \u003cdetails\u003e\n          \u003csummary\u003eHow can I make two panels look even?\u003c\/summary\u003e\n          \u003cp\u003eStart with both tiebacks at the same height. Step back, then loosen or tighten the curtain folds until the two sides look balanced.\u003c\/p\u003e\n        \u003c\/details\u003e\n      \u003c\/section\u003e\n    \u003c\/div\u003e\n\n    \u003cfooter class=\"ajch-footer\"\u003e\n      \u003ch3\u003eWhich Elf Gets Your Window?\u003c\/h3\u003e\n      \u003ca class=\"ajch-cta\" href=\"#top\"\u003ePick My Curtain Elf ↑\u003c\/a\u003e\n      \u003clabel class=\"ajch-control\"\u003e\n        \u003cinput class=\"ajch-off\" type=\"checkbox\"\u003e\n        Turn off the curtain animation\n      \u003c\/label\u003e\n    \u003c\/footer\u003e\n  \u003c\/div\u003e\n\n  \u003cdiv class=\"ajch-effects\" aria-hidden=\"true\"\u003e\n    \u003cspan class=\"ajch-glow\"\u003e\u003c\/span\u003e\n    \u003cdiv class=\"ajch-wing\"\u003e\n      \u003cspan class=\"ajch-drape\"\u003e\u003c\/span\u003e\n      \u003cspan class=\"ajch-clasp\"\u003e\u003c\/span\u003e\n    \u003c\/div\u003e\n    \u003cdiv class=\"ajch-wing ajch-wing-right\"\u003e\n      \u003cspan class=\"ajch-drape\"\u003e\u003c\/span\u003e\n      \u003cspan class=\"ajch-clasp\"\u003e\u003c\/span\u003e\n    \u003c\/div\u003e\n  \u003c\/div\u003e\n\u003c\/section\u003e\n\n\u003cscript\u003e\n(() =\u003e {\n  const page = document.getElementById('aj-curtain-helpers');\n  if (!page || page.dataset.ready) return;\n  page.dataset.ready = 'true';\n\n  const motion = window.matchMedia('(prefers-reduced-motion: reduce)');\n  const toggle = page.querySelector('.ajch-off');\n  const preference = 'aj-curtain-helpers-motion-off';\n\n  try { toggle.checked = sessionStorage.getItem(preference) === '1'; } catch {}\n\n  toggle.addEventListener('change', () =\u003e {\n    try { sessionStorage.setItem(preference, toggle.checked ? '1' : '0'); } catch {}\n  });\n\n  page.querySelector('.ajch-cta').addEventListener('click', event =\u003e {\n    event.preventDefault();\n    window.scrollTo({ top: 0, behavior: motion.matches ? 'auto' : 'smooth' });\n  });\n\n  const slots = Array.from(page.querySelectorAll('[data-ajch-photo]'));\n  const gallery = page.querySelector('[data-ajch-gallery]');\n  const grid = page.querySelector('[data-ajch-grid]');\n\n  function currentProductEndpoint() {\n    const canonical = document.querySelector('link[rel=\"canonical\"]');\n    for (const source of [location.href, canonical?.href]) {\n      if (!source) continue;\n      const url = new URL(source, location.origin);\n      const match = url.pathname.match(\/^(.*\\\/products\\\/[^\/]+)\\\/?$\/);\n      if (match) return match[1] + '.js';\n    }\n    return '';\n  }\n\n  function themeImages() {\n    const main = document.querySelector('main') || document;\n    const selectors = 'media-gallery, [id^=\"MediaGallery-\"], .product__media-list, [data-product-media-gallery]';\n    const nativeGallery = Array.from(main.querySelectorAll(selectors))\n      .find(element =\u003e !page.contains(element) \u0026\u0026 element.querySelector('img'));\n    return Array.from(nativeGallery?.querySelectorAll('img') || [], image =\u003e ({\n      src: image.getAttribute('data-src') || image.currentSrc || image.getAttribute('src'),\n      alt: image.alt\n    }));\n  }\n\n  async function productImages() {\n    const endpoint = currentProductEndpoint();\n    if (!endpoint) return [];\n    const controller = new AbortController();\n    const timer = setTimeout(() =\u003e controller.abort(), 3500);\n\n    try {\n      const response = await fetch(endpoint, {\n        signal: controller.signal,\n        headers: { Accept: 'application\/json' }\n      });\n      if (!response.ok) return [];\n      const product = await response.json();\n      return Array.isArray(product.images) ? product.images : [];\n    } catch {\n      return [];\n    } finally {\n      clearTimeout(timer);\n    }\n  }\n\n  async function showPhotos() {\n    const originals = await productImages();\n    const sources = [...originals, ...themeImages()];\n    const seen = new Set();\n    let count = 0;\n\n    for (const item of sources) {\n      if (!page.isConnected || count \u003e= 6) break;\n      const src = typeof item === 'string' ? item : item?.src;\n      if (!src) continue;\n\n      let url;\n      try { url = new URL(src, location.origin); } catch { continue; }\n      if (url.protocol !== 'https:' \u0026\u0026 url.protocol !== 'http:') continue;\n      const key = url.pathname.replace(\/^\\\/cdn\\\/shop\\\/files\\\/\/, '\/files\/')\n        .replace(\/^\\\/s\\\/files\\\/[\\d\/]+\\\/files\\\/\/, '\/files\/');\n      if (seen.has(key)) continue;\n\n      const image = new Image();\n      image.alt = item?.alt || 'Christmas elf curtain tieback, product view ' + (count + 1);\n      image.decoding = 'async';\n      image.src = url.href;\n\n      try { await image.decode(); } catch { continue; }\n      if (!page.isConnected) return;\n      seen.add(key);\n\n      const slot = slots[count];\n      if (slot) {\n        slot.append(image);\n        slot.hidden = false;\n        slot.parentElement.classList.add('ajch-has-image');\n      } else {\n        const figure = document.createElement('figure');\n        figure.className = 'ajch-photo';\n        figure.append(image);\n        grid.append(figure);\n        gallery.hidden = false;\n      }\n      count += 1;\n    }\n  }\n\n  showPhotos();\n})();\n\u003c\/script\u003e","brand":"zhidou","offers":[{"title":"❤️ Finn","offer_id":68308505362669,"sku":null,"price":22.99,"currency_code":"USD","in_stock":true},{"title":"💚 Oliver","offer_id":68308505395437,"sku":null,"price":22.99,"currency_code":"USD","in_stock":true},{"title":"🎀 Holly","offer_id":68308505428205,"sku":null,"price":22.99,"currency_code":"USD","in_stock":true},{"title":"🎄 The Whole Merry Crew — All 3 · Save 10%","offer_id":68308505460973,"sku":null,"price":62.07,"currency_code":"USD","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0841\/9354\/2381\/files\/8_fdd3e0f2-94ff-478f-9a3e-192ed83242bb.png?v=1794627304","url":"https:\/\/alasjoy.com\/products\/curtain-helpers-playful-elf-tiebacks-in-3-charming-styles","provider":"alasjoy","version":"1.0","type":"link"}