← back to Big Red
feat(big-red/tick1): per-mode launcher ring color (next: shopify TTL cache)
56b06d56f5a1a9026a7beb27465bce0fc12aff6e · 2026-05-12 00:47:59 -0700 · Steve Abrams
Closed-state launcher ring now reflects mode:
- retail → red glow (unchanged default)
- wholesale → trade-blue (#5fa8ff) ring + blue tag 'TRADE · BIG RED'
- admin → operator-amber (#f0a93a) ring + amber tag 'OPERATOR · BIG RED'
Live (open) state still goes green across all modes — preserves the
red→green active-chat metaphor while letting the closed launcher
telegraph which persona Big Red will load when clicked.
CSS attribute selectors keyed on data-mode set on the launcher element.
Three new keyframe animations (blue/amber/green pulses) match the
existing red rhythm. Tag color shadow follows mode on hover.
YOLO tick 1 — next tick (T+30m): Shopify lookup TTL cache.
Files touched
Diff
commit 56b06d56f5a1a9026a7beb27465bce0fc12aff6e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue May 12 00:47:59 2026 -0700
feat(big-red/tick1): per-mode launcher ring color (next: shopify TTL cache)
Closed-state launcher ring now reflects mode:
- retail → red glow (unchanged default)
- wholesale → trade-blue (#5fa8ff) ring + blue tag 'TRADE · BIG RED'
- admin → operator-amber (#f0a93a) ring + amber tag 'OPERATOR · BIG RED'
Live (open) state still goes green across all modes — preserves the
red→green active-chat metaphor while letting the closed launcher
telegraph which persona Big Red will load when clicked.
CSS attribute selectors keyed on data-mode set on the launcher element.
Three new keyframe animations (blue/amber/green pulses) match the
existing red rhythm. Tag color shadow follows mode on hover.
YOLO tick 1 — next tick (T+30m): Shopify lookup TTL cache.
---
public/widget.js | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 81 insertions(+), 2 deletions(-)
diff --git a/public/widget.js b/public/widget.js
index 11291e1..1cd9b49 100644
--- a/public/widget.js
+++ b/public/widget.js
@@ -201,6 +201,74 @@
.bigred-tag { right: 80px; bottom: 28px; font-size: 9px; }
.bigred-panel { left: 8px; right: 8px; bottom: 8px; width: auto; height: min(560px, calc(100vh - 40px)); }
}
+
+ /* Per-mode launcher ring — closed state only. Live (open) state stays
+ green across all modes to signal "actively chatting" universally.
+ Wholesale = trade-blue, admin = operator-amber, retail = default red. */
+ .bigred-launcher[data-mode="wholesale"] {
+ box-shadow:
+ 0 0 0 3px #5fa8ff,
+ 0 0 0 5px rgba(95,168,255,.18),
+ 0 8px 24px rgba(95,168,255,.5),
+ 0 2px 10px rgba(0,0,0,.4);
+ animation: bigred-pulse-blue 2.8s ease-in-out infinite;
+ }
+ .bigred-launcher[data-mode="wholesale"]::after {
+ background: radial-gradient(circle at 35% 30%, rgba(140,190,255,.18) 0%, rgba(46,96,180,.40) 65%, rgba(20,50,120,.52) 100%);
+ }
+ .bigred-launcher[data-mode="admin"] {
+ box-shadow:
+ 0 0 0 3px #f0a93a,
+ 0 0 0 5px rgba(240,169,58,.22),
+ 0 8px 24px rgba(240,169,58,.5),
+ 0 2px 10px rgba(0,0,0,.4);
+ animation: bigred-pulse-amber 2.2s ease-in-out infinite;
+ }
+ .bigred-launcher[data-mode="admin"]::after {
+ background: radial-gradient(circle at 35% 30%, rgba(255,220,140,.20) 0%, rgba(180,120,30,.40) 65%, rgba(90,55,15,.55) 100%);
+ }
+ /* Live state always wins — green ring overrides mode ring while open. */
+ .bigred-launcher.live[data-mode] {
+ box-shadow:
+ 0 0 0 3px #2fbf4a,
+ 0 0 0 5px rgba(47,191,74,.20),
+ 0 8px 28px rgba(47,191,74,.55),
+ 0 2px 10px rgba(0,0,0,.4);
+ animation: bigred-pulse-green 1.8s ease-in-out infinite;
+ }
+ @keyframes bigred-pulse-blue {
+ 0%, 100% { box-shadow:
+ 0 0 0 3px #5fa8ff,
+ 0 0 0 5px rgba(95,168,255,.18),
+ 0 8px 24px rgba(95,168,255,.5),
+ 0 2px 10px rgba(0,0,0,.4); }
+ 50% { box-shadow:
+ 0 0 0 3px #8cc3ff,
+ 0 0 0 7px rgba(140,195,255,.24),
+ 0 8px 32px rgba(140,195,255,.72),
+ 0 2px 12px rgba(0,0,0,.45); }
+ }
+ @keyframes bigred-pulse-amber {
+ 0%, 100% { box-shadow:
+ 0 0 0 3px #f0a93a,
+ 0 0 0 5px rgba(240,169,58,.22),
+ 0 8px 24px rgba(240,169,58,.5),
+ 0 2px 10px rgba(0,0,0,.4); }
+ 50% { box-shadow:
+ 0 0 0 3px #ffcc60,
+ 0 0 0 7px rgba(255,204,96,.28),
+ 0 8px 32px rgba(255,204,96,.72),
+ 0 2px 12px rgba(0,0,0,.45); }
+ }
+ /* Tag color follows mode in closed state */
+ .bigred-launcher[data-mode="wholesale"]:hover + .bigred-tag {
+ color: #8cc3ff;
+ text-shadow: 0 0 12px rgba(140,195,255,.55), 0 0 2px rgba(0,0,0,.6);
+ }
+ .bigred-launcher[data-mode="admin"]:hover + .bigred-tag {
+ color: #ffcc60;
+ text-shadow: 0 0 12px rgba(255,204,96,.55), 0 0 2px rgba(0,0,0,.6);
+ }
`;
const style = document.createElement('style');
@@ -211,7 +279,14 @@
const launcher = document.createElement('button');
launcher.type = 'button';
launcher.className = 'bigred-launcher';
- launcher.setAttribute('aria-label', 'Open Big Red voice chat');
+ // data-mode drives the closed-state ring color via CSS attribute selectors
+ // (retail = default red, wholesale = blue, admin = amber).
+ launcher.setAttribute('data-mode', mode);
+ launcher.setAttribute('aria-label', mode === 'admin'
+ ? 'Open Big Red (admin operator mode)'
+ : mode === 'wholesale'
+ ? 'Open Big Red (trade chat)'
+ : 'Open Big Red voice chat');
// Avatar image — falls back to Steve's stored avatar at /avatar/steve.jpg.
// Add a query bust so updated frames refresh on next page load.
const avatarImg = document.createElement('img');
@@ -229,7 +304,11 @@
const tag = document.createElement('div');
tag.className = 'bigred-tag';
- tag.textContent = 'TALK TO BIG RED';
+ tag.textContent = mode === 'admin'
+ ? 'OPERATOR · BIG RED'
+ : mode === 'wholesale'
+ ? 'TRADE · BIG RED'
+ : 'TALK TO BIG RED';
const panel = document.createElement('div');
panel.className = 'bigred-panel';
← bd46b8f feat(big-red/tick0): chat-only /embed.html (panel iframe rep
·
back to Big Red
·
feat(big-red/tick2): Shopify lookup 60s TTL cache (next: SKU 8379170 →