diff --git a/themes/bonsai/assets/js/share.js b/themes/bonsai/assets/js/share.js
new file mode 100644
index 0000000..57a6ef7
--- /dev/null
+++ b/themes/bonsai/assets/js/share.js
@@ -0,0 +1,39 @@
+// Bonsai page-share button.
+// Tries navigator.share first; falls back to clipboard.writeText with a toast.
+// Loaded only when params.share = true.
+(function () {
+ var btn = document.querySelector('[data-bonsai-share]');
+ if (!btn) return;
+ var toast = document.querySelector('.bio__share-toast');
+ var toastTimer;
+
+ function showToast(msg) {
+ if (!toast) return;
+ toast.textContent = msg;
+ toast.hidden = false;
+ clearTimeout(toastTimer);
+ toastTimer = setTimeout(function () { toast.hidden = true; }, 2000);
+ }
+
+ btn.addEventListener('click', async function () {
+ var url = btn.getAttribute('data-share-url');
+ var title = btn.getAttribute('data-share-title');
+ var copiedMsg = btn.getAttribute('data-toast-copied') || 'Link copied';
+ var failedMsg = btn.getAttribute('data-toast-failed') || 'Could not share';
+ try {
+ if (navigator.share) {
+ await navigator.share({ title: title, url: url });
+ return;
+ }
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ await navigator.clipboard.writeText(url);
+ showToast(copiedMsg);
+ return;
+ }
+ window.prompt('Copy link:', url);
+ } catch (e) {
+ if (e && e.name === 'AbortError') return;
+ showToast(failedMsg);
+ }
+ });
+})();
diff --git a/themes/bonsai/layouts/partials/analytics-loader.html b/themes/bonsai/layouts/partials/analytics-loader.html
new file mode 100644
index 0000000..4c1eec1
--- /dev/null
+++ b/themes/bonsai/layouts/partials/analytics-loader.html
@@ -0,0 +1,18 @@
+{{- /* Google Analytics 4 loader.
+ Emits nothing when params.analytics.measurementId is unset/empty.
+ Pairs with data-analytics-event attrs added by partials/link-button.html.
+ GA4 sets cookies — site operator is responsible for GDPR/PECR/CPRA consent. */ -}}
+{{- $a := site.Params.analytics -}}
+{{- if and $a $a.measurementId -}}
+{{- $id := $a.measurementId -}}
+{{- $trackClicks := ne ($a.trackClicks | default true) false -}}
+
+
+{{- end -}}