Choose one of our six evening presets, or pick any three of our six botanicals to make a calming cup that’s all your own. Blended by hand in equal parts and packed into a 50g jar, made for slow evenings and a gentle wind-down.
.tt-tb{--tt-cream:#faf5ea;--tt-card:#fffdf8;--tt-line:#e6dcc8;--tt-green:#5f7350;--tt-green-soft:#e8eedf;--tt-brown:#6b4f2a;--tt-ink:#2f3a2f;font-family:Georgia,'Times New Roman',serif;color:var(--tt-ink);background:var(--tt-cream);border:1px solid var(--tt-line);border-radius:18px;padding:22px 18px;margin:0 0 1.5em;box-sizing:border-box}
.tt-tb *{box-sizing:border-box}
.tt-tb h3{font-size:1.25em;color:var(--tt-green);margin:0 0 4px;font-weight:normal;letter-spacing:.02em}
.tt-tb .tt-tb-sub{margin:0 0 14px;font-size:.95em;color:var(--tt-brown)}
.tt-tb .tt-tb-label{font-size:.78em;letter-spacing:.14em;text-transform:uppercase;color:var(--tt-brown);margin:16px 0 8px}
.tt-tb .tt-tb-presets{display:flex;flex-wrap:wrap;gap:8px}
.tt-tb .tt-tb-preset{font:inherit;font-size:.92em;cursor:pointer;border:1px solid var(--tt-line);background:var(--tt-card);color:var(--tt-ink);border-radius:999px;padding:8px 14px;line-height:1.2;transition:border-color .2s}
.tt-tb .tt-tb-preset small{display:block;font-size:.78em;color:#7b7262;margin-top:2px}
.tt-tb .tt-tb-preset:hover{border-color:var(--tt-green)}
.tt-tb .tt-tb-preset.is-active{background:var(--tt-green);border-color:var(--tt-green);color:#fff}
.tt-tb .tt-tb-preset.is-active small{color:#eef2e8}
.tt-tb .tt-tb-herbs{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.tt-tb .tt-tb-herb{font:inherit;cursor:pointer;text-align:center;border:1px solid var(--tt-line);background:var(--tt-card);color:var(--tt-ink);border-radius:16px;padding:12px 8px 10px;position:relative;transition:border-color .2s}
.tt-tb .tt-tb-herb:hover{border-color:var(--tt-green)}
.tt-tb .tt-tb-herb.is-on{background:var(--tt-green-soft);border-color:var(--tt-green);box-shadow:0 0 0 2px var(--tt-green) inset}
.tt-tb .tt-tb-img{display:flex;align-items:center;justify-content:center;width:64px;height:64px;margin:0 auto 8px;border-radius:50%;background:#efe6d3 center/cover no-repeat;color:var(--tt-brown);font-size:1.5em}
.tt-tb .tt-tb-name{display:block;font-size:1em}
.tt-tb .tt-tb-desc{display:block;font-size:.8em;color:#7b7262;margin-top:2px}
.tt-tb .tt-tb-tick{position:absolute;top:8px;right:8px;width:20px;height:20px;border-radius:50%;background:var(--tt-green);color:#fff;font-size:12px;line-height:20px;display:none}
.tt-tb .tt-tb-herb.is-on .tt-tb-tick{display:block}
.tt-tb .tt-tb-summary{margin-top:16px;padding:12px 14px;border-radius:12px;background:var(--tt-card);border:1px dashed var(--tt-line);font-size:.98em}
.tt-tb .tt-tb-summary strong{color:var(--tt-green);font-weight:normal}
.tt-tb .tt-tb-msg{min-height:1.3em;margin-top:8px;font-size:.88em;color:var(--tt-brown);font-style:italic}
.tt-tb .tt-tb-note{margin-top:6px;font-size:.82em;color:#7b7262}
.tt-tb button:focus-visible{outline:2px solid var(--tt-brown);outline-offset:2px}
@media (max-width:520px){.tt-tb{padding:18px 12px}.tt-tb .tt-tb-herbs{grid-template-columns:repeat(2,1fr)}.tt-tb .tt-tb-preset{flex:1 1 calc(50% - 8px)}}
/* Optional: hide WooCommerce's own "Your blend" dropdown row once you're happy the builder works. Uncomment the next line. */
/* .single-product form.variations_form table.variations{display:none} */
(function () {
/* ---- Settings: add a herb photo URL in img when you have one ---- */
var AMP = String.fromCharCode(38), DOT = String.fromCharCode(183), TICK = String.fromCharCode(10003);
var HERBS = [
{ key: 'chamomile', name: 'Chamomile', desc: 'Soft ' + AMP + ' comforting', img: '' },
{ key: 'lavender', name: 'Lavender', desc: 'Floral ' + AMP + ' relaxing', img: '' },
{ key: 'lemonbalm', name: 'Lemon Balm', desc: 'Fresh ' + AMP + ' lemony', img: '' },
{ key: 'rose', name: 'Rose Petals', desc: 'Delicate ' + AMP + ' floral', img: '', alias: ['rose', 'rosepetals'] },
{ key: 'peppermint', name: 'Peppermint', desc: 'Cool ' + AMP + ' refreshing', img: '' },
{ key: 'passionflower', name: 'Passionflower', desc: 'Earthy ' + AMP + ' mellow', img: '' }
];
/* Preset icons are built from code points (no raw emoji in the script, so WordPress cannot turn them into entities). */
function emo(cp) { return String.fromCodePoint ? String.fromCodePoint(cp) : ''; }
var PRESETS = [
{ name: 'Sleep / Bedtime', icon: emo(0x1F319), herbs: ['chamomile', 'lavender', 'passionflower'] },
{ name: 'Gentle Calm', icon: emo(0x1F90D), herbs: ['chamomile', 'lemonbalm', 'rose'] },
{ name: 'Floral Relaxation', icon: emo(0x1F49C), herbs: ['chamomile', 'lavender', 'rose'] },
{ name: 'Fresh ' + AMP + ' Calm', icon: emo(0x1F34B), herbs: ['chamomile', 'lemonbalm', 'peppermint'] },
{ name: 'Evening Wind-Down', icon: emo(0x1F33F), herbs: ['lavender', 'lemonbalm', 'passionflower'] },
{ name: 'Garden Breeze', icon: emo(0x1F339), herbs: ['lavender', 'peppermint', 'rose'] }
];
var MAX = 3;
/* ---- End of settings ---- */
var root = document.getElementById('tt-tea-builder');
if (!root || root.getAttribute('data-ready')) return;
root.setAttribute('data-ready', '1');
var byKey = {}, aliasMap = {};
HERBS.forEach(function (h) {
byKey[h.key] = h;
(h.alias || [norm(h.name)]).concat([h.key]).forEach(function (a) { aliasMap[a] = h.key; });
});
var selected = [], syncing = false, msgTimer = null, herbBtns = {}, presetBtns = [];
function norm(s) { return String(s || '').toLowerCase().replace(/[^a-z]/g, ''); }
function keyOf(list) { return list.slice().sort().join('|'); }
function el(tag, cls, text) { var e = document.createElement(tag); if (cls) e.className = cls; if (text != null) e.textContent = text; return e; }
function names(list) { return list.map(function (k) { return byKey[k].name; }); }
/* Work out which herbs an option stands for, from its label (or value). */
function herbsFromLabel(label) {
var s = String(label || '');
var m = s.match(/[(]([^)]*)[)]/);
if (m) s = m[1]; else if (/^ *custom *:/i.test(s)) s = s.replace(/^ *custom *:/i, '');
var parts = s.split(/[,+/]/), found = [];
parts.forEach(function (p) { var k = aliasMap[norm(p)]; if (k) { if (found.indexOf(k) === -1) found.push(k); } });
if (found.length !== MAX) {
/* Fallback for slug-style values, e.g. "custom-chamomile-lavender-lemon-balm" */
var flat = norm(s); found = [];
HERBS.forEach(function (h) { if (flat.indexOf(norm(h.name)) !== -1) found.push(h.key); else if (h.key === 'rose') { if (flat.indexOf('rose') !== -1) found.push('rose'); } });
}
return found;
}
function findSelect() {
var forms = document.querySelectorAll('form.variations_form');
var scope = forms.length ? forms[0] : document;
var sels = scope.querySelectorAll("select[name^='attribute_']");
for (var i = 0; i < sels.length; i++) { if (/blend/i.test(sels[i].name)) return sels[i]; }
return sels[0] || null;
}
function optionMap(sel) {
var map = {};
Array.prototype.forEach.call(sel.options, function (o) {
if (!o.value) return;
var hs = herbsFromLabel(o.textContent);
if (hs.length !== MAX) hs = herbsFromLabel(o.value);
if (hs.length !== MAX) return;
var k = keyOf(hs), isCustom = /^ *custom/i.test(o.textContent);
if (!map[k] || !isCustom) map[k] = o; /* a preset wins over a custom label with the same herbs */
});
return map;
}
function fireChange(sel) {
syncing = true;
try {
sel.dispatchEvent(new Event('change', { bubbles: true }));
if (window.jQuery) window.jQuery(sel).trigger('change');
} finally { syncing = false; }
}
function say(text) {
msg.textContent = text || '';
if (msgTimer) clearTimeout(msgTimer);
if (text) msgTimer = setTimeout(function () { msg.textContent = ''; }, 4500);
}
function matchingPreset() {
if (selected.length !== MAX) return null;
var k = keyOf(selected);
for (var i = 0; i = MAX) { say('You have chosen your three. Tap one of them to swap it for another.'); return; }
else { selected.push(k); say(''); }
apply();
}
function choosePreset(p) { selected = p.herbs.slice(); say(''); apply(); }
/* If the customer uses the dropdown (or WooCommerce's Clear link), mirror it in the builder. */
function syncFromSelect() {
if (syncing) return;
var sel = findSelect(); if (!sel) return;
if (!sel.value) { selected = []; render(); return; }
var o = sel.options[sel.selectedIndex];
var hs = herbsFromLabel(o ? o.textContent : '');
if (hs.length !== MAX) hs = herbsFromLabel(sel.value);
if (hs.length === MAX) { selected = hs; render(); }
}
/* ---- Build the UI ---- */
root.appendChild(el('h3', '', 'Create your evening blend'));
root.appendChild(el('p', 'tt-tb-sub', 'Choose one of our presets, or pick any 3 herbs. We blend them in equal parts.'));
root.appendChild(el('div', 'tt-tb-label', 'Our presets'));
var presetWrap = el('div', 'tt-tb-presets'); root.appendChild(presetWrap);
PRESETS.forEach(function (p) {
var b = el('button', 'tt-tb-preset'); b.type = 'button';
b.appendChild(document.createTextNode((p.icon ? p.icon + ' ' : '') + p.name));
b.appendChild(el('small', '', names(p.herbs).join(' ' + DOT + ' ')));
b.addEventListener('click', function () { choosePreset(p); });
presetBtns.push(b); presetWrap.appendChild(b);
});
root.appendChild(el('div', 'tt-tb-label', 'Or pick any 3 herbs'));
var herbWrap = el('div', 'tt-tb-herbs'); root.appendChild(herbWrap);
HERBS.forEach(function (h) {
var b = el('button', 'tt-tb-herb'); b.type = 'button'; b.setAttribute('aria-pressed', 'false');
var img = el('span', 'tt-tb-img', h.img ? '' : h.name.charAt(0));
if (h.img) img.style.backgroundImage = 'url("' + h.img + '")';
img.setAttribute('aria-hidden', 'true');
b.appendChild(img);
b.appendChild(el('span', 'tt-tb-name', h.name));
b.appendChild(el('span', 'tt-tb-desc', h.desc));
var tick = el('span', 'tt-tb-tick', TICK); tick.setAttribute('aria-hidden', 'true'); b.appendChild(tick);
b.addEventListener('click', function () { toggleHerb(h.key); });
herbBtns[h.key] = b; herbWrap.appendChild(b);
});
var summary = el('div', 'tt-tb-summary'); summary.setAttribute('aria-live', 'polite'); root.appendChild(summary);
var msg = el('div', 'tt-tb-msg'); msg.setAttribute('role', 'status'); root.appendChild(msg);
var note = el('div', 'tt-tb-note'); root.appendChild(note);
render();
function hookSelect() {
var sel = findSelect(); if (!sel) return;
sel.addEventListener('change', syncFromSelect);
if (window.jQuery) window.jQuery(sel).on('change', syncFromSelect);
syncFromSelect();
}
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', hookSelect); else hookSelect();
/* Expose for testing only */
root.ttTea = { toggleHerb: toggleHerb, choosePreset: choosePreset, presets: PRESETS, state: function () { return selected.slice(); } };
})();
document.addEventListener('DOMContentLoaded',function(){var b=document.querySelector('.single-product-extras');if(!b){return;}var s=b.querySelector('p strong');if(s){s.textContent='Hand-blended in small batches';}var t=['Pure dried herbs, nothing added','Naturally caffeine-free','Colour and flavour may vary slightly between harvests'];b.querySelectorAll('li').forEach(function(li,i){if(i>=t.length){return;}var sp=li.querySelector('span');li.textContent='';if(sp){li.appendChild(sp);}li.appendChild(document.createTextNode(' '+t[i]));});});
document.addEventListener('DOMContentLoaded',function(){var U='https://thymenthistle.co.za/wp-content/uploads/2026/10/';var M={'Chamomile':'Sunlit-Chamomile-Tea-Still-Life','Lavender':'Lavender-Tea-Apothecary-Still-Life','Lemon Balm':'Sunlit-Lemon-Balm-Tea-Still-Life','Rose Petals':'Romantic-Rose-Herbal-Tea-Still-Life','Peppermint':'Sunlit-Peppermint-Tea-Still-Life','Passionflower':'Golden-Passionflower-Tea-Still-Life'};function show(f){var g=document.querySelector('.woocommerce-product-gallery');if(!g){return;}var slides=g.querySelectorAll('.woocommerce-product-gallery__image');var th=g.querySelectorAll('.flex-control-thumbs li img');for(var i=0;i<slides.length;i++){var im=slides[i].querySelector('img');if(!im){continue;}var s=im.getAttribute('data-large_image')||im.src;if(s.indexOf(f)===-1){continue;}if(th[i]){th[i].click();return;}if(window.jQuery){var fs=jQuery(g).data('flexslider');if(fs){fs.flexAnimate(i);return;}}}var m=g.querySelector('.woocommerce-product-gallery__image img');if(!m){return;}var u=U+f+'.png';m.removeAttribute('srcset');m.src=u;m.setAttribute('data-large_image',u);}document.addEventListener('click',function(e){if(!e.target.closest){return;}var b=e.target.closest('.tt-tb-herb');if(!b){return;}var n=b.querySelector('.tt-tb-name');if(!n){return;}var f=M[n.textContent.trim()];if(f){show(f);}});});