diff --git a/pages/solutions.php b/pages/solutions.php index e052496..3547c07 100644 --- a/pages/solutions.php +++ b/pages/solutions.php @@ -11,18 +11,18 @@ return <<<'ORIBI_SYNC_CONTENT' - + - + - + - + - - - - + + + + diff --git a/theme/assets/css/main.css b/theme/assets/css/main.css index 3e6a8d9..7385153 100644 --- a/theme/assets/css/main.css +++ b/theme/assets/css/main.css @@ -6262,3 +6262,1481 @@ p:last-child { margin-bottom: 0; } .hosp-menu__desc { display: none; } .hosp-menu__price { font-size: 14px; } } + +/* ═══════════════════════════════════════════════════════════════ + RETAIL PROMO ANIMATION (.platform-visual.has-retail) + TV cycling 3 slides: Flash Sale → New In Store → Member Rewards (9s) + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-retail { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.retail-stage { + width: 100%; + max-width: 520px; + margin: 0 auto; +} + +.retail-tv { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; +} + +.retail-tv__body { + width: 100%; + background: #111; + border: 5px solid #1a1a1a; + border-radius: 8px 8px 4px 4px; + outline: 2px solid #000; + padding: 4px; + box-shadow: 0 14px 48px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.06); +} + +.retail-tv__screen { + width: 100%; + aspect-ratio: 16/9; + background: #0a0a0a; + border-radius: 2px; + overflow: hidden; + position: relative; +} + +.retail-tv__feet { + display: flex; + justify-content: space-between; + width: 60%; + max-width: 300px; +} + +.retail-tv__foot { + width: 12px; + height: 8px; + background: #111; + border: 1px solid #000; + border-radius: 0 0 4px 4px; +} + +.retail-slides { + position: relative; + width: 100%; + height: 100%; +} + +.retail-slide { + position: absolute; + inset: 0; + opacity: 0; + animation: retail-fade 9s infinite; + display: flex; + align-items: stretch; +} + +.retail-slide--sale { animation-delay: 0s; } +.retail-slide--new { animation-delay: 3s; } +.retail-slide--loyalty { animation-delay: 6s; } + +.retail-promo { + width: 100%; + padding: 20px 28px; + display: flex; + flex-direction: column; + justify-content: center; + gap: 10px; +} + +/* Sale slide */ +.retail-slide--sale .retail-promo { background: linear-gradient(135deg, #1a0a0a 0%, #2a0d0d 100%); } +/* New arrivals slide */ +.retail-slide--new .retail-promo { background: linear-gradient(135deg, #0a0f1a 0%, #0d1a2a 100%); } +/* Loyalty slide */ +.retail-slide--loyalty .retail-promo { background: linear-gradient(135deg, #0a1a0d 0%, #0d2a12 100%); } + +.retail-promo__eyebrow { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 1.5px; + color: rgba(255,255,255,0.5); +} + +.retail-promo__headline { + font-size: 28px; + font-weight: 800; + color: #fff; + line-height: 1.1; +} + +.retail-promo__badge { + display: inline-block; + background: var(--color-primary); + color: #fff; + font-size: 13px; + font-weight: 700; + padding: 4px 12px; + border-radius: 4px; + width: fit-content; +} + +.retail-promo__items { + display: flex; + flex-direction: column; + gap: 6px; + margin-top: 4px; +} + +.retail-promo__item { + display: flex; + align-items: center; + gap: 8px; + color: rgba(255,255,255,0.8); + font-size: 13px; +} + +.retail-promo__dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: var(--color-primary); + flex-shrink: 0; +} + +.retail-promo__cta { + font-size: 11px; + color: rgba(255,255,255,0.4); + text-transform: uppercase; + letter-spacing: 1px; + margin-top: 4px; +} + +/* New arrivals swatches */ +.retail-promo__grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 8px; + margin: 4px 0; +} + +.retail-promo__swatch { + aspect-ratio: 1; + border-radius: 4px; + animation: retail-swatch-pulse 3s ease-in-out infinite; +} +.retail-promo__swatch--a { background: #c8a882; animation-delay: 0s; } +.retail-promo__swatch--b { background: #4a7c59; animation-delay: 0.4s; } +.retail-promo__swatch--c { background: #2c4a8a; animation-delay: 0.8s; } +.retail-promo__swatch--d { background: #8a2c2c; animation-delay: 1.2s; } + +.retail-promo__sub { + font-size: 12px; + color: rgba(255,255,255,0.5); +} + +/* Loyalty points */ +.retail-promo__points { + display: flex; + align-items: baseline; + gap: 10px; +} + +.retail-promo__pts-val { + font-size: 48px; + font-weight: 900; + color: var(--color-accent); + line-height: 1; +} + +.retail-promo__pts-lbl { + font-size: 15px; + color: rgba(255,255,255,0.8); +} + +.retail-promo__bar { + height: 8px; + background: rgba(255,255,255,0.12); + border-radius: 4px; + overflow: hidden; +} + +.retail-promo__bar-fill { + height: 100%; + width: 72%; + background: var(--color-accent); + border-radius: 4px; + animation: retail-bar-grow 2s ease-out infinite alternate; +} + +@keyframes retail-fade { + 0%, 2% { opacity: 0; transform: translateY(10px); } + 5%, 30% { opacity: 1; transform: translateY(0); } + 33%, 100% { opacity: 0; transform: translateY(-10px); } +} + +@keyframes retail-swatch-pulse { + 0%, 100% { opacity: 0.7; transform: scale(1); } + 50% { opacity: 1; transform: scale(1.04); } +} + +@keyframes retail-bar-grow { + from { width: 50%; } + to { width: 82%; } +} + +@media (prefers-reduced-motion: reduce) { + .retail-slide { animation: none; opacity: 0; } + .retail-slide--sale { opacity: 1; } + .retail-promo__swatch { animation: none; } + .retail-promo__bar-fill { animation: none; } +} + +@media (max-width: 640px) { + .retail-promo { padding: 14px 18px; gap: 7px; } + .retail-promo__headline { font-size: 20px; } + .retail-promo__pts-val { font-size: 36px; } +} + +/* ═══════════════════════════════════════════════════════════════ + CORPORATE MEETING ROOM PANEL (.platform-visual.has-corporate) + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-corporate { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.corp-stage { + width: 100%; + max-width: 400px; + margin: 0 auto; +} + +.corp-panel { + background: #0f1117; + border: 1px solid #1e2435; + border-radius: 12px; + padding: 24px 28px; + display: flex; + flex-direction: column; + gap: 20px; + box-shadow: 0 20px 60px rgba(0,0,0,0.5), 0 0 0 1px rgba(255,255,255,0.04); + color: #fff; +} + +.corp-panel__header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.corp-panel__room { + font-size: 20px; + font-weight: 700; + color: #fff; +} + +.corp-panel__status { + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + padding: 4px 10px; + border-radius: 20px; +} + +.corp-panel__status--busy { + background: rgba(239,68,68,0.15); + color: #f87171; + border: 1px solid rgba(239,68,68,0.3); +} + +.corp-panel__dot { + width: 7px; + height: 7px; + border-radius: 50%; + background: #ef4444; + animation: corp-dot-pulse 1.8s ease-in-out infinite; +} + +.corp-panel__meeting { + border-left: 3px solid var(--color-primary); + padding-left: 14px; + display: flex; + flex-direction: column; + gap: 4px; +} + +.corp-panel__meeting-name { + font-size: 16px; + font-weight: 600; + color: #fff; +} + +.corp-panel__meeting-time { + font-size: 13px; + color: rgba(255,255,255,0.5); + font-family: monospace; +} + +.corp-panel__organiser { + font-size: 12px; + color: rgba(255,255,255,0.35); +} + +/* Timeline bar */ +.corp-panel__timeline { + display: flex; + flex-direction: column; + gap: 6px; +} + +.corp-panel__tl-track { + height: 8px; + background: rgba(255,255,255,0.08); + border-radius: 4px; + position: relative; + overflow: hidden; +} + +.corp-panel__tl-fill { + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 42%; + background: linear-gradient(90deg, var(--color-primary), #ff6b35); + border-radius: 4px; + animation: corp-tl-progress 12s linear infinite; +} + +.corp-panel__tl-now { + position: absolute; + top: -2px; + bottom: -2px; + left: 42%; + width: 2px; + background: #fff; + border-radius: 2px; + animation: corp-tl-now 12s linear infinite; +} + +.corp-panel__tl-labels { + display: flex; + justify-content: space-between; + font-size: 10px; + color: rgba(255,255,255,0.3); + font-family: monospace; +} + +/* Next meeting */ +.corp-panel__next { + background: rgba(255,255,255,0.04); + border-radius: 8px; + padding: 12px 14px; + display: flex; + flex-direction: column; + gap: 3px; +} + +.corp-panel__next-lbl { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 1px; + color: rgba(255,255,255,0.35); +} + +.corp-panel__next-name { + font-size: 14px; + font-weight: 500; + color: rgba(255,255,255,0.8); +} + +.corp-panel__next-time { + font-size: 12px; + color: rgba(255,255,255,0.4); + font-family: monospace; +} + +/* Teams indicator */ +.corp-panel__teams { + display: flex; + align-items: center; + gap: 8px; + font-size: 12px; + color: rgba(255,255,255,0.45); +} + +.corp-panel__teams-icon { + width: 18px; + height: 18px; + background: #4a90d9; + border-radius: 4px; + flex-shrink: 0; +} + +@keyframes corp-dot-pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.4; transform: scale(0.7); } +} + +@keyframes corp-tl-progress { + 0% { width: 35%; } + 100% { width: 55%; } +} + +@keyframes corp-tl-now { + 0% { left: 35%; } + 100% { left: 55%; } +} + +@media (prefers-reduced-motion: reduce) { + .corp-panel__dot { animation: none; } + .corp-panel__tl-fill { animation: none; } + .corp-panel__tl-now { animation: none; } +} + +@media (max-width: 640px) { + .corp-panel { padding: 18px 20px; gap: 16px; } + .corp-panel__room { font-size: 16px; } + .corp-panel__meeting-name { font-size: 14px; } +} + +/* ═══════════════════════════════════════════════════════════════ + EDUCATION SCHEDULE BOARD (.platform-visual.has-education) + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-education { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.edu-stage { + width: 100%; + max-width: 480px; + margin: 0 auto; +} + +.edu-board { + background: #0d1117; + border: 1px solid #1e2435; + border-radius: 10px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0,0,0,0.5); + color: #fff; +} + +.edu-board__header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 14px 20px; + background: linear-gradient(135deg, #1a1f2e 0%, #141928 100%); + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.edu-board__title { + font-size: 15px; + font-weight: 700; + color: #fff; +} + +.edu-board__date { + font-size: 11px; + color: rgba(255,255,255,0.4); + font-family: monospace; +} + +.edu-board__rows { + display: flex; + flex-direction: column; +} + +.edu-board__row { + display: grid; + grid-template-columns: 56px 1fr 70px auto; + align-items: center; + gap: 12px; + padding: 10px 20px; + border-bottom: 1px solid rgba(255,255,255,0.04); + transition: background 0.2s; +} + +.edu-row--done { + opacity: 0.35; +} + +.edu-row--now { + background: rgba(76,175,80,0.08); + border-left: 3px solid var(--color-accent); + padding-left: 17px; + animation: edu-row-pulse 3s ease-in-out infinite; +} + +.edu-row__time { + font-size: 12px; + color: rgba(255,255,255,0.45); + font-family: monospace; +} + +.edu-row__subject { + font-size: 13px; + font-weight: 500; + color: rgba(255,255,255,0.85); +} + +.edu-row--now .edu-row__subject { + color: #fff; + font-weight: 600; +} + +.edu-row__room { + font-size: 11px; + color: rgba(255,255,255,0.35); + text-align: right; +} + +.edu-row__badge { + font-size: 10px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.5px; + background: var(--color-accent); + color: #fff; + padding: 2px 7px; + border-radius: 4px; +} + +/* Emergency alert bar */ +.edu-board__alert { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 20px; + background: rgba(245,158,11,0.12); + border-top: 1px solid rgba(245,158,11,0.25); + animation: edu-alert-glow 2.5s ease-in-out infinite; +} + +.edu-alert__icon { + width: 20px; + height: 20px; + border-radius: 50%; + background: rgba(245,158,11,0.3); + border: 1px solid #f59e0b; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + font-weight: 800; + color: #f59e0b; + flex-shrink: 0; + line-height: 20px; + text-align: center; +} + +.edu-alert__txt { + font-size: 12px; + color: #fbbf24; +} + +@keyframes edu-row-pulse { + 0%, 100% { background: rgba(76,175,80,0.08); } + 50% { background: rgba(76,175,80,0.14); } +} + +@keyframes edu-alert-glow { + 0%, 100% { background: rgba(245,158,11,0.10); } + 50% { background: rgba(245,158,11,0.18); } +} + +@media (prefers-reduced-motion: reduce) { + .edu-row--now { animation: none; } + .edu-board__alert { animation: none; } +} + +@media (max-width: 640px) { + .edu-board__row { grid-template-columns: 46px 1fr auto; gap: 8px; padding: 9px 14px; } + .edu-row__room { display: none; } + .edu-row__subject { font-size: 12px; } + .edu-board__header { padding: 12px 14px; } +} + +/* ═══════════════════════════════════════════════════════════════ + OUTDOOR MARKETPLACE BOARD (.platform-visual.has-outdoor) + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-outdoor { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.outdoor-stage { + width: 100%; + max-width: 520px; + margin: 0 auto; +} + +.outdoor-board { + background: #1a1a1a; + border: 6px solid #222; + border-radius: 8px; + outline: 2px solid #000; + box-shadow: 0 16px 60px rgba(0,0,0,0.65), inset 0 1px 0 rgba(255,255,255,0.06); + position: relative; +} + +.outdoor-board__screen { + aspect-ratio: 16/7; + overflow: hidden; + background: #090909; + border-radius: 2px; + position: relative; +} + +.outdoor-board__bezel { + height: 10px; + background: linear-gradient(180deg, #1a1a1a 0%, #111 100%); + border-top: 1px solid #0a0a0a; +} + +.outdoor-slides { + position: relative; + width: 100%; + height: 100%; +} + +.outdoor-slide { + position: absolute; + inset: 0; + opacity: 0; + animation: outdoor-fade 8s infinite; +} + +.outdoor-slide--info { animation-delay: 0s; } +.outdoor-slide--directory { animation-delay: 4s; } + +/* Market info slide */ +.outdoor-info { + height: 100%; + padding: 18px 24px; + background: linear-gradient(135deg, #0d1a0d 0%, #0a1a10 100%); + display: flex; + flex-direction: column; + gap: 12px; + color: #fff; +} + +.outdoor-info__header { + display: flex; + justify-content: space-between; + align-items: flex-start; +} + +.outdoor-info__name { + font-size: 20px; + font-weight: 800; + color: #fff; +} + +.outdoor-info__weather { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 2px; +} + +.outdoor-info__temp { + font-size: 24px; + font-weight: 700; + color: #fbbf24; +} + +.outdoor-info__cond { + font-size: 10px; + color: rgba(255,255,255,0.5); +} + +.outdoor-info__details { + display: flex; + flex-direction: column; + gap: 7px; +} + +.outdoor-info__row { + display: flex; + align-items: center; + gap: 8px; + font-size: 13px; + color: rgba(255,255,255,0.8); +} + +.outdoor-info__icon { + width: 16px; + height: 16px; + border-radius: 3px; + background: rgba(76,175,80,0.3); + border: 1px solid rgba(76,175,80,0.5); + flex-shrink: 0; +} + +/* Directory slide */ +.outdoor-dir { + height: 100%; + padding: 18px 24px; + background: linear-gradient(135deg, #0d0d1a 0%, #0a0a1a 100%); + display: flex; + flex-direction: column; + gap: 12px; + color: #fff; +} + +.outdoor-dir__title { + font-size: 16px; + font-weight: 700; + color: #fff; + border-bottom: 1px solid rgba(255,255,255,0.08); + padding-bottom: 8px; +} + +.outdoor-dir__grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + flex: 1; + align-content: start; +} + +.outdoor-dir__cell { + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.08); + border-radius: 6px; + padding: 8px 10px; + display: flex; + flex-direction: column; + gap: 3px; +} + +.outdoor-dir__zone { + font-size: 10px; + font-weight: 700; + color: var(--color-accent); + font-family: monospace; + text-transform: uppercase; +} + +.outdoor-dir__cat { + font-size: 12px; + color: rgba(255,255,255,0.7); +} + +@keyframes outdoor-fade { + 0%, 2% { opacity: 0; transform: scale(0.98); } + 8%, 45% { opacity: 1; transform: scale(1); } + 50%, 100% { opacity: 0; transform: scale(0.98); } +} + +@media (prefers-reduced-motion: reduce) { + .outdoor-slide { animation: none; opacity: 0; } + .outdoor-slide--info { opacity: 1; } +} + +@media (max-width: 640px) { + .outdoor-info { padding: 12px 16px; } + .outdoor-dir { padding: 12px 16px; } + .outdoor-info__name { font-size: 16px; } +} + +/* ═══════════════════════════════════════════════════════════════ + LIVE DATA / OPS BOARD (.platform-visual.has-live-data) + KPI counters ticked by solutions-animator.js + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-live-data { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.ld-stage { + width: 100%; + max-width: 480px; + margin: 0 auto; +} + +.ld-board { + background: #0a0d14; + border: 1px solid #1a2035; + border-radius: 10px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0,0,0,0.6); + color: #fff; +} + +.ld-board__header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 12px 18px; + background: rgba(255,255,255,0.03); + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.ld-board__title { + font-size: 13px; + font-weight: 600; + color: rgba(255,255,255,0.7); + text-transform: uppercase; + letter-spacing: 0.8px; + font-size: 11px; +} + +.ld-board__live { + display: flex; + align-items: center; + gap: 5px; + font-size: 10px; + font-weight: 700; + color: #f87171; + text-transform: uppercase; + letter-spacing: 1px; +} + +.ld-board__live-dot { + width: 6px; + height: 6px; + border-radius: 50%; + background: #ef4444; + animation: ld-live-pulse 1.4s ease-in-out infinite; +} + +.ld-kpis { + display: grid; + grid-template-columns: repeat(4, 1fr); + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.ld-kpi { + padding: 14px 12px; + border-right: 1px solid rgba(255,255,255,0.06); + display: flex; + flex-direction: column; + gap: 4px; +} + +.ld-kpi:last-child { border-right: none; } + +.ld-kpi__label { + font-size: 9px; + text-transform: uppercase; + letter-spacing: 0.6px; + color: rgba(255,255,255,0.35); +} + +.ld-kpi__value { + font-size: 18px; + font-weight: 700; + color: #fff; + font-family: monospace; + transition: color 0.2s; +} + +.ld-kpi__trend::after { + display: block; + font-size: 10px; + margin-top: 2px; +} + +.ld-kpi--up .ld-kpi__value { color: #4ade80; } +.ld-kpi--down .ld-kpi__value { color: #f87171; } +.ld-kpi--up .ld-kpi__trend::after { content: '▲'; color: #4ade80; } +.ld-kpi--down .ld-kpi__trend::after { content: '▼'; color: #f87171; } +.ld-kpi--neutral .ld-kpi__trend::after { content: '—'; color: rgba(255,255,255,0.3); } + +/* Sparkline chart area */ +.ld-chart { + padding: 12px 18px 8px; + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.ld-sparkline { + width: 100%; + height: 60px; + display: block; +} + +.ld-chart__label { + font-size: 10px; + color: rgba(255,255,255,0.25); + margin-top: 4px; +} + +/* Service status row */ +.ld-status { + display: flex; + align-items: center; + gap: 16px; + padding: 10px 18px; + flex-wrap: wrap; +} + +.ld-svc { + display: flex; + align-items: center; + gap: 5px; + font-size: 11px; + color: rgba(255,255,255,0.55); +} + +.ld-svc__dot { + width: 7px; + height: 7px; + border-radius: 50%; + flex-shrink: 0; +} + +.ld-svc--ok .ld-svc__dot { background: #4ade80; box-shadow: 0 0 6px #4ade80; } +.ld-svc--warn .ld-svc__dot { background: #fbbf24; box-shadow: 0 0 6px #fbbf24; animation: ld-warn-pulse 1.5s ease-in-out infinite; } +.ld-svc--err .ld-svc__dot { background: #f87171; box-shadow: 0 0 6px #f87171; animation: ld-warn-pulse 0.8s ease-in-out infinite; } + +@keyframes ld-live-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.3; } +} + +@keyframes ld-warn-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.4; } +} + +@media (max-width: 640px) { + .ld-kpis { grid-template-columns: repeat(2, 1fr); } + .ld-kpi__value { font-size: 15px; } + .ld-status { gap: 10px; padding: 8px 14px; } +} + +/* ═══════════════════════════════════════════════════════════════ + HEALTHCARE QUEUE BOARD (.platform-visual.has-healthcare) + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-healthcare { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.hc-stage { + width: 100%; + max-width: 460px; + margin: 0 auto; +} + +.hc-board { + background: #0a1419; + border: 1px solid #162030; + border-radius: 10px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0,0,0,0.55); + color: #fff; +} + +.hc-board__header { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 18px; + background: #0d1c2a; + border-bottom: 1px solid rgba(255,255,255,0.07); +} + +.hc-board__logo { + width: 28px; + height: 28px; + border-radius: 6px; + background: linear-gradient(135deg, #0ea5e9, #38bdf8); + flex-shrink: 0; +} + +.hc-board__title { + font-size: 15px; + font-weight: 600; + color: #fff; +} + +/* Now serving hero */ +.hc-now { + padding: 20px 18px 16px; + text-align: center; + border-bottom: 1px solid rgba(255,255,255,0.06); + background: linear-gradient(135deg, rgba(14,165,233,0.06) 0%, rgba(56,189,248,0.03) 100%); +} + +.hc-now__lbl { + font-size: 11px; + text-transform: uppercase; + letter-spacing: 1.5px; + color: rgba(255,255,255,0.4); + margin-bottom: 6px; +} + +.hc-now__number { + font-size: 40px; + font-weight: 900; + color: #38bdf8; + font-family: monospace; + letter-spacing: 4px; + animation: hc-number-flash 3.5s ease-in-out infinite; +} + +.hc-now__counter { + font-size: 12px; + color: rgba(255,255,255,0.5); + margin-top: 4px; +} + +/* Counter rows */ +.hc-counters { + display: flex; + flex-direction: column; + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.hc-counter { + display: grid; + grid-template-columns: 32px 1fr auto auto; + align-items: center; + gap: 10px; + padding: 10px 18px; + border-bottom: 1px solid rgba(255,255,255,0.04); + font-size: 12px; +} + +.hc-counter:last-child { border-bottom: none; } + +.hc-counter--active { } +.hc-counter--closed { opacity: 0.3; } + +.hc-counter__id { + font-size: 11px; + font-weight: 700; + color: rgba(255,255,255,0.4); + font-family: monospace; +} + +.hc-counter__doctor { + color: rgba(255,255,255,0.75); + font-size: 12px; +} + +.hc-counter__ticket { + font-size: 13px; + font-weight: 700; + color: #38bdf8; + font-family: monospace; + min-width: 36px; + text-align: right; +} + +.hc-counter__wait { + font-size: 11px; + color: rgba(255,255,255,0.35); + min-width: 50px; + text-align: right; +} + +.hc-board__footer { + padding: 10px 18px; + font-size: 11px; + color: rgba(255,255,255,0.3); + text-align: center; + background: rgba(255,255,255,0.02); +} + +@keyframes hc-number-flash { + 0%, 100% { opacity: 1; color: #38bdf8; } + 10% { opacity: 0.5; color: #7dd3fc; } + 20% { opacity: 1; color: #38bdf8; } +} + +@media (prefers-reduced-motion: reduce) { + .hc-now__number { animation: none; } +} + +@media (max-width: 640px) { + .hc-now__number { font-size: 28px; } + .hc-counter { grid-template-columns: 28px 1fr auto; gap: 8px; } + .hc-counter__wait { display: none; } +} + +/* ═══════════════════════════════════════════════════════════════ + TRANSIT DEPARTURE BOARD (.platform-visual.has-transit) + Split-flap flip characters; rows cycled by solutions-animator.js + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-transit { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.transit-stage { + width: 100%; + max-width: 500px; + margin: 0 auto; +} + +.transit-board { + background: #111; + border: 1px solid #1a1a1a; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0,0,0,0.7); + font-family: monospace; +} + +.transit-board__header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px 16px; + background: #1a1a1a; + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.transit-board__title { + font-size: 14px; + font-weight: 700; + color: #f5f5a0; + letter-spacing: 1px; + text-transform: uppercase; +} + +.transit-board__clock { + font-size: 18px; + font-weight: 700; + color: #f5f5a0; + letter-spacing: 2px; +} + +.transit-board__cols { + display: grid; + grid-template-columns: 56px 1fr 64px 80px; + gap: 0; + padding: 6px 16px; + background: #161616; + border-bottom: 1px solid rgba(255,255,255,0.08); +} + +.transit-col-hd { + font-size: 9px; + text-transform: uppercase; + letter-spacing: 1px; + color: rgba(255,255,255,0.3); +} + +.transit-rows { + display: flex; + flex-direction: column; +} + +.transit-row { + display: grid; + grid-template-columns: 56px 1fr 64px 80px; + align-items: center; + padding: 7px 16px; + border-bottom: 1px solid rgba(255,255,255,0.04); + gap: 0; + transition: background 0.3s; +} + +.transit-row:last-child { border-bottom: none; } + +.transit-cell { + font-size: 13px; + color: #f5f5a0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.transit-cell--time { + font-weight: 700; + letter-spacing: 1px; +} + +.transit-cell--plat { + text-align: center; + color: rgba(245,245,160,0.7); +} + +.transit-cell--status { } + +.transit-status--on-time { color: #4ade80; } +.transit-status--delayed { color: #f87171; animation: transit-delayed-blink 2s step-end infinite; } +.transit-status--cancelled { color: #f87171; text-decoration: line-through; } + +/* Split-flap character flip animation */ +.transit-flap { + display: inline-block; + animation: transit-flap-flip 0s; +} + +.transit-flap.is-flipping { + animation: transit-flap-flip 0.25s ease-in-out forwards; +} + +@keyframes transit-flap-flip { + 0% { transform: scaleY(1); } + 40% { transform: scaleY(0); opacity: 0.5; } + 60% { transform: scaleY(0); opacity: 0.5; } + 100% { transform: scaleY(1); } +} + +@keyframes transit-delayed-blink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.4; } +} + +@media (prefers-reduced-motion: reduce) { + .transit-flap.is-flipping { animation: none; } + .transit-status--delayed { animation: none; } +} + +@media (max-width: 640px) { + .transit-board__cols, + .transit-row { grid-template-columns: 50px 1fr 52px; } + .transit-cell--plat { display: none; } + .transit-col-hd:nth-child(3) { display: none; } + .transit-cell { font-size: 11px; } +} + +/* ═══════════════════════════════════════════════════════════════ + FITNESS CLASS SCHEDULE (.platform-visual.has-fitness) + ═══════════════════════════════════════════════════════════════ */ + +.platform-visual.has-fitness { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + box-shadow: none; +} + +.fit-stage { + width: 100%; + max-width: 460px; + margin: 0 auto; +} + +.fit-board { + background: #0d0d0d; + border: 1px solid #1a1a1a; + border-radius: 10px; + overflow: hidden; + box-shadow: 0 20px 60px rgba(0,0,0,0.6); + color: #fff; +} + +.fit-board__header { + display: flex; + align-items: center; + gap: 10px; + padding: 12px 18px; + background: #111; + border-bottom: 1px solid rgba(255,255,255,0.07); +} + +.fit-board__logo { + width: 26px; + height: 26px; + border-radius: 6px; + background: linear-gradient(135deg, var(--color-primary), #ff6b35); + flex-shrink: 0; +} + +.fit-board__title { + font-size: 14px; + font-weight: 700; + color: #fff; +} + +/* Live now hero */ +.fit-now { + padding: 18px 18px 14px; + background: linear-gradient(135deg, rgba(216,51,2,0.1) 0%, rgba(255,107,53,0.06) 100%); + border-bottom: 1px solid rgba(255,255,255,0.06); +} + +.fit-now__badge { + display: inline-flex; + align-items: center; + gap: 6px; + background: var(--color-primary); + color: #fff; + font-size: 10px; + font-weight: 800; + letter-spacing: 1px; + padding: 3px 10px; + border-radius: 4px; + margin-bottom: 8px; + animation: fit-badge-pulse 2s ease-in-out infinite; +} + +.fit-now__name { + font-size: 22px; + font-weight: 800; + color: #fff; + margin-bottom: 4px; +} + +.fit-now__detail { + font-size: 12px; + color: rgba(255,255,255,0.45); + margin-bottom: 12px; +} + +/* Capacity bar */ +.fit-now__capacity { + display: flex; + align-items: center; + gap: 10px; +} + +.fit-cap__lbl { + font-size: 10px; + text-transform: uppercase; + letter-spacing: 0.5px; + color: rgba(255,255,255,0.35); + white-space: nowrap; +} + +.fit-cap__track { + flex: 1; + height: 8px; + background: rgba(255,255,255,0.1); + border-radius: 4px; + overflow: hidden; +} + +.fit-cap__fill { + height: 100%; + width: 80%; + background: linear-gradient(90deg, var(--color-primary), #ff6b35); + border-radius: 4px; + animation: fit-cap-breathe 3s ease-in-out infinite alternate; +} + +.fit-cap__val { + font-size: 11px; + font-weight: 600; + color: rgba(255,255,255,0.6); + white-space: nowrap; + font-family: monospace; +} + +/* Upcoming classes list */ +.fit-upcoming { + display: flex; + flex-direction: column; +} + +.fit-class { + display: grid; + grid-template-columns: 48px 1fr 1fr auto; + align-items: center; + gap: 10px; + padding: 10px 18px; + border-bottom: 1px solid rgba(255,255,255,0.04); + font-size: 12px; +} + +.fit-class:last-child { border-bottom: none; } + +.fit-class__time { + font-size: 12px; + font-weight: 600; + color: rgba(255,255,255,0.5); + font-family: monospace; +} + +.fit-class__name { + font-size: 13px; + font-weight: 500; + color: rgba(255,255,255,0.85); +} + +.fit-class__coach { + font-size: 11px; + color: rgba(255,255,255,0.35); +} + +.fit-class__spaces { + font-size: 11px; + color: rgba(255,255,255,0.4); + text-align: right; + white-space: nowrap; +} + +.fit-class--filling .fit-class__spaces { + color: #fbbf24; + font-weight: 600; +} + +@keyframes fit-badge-pulse { + 0%, 100% { box-shadow: 0 0 0 0 rgba(216,51,2,0.5); } + 50% { box-shadow: 0 0 0 6px rgba(216,51,2,0); } +} + +@keyframes fit-cap-breathe { + from { width: 76%; } + to { width: 83%; } +} + +@media (prefers-reduced-motion: reduce) { + .fit-now__badge { animation: none; } + .fit-cap__fill { animation: none; } +} + +@media (max-width: 640px) { + .fit-now { padding: 14px 14px 12px; } + .fit-now__name { font-size: 18px; } + .fit-class { grid-template-columns: 42px 1fr auto; gap: 8px; padding: 9px 14px; } + .fit-class__coach { display: none; } +} diff --git a/theme/assets/js/solutions-animator.js b/theme/assets/js/solutions-animator.js new file mode 100644 index 0000000..e921920 --- /dev/null +++ b/theme/assets/js/solutions-animator.js @@ -0,0 +1,291 @@ +/** + * Solutions Page Animators + * Handles the two JS-driven animations on the Solutions page: + * 1. Live Data board — ticking KPI values + animated sparkline + * 2. Transit board — live clock, split-flap flip characters, row cycling + * + * Both respect prefers-reduced-motion and pause via IntersectionObserver. + * Mirrors the patterns and conventions of dashboard-animator.js. + */ + +/* ── 1. Live Data KPI Animator ─────────────────────────────────────────── */ +(function () { + 'use strict'; + + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return; + + /* KPI definitions: label, base value, unit, variance range, display format */ + var KPIS = [ + { id: 'ld-orders', base: 1847, range: 120, fmt: function (v) { return v.toLocaleString(); } }, + { id: 'ld-uptime', base: 9997, range: 2, fmt: function (v) { return (v / 100).toFixed(2) + '%'; } }, + { id: 'ld-alerts', base: 3, range: 2, fmt: function (v) { return Math.max(0, v).toString(); } }, + { id: 'ld-latency', base: 42, range: 18, fmt: function (v) { return Math.max(8, v) + 'ms'; } }, + ]; + + /* Sparkline path parameters */ + var LINE_PTS = 16; + var LINE_W = 260; + var LINE_H = 60; + var SPEED = 0.0008; + + function wave(t, off) { + return Math.max(0, Math.min(1, + 0.5 + + Math.sin(t + off) * 0.28 + + Math.sin(t * 2.1 + off * 1.7) * 0.12 + )); + } + + function makeState(stage) { + var kpiEls = []; + for (var i = 0; i < KPIS.length; i++) { + kpiEls.push(stage.querySelector('#' + KPIS[i].id)); + } + return { + stage: stage, + kpiEls: kpiEls, + linePath: stage.querySelector('#ld-line-path'), + fillPath: stage.querySelector('#ld-fill-path'), + phase: Math.random() * Math.PI * 2, + ticker: 0, /* frame counter — update KPI text every N frames */ + paused: false, + }; + } + + function updateKpis(st) { + for (var i = 0; i < KPIS.length; i++) { + var el = st.kpiEls[i]; + if (!el) continue; + var k = KPIS[i]; + var raw = Math.round(k.base + wave(st.phase, i * 1.5) * k.range - k.range / 2); + el.textContent = k.fmt(raw); + } + } + + function updateSparkline(st) { + if (!st.linePath) return; + var pts = []; + for (var i = 0; i < LINE_PTS; i++) { + var x = (i / (LINE_PTS - 1)) * LINE_W; + var y = 8 + (1 - wave(st.phase * 0.7, i * 0.8)) * (LINE_H - 16); + pts.push(x.toFixed(1) + ',' + y.toFixed(1)); + } + var d = 'M' + pts.join(' L'); + st.linePath.setAttribute('d', d); + if (st.fillPath) { + st.fillPath.setAttribute('d', d + ' L' + LINE_W + ',' + LINE_H + ' L0,' + LINE_H + ' Z'); + } + } + + function tick(st) { + if (!st.paused) { + st.phase += SPEED * 16; + st.ticker++; + /* Update KPI text every 12 frames (~5/sec at 60fps) for legibility */ + if (st.ticker >= 12) { + st.ticker = 0; + updateKpis(st); + } + updateSparkline(st); + } + requestAnimationFrame(function () { tick(st); }); + } + + function observe(st) { + if (!('IntersectionObserver' in window)) return; + new IntersectionObserver(function (entries) { + for (var i = 0; i < entries.length; i++) { + st.paused = !entries[i].isIntersecting; + } + }, { rootMargin: '200px', threshold: 0.05 }).observe(st.stage); + } + + function boot() { + var stages = document.querySelectorAll('.ld-stage'); + if (!stages.length) return; + for (var i = 0; i < stages.length; i++) { + if (stages[i]._ldAnim) continue; + var st = makeState(stages[i]); + stages[i]._ldAnim = st; + observe(st); + tick(st); + } + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', boot); + } else { + boot(); + } +})(); + +/* ── 2. Transit Departure Board Animator ───────────────────────────────── */ +(function () { + 'use strict'; + + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + /* Still run the clock in reduced-motion mode */ + startClocks(); + return; + } + + /* Departure data sets — cycle between these every CYCLE_MS */ + var CYCLE_MS = 8000; + + var DATA_SETS = [ + [ + { time: '10:14', dest: 'London Victoria', plat: '2', status: 'On Time', cls: 'on-time' }, + { time: '10:22', dest: 'Brighton', plat: '4', status: 'On Time', cls: 'on-time' }, + { time: '10:31', dest: 'Gatwick Airport', plat: '1', status: 'Delayed', cls: 'delayed' }, + { time: '10:45', dest: 'London Bridge', plat: '3', status: 'On Time', cls: 'on-time' }, + { time: '11:02', dest: 'East Croydon', plat: '2', status: 'On Time', cls: 'on-time' }, + ], + [ + { time: '10:22', dest: 'Brighton', plat: '4', status: 'On Time', cls: 'on-time' }, + { time: '10:31', dest: 'Gatwick Airport', plat: '1', status: 'Delayed', cls: 'delayed' }, + { time: '10:45', dest: 'London Bridge', plat: '3', status: 'On Time', cls: 'on-time' }, + { time: '11:02', dest: 'East Croydon', plat: '2', status: 'On Time', cls: 'on-time' }, + { time: '11:14', dest: 'London Victoria', plat: '2', status: 'On Time', cls: 'on-time' }, + ], + [ + { time: '10:31', dest: 'Gatwick Airport', plat: '1', status: 'Delayed', cls: 'delayed' }, + { time: '10:45', dest: 'London Bridge', plat: '3', status: 'On Time', cls: 'on-time' }, + { time: '11:02', dest: 'East Croydon', plat: '2', status: 'On Time', cls: 'on-time' }, + { time: '11:14', dest: 'London Victoria', plat: '2', status: 'On Time', cls: 'on-time' }, + { time: '11:28', dest: 'Three Bridges', plat: '4', status: 'Cancelled', cls: 'cancelled'}, + ], + ]; + + /* ── Clock ── */ + function startClocks() { + var clocks = document.querySelectorAll('#transit-clock'); + if (!clocks.length) return; + + function updateClock() { + var now = new Date(); + var hh = String(now.getHours()).padStart(2, '0'); + var mm = String(now.getMinutes()).padStart(2, '0'); + var ss = String(now.getSeconds()).padStart(2, '0'); + var str = hh + ':' + mm + ':' + ss; + for (var i = 0; i < clocks.length; i++) clocks[i].textContent = str; + } + updateClock(); + setInterval(updateClock, 1000); + } + + /* ── Flip helpers ── */ + function flipCells(rowEl, newDest) { + var flapEls = rowEl.querySelectorAll('.transit-flap'); + var chars = newDest.split(''); + + /* Extend or shrink the flap container to match new length */ + var destCell = rowEl.querySelector('.transit-cell--dest'); + if (!destCell) return; + + /* Animate existing flaps, create/remove extras */ + var i; + for (i = 0; i < chars.length; i++) { + var ch = chars[i] === ' ' ? '\u00a0' : chars[i]; + if (i < flapEls.length) { + /* Animate existing */ + (function (el, character) { + el.classList.add('is-flipping'); + setTimeout(function () { + el.textContent = character; + el.classList.remove('is-flipping'); + }, 125); + })(flapEls[i], ch); + } else { + /* Append new flap */ + var newFlap = document.createElement('span'); + newFlap.className = 'transit-flap is-flipping'; + newFlap.textContent = ch; + destCell.appendChild(newFlap); + setTimeout(function (el) { + el.classList.remove('is-flipping'); + }, 125, newFlap); + } + } + /* Remove surplus flaps */ + for (i = chars.length; i < flapEls.length; i++) { + (function (el) { + el.classList.add('is-flipping'); + setTimeout(function () { el.parentNode && el.parentNode.removeChild(el); }, 250); + })(flapEls[i]); + } + } + + function applyRow(rowEl, departure) { + var timeEl = rowEl.querySelector('.transit-cell--time'); + var platEl = rowEl.querySelector('.transit-cell--plat'); + var statusEl = rowEl.querySelector('.transit-cell--status'); + + if (timeEl) timeEl.textContent = departure.time; + if (platEl) platEl.textContent = departure.platform || departure.plat; + if (statusEl) { + statusEl.textContent = departure.status; + statusEl.className = 'transit-cell transit-cell--status transit-status--' + departure.cls; + } + flipCells(rowEl, departure.dest); + } + + function cycleBoard(stage, dataIdx) { + var rows = stage.querySelectorAll('.transit-row'); + var set = DATA_SETS[dataIdx % DATA_SETS.length]; + + for (var i = 0; i < Math.min(rows.length, set.length); i++) { + /* Stagger each row by 180ms */ + (function (row, dep) { + setTimeout(function () { applyRow(row, dep); }, i * 180); + })(rows[i], set[i]); + } + } + + function initBoard(stage) { + var state = { idx: 0, timer: null, paused: false }; + + function advance() { + if (state.paused) return; + state.idx++; + cycleBoard(stage, state.idx); + } + + function startTimer() { + if (state.timer) return; + state.timer = setInterval(advance, CYCLE_MS); + } + + function stopTimer() { + clearInterval(state.timer); + state.timer = null; + } + + if ('IntersectionObserver' in window) { + new IntersectionObserver(function (entries) { + entries.forEach(function (e) { + state.paused = !e.isIntersecting; + e.isIntersecting ? startTimer() : stopTimer(); + }); + }, { rootMargin: '200px', threshold: 0.05 }).observe(stage); + } + + startTimer(); + } + + function boot() { + startClocks(); + var stages = document.querySelectorAll('.transit-stage'); + if (!stages.length) return; + for (var i = 0; i < stages.length; i++) { + if (stages[i]._transitAnim) continue; + stages[i]._transitAnim = true; + initBoard(stages[i]); + } + } + + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', boot); + } else { + boot(); + } +})(); diff --git a/theme/blocks/index.php b/theme/blocks/index.php index 72e11d4..8756e24 100644 --- a/theme/blocks/index.php +++ b/theme/blocks/index.php @@ -576,6 +576,15 @@ add_action('init', function () { 'cameraAnim' => ['type' => 'boolean', 'default' => false], 'neverGoesDark' => ['type' => 'boolean', 'default' => false], 'brandedAnim' => ['type' => 'boolean', 'default' => false], + 'hospitalityAnim' => ['type' => 'boolean', 'default' => false], + 'retailAnim' => ['type' => 'boolean', 'default' => false], + 'corporateAnim' => ['type' => 'boolean', 'default' => false], + 'educationAnim' => ['type' => 'boolean', 'default' => false], + 'outdoorAnim' => ['type' => 'boolean', 'default' => false], + 'liveDataAnim' => ['type' => 'boolean', 'default' => false], + 'healthcareAnim' => ['type' => 'boolean', 'default' => false], + 'transitAnim' => ['type' => 'boolean', 'default' => false], + 'fitnessAnim' => ['type' => 'boolean', 'default' => false], 'galleryIds' => ['type' => 'array', 'default' => [], 'items' => ['type' => 'number']], ], 'supports' => $block_supports, @@ -2062,6 +2071,355 @@ function oribi_render_platform_row($a) $visual_html = $bd; $visual_cls = 'platform-visual has-branded'; } + elseif (!empty($a['retailAnim'])) { + /* ── Retail Sign: TV cycling 3 promo slides ── */ + $ra = '
'; // retail-stage + + $visual_html = $ra; + $visual_cls = 'platform-visual has-retail'; + } + elseif (!empty($a['corporateAnim'])) { + /* ── Corporate: Meeting room door panel ── */ + $ca = ''; // corp-stage + + $visual_html = $ca; + $visual_cls = 'platform-visual has-corporate'; + } + elseif (!empty($a['educationAnim'])) { + /* ── Education: Campus schedule board ── */ + $ea = ''; // edu-stage + + $visual_html = $ea; + $visual_cls = 'platform-visual has-education'; + } + elseif (!empty($a['outdoorAnim'])) { + /* ── Outdoor Marketplace: wide board cycling 2 slides ── */ + $oa = ''; // outdoor-stage + + $visual_html = $oa; + $visual_cls = 'platform-visual has-outdoor'; + } + elseif (!empty($a['liveDataAnim'])) { + /* ── Live Data: Operations centre KPI board ── */ + $la = ''; // ld-stage + + $visual_html = $la; + $visual_cls = 'platform-visual has-live-data'; + } + elseif (!empty($a['healthcareAnim'])) { + /* ── Healthcare: Queue management display ── */ + $hca = ''; // hc-stage + + $visual_html = $hca; + $visual_cls = 'platform-visual has-healthcare'; + } + elseif (!empty($a['transitAnim'])) { + /* ── Transit: Split-flap departure board ── */ + $ta = ''; // transit-stage + + $visual_html = $ta; + $visual_cls = 'platform-visual has-transit'; + } + elseif (!empty($a['fitnessAnim'])) { + /* ── Fitness: Class schedule with live capacity bar ── */ + $fa = ''; // fit-stage + + $visual_html = $fa; + $visual_cls = 'platform-visual has-fitness'; + } elseif (!empty($a['hospitalityAnim'])) { /* ── Hospitality Sign: Rotating Menu (Breakfast, Lunch, Dinner) ── */ $ha = '