GardenWise.

Privacy-first approach Updated:

Privacy Policy

We keep data collection minimal and transparent. This policy explains what we collect, why we collect it, and how you can control it.

Back to Home

Primary contact

[email protected]

Phone

+1 (415) 728-6049

Response time

Usually within 72 hours

Overview

GardenWise Academy is designed to work without requiring personal data in most browsing scenarios. When data is needed (for example, to respond to a support request), we collect only what’s necessary.

Key principles

  • Minimal collection: only what’s needed for the purpose.
  • Transparent use: we explain each category and retention period.
  • User control: you can adjust preferences, delete local data, or request help.

This policy applies to this website and related pages where it is posted. If we publish updates, we revise the “Updated” date above.

Data we collect

We separate data into two buckets: (1) data you choose to provide and (2) technical data required to deliver the site.

Data you provide

  • Support messages (name/email if you include them).
  • Form submissions you explicitly send to us.

Technical data

  • Basic logs (IP address, device/browser type) for security and reliability.
  • Preference storage (theme, consent choice) in your browser.
We do not sell personal information. We do not knowingly collect personal data from children under 13.

Retention

Support messages are retained only as long as needed to resolve the request and meet legal obligations. Browser preferences remain on your device until you delete them.

How we use data

We use data strictly to operate and improve the site, provide requested services, and protect users.

  • 1

    Provide site functionality

    Remember preferences such as theme and consent selection.

  • 2

    Respond to you

    Answer support requests and privacy inquiries.

  • 3

    Protect the service

    Detect abuse, prevent fraud, and maintain reliability.

Legal bases (where applicable) may include consent (for optional features), legitimate interests (for security), and contractual necessity (to provide requested services).

Cookies & localStorage

We use a small set of browser storage items to remember your choices. You can delete them at any time.

What we store locally

Key

gw_theme

Purpose

Remember light/dark theme

Type

localStorage

Key

gw_cookie_consent

Purpose

Remember consent choice

Type

localStorage

Key

gw_favorites

Purpose

Optional favorites list

Type

localStorage

Key

gw_cart

Purpose

Optional cart list

Type

localStorage

Security

We use practical security measures to reduce risk, but no online service can guarantee absolute security.

Measures we use

  • Transport protections (HTTPS where available).
  • Access limitation to administrative tools.
  • Abuse prevention and basic rate limiting where applicable.

You can help by using a modern browser, keeping your device updated, and avoiding sharing sensitive information in free-form messages.

Your rights

Depending on your location, you may have rights to access, delete, correct, or export certain data.

Common requests

Access

Ask what personal data we hold about you.

Deletion

Request deletion of support communications.

Correction

Correct inaccuracies in submitted info.

Portability

Export local preferences from your own device.

Make a request

Email [email protected] with your request. For your protection, we may ask for limited verification to confirm you control the inbox used to contact us.

Contact

Use this form for privacy requests. We’ll reply to the email you provide.

If you prefer, email us directly: [email protected] or call +1 (415) 728-6049.

Data export

Export localStorage preferences

This export is generated locally in your browser. Nothing is uploaded when you export.

Included keys

  • gw_theme
  • gw_cookie_consent
  • gw_favorites
  • gw_cart

Format

JSON file with a timestamp and values. You can import later by pasting the JSON into your browser console or by using a future import tool.

Preview


      

Safety note: exported file may contain course IDs or product IDs in favorites/cart.

`; }; try{ const [h, f] = await Promise.all([load('./header.html'), load('./footer.html')]); if(header) header.innerHTML = h; if(footer) footer.innerHTML = f; }catch(e){ if(header) header.innerHTML = fallbackHeader(); if(footer) footer.innerHTML = fallbackFooter(); } const yr = z('#y1f7c'); if(yr) yr.textContent = String(new Date().getFullYear()); const hThemeBtn = z('#h2m8p'); if(hThemeBtn){ hThemeBtn.addEventListener('click', ()=> z('#t8q2n')?.click()); } }; const initTOCActive = () => { const links = zz('#c1x7u a[href^="#"]'); const map = new Map(); links.forEach(a => { const id = a.getAttribute('href')?.slice(1); if(id) map.set(id, a); }); const setActive = (id) => { links.forEach(a => a.classList.remove('bg-emerald-50','text-emerald-900','dark:bg-white/10')); const a = map.get(id); if(a){ a.classList.add('bg-emerald-50','text-emerald-900','dark:bg-white/10'); } }; const ids = Array.from(map.keys()); const observer = new IntersectionObserver((entries) => { const visible = entries.filter(e => e.isIntersecting).sort((a,b)=>b.intersectionRatio-a.intersectionRatio); if(visible[0]) setActive(visible[0].target.id); }, { root: null, rootMargin: '-20% 0px -70% 0px', threshold: [0.1, 0.2, 0.3, 0.5, 0.75] }); ids.forEach(id => { const el = z('#'+CSS.escape(id)); if(el) observer.observe(el); }); const initial = location.hash ? location.hash.slice(1) : 'overview'; if(map.has(initial)) setActive(initial); }; const initAccordion = () => { const toggles = zz('[data-a11y-toggle]'); toggles.forEach(btn => { const key = btn.getAttribute('data-a11y-toggle'); const panel = z(`[data-a11y-panel="${CSS.escape(key)}"]`); const setState = (open) => { if(!panel) return; panel.classList.toggle('hidden', !open); btn.textContent = open ? 'Collapse' : 'Expand'; btn.setAttribute('aria-expanded', open ? 'true' : 'false'); }; btn.setAttribute('aria-controls', `panel-${key}`); btn.setAttribute('aria-expanded', 'true'); if(panel) panel.id = `panel-${key}`; btn.addEventListener('click', ()=> { const isHidden = panel?.classList.contains('hidden'); setState(!!isHidden); }); }); const expandAll = z('#b8r1e'); const collapseAll = z('#n4f0z'); const setAll = (open) => { toggles.forEach(btn => { const key = btn.getAttribute('data-a11y-toggle'); const panel = z(`[data-a11y-panel="${CSS.escape(key)}"]`); if(panel){ panel.classList.toggle('hidden', !open); btn.textContent = open ? 'Collapse' : 'Expand'; btn.setAttribute('aria-expanded', open ? 'true' : 'false'); } }); }; expandAll?.addEventListener('click', ()=>setAll(true)); collapseAll?.addEventListener('click', ()=>setAll(false)); }; const initCopyLink = () => { const btn = z('#p9k4w'); btn?.addEventListener('click', async () => { const hash = location.hash || '#overview'; const url = `${location.origin}${location.pathname}${hash}`; try{ if(navigator.clipboard && window.isSecureContext) await navigator.clipboard.writeText(url); else{ const ta = document.createElement('textarea'); ta.value = url; ta.style.position = 'fixed'; ta.style.top = '-1000px'; document.body.appendChild(ta); ta.focus(); ta.select(); const res = document.execCommand('copy'); ta.remove(); if(!res) throw new Error('copy fail'); } btn.textContent = 'Copied'; window.setTimeout(()=>btn.textContent='Copy link', 1200); }catch(e){ btn.textContent = 'Copy failed'; window.setTimeout(()=>btn.textContent='Copy link', 1400); } }); }; const initForm = () => { const form = z('#s7w0f'); if(!form) return; const ok = z('#w5t8n'); const showErr = (name, msg) => { const p = z(`[data-err="${CSS.escape(name)}"]`); if(!p) return; p.textContent = msg; p.classList.remove('hidden'); }; const hideErr = (name) => { const p = z(`[data-err="${CSS.escape(name)}"]`); if(!p) return; p.textContent = ''; p.classList.add('hidden'); }; const emailOk = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(String(v||'').trim()); const minLen = (v,n) => String(v||'').trim().length >= n; form.addEventListener('input', (e)=>{ const n = e.target && e.target.name; if(n) hideErr(n); if(ok) ok.classList.add('hidden'); }); form.addEventListener('submit', (e)=>{ e.preventDefault(); if(ok) ok.classList.add('hidden'); const fd = new FormData(form); const name = String(fd.get('name')||'').trim(); const email = String(fd.get('email')||'').trim(); const message = String(fd.get('message')||'').trim(); let bad = false; if(email.length === 0 || !emailOk(email)){ showErr('email','Please enter a valid email address.'); bad = true; } else hideErr('email'); if(message.length === 0 || !minLen(message, 12)){ showErr('message','Please provide a bit more detail (min 12 characters).'); bad = true; } else hideErr('message'); if(name.length > 0 && name.length < 2){ showErr('name','Name is too short.'); bad = true; } else hideErr('name'); if(bad) return; const ticket = 'GW-' + Math.random().toString(36).slice(2,6).toUpperCase() + '-' + Math.random().toString(36).slice(2,6).toUpperCase(); if(ok){ ok.classList.remove('hidden'); ok.textContent = `Request prepared. Reference: ${ticket}. (Demo: no network request sent.)`; } form.reset(); }); z('#x9a2u')?.addEventListener('click', ()=>{ z('#f1a6p').value = 'Alex Green'; z('#k2v9z').value = '[email protected]'; z('#q0e4d').value = 'access'; z('#z6n1t').value = 'Hi! Please confirm what personal data (if any) is associated with this email. Also tell me how long support messages are retained.'; ['name','email','message'].forEach(hideErr); if(ok) ok.classList.add('hidden'); }); }; const initThemeToggle = () => { const btn = z('#t8q2n'); btn?.addEventListener('click', ()=>{ const prefs = readPrefs(); if(!prefs.theme){ const note = z('#h4c2v'); if(note){ note.classList.remove('hidden'); note.textContent = 'Theme storage is disabled by your settings. Enable Theme in cookie settings to persist your choice.'; window.clearTimeout(note.__t); note.__t = window.setTimeout(()=>note.classList.add('hidden'), 4500); } } const current = document.documentElement.classList.contains('dark') ? 'dark' : 'light'; const next = current === 'dark' ? 'light' : 'dark'; setTheme(next); if(prefs.theme) lsSet(KEY_THEME, next); syncSnapshot(); }); }; const initCookieBannerControls = () => { z('#r0m2l')?.addEventListener('click', ()=>setConsent('accepted')); z('#k0a9v')?.addEventListener('click', ()=>setConsent('essential')); z('#c8p1j')?.addEventListener('click', ()=>hideBanner()); z('#h9t2r')?.addEventListener('click', ()=>openSettingsPanel()); z('#m9d2c')?.addEventListener('click', ()=>closeSettingsPanel()); z('#l8p2d')?.addEventListener('click', ()=>openSettingsPanel()); z('#r7h1y')?.addEventListener('click', ()=>{ const prefs = readPrefs(); const t = z('#e0q9b')?.checked; const fc = z('#a2n6t')?.checked; const updated = { theme: !!t, fc: !!fc }; writePrefs(updated); if(!updated.fc){ lsDel(KEY_FAV); lsDel(KEY_CART); } if(!updated.theme){ lsDel(KEY_THEME); setTheme(getEffectiveTheme()); }else{ const current = document.documentElement.classList.contains('dark') ? 'dark' : 'light'; lsSet(KEY_THEME, current); } const msg = z('#k2c6z'); if(msg){ msg.classList.remove('hidden'); msg.textContent = 'Saved.'; window.clearTimeout(msg.__t); msg.__t = window.setTimeout(()=>msg.classList.add('hidden'), 1600); } syncSnapshot(); }); }; const initExportDialog = () => { z('#y3m8c')?.addEventListener('click', openExport); z('#u6j5s')?.addEventListener('click', openExport); z('#r6c9f')?.addEventListener('click', openExport); z('#q9l1x')?.addEventListener('click', closeExport); z('#s5c8m')?.addEventListener('click', closeExport); z('#v7u2k')?.addEventListener('click', renderExportPreview); z('#k6b9n')?.addEventListener('click', downloadJSON); z('#z3e5t')?.addEventListener('click', copyJSON); exportDialog?.addEventListener('click', (e)=>{ const r = exportDialog.getBoundingClientRect(); const inDialog = (r.top <= e.clientY && e.clientY <= r.bottom && r.left <= e.clientX && e.clientX <= r.right); if(!inDialog) closeExport(); }); document.addEventListener('keydown', (e)=>{ if(e.key === 'Escape' && exportDialog?.open) closeExport(); }); }; const initMisc = () => { const updated = z('#k7s1p'); if(updated) updated.textContent = new Date().toLocaleDateString('en-US', { year:'numeric', month:'short', day:'2-digit' }); z('#e1q9a')?.addEventListener('click', clearLocalPrefs); }; const init = async () => { await setHeaderFooter(); applyThemeFromStorage(); initThemeToggle(); enforceConsent(); ensureConsentUI(); initCookieBannerControls(); initTOCActive(); initAccordion(); initCopyLink(); initForm(); initExportDialog(); initMisc(); syncSnapshot(); }; init(); })();