diff --git a/pages/about.php b/pages/about.php
index 38a5e04..c5e2a30 100644
--- a/pages/about.php
+++ b/pages/about.php
@@ -1,30 +1,36 @@
+
+return <<<'ORIBI_SYNC_CONTENT'
-
+
+
-
+
-
-
+
+
+
+
-
+
+
+
+
+
@@ -33,3 +39,4 @@
+ORIBI_SYNC_CONTENT;
diff --git a/pages/contact.php b/pages/contact.php
index 988145c..38a8c3e 100644
--- a/pages/contact.php
+++ b/pages/contact.php
@@ -1,20 +1,22 @@
-
-
+return <<<'ORIBI_SYNC_CONTENT'
+
+
+
+
+
+
-
-
+
+
@@ -26,3 +28,4 @@
+ORIBI_SYNC_CONTENT;
diff --git a/pages/demo.php b/pages/demo.php
index eb9627a..8bf6f72 100644
--- a/pages/demo.php
+++ b/pages/demo.php
@@ -1,25 +1,31 @@
-
-
+return <<<'ORIBI_SYNC_CONTENT'
+
+
+
+
-
+
+
+
-
-
+
+
+
+
+
+ORIBI_SYNC_CONTENT;
diff --git a/pages/design.php b/pages/design.php
new file mode 100644
index 0000000..9e61fc7
--- /dev/null
+++ b/pages/design.php
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ORIBI_SYNC_CONTENT;
diff --git a/pages/devices.php b/pages/devices.php
index a1d6ca9..8a8cde4 100644
--- a/pages/devices.php
+++ b/pages/devices.php
@@ -1,27 +1,31 @@
+
+return <<<'ORIBI_SYNC_CONTENT'
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -30,10 +34,30 @@
-
+
+
+
+
+
+
Pre-Configured OTS Players
+
Every player device ordered through OTS arrives pre-configured and already paired with your Command Center. Plug in power and HDMI, connect to your network, and your screens are ready to publish.
+
+
+
Bring Your Own Player (BYO)
+
Already have compatible media players? We can onboard BYO hardware and connect it to your Command Center. Our team will confirm compatibility requirements and provide setup guidance before rollout.
+
+
+
+
+
+
+
+
+
+ORIBI_SYNC_CONTENT;
diff --git a/pages/faq.php b/pages/faq.php
index 1e58473..fa063e2 100644
--- a/pages/faq.php
+++ b/pages/faq.php
@@ -1,37 +1,46 @@
-
-
-
+return <<<'ORIBI_SYNC_CONTENT'
+
+
+
+
+
+
-
+
+
-
-
+
+
+
+
+
-
+
+
+
+
-
+
+ORIBI_SYNC_CONTENT;
diff --git a/pages/features.php b/pages/features.php
index c689349..702abe9 100644
--- a/pages/features.php
+++ b/pages/features.php
@@ -1,33 +1,51 @@
-
-
-
-
-
+return <<<'ORIBI_SYNC_CONTENT'
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -39,10 +57,25 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ORIBI_SYNC_CONTENT;
diff --git a/pages/home.php b/pages/home.php
index 87d2ad3..b2f101b 100644
--- a/pages/home.php
+++ b/pages/home.php
@@ -6,14 +6,16 @@
*/
return <<<'ORIBI_SYNC_CONTENT'
-
+
-
-
+
+
+
+
-
+
diff --git a/pages/pricing.php b/pages/pricing.php
index 62c5d54..60407d1 100644
--- a/pages/pricing.php
+++ b/pages/pricing.php
@@ -9,22 +9,22 @@ return <<<'ORIBI_SYNC_CONTENT'
-
+
-
+
-
+
-
-
+
+
-
+
-
+
diff --git a/pages/resources.php b/pages/resources.php
index 6bd2b91..950a884 100644
--- a/pages/resources.php
+++ b/pages/resources.php
@@ -1,13 +1,12 @@
-
+
+return <<<'ORIBI_SYNC_CONTENT'
+
@@ -40,3 +39,4 @@
+ORIBI_SYNC_CONTENT;
diff --git a/pages/solutions.php b/pages/solutions.php
index e702a4e..7ac9587 100644
--- a/pages/solutions.php
+++ b/pages/solutions.php
@@ -1,20 +1,24 @@
+
+return <<<'ORIBI_SYNC_CONTENT'
-
+
+
-
-
+
+
+
+
+
+
@@ -22,10 +26,14 @@
-
-
-
-
+
+
+
+
+
+
+
-
+
+ORIBI_SYNC_CONTENT;
diff --git a/theme/assets/css/main.css b/theme/assets/css/main.css
index 518c377..d87a104 100644
--- a/theme/assets/css/main.css
+++ b/theme/assets/css/main.css
@@ -5,11 +5,11 @@
/* ── 1. CSS Variables ───────────────────────────────────────── */
:root,
[data-theme="light"] {
- /* ── Light palette - British Racing Green + Monochrome ── */
- --color-primary: var(--wp--preset--color--primary, #004225);
- --color-primary-dk: var(--wp--preset--color--primary-dk, #002E1A);
- --color-primary-lt: var(--wp--preset--color--primary-lt, #E8F5E9);
- --color-primary-rgb: 0,66,37;
+ /* ── Light palette - Orange Primary + Green Accent ── */
+ --color-primary: var(--wp--preset--color--primary, #D83302);
+ --color-primary-dk: var(--wp--preset--color--primary-dk, #A22702);
+ --color-primary-lt: var(--wp--preset--color--primary-lt, #FFF0EB);
+ --color-primary-rgb: 216,51,2;
--color-accent: var(--wp--preset--color--accent, #4CAF50);
--color-accent-dk: var(--wp--preset--color--accent-dk, #388E3C);
--color-accent-lt: var(--wp--preset--color--accent-lt, #E8F5E9);
@@ -52,10 +52,10 @@
/* ── Dark Mode ────────────────────────────────────────────── */
[data-theme="dark"] {
- --color-primary: var(--wp--custom--dark--primary, #4CAF50);
- --color-primary-dk: var(--wp--custom--dark--primary-dk, #004225);
- --color-primary-lt: var(--wp--custom--dark--primary-lt, rgba(0,66,37,.15));
- --color-primary-rgb: 76,175,80;
+ --color-primary: var(--wp--custom--dark--primary, #FF6B3D);
+ --color-primary-dk: var(--wp--custom--dark--primary-dk, #D83302);
+ --color-primary-lt: var(--wp--custom--dark--primary-lt, rgba(216,51,2,.15));
+ --color-primary-rgb: 255,107,61;
--color-accent: var(--wp--custom--dark--accent, #66BB6A);
--color-accent-dk: var(--wp--custom--dark--accent-dk, #388E3C);
--color-accent-lt: var(--wp--custom--dark--accent-lt, rgba(76,175,80,.12));
@@ -97,6 +97,25 @@ img, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; transition: color var(--transition); }
a:hover { color: var(--color-primary); }
+/* ── Scroll-reveal animation classes ───────────────────────── */
+.scroll-hidden {
+ opacity: 0 !important;
+ transform: translateY(24px) !important;
+ /* Prevent transition: all on card elements from animating the hide,
+ which would cause a visible fade-out flicker and race conditions
+ with IntersectionObserver — especially after Gutenberg re-saves
+ inject inline styles onto the block element. */
+ transition: none !important;
+}
+.scroll-visible {
+ opacity: 1;
+ transform: translateY(0);
+ /* !important ensures this wins over transition: all on .oribi-card
+ (same selector specificity, but .oribi-card appears later in the
+ stylesheet and would otherwise override this). */
+ transition: opacity .5s ease, transform .5s ease !important;
+}
+
/* Smooth theme transition */
body,
.site-header,
@@ -104,9 +123,15 @@ body,
.pricing-card,
.contact-form-wrap,
.platform-visual,
+.platform-text h3,
+.platform-text p,
.form-group input,
.form-group textarea,
-.form-group select { transition: background var(--transition), color var(--transition), border-color var(--transition), box-shadow var(--transition); }
+.form-group select,
+.comparison-table-wrap,
+.comparison-table thead th,
+.comparison-table tbody td,
+.comparison-group-row td { transition: background var(--transition), color var(--transition), border-color var(--transition), box-shadow var(--transition); }
ul { list-style: none; }
button { font-family: inherit; cursor: pointer; border: none; background: none; }
@@ -258,9 +283,6 @@ p:last-child { margin-bottom: 0; }
backdrop-filter: blur(8px);
}
-.site-header.scrolled .logo-text { color: var(--color-heading); }
-.site-header.scrolled .nav-menu a { color: var(--header-scrolled-text); }
-
.header-inner {
display: flex;
align-items: center;
@@ -273,8 +295,9 @@ p:last-child { margin-bottom: 0; }
display: flex;
align-items: center;
flex-shrink: 0;
- max-height: 60px;
+ max-height: 80px;
overflow: hidden;
+ gap: 1.25rem;
}
.site-logo a { display: flex; align-items: center; }
.custom-logo-link { display: flex; align-items: center; }
@@ -282,10 +305,10 @@ p:last-child { margin-bottom: 0; }
.custom-logo-link img,
.custom-logo,
.header-inner img {
- max-height: 60px !important;
+ max-height: 80px !important;
width: auto !important;
height: auto !important;
- max-width: 220px !important;
+ max-width: 260px !important;
display: block !important;
object-fit: contain;
}
@@ -296,12 +319,14 @@ p:last-child { margin-bottom: 0; }
letter-spacing: -.01em;
transition: color var(--transition);
}
-.logo-text strong { font-weight: 800; color: var(--color-accent); }
+.logo-text strong { font-weight: 800; color: var(--color-primary); margin-right: .25em; }
-/* When header is over light background (inner pages) */
-.page-header-light .site-header { background: var(--color-bg); box-shadow: var(--shadow-sm); }
-.page-header-light .logo-text { color: var(--color-heading); }
-.page-header-light .nav-menu a { color: var(--color-text); }
+/* When header is over a light hero (set by JS) — unscrolled only */
+.site-header.over-light-hero:not(.scrolled) .nav-menu a { color: var(--color-text); }
+.site-header.over-light-hero:not(.scrolled) .nav-menu a:hover,
+.site-header.over-light-hero:not(.scrolled) .nav-menu .current-menu-item > a { color: var(--color-primary); }
+.site-header.over-light-hero:not(.scrolled) .logo-text { color: var(--color-heading); }
+.site-header.over-light-hero:not(.scrolled) .nav-toggle span { background: var(--color-heading); }
/* Nav */
.site-nav { margin-left: auto; }
@@ -318,12 +343,12 @@ p:last-child { margin-bottom: 0; }
padding-bottom: 2px;
}
-/* Light mode: nav text over hero needs to be dark */
-[data-theme="light"] .nav-menu a { color: var(--color-text); }
-[data-theme="light"] .nav-menu a:hover,
-[data-theme="light"] .nav-menu .current-menu-item > a { color: var(--color-primary); }
-[data-theme="light"] .logo-text { color: var(--color-heading); }
-[data-theme="light"] .nav-toggle span { background: var(--color-heading); }
+/* Scrolled: switch to theme-appropriate text on solid bg */
+.site-header.scrolled .nav-menu a { color: var(--header-scrolled-text); }
+.site-header.scrolled .nav-menu a:hover,
+.site-header.scrolled .nav-menu .current-menu-item > a { color: var(--color-primary); }
+.site-header.scrolled .logo-text { color: var(--color-heading); }
+.site-header.scrolled .nav-toggle span { background: var(--color-heading); }
.nav-menu a::after {
content: '';
position: absolute;
@@ -339,10 +364,6 @@ p:last-child { margin-bottom: 0; }
.nav-menu a:hover::after,
.nav-menu .current-menu-item > a::after { width: 100%; }
-.site-header.scrolled .nav-menu a { color: var(--header-scrolled-text); }
-.site-header.scrolled .nav-menu a:hover,
-.site-header.scrolled .nav-menu .current-menu-item > a { color: var(--color-primary); }
-
/* ── Dropdown sub-menu ─────────────────────────────────────── */
.nav-menu > li {
position: relative;
@@ -472,7 +493,6 @@ p:last-child { margin-bottom: 0; }
border-radius: 2px;
transition: all var(--transition);
}
-.site-header.scrolled .nav-toggle span { background: var(--color-heading); }
.nav-toggle.open span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.open span:nth-child(2) { opacity: 0; }
.nav-toggle.open span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
@@ -486,8 +506,16 @@ p:last-child { margin-bottom: 0; }
top: 0; left: 0; right: 0; bottom: 0;
background: var(--color-dark);
z-index: 99;
+ overflow: hidden;
+ }
+ .site-nav.open .nav-menu {
padding: 5rem 2rem 2rem;
+ height: 100vh;
overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ }
+ body.menu-open {
+ overflow: hidden;
}
.site-nav.open .nav-menu {
flex-direction: column;
@@ -560,7 +588,7 @@ p:last-child { margin-bottom: 0; }
animation: dc-breathe 8s ease-in-out infinite;
pointer-events: none;
display: block;
- will-change: transform;
+ will-change: filter;
}
.hero-overlay {
@@ -1957,7 +1985,7 @@ p:last-child { margin-bottom: 0; }
.platform-row.reverse .platform-text { order: 2; }
.platform-row.reverse .platform-visual { order: 1; }
-.platform-text h3 { font-size: 1.5rem; margin-bottom: 1rem; }
+.platform-text h3 { font-size: 1.5rem; margin-bottom: 1rem; color: var(--color-heading); }
.platform-text p { color: var(--color-text-muted); }
.platform-visual {
@@ -2061,6 +2089,7 @@ p:last-child { margin-bottom: 0; }
border: none !important;
border-radius: 0;
aspect-ratio: unset;
+ min-height: 300px;
padding: 0;
overflow: visible;
position: relative;
@@ -2135,6 +2164,91 @@ p:last-child { margin-bottom: 0; }
animation: da-scan 3s linear infinite;
pointer-events: none;
}
+
+.da-promo {
+ position: absolute;
+ inset: 0;
+ z-index: 1;
+ padding: 6% 7%;
+ display: flex;
+ flex-direction: column;
+ gap: 6%;
+}
+
+.da-promo__top {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.da-promo__dot {
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ background: #f97316;
+ box-shadow: 0 0 6px rgba(249,115,22,.55);
+ animation: da-dot-pulse 2.8s ease-in-out infinite;
+}
+
+.da-promo__brand {
+ width: 40%;
+ height: 5px;
+ border-radius: 999px;
+ background: linear-gradient(90deg, rgba(249,115,22,.95), rgba(251,191,36,.75));
+}
+
+.da-promo__hero {
+ height: 30%;
+ border-radius: 4px;
+ background:
+ linear-gradient(160deg, rgba(2,132,199,.38), rgba(15,23,42,.08) 58%),
+ linear-gradient(115deg, rgba(249,115,22,.42), rgba(249,115,22,.08) 62%);
+}
+
+.da-promo__row {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.da-promo__line {
+ display: block;
+ height: 4px;
+ border-radius: 999px;
+ background: rgba(241,245,249,.70);
+}
+
+.da-promo__line--lg { width: 56%; }
+.da-promo__line--md { width: 46%; }
+.da-promo__line--sm { width: 24%; background: rgba(74,222,128,.72); }
+.da-promo__line--xs { width: 19%; background: rgba(249,115,22,.72); }
+
+.da-promo__ticker {
+ margin-top: auto;
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ animation: da-ticker 6.5s linear infinite;
+}
+
+.da-promo__chip {
+ width: 34%;
+ height: 8px;
+ border-radius: 999px;
+ background: linear-gradient(90deg, rgba(74,222,128,.72), rgba(56,189,248,.72));
+ flex: 0 0 auto;
+}
+
+@keyframes da-dot-pulse {
+ 0%, 100% { transform: scale(1); opacity: .92; }
+ 50% { transform: scale(1.22); opacity: 1; }
+}
+
+@keyframes da-ticker {
+ 0% { transform: translateX(0); }
+ 50% { transform: translateX(-8%); }
+ 100% { transform: translateX(0); }
+}
/* Device label */
.da-label {
display: block;
@@ -2385,6 +2499,9 @@ p:last-child { margin-bottom: 0; }
.da-vwall .da-panel:nth-child(2) .da-screen::after { animation-delay: -0.75s; }
.da-vwall .da-panel:nth-child(3) .da-screen::after { animation-delay: -1.5s; }
.da-vwall .da-panel:nth-child(4) .da-screen::after { animation-delay: -2.25s; }
+.da-vwall .da-panel:nth-child(2) .da-promo { filter: hue-rotate(32deg); }
+.da-vwall .da-panel:nth-child(3) .da-promo { filter: hue-rotate(-18deg); }
+.da-vwall .da-panel:nth-child(4) .da-promo { filter: hue-rotate(58deg); }
/* ── Responsive scale-down ─────────────────────── */
@media (max-width: 900px) {
.da-device { transform: translate(-50%,-50%) scale(0.76); }
@@ -2399,6 +2516,8 @@ p:last-child { margin-bottom: 0; }
@media (prefers-reduced-motion: reduce) {
.da-device { transition: none; }
.da-screen::after { animation: none; }
+ .da-promo__dot,
+ .da-promo__ticker { animation: none; }
}
/* ── 10c. TV Stick Plug Animation ──────────────────────────── */
@@ -2411,6 +2530,10 @@ p:last-child { margin-bottom: 0; }
overflow: visible;
position: relative;
font-size: inherit;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ align-self: center;
}
.ts-stage {
position: relative;
@@ -2419,6 +2542,9 @@ p:last-child { margin-bottom: 0; }
display: flex;
align-items: center;
justify-content: center;
+ /* Offset center leftward to account for the stick protruding on the right,
+ so the TV+stick combo appears visually centered in the column */
+ padding-right: 90px;
}
/* ── TV ── */
.ts-tv {
@@ -2428,8 +2554,8 @@ p:last-child { margin-bottom: 0; }
position: relative;
}
.ts-tv__body {
- width: 320px;
- height: 188px;
+ width: 400px;
+ height: 235px;
background: #111;
border: 4px solid #111;
border-radius: 6px 6px 4px 4px;
@@ -2487,6 +2613,266 @@ p:last-child { margin-bottom: 0; }
40% { filter: brightness(1.25); }
100% { filter: brightness(1); }
}
+/* ── Promotional slides inside screen ── */
+.ts-slides {
+ position: absolute;
+ inset: 0;
+ opacity: 0;
+ transition: opacity 0.6s ease;
+ z-index: 1;
+}
+.ts-stage.is-playing .ts-slides { opacity: 1; }
+.ts-slide {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 12%;
+ opacity: 0;
+ transition: opacity 0.7s ease;
+}
+.ts-slide.is-active { opacity: 1; }
+
+/* ═══════════════════════════════════════════════════════════
+ Slide 1 — Menu Board
+ ═══════════════════════════════════════════════════════════ */
+.ts-slide--menu {
+ background: linear-gradient(170deg, #1a1206 0%, #0d0a04 100%);
+ padding: 8%;
+}
+.ts-menu { width: 100%; height: 100%; display: flex; flex-direction: column; }
+.ts-menu__header {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ margin-bottom: 6px;
+ padding-bottom: 4px;
+ border-bottom: 1px solid rgba(255,200,100,0.25);
+}
+.ts-menu__logo {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: #e6a730;
+ flex-shrink: 0;
+}
+.ts-menu__title {
+ width: 50%;
+ height: 5px;
+ background: rgba(255,220,150,0.8);
+ border-radius: 1px;
+}
+.ts-menu__cols {
+ display: flex;
+ gap: 10px;
+ flex: 1;
+}
+.ts-menu__col {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.ts-menu__cat {
+ width: 55%;
+ height: 4px;
+ background: #e6a730;
+ border-radius: 1px;
+ margin-bottom: 1px;
+}
+.ts-menu__item {
+ display: flex;
+ align-items: center;
+ gap: 2px;
+}
+.ts-menu__name {
+ width: 40%;
+ height: 3px;
+ background: rgba(255,255,255,0.6);
+ border-radius: 1px;
+ flex-shrink: 0;
+}
+.ts-menu__dots {
+ flex: 1;
+ height: 0;
+ border-bottom: 1px dotted rgba(255,255,255,0.18);
+}
+.ts-menu__price {
+ width: 14%;
+ height: 3px;
+ background: rgba(255,220,150,0.7);
+ border-radius: 1px;
+ flex-shrink: 0;
+}
+
+/* ═══════════════════════════════════════════════════════════
+ Slide 2 — Wayfinding Sign
+ ═══════════════════════════════════════════════════════════ */
+.ts-slide--wayfind {
+ background: linear-gradient(170deg, #0c1a2e 0%, #081220 100%);
+ padding: 8%;
+}
+.ts-wf { width: 100%; height: 100%; display: flex; flex-direction: column; }
+.ts-wf__header {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 8px;
+ padding-bottom: 5px;
+ border-bottom: 1px solid rgba(74,222,128,0.2);
+}
+.ts-wf__building {
+ width: 60%;
+ height: 5px;
+ background: rgba(255,255,255,0.7);
+ border-radius: 1px;
+}
+.ts-wf__rows {
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+ flex: 1;
+ justify-content: center;
+}
+.ts-wf__row {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ padding: 3px 4px;
+ background: rgba(255,255,255,0.04);
+ border-radius: 2px;
+}
+.ts-wf__arrow {
+ width: 0;
+ height: 0;
+ flex-shrink: 0;
+}
+.ts-wf__arrow--left {
+ border-top: 3px solid transparent;
+ border-bottom: 3px solid transparent;
+ border-right: 5px solid #4ade80;
+}
+.ts-wf__arrow--right {
+ border-top: 3px solid transparent;
+ border-bottom: 3px solid transparent;
+ border-left: 5px solid #4ade80;
+}
+.ts-wf__arrow--up {
+ border-left: 3px solid transparent;
+ border-right: 3px solid transparent;
+ border-bottom: 5px solid #4ade80;
+}
+.ts-wf__label {
+ height: 3px;
+ background: rgba(255,255,255,0.55);
+ border-radius: 1px;
+ flex: 1;
+}
+.ts-wf__label--w1 { max-width: 60%; }
+.ts-wf__label--w2 { max-width: 45%; }
+.ts-wf__label--w3 { max-width: 70%; }
+.ts-wf__label--w4 { max-width: 50%; }
+.ts-wf__floor {
+ width: 14px;
+ height: 8px;
+ background: rgba(74,222,128,0.15);
+ border: 1px solid rgba(74,222,128,0.3);
+ border-radius: 2px;
+ flex-shrink: 0;
+ margin-left: auto;
+}
+
+/* ═══════════════════════════════════════════════════════════
+ Slide 3 — Schedule / Timetable
+ ═══════════════════════════════════════════════════════════ */
+.ts-slide--sched {
+ background: linear-gradient(170deg, #111827 0%, #0a0f1a 100%);
+ padding: 8%;
+}
+.ts-sched { width: 100%; height: 100%; display: flex; flex-direction: column; }
+.ts-sched__header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 6px;
+ padding-bottom: 4px;
+ border-bottom: 1px solid rgba(74,222,128,0.2);
+}
+.ts-sched__title {
+ width: 35%;
+ height: 5px;
+ background: rgba(255,255,255,0.75);
+ border-radius: 1px;
+}
+.ts-sched__date {
+ width: 20%;
+ height: 4px;
+ background: rgba(255,255,255,0.3);
+ border-radius: 1px;
+}
+.ts-sched__table {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ flex: 1;
+}
+.ts-sched__hrow,
+.ts-sched__row {
+ display: flex;
+ gap: 3px;
+}
+.ts-sched__hrow {
+ margin-bottom: 2px;
+}
+.ts-sched__hcell {
+ flex: 1;
+ height: 3px;
+ background: rgba(255,255,255,0.25);
+ border-radius: 1px;
+}
+.ts-sched__hcell:first-child { flex: 0.5; }
+.ts-sched__row {
+ align-items: stretch;
+}
+.ts-sched__time {
+ flex: 0.5;
+ height: 10px;
+ display: flex;
+ align-items: center;
+}
+.ts-sched__time::before {
+ content: '';
+ width: 80%;
+ height: 3px;
+ background: rgba(255,255,255,0.3);
+ border-radius: 1px;
+}
+.ts-sched__cell {
+ flex: 1;
+ height: 10px;
+ background: rgba(255,255,255,0.04);
+ border-radius: 2px;
+ border: 1px solid rgba(255,255,255,0.06);
+}
+.ts-sched__event {
+ flex: 1;
+ height: 10px;
+ border-radius: 2px;
+}
+.ts-sched__event--a {
+ background: rgba(74,222,128,0.25);
+ border: 1px solid rgba(74,222,128,0.4);
+}
+.ts-sched__event--b {
+ background: rgba(96,165,250,0.25);
+ border: 1px solid rgba(96,165,250,0.4);
+}
+.ts-sched__event--c {
+ background: rgba(251,191,36,0.25);
+ border: 1px solid rgba(251,191,36,0.4);
+}
/* HDMI port on back-right of TV */
.ts-tv__port {
position: absolute;
@@ -2515,7 +2901,7 @@ p:last-child { margin-bottom: 0; }
.ts-tv__feet {
display: flex;
justify-content: space-between;
- width: 180px;
+ width: 224px;
}
.ts-tv__foot {
width: 12px;
@@ -2529,15 +2915,15 @@ p:last-child { margin-bottom: 0; }
position: absolute;
right: -20px;
top: 50%;
- transform: translateY(-50%) translateX(80px);
+ transform: translateY(-50%) translateX(80px) scaleX(-1);
display: flex;
align-items: center;
opacity: 0;
z-index: 2;
}
.ts-stick__body {
- width: 68px;
- height: 26px;
+ width: 84px;
+ height: 32px;
background: linear-gradient(180deg, #f5f5f5, #e0e0e0);
border: 1px solid #ccc;
border-radius: 5px;
@@ -2575,8 +2961,8 @@ p:last-child { margin-bottom: 0; }
}
/* HDMI connector */
.ts-stick__connector {
- width: 14px;
- height: 10px;
+ width: 18px;
+ height: 14px;
background: linear-gradient(180deg, #888, #666);
border-radius: 0 2px 2px 0;
margin-left: -1px;
@@ -2588,8 +2974,8 @@ p:last-child { margin-bottom: 0; }
position: absolute;
left: 2px;
top: 2px;
- width: 6px;
- height: 6px;
+ width: 8px;
+ height: 8px;
background: #555;
border-radius: 1px;
}
@@ -2598,30 +2984,32 @@ p:last-child { margin-bottom: 0; }
animation: ts-slide-in 1.4s cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
}
@keyframes ts-slide-in {
- 0% { opacity: 0; transform: translateY(-50%) translateX(80px); }
- 20% { opacity: 1; transform: translateY(-50%) translateX(60px); }
- 70% { transform: translateY(-50%) translateX(8px); }
- 85% { transform: translateY(-50%) translateX(12px); }
- 100% { opacity: 1; transform: translateY(-50%) translateX(6px); }
+ 0% { opacity: 0; transform: translateY(-50%) translateX(80px) scaleX(-1); }
+ 20% { opacity: 1; transform: translateY(-50%) translateX(60px) scaleX(-1); }
+ 70% { transform: translateY(-50%) translateX(8px) scaleX(-1); }
+ 85% { transform: translateY(-50%) translateX(12px) scaleX(-1); }
+ 100% { opacity: 1; transform: translateY(-50%) translateX(6px) scaleX(-1); }
}
/* Responsive scale-down */
@media (max-width: 900px) {
- .ts-tv__body { width: 260px; height: 152px; }
- .ts-tv__feet { width: 140px; }
- .ts-stick__body { width: 56px; height: 22px; }
+ .ts-tv__body { width: 320px; height: 188px; }
+ .ts-tv__feet { width: 178px; }
+ .ts-stick__body { width: 68px; height: 26px; }
+ .ts-stage { padding-right: 72px; }
}
@media (max-width: 640px) {
- .ts-tv__body { width: 200px; height: 118px; }
- .ts-tv__feet { width: 110px; }
- .ts-stick__body { width: 46px; height: 18px; }
- .ts-stick__connector { width: 10px; height: 8px; }
- .ts-stick__body::before { top: 4px; left: 6px; width: 20px; height: 8px; }
+ .ts-tv__body { width: 240px; height: 142px; }
+ .ts-tv__feet { width: 134px; }
+ .ts-stick__body { width: 52px; height: 20px; }
+ .ts-stick__connector { width: 12px; height: 10px; }
+ .ts-stick__body::before { top: 4px; left: 6px; width: 22px; height: 10px; }
.ts-stick__led { width: 3px; height: 3px; right: 5px; }
+ .ts-stage { padding-right: 56px; }
}
@media (prefers-reduced-motion: reduce) {
.ts-stage .ts-stick {
opacity: 1;
- transform: translateY(-50%) translateX(6px);
+ transform: translateY(-50%) translateX(6px) scaleX(-1);
}
.ts-stage.is-animating .ts-stick { animation: none; }
.ts-stage.is-plugged .ts-tv__screen { animation: none; }
@@ -2658,15 +3046,20 @@ p:last-child { margin-bottom: 0; }
100% { transform: translateY(var(--p-ty, -100vh)) translateX(var(--p-tx, 40px)) scale(var(--p-scale-end, 0.3)); opacity: 0; }
}
+@keyframes glow-appear {
+ from { opacity: 0; filter: blur(80px); transform: translate(-50%, -50%) scale(0.2); }
+ to { opacity: 0.65; filter: blur(22px); transform: translate(-50%, -50%) scale(0.85); }
+}
+
@keyframes glow-drift {
- 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.35; }
- 15% { transform: translate(-20%, -30%) scale(1.15); opacity: 0.45; }
- 30% { transform: translate(-65%, -70%) scale(0.9); opacity: 0.3; }
- 45% { transform: translate(-80%, -40%) scale(1.1); opacity: 0.5; }
- 60% { transform: translate(-30%, -75%) scale(0.95); opacity: 0.35; }
- 75% { transform: translate(-70%, -25%) scale(1.2); opacity: 0.45; }
- 90% { transform: translate(-40%, -60%) scale(1.05); opacity: 0.4; }
- 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.35; }
+ 0% { transform: translate(-50%, -50%) scale(0.85); opacity: 0.6; }
+ 15% { transform: translate(-20%, -30%) scale(1.35); opacity: 0.75; }
+ 30% { transform: translate(-65%, -70%) scale(0.65); opacity: 0.5; }
+ 45% { transform: translate(-80%, -40%) scale(1.45); opacity: 0.8; }
+ 60% { transform: translate(-30%, -75%) scale(0.7); opacity: 0.55; }
+ 75% { transform: translate(-70%, -25%) scale(1.5); opacity: 0.75; }
+ 90% { transform: translate(-40%, -60%) scale(0.8); opacity: 0.65; }
+ 100% { transform: translate(-50%, -50%) scale(0.85); opacity: 0.6; }
}
/* Particle container */
@@ -2706,14 +3099,16 @@ p:last-child { margin-bottom: 0; }
position: absolute;
top: 50%;
left: 50%;
- width: 700px;
- height: 700px;
+ width: 520px;
+ height: 520px;
border-radius: 50%;
- background: radial-gradient(circle, rgba(var(--color-primary-rgb), 0.18) 0%, rgba(var(--color-primary-rgb), 0.06) 50%, transparent 70%);
+ background: radial-gradient(circle, rgba(var(--color-primary-rgb), 0.32) 0%, rgba(var(--color-primary-rgb), 0.14) 45%, rgba(var(--color-primary-rgb), 0.04) 70%, transparent 90%);
z-index: 1;
pointer-events: none;
- filter: blur(40px);
- animation: glow-drift 20s ease-in-out infinite;
+ filter: blur(22px);
+ animation:
+ glow-appear 0.45s cubic-bezier(0.16, 1, 0.3, 1) forwards,
+ glow-drift 20s 0.45s ease-in-out infinite;
}
/* Animated hero layout - centered single-column content */
@@ -2745,10 +3140,32 @@ p:last-child { margin-bottom: 0; }
justify-content: center;
}
+/* Keep secondary CTA visible on light homepage hero */
+.hero-animated .btn-ghost {
+ border-color: rgba(var(--color-primary-rgb), .35);
+ color: var(--color-text);
+ background: rgba(255,255,255,.55);
+}
+
+.hero-animated .btn-ghost:hover {
+ border-color: rgba(var(--color-primary-rgb), .6);
+ background: rgba(var(--color-primary-rgb), .08);
+ color: var(--color-text);
+}
+
.hero-animated__content .hero-stats {
justify-content: center;
}
+/* Homepage flow: avoid oversized gap before use-cases section */
+.hero-animated {
+ min-height: auto;
+}
+
+.hero-animated + .use-cases-section {
+ padding-top: clamp(2rem, 4vw, 3.5rem);
+}
+
.hero-stats--three {
display: flex;
gap: 3rem;
@@ -2769,12 +3186,14 @@ p:last-child { margin-bottom: 0; }
.hero-particle,
.hero-animated__glow {
animation: none;
- opacity: var(--p-opacity, 0.2);
+ opacity: 0.6;
+ transform: translate(-50%, -50%) scale(0.85);
+ filter: blur(22px);
}
}
@media (max-width: 768px) {
- .hero-animated__glow { width: 400px; height: 400px; }
+ .hero-animated__glow { width: 340px; height: 340px; }
.hero-animated__inner { padding-block: 7rem 4rem; }
.hero-stats--three { gap: 1.5rem; flex-wrap: wrap; justify-content: center; }
}
@@ -2938,6 +3357,44 @@ p:last-child { margin-bottom: 0; }
.cta-banner h2 { color: #fff; margin-bottom: 1rem; }
.cta-banner p { color: rgba(255,255,255,.85); margin-bottom: 2rem; font-size: 1.1rem; }
+.devices-split-card {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ border-radius: var(--radius-xl);
+ overflow: hidden;
+ border: 1px solid var(--color-border);
+ background: var(--card-bg);
+}
+
+.devices-split-card__panel {
+ padding: clamp(1.5rem, 3vw, 2.5rem);
+}
+
+.devices-split-card__panel h3 {
+ margin-bottom: .85rem;
+}
+
+.devices-split-card__panel p {
+ color: var(--color-text-muted);
+ line-height: 1.75;
+}
+
+.devices-split-card__panel--brand {
+ background: var(--color-primary);
+ color: var(--color-bg);
+}
+
+.devices-split-card__panel--brand h3,
+.devices-split-card__panel--brand p {
+ color: inherit;
+}
+
+@media (max-width: 768px) {
+ .devices-split-card {
+ grid-template-columns: 1fr;
+ }
+}
+
/* ── 15. Footer ────────────────────────────────────────────── */
.site-footer {
background: #111111;
@@ -3108,14 +3565,18 @@ p:last-child { margin-bottom: 0; }
.comparison-feature-col { min-width: 220px; }
.comparison-feature-name { color: var(--color-text); }
.comparison-group-row td {
- background: var(--color-bg-alt);
+ background: var(--color-primary);
font-weight: 700;
- font-size: .85rem;
+ font-size: .82rem;
text-transform: uppercase;
- letter-spacing: .05em;
- color: var(--color-primary);
+ letter-spacing: .08em;
+ color: #fff;
text-align: left !important;
- padding: .75rem 1.25rem;
+ padding: .85rem 1.25rem;
+ border-bottom-color: var(--color-primary) !important;
+}
+.comparison-group-row td:first-child {
+ border-left: 4px solid var(--color-accent);
}
.comparison-yes {
color: var(--color-accent);
@@ -3247,7 +3708,7 @@ p:last-child { margin-bottom: 0; }
[data-theme="dark"] .hero-animated { background: #0D0D0D; }
[data-theme="dark"] .page-hero-animated { background: #0D0D0D; }
[data-theme="dark"] .hero-animated__glow {
- background: radial-gradient(circle, rgba(var(--color-primary-rgb), 0.22) 0%, rgba(var(--color-primary-rgb), 0.08) 50%, transparent 70%);
+ background: radial-gradient(circle, rgba(var(--color-primary-rgb), 0.40) 0%, rgba(var(--color-primary-rgb), 0.18) 45%, rgba(var(--color-primary-rgb), 0.06) 70%, transparent 90%);
}
[data-theme="dark"] .site-footer { background: #0D0D0D; }
@@ -3255,7 +3716,7 @@ p:last-child { margin-bottom: 0; }
[data-theme="dark"] .site-nav.open { background: #111111; }
[data-theme="dark"] .logo-text { color: #F5F5F5; }
-[data-theme="dark"] .logo-text strong { color: var(--color-accent); }
+[data-theme="dark"] .logo-text strong { color: var(--color-primary); }
[data-theme="dark"] .nav-menu a { color: rgba(255,255,255,.8); }
[data-theme="dark"] .nav-menu a:hover,
@@ -3271,6 +3732,16 @@ p:last-child { margin-bottom: 0; }
border-color: rgba(255,255,255,.25);
}
+[data-theme="dark"] .hero-animated .btn-ghost {
+ color: #fff;
+ background: transparent;
+}
+
+[data-theme="dark"] .hero-animated .btn-ghost:hover {
+ background: rgba(255,255,255,.1);
+ color: #fff;
+}
+
[data-theme="dark"] .platform-visual:not(.has-img):not(.has-dashboard) {
background: var(--color-bg-alt);
border-color: var(--color-border);
@@ -3354,6 +3825,9 @@ p:last-child { margin-bottom: 0; }
Photo camera (left) + product scene (centre) + VHS camcorder on tripod (right)
══════════════════════════════════════════════════════════════════════════════ */
.platform-visual.has-camera {
+ --cam-cycle: 9s;
+ --cam-rec-cycle: 1.4s;
+ --cam-lens-cycle: 4s;
background: none !important;
border: none !important;
border-radius: 0;
@@ -3372,7 +3846,7 @@ p:last-child { margin-bottom: 0; }
flex-direction: row;
align-items: center;
justify-content: center;
- gap: 12px;
+ gap: 6px;
padding-bottom: 4px;
}
@@ -3392,7 +3866,7 @@ p:last-child { margin-bottom: 0; }
background-size: 18px 18px;
}
-/* ── Shared subject shapes ── */
+/* ── Rotating product items: shoe, food, laptop ── */
.cam-subject {
position: absolute;
inset: 0;
@@ -3401,29 +3875,77 @@ p:last-child { margin-bottom: 0; }
justify-content: center;
opacity: 0;
}
-.cam-subject::before {
+.cam-subject::before,
+.cam-subject::after {
content: '';
- display: block;
- border-radius: 8px;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
}
-.cam-subject--1 { animation: cam-subject-1 9s ease-in-out infinite; }
-.cam-subject--1::before {
- width: 40px; height: 58px;
- background: linear-gradient(135deg, #064e3b 0%, #4ade80 100%);
- box-shadow: 0 0 18px rgba(74,222,128,.4);
+
+.cam-subject--shoe { animation: cam-subject-1 var(--cam-cycle) ease-in-out infinite; }
+.cam-subject--shoe::before {
+ width: 76px;
+ height: 28px;
+ border-radius: 16px 20px 10px 14px;
+ background: linear-gradient(145deg, #312e81 0%, #4f46e5 45%, #818cf8 100%);
+ box-shadow:
+ 0 0 14px rgba(129,140,248,.25),
+ inset 0 -2px 0 rgba(0,0,0,.22),
+ inset 0 2px 0 rgba(255,255,255,.18);
}
-.cam-subject--2 { animation: cam-subject-2 9s ease-in-out infinite; }
-.cam-subject--2::before {
- width: 32px; height: 68px;
- background: linear-gradient(160deg, #78350f 0%, #fbbf24 100%);
- border-radius: 6px 6px 12px 12px;
- box-shadow: 0 0 18px rgba(251,191,36,.35);
+.cam-subject--shoe::after {
+ width: 80px;
+ height: 8px;
+ border-radius: 999px;
+ background: #e5e7eb;
+ transform: translate(-50%, calc(-50% + 13px));
+ box-shadow: inset 0 -1px 0 rgba(0,0,0,.2);
}
-.cam-subject--3 { animation: cam-subject-3 9s ease-in-out infinite; }
-.cam-subject--3::before {
- width: 74px; height: 50px;
- background: linear-gradient(135deg, #1e1b4b 0%, #818cf8 100%);
- box-shadow: 0 0 18px rgba(129,140,248,.35);
+
+.cam-subject--food { animation: cam-subject-2 var(--cam-cycle) ease-in-out infinite; }
+.cam-subject--food::before {
+ width: 68px;
+ height: 46px;
+ border-radius: 22px 22px 14px 14px;
+ background:
+ linear-gradient(to bottom,
+ #fbbf24 0 34%,
+ #65a30d 34% 43%,
+ #7c2d12 43% 60%,
+ #f59e0b 60% 100%);
+ box-shadow:
+ 0 0 14px rgba(251,191,36,.28),
+ inset 0 1px 0 rgba(255,255,255,.35);
+}
+.cam-subject--food::after {
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background: rgba(255,255,255,.26);
+ transform: translate(calc(-50% - 14px), calc(-50% - 10px));
+}
+
+.cam-subject--laptop { animation: cam-subject-3 var(--cam-cycle) ease-in-out infinite; }
+.cam-subject--laptop::before {
+ width: 74px;
+ height: 44px;
+ border-radius: 6px;
+ background:
+ linear-gradient(165deg, #0f172a 0%, #1e293b 100%);
+ border: 2px solid #94a3b8;
+ box-shadow:
+ 0 0 16px rgba(148,163,184,.25),
+ inset 0 0 0 2px rgba(15,23,42,.7);
+}
+.cam-subject--laptop::after {
+ width: 90px;
+ height: 10px;
+ border-radius: 4px;
+ background: linear-gradient(180deg, #d1d5db, #9ca3af);
+ transform: translate(-50%, calc(-50% + 28px));
+ box-shadow: inset 0 1px 0 rgba(255,255,255,.5);
}
/* Flash overlay */
@@ -3433,7 +3955,7 @@ p:last-child { margin-bottom: 0; }
background: #fff;
opacity: 0;
pointer-events: none;
- animation: cam-flash-pulse 9s linear infinite;
+ animation: cam-flash-pulse var(--cam-cycle) linear infinite;
}
/* CRT scanlines from the video cam */
.cam-vid-overlay {
@@ -3482,7 +4004,7 @@ p:last-child { margin-bottom: 0; }
top: 2px; left: 4px; right: 4px; bottom: 2px;
background: #c8c870;
border-radius: 1px;
- animation: pc-flash-glow 9s linear infinite;
+ animation: pc-flash-glow var(--cam-cycle) linear infinite;
}
/* Top strip */
.pc-top {
@@ -3506,7 +4028,7 @@ p:last-child { margin-bottom: 0; }
border-radius: 50%;
border: 2px solid var(--color-border);
box-shadow: 0 0 0 1px rgba(255,255,255,.15), inset 0 1px 0 rgba(255,255,255,.1);
- animation: pc-shutter 9s linear infinite;
+ animation: pc-shutter var(--cam-cycle) linear infinite;
transform-origin: center;
}
.pc-viewfinder {
@@ -3594,9 +4116,9 @@ p:last-child { margin-bottom: 0; }
height: 38px;
border-radius: 1px;
}
-.pc-print--1 { left: 0; top: 0; transform-origin: bottom center; animation: pc-print-1 9s linear infinite; }
-.pc-print--2 { left: 18px; top: 0; transform-origin: bottom center; animation: pc-print-2 9s linear infinite; }
-.pc-print--3 { left: 36px; top: 0; transform-origin: bottom center; animation: pc-print-3 9s linear infinite; }
+.pc-print--1 { left: 0; top: 0; transform-origin: bottom center; animation: pc-print-1 var(--cam-cycle) linear infinite; }
+.pc-print--2 { left: 18px; top: 0; transform-origin: bottom center; animation: pc-print-2 var(--cam-cycle) linear infinite; }
+.pc-print--3 { left: 36px; top: 0; transform-origin: bottom center; animation: pc-print-3 var(--cam-cycle) linear infinite; }
.pc-print--1 .pc-print__img { background: linear-gradient(135deg, #064e3b, #4ade80); }
.pc-print--2 .pc-print__img { background: linear-gradient(160deg, #78350f, #fbbf24); }
.pc-print--3 .pc-print__img { background: linear-gradient(135deg, #1e1b4b, #818cf8); }
@@ -3645,18 +4167,18 @@ p:last-child { margin-bottom: 0; }
background: var(--color-bg-alt);
border: 1px solid var(--color-border);
border-top: 1px solid rgba(255,255,255,.12);
- border-radius: 0 4px 4px 0;
+ border-radius: 4px 0 0 4px;
position: relative;
display: flex;
align-items: center;
overflow: visible;
box-shadow: inset 0 -1px 0 rgba(0,0,0,.3);
}
-/* Lens barrel — extends LEFT toward the scene */
+/* Lens barrel — extends RIGHT */
.vc-lens-barrel {
position: absolute;
- left: -34px;
- top: 50%;
+ right: -34px;
+ top: calc(50% - 1px);
transform: translateY(-50%);
width: 38px; height: 38px;
border-radius: 50%;
@@ -3666,7 +4188,7 @@ p:last-child { margin-bottom: 0; }
display: flex;
align-items: center;
justify-content: center;
- animation: vc-lens-zoom 4s ease-in-out infinite;
+ animation: vc-lens-zoom var(--cam-lens-cycle) ease-in-out infinite;
}
.vc-lens-tip {
width: 26px; height: 26px;
@@ -3705,24 +4227,25 @@ p:last-child { margin-bottom: 0; }
/* REC indicator */
.vc-rec-light {
position: absolute;
- top: 8px; left: 16px;
+ top: 8px;
+ right: 16px;
width: 7px; height: 7px;
border-radius: 50%;
background: #ef4444;
box-shadow: 0 0 8px #ef4444, 0 0 16px rgba(239,68,68,.4);
- animation: vc-rec-blink 1.4s ease-in-out infinite;
+ animation: vc-rec-blink var(--cam-rec-cycle) ease-in-out infinite;
}
-/* Eyepiece — extends RIGHT */
+/* Eyepiece — extends LEFT */
.vc-eyepiece {
position: absolute;
- right: -14px;
+ left: -14px;
top: 50%;
transform: translateY(-50%);
width: 14px; height: 18px;
background: var(--color-bg-alt);
border: 1px solid var(--color-border);
- border-left: none;
- border-radius: 0 4px 4px 0;
+ border-right: none;
+ border-radius: 4px 0 0 4px;
display: flex;
align-items: center;
justify-content: center;
@@ -3738,7 +4261,7 @@ p:last-child { margin-bottom: 0; }
.vc-body::after {
content: '';
position: absolute;
- right: 6px; top: 7px;
+ left: 6px; top: 7px;
width: 28px; height: 34px;
background: rgba(0,0,0,.2);
border: 1px solid var(--color-border);
@@ -3860,12 +4383,20 @@ p:last-child { margin-bottom: 0; }
50% { transform: translateY(-50%) scale(1.08); }
}
+/* ── Responsive scale-down ── */
+@media (max-width: 900px) {
+ .cam-stage { transform: scale(0.85); transform-origin: center center; }
+}
+@media (max-width: 640px) {
+ .cam-stage { transform: scale(0.72); transform-origin: center center; }
+}
+
/* ── Reduced-motion ── */
@media (prefers-reduced-motion: reduce) {
- .cam-subject--2, .cam-subject--3,
+ .cam-subject--food, .cam-subject--laptop,
.cam-flash-overlay,
.pc-print--2, .pc-print--3 { animation: none !important; opacity: 0 !important; }
- .cam-subject--1 { animation: none !important; opacity: 1 !important; }
+ .cam-subject--shoe { animation: none !important; opacity: 1 !important; }
.pc-shutter-btn, .pc-flash-unit::after,
.vc-lens-barrel, .vc-rec-light { animation: none !important; }
.pc-print--1 {
@@ -3874,3 +4405,1444 @@ p:last-child { margin-bottom: 0; }
transform: rotate(-12deg) translateY(0) !important;
}
}
+
+/* ═══════════════════════════════════════════════════════════════════════
+ USE CASES SHOWCASE (uc-*)
+ Four animated circles in a rounded-border track beneath the hero.
+ ═══════════════════════════════════════════════════════════════════════ */
+
+.uc-track {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ gap: 1.5rem;
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-xl, 1.25rem);
+ padding: 2.5rem 3rem;
+ background: var(--color-bg-alt);
+}
+
+.uc-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 1;
+}
+
+.uc-circle {
+ width: 158px;
+ height: 158px;
+ border-radius: 50%;
+ border: 1.5px solid var(--color-border);
+ overflow: hidden;
+ position: relative;
+ background: var(--color-bg);
+ flex-shrink: 0;
+}
+
+.uc-item-body {
+ margin-top: 1.1rem;
+ text-align: center;
+}
+.uc-item-title {
+ font-size: .875rem;
+ font-weight: 600;
+ color: var(--color-heading);
+}
+.uc-item-desc {
+ font-size: .75rem;
+ color: var(--color-muted);
+ margin-top: .3rem;
+ line-height: 1.45;
+ max-width: 160px;
+}
+
+/* ── Shared inner wrapper ─────────────────────────────────────────────── */
+.uc-inner {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 18px;
+ box-sizing: border-box;
+ gap: 6px;
+}
+
+/* ══════════════════════════════════
+ 1 — MENU BOARD
+ ══════════════════════════════════ */
+.uc-inner--menu { gap: 0; padding: 14px 18px; }
+
+.uc-menu-header {
+ width: 100%;
+ height: 16px;
+ border-radius: 3px;
+ background: var(--color-primary);
+ margin-bottom: 10px;
+ flex-shrink: 0;
+}
+.uc-menu-row {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 5px 4px;
+ border-radius: 3px;
+ gap: 6px;
+ flex-shrink: 0;
+}
+.uc-menu-row + .uc-menu-row { margin-top: 4px; }
+
+.uc-menu-divider {
+ width: 100%;
+ height: 1px;
+ background: var(--color-border);
+ margin: 6px 0;
+ flex-shrink: 0;
+}
+.uc-menu-name {
+ height: 7px;
+ flex: 1;
+ border-radius: 3px;
+ background: var(--color-border);
+}
+.uc-menu-name--sm { max-width: 55%; }
+.uc-menu-price {
+ height: 7px;
+ width: 22px;
+ border-radius: 3px;
+ background: var(--color-border);
+ flex-shrink: 0;
+}
+.uc-menu-row--highlight {
+ background: color-mix(in srgb, var(--color-primary) 15%, transparent);
+ animation: uc-menu-highlight 3s ease-in-out infinite;
+}
+.uc-menu-row--highlight .uc-menu-name,
+.uc-menu-row--highlight .uc-menu-price {
+ background: var(--color-primary);
+ animation: uc-menu-price-update 3s ease-in-out infinite;
+}
+
+@keyframes uc-menu-highlight {
+ 0%, 100% { background: color-mix(in srgb, var(--color-primary) 15%, transparent); }
+ 45%, 55% { background: color-mix(in srgb, var(--color-accent) 25%, transparent); }
+}
+@keyframes uc-menu-price-update {
+ 0%, 38% { opacity: 1; }
+ 42% { opacity: 0; }
+ 48% { opacity: 1; }
+ 52% { opacity: 0; }
+ 58%, 100%{ opacity: 1; }
+}
+
+/* ══════════════════════════════════
+ 2 — EVENT DISPLAY
+ ══════════════════════════════════ */
+.uc-inner--event {
+ gap: 0;
+ padding: 16px 18px;
+ position: relative;
+}
+
+.uc-event-header {
+ width: 100%;
+ height: 13px;
+ border-radius: 3px;
+ background: var(--color-border);
+ margin-bottom: 10px;
+ flex-shrink: 0;
+ display: flex;
+ align-items: center;
+ padding: 0 6px;
+ font-size: 9px;
+ font-weight: 700;
+ color: var(--color-text);
+ letter-spacing: 0.5px;
+}
+.uc-event-row {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ flex-shrink: 0;
+}
+.uc-event-row + .uc-event-row { margin-top: 7px; }
+.uc-event-time {
+ height: 10px;
+ width: 28px;
+ border-radius: 2px;
+ background: var(--color-border);
+ flex-shrink: 0;
+ font-size: 7px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--color-muted);
+ font-weight: 600;
+}
+.uc-event-title {
+ height: 14px;
+ flex: 1;
+ border-radius: 3px;
+ background: var(--color-border);
+ position: relative;
+ overflow: hidden;
+ font-size: 8px;
+ display: flex;
+ align-items: center;
+ padding: 0 6px;
+ color: var(--color-muted);
+ font-weight: 500;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+.uc-event-title::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.2) 50%, transparent 100%);
+ transform: translateX(-150%);
+ pointer-events: none;
+}
+.uc-event-title--active {
+ background: var(--color-primary);
+ color: #fff;
+}
+.uc-event-title--accent {
+ background: color-mix(in srgb, var(--color-accent) 55%, var(--color-border));
+ color: var(--color-text);
+}
+.uc-event-title--active::after { animation: uc-event-shimmer 2.2s linear infinite; }
+.uc-event-title--accent::after { animation: uc-event-shimmer 2.2s linear infinite 1.1s; }
+
+.uc-event-cursor {
+ position: absolute;
+ top: 32px;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: var(--color-primary);
+ opacity: .85;
+ pointer-events: none;
+ box-shadow: 0 0 8px rgba(var(--color-primary-rgb), 0.4);
+ animation: uc-event-time-progress 20s linear infinite;
+}
+.uc-event-cursor::before {
+ content: '';
+ position: absolute;
+ left: -6px;
+ top: -4px;
+ width: 12px;
+ height: 10px;
+ background: var(--color-primary);
+ border-radius: 50%;
+ box-shadow: 0 0 8px rgba(var(--color-primary-rgb), 0.6);
+}
+
+@keyframes uc-event-shimmer {
+ 0% { transform: translateX(-150%); }
+ 100% { transform: translateX(250%); }
+}
+@keyframes uc-event-time-progress {
+ 0% { top: 32px; }
+ 100% { top: calc(100% - 10px); }
+}
+
+/* ══════════════════════════════════
+ 3 — OFFICE DASHBOARD
+ ══════════════════════════════════ */
+.uc-inner--dashboard {
+ justify-content: flex-end;
+ padding: 18px 16px 12px;
+}
+.uc-db-bars {
+ display: flex;
+ align-items: stretch;
+ gap: 9px;
+ width: 100%;
+ height: 80px;
+}
+.uc-db-bar {
+ flex: 1;
+ border-radius: 4px 4px 0 0;
+ transform-origin: bottom;
+ transform: scaleY(.55);
+}
+.uc-db-bar--1, .uc-db-bar--3 { background: var(--color-primary); }
+.uc-db-bar--2, .uc-db-bar--4 { background: color-mix(in srgb, var(--color-primary) 45%, var(--color-border)); }
+
+.uc-db-bar--1 { animation: uc-db-scale-1 3s ease-in-out infinite; }
+.uc-db-bar--2 { animation: uc-db-scale-2 3s ease-in-out infinite .4s; }
+.uc-db-bar--3 { animation: uc-db-scale-3 3s ease-in-out infinite .8s; }
+.uc-db-bar--4 { animation: uc-db-scale-4 3s ease-in-out infinite 1.2s; }
+
+.uc-db-baseline {
+ width: 100%;
+ height: 1px;
+ background: var(--color-border);
+ flex-shrink: 0;
+ margin-bottom: 6px;
+}
+.uc-db-labels {
+ display: flex;
+ gap: 9px;
+ width: 100%;
+ flex-shrink: 0;
+}
+.uc-db-lbl {
+ flex: 1;
+ height: 5px;
+ border-radius: 2px;
+ background: var(--color-border);
+ opacity: .6;
+}
+
+@keyframes uc-db-scale-1 {
+ 0%, 100% { transform: scaleY(.55); }
+ 40% { transform: scaleY(.82); }
+ 70% { transform: scaleY(.42); }
+}
+@keyframes uc-db-scale-2 {
+ 0%, 100% { transform: scaleY(.70); }
+ 40% { transform: scaleY(.38); }
+ 70% { transform: scaleY(.78); }
+}
+@keyframes uc-db-scale-3 {
+ 0%, 100% { transform: scaleY(.40); }
+ 40% { transform: scaleY(.68); }
+ 70% { transform: scaleY(.58); }
+}
+@keyframes uc-db-scale-4 {
+ 0%, 100% { transform: scaleY(.62); }
+ 40% { transform: scaleY(.50); }
+ 70% { transform: scaleY(.88); }
+}
+
+/* ══════════════════════════════════
+ 4 — WAYFINDING
+ ══════════════════════════════════ */
+.uc-inner--wayfinding { padding: 0; }
+
+/* Corridor lines */
+.uc-wf-corridor {
+ position: absolute;
+ background: var(--color-border);
+}
+.uc-wf-corridor--h {
+ height: 8px;
+ width: 70%;
+ top: 50%;
+ left: 15%;
+ transform: translateY(-50%);
+ border-radius: 2px;
+}
+.uc-wf-corridor--v {
+ width: 8px;
+ height: 54%;
+ left: 50%;
+ top: 23%;
+ transform: translateX(-50%);
+ border-radius: 2px;
+}
+
+/* Rooms */
+.uc-wf-room {
+ position: absolute;
+ border: 1.5px solid var(--color-border);
+ border-radius: 3px;
+ background: var(--color-bg-alt);
+}
+.uc-wf-room--1 { width: 32px; height: 28px; top: 17%; left: 17%; }
+.uc-wf-room--2 { width: 28px; height: 26px; top: 17%; right: 17%; }
+.uc-wf-room--3 { width: 30px; height: 28px; bottom: 17%; left: 50%; transform: translateX(-50%); }
+
+/* Location dot */
+.uc-wf-dot {
+ position: absolute;
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ background: var(--color-primary);
+ top: 50%;
+ left: 36%;
+ transform: translate(-50%, -50%);
+}
+.uc-wf-dot::after {
+ content: '';
+ position: absolute;
+ inset: -5px;
+ border-radius: 50%;
+ border: 1.5px solid var(--color-primary);
+ animation: uc-wf-pulse 2s ease-out infinite;
+}
+
+/* Direction arrow */
+.uc-wf-arrow {
+ position: absolute;
+ top: 50%;
+ left: 36%;
+ transform: translate(-50%, calc(-50% - 18px));
+ width: 0;
+ height: 0;
+ border-left: 6px solid transparent;
+ border-right: 6px solid transparent;
+ border-bottom: 11px solid var(--color-accent);
+ animation: uc-wf-arrow-bob 1.8s ease-in-out infinite;
+}
+
+@keyframes uc-wf-pulse {
+ 0% { transform: scale(1); opacity: .7; }
+ 70% { transform: scale(2.4); opacity: 0; }
+ 100% { transform: scale(1); opacity: 0; }
+}
+@keyframes uc-wf-arrow-bob {
+ 0%, 100% { transform: translate(-50%, calc(-50% - 18px)); }
+ 50% { transform: translate(-50%, calc(-50% - 24px)); }
+}
+
+/* ── Responsive ──────────────────────────────────────────── */
+@media (max-width: 900px) {
+ .uc-track { flex-wrap: wrap; justify-content: center; gap: 2rem; padding: 2.5rem 2rem; }
+ .uc-item { width: calc(50% - 1rem); flex: none; }
+}
+@media (max-width: 500px) {
+ .uc-track { padding: 2rem 1.5rem; }
+ .uc-item { width: 100%; }
+ .uc-item-desc { max-width: none; }
+}
+
+/* ── Reduced-motion overrides ────────────────────────────── */
+@media (prefers-reduced-motion: reduce) {
+ .uc-menu-row--highlight,
+ .uc-menu-row--highlight .uc-menu-name,
+ .uc-menu-row--highlight .uc-menu-price,
+ .uc-event-title--active::after,
+ .uc-event-title--accent::after,
+ .uc-event-cursor,
+ .uc-db-bar--1, .uc-db-bar--2, .uc-db-bar--3, .uc-db-bar--4,
+ .uc-wf-dot::after,
+ .uc-wf-arrow { animation: none !important; }
+ /* Static bar heights when animation is off */
+ .uc-db-bar--1 { transform: scaleY(.55) !important; }
+ .uc-db-bar--2 { transform: scaleY(.70) !important; }
+ .uc-db-bar--3 { transform: scaleY(.40) !important; }
+ .uc-db-bar--4 { transform: scaleY(.62) !important; }
+}
+
+/* ═══════════════════════════════════════════════════════════
+ NEVER GOES DARK ANIMATION (.platform-visual.has-ngd)
+ Sequence (10 s loop):
+ 0 – 30 % : Connected – dots travel player → cloud, cloud green
+ 30 – 45 % : Breaking – line turns red, × icon fades in
+ 45 – 72 % : Offline – × visible, ✓ on player, TV still plays
+ 72 – 85 % : Reconnect – × fades, dots resume, cloud back to green
+ 85 – 100% : Connected – steady state before next loop
+ ═══════════════════════════════════════════════════════════ */
+
+/* ── Wrapper overrides ─────────────────────────────────────── */
+.platform-visual.has-ngd {
+ background: none !important;
+ border: none !important;
+ border-radius: 0;
+ aspect-ratio: unset;
+ padding: 0;
+ overflow: visible;
+ position: relative;
+ font-size: inherit;
+}
+
+/* ── Stage ─────────────────────────────────────────────────── */
+.ngd-stage {
+ position: relative;
+ width: 100%;
+ max-width: 560px;
+ aspect-ratio: 1/1;
+ margin: 0 auto;
+}
+
+/* ── TV ─────────────────────────────────────────────────────── */
+.ngd-tv {
+ position: absolute;
+ left: 20px;
+ top: 72px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+.ngd-tv__body {
+ width: 400px;
+ height: 235px;
+ background: #111;
+ border: 4px solid #111;
+ border-radius: 6px 6px 4px 4px;
+ outline: 1px solid #000;
+ padding: 3px;
+ display: flex;
+ align-items: stretch;
+ position: relative;
+ box-shadow: 0 14px 48px rgba(0,0,0,.55);
+}
+/* HDMI port stub on right side */
+.ngd-tv__port {
+ position: absolute;
+ right: -6px;
+ top: 110px;
+ width: 6px;
+ height: 14px;
+ background: #1a1a1a;
+ border: 1px solid #000;
+ border-left: none;
+ border-radius: 0 2px 2px 0;
+}
+.ngd-tv__port::before {
+ content: '';
+ position: absolute;
+ left: 0;
+ top: 2px;
+ width: 3px;
+ height: 8px;
+ background: #333;
+ border-radius: 0 1px 1px 0;
+}
+.ngd-tv__screen {
+ --ngd-menu-scale-x: 1.8182;
+ --ngd-menu-scale-y: 1.4506;
+ width: 100%;
+ height: 100%;
+ border-radius: 2px;
+ position: relative;
+ overflow: hidden;
+ background:
+ repeating-linear-gradient(
+ 180deg,
+ transparent, transparent 3px,
+ rgba(0,0,0,.10) 3px, rgba(0,0,0,.10) 4px
+ ),
+ linear-gradient(135deg, #0c1016 0%, #151c28 60%, #0c1016 100%);
+}
+/* Scanline sweep */
+.ngd-tv__screen::after {
+ content: '';
+ position: absolute;
+ left: 0; width: 100%; height: 3px;
+ background: linear-gradient(90deg, transparent, rgba(74,222,128,.22), transparent);
+ animation: da-scan 4s linear infinite;
+ pointer-events: none;
+}
+/* TV feet */
+.ngd-tv__feet {
+ display: flex;
+ justify-content: space-between;
+ width: 224px;
+}
+.ngd-tv__foot {
+ width: 12px;
+ height: 8px;
+ background: #111;
+ border: 1px solid #000;
+ border-radius: 0 0 4px 4px;
+}
+
+/* ── Menu board content (always playing) ───────────────────── */
+.ngd-menu {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 220px;
+ height: 162px;
+ transform: scale(var(--ngd-menu-scale-x), var(--ngd-menu-scale-y));
+ transform-origin: top left;
+ display: flex;
+ flex-direction: column;
+ padding: 7px 6px 4px;
+ gap: 3px;
+}
+.ngd-menu__hd {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ padding-bottom: 4px;
+ border-bottom: 1px solid rgba(255,200,80,.18);
+ flex-shrink: 0;
+}
+.ngd-menu__logo {
+ width: 9px; height: 9px;
+ background: #4CAF50;
+ border-radius: 50%;
+ flex-shrink: 0;
+}
+.ngd-menu__ttl {
+ flex: 1; height: 5px;
+ background: rgba(255,200,80,.45);
+ border-radius: 2px;
+ max-width: 55px;
+}
+.ngd-menu__cols {
+ display: flex;
+ gap: 6px;
+ flex: 1;
+}
+.ngd-menu__col {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.ngd-menu__cat {
+ height: 4px;
+ background: rgba(76,175,80,.5);
+ border-radius: 1px;
+ margin-bottom: 1px;
+}
+.ngd-menu__row {
+ display: flex;
+ align-items: center;
+ gap: 3px;
+ padding: 2px 3px;
+ border-radius: 2px;
+ transition: background .3s;
+}
+.ngd-menu__row--hl {
+ background: rgba(76,175,80,.14);
+ animation: ngd-hl-pulse 1.75s ease-in-out infinite;
+}
+.ngd-menu__name {
+ flex: 1; height: 4px;
+ background: rgba(255,255,255,.25);
+ border-radius: 1px;
+}
+.ngd-menu__row--hl .ngd-menu__name {
+ background: rgba(76,175,80,.55);
+}
+.ngd-menu__price {
+ width: 16px; height: 4px;
+ background: rgba(255,200,80,.4);
+ border-radius: 1px;
+}
+.ngd-menu__row--hl .ngd-menu__price {
+ background: rgba(255,200,80,.7);
+}
+/* Scrolling ticker at bottom */
+.ngd-menu__ticker {
+ height: 6px;
+ background: rgba(76,175,80,.12);
+ border-radius: 1px;
+ overflow: hidden;
+ flex-shrink: 0;
+}
+.ngd-menu__ticker-inner {
+ width: 250%;
+ height: 100%;
+ background: repeating-linear-gradient(
+ 90deg,
+ rgba(76,175,80,.5) 0px, rgba(76,175,80,.5) 30px,
+ transparent 30px, transparent 50px
+ );
+ animation: ngd-ticker 2s linear infinite;
+}
+
+/* ── Player device (stick plugged into TV right-side HDMI port) ── */
+.ngd-player {
+ position: absolute;
+ /* TV: left(20) + border(4) + width(400) + border(4) = 428px */
+ left: 428px;
+ /* TV top(72) + border(4) + port.top(110) + port half-h(7) = 193px
+ stick h=32px → top = 193 − 16 = 177px */
+ top: 177px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+}
+/* HDMI connector plug — left side, inserts into TV port */
+.ngd-player__connector {
+ width: 18px;
+ height: 14px;
+ background: linear-gradient(180deg, #888, #666);
+ border-radius: 2px 0 0 2px;
+ position: relative;
+ box-shadow: 0 1px 3px rgba(0,0,0,.3);
+ flex-shrink: 0;
+ z-index: 1;
+}
+.ngd-player__connector::before {
+ content: '';
+ position: absolute;
+ right: 2px;
+ top: 2px;
+ width: 8px;
+ height: 8px;
+ background: #555;
+ border-radius: 1px;
+}
+/* Main stick body — white gradient capsule */
+.ngd-player__body {
+ width: 84px;
+ height: 32px;
+ background: linear-gradient(180deg, #f5f5f5, #e0e0e0);
+ border: 1px solid #ccc;
+ border-radius: 0 5px 5px 0;
+ position: relative;
+ box-shadow: 0 2px 8px rgba(0,0,0,.25), inset 0 1px 0 rgba(255,255,255,.6);
+}
+/* Brand logo area subtle inset */
+.ngd-player__body::before {
+ content: '';
+ position: absolute;
+ top: 6px;
+ left: 8px;
+ width: 28px;
+ height: 12px;
+ background: rgba(0,0,0,.04);
+ border-radius: 2px;
+}
+/* LED indicator — right side of body */
+.ngd-player__led {
+ position: absolute;
+ right: 8px;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: #4CAF50;
+ box-shadow: 0 0 6px rgba(76,175,80,.8);
+ animation: ngd-led 5s ease-in-out infinite;
+}
+/* Checkmark badge — visible only during offline phase */
+.ngd-player__check {
+ position: absolute;
+ top: -14px;
+ right: -11px;
+ width: 24px; height: 24px;
+ opacity: 0;
+ transform: scale(0.4);
+ transform-origin: center;
+ animation: ngd-check-show 5s ease-in-out infinite;
+ filter: drop-shadow(0 0 4px rgba(76,175,80,.6));
+}
+
+/* ── Signal wrap (globe + vertical line to player) ─────────── */
+.ngd-signal-wrap {
+ position: absolute;
+ /* body centre X: player left(428) + connector(18) + body half(42) = 488
+ globe width 88px → half = 44 → left = 488 − 44 = 444px */
+ left: 444px;
+ top: 22px;
+ width: 88px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+.ngd-cloud {
+ width: 88px;
+ flex-shrink: 0;
+}
+.ngd-cloud__svg {
+ width: 100%;
+ height: auto;
+ display: block;
+}
+.ngd-cloud__path {
+ stroke: #4CAF50;
+ opacity: .85;
+ animation: ngd-cloud-color 5s ease-in-out infinite;
+}
+/* Vertical signal line */
+.ngd-signal-line {
+ width: 3px;
+ height: 92px;
+ background: rgba(76,175,80,.35);
+ border-radius: 2px;
+ position: relative;
+ overflow: visible;
+ animation: ngd-line-col 5s ease-in-out infinite;
+}
+/* Dots container — hidden during break phase */
+.ngd-signal__dots {
+ position: absolute;
+ inset: 0;
+ overflow: hidden;
+ animation: ngd-dots-vis 5s linear infinite;
+}
+.ngd-signal__dot {
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 5px; height: 5px;
+ border-radius: 50%;
+ background: #4CAF50;
+ box-shadow: 0 0 5px rgba(76,175,80,.8);
+ animation: ngd-dot-up 0.9s ease-in-out infinite;
+}
+.ngd-signal__dot--2 { animation-delay: -0.6s; }
+.ngd-signal__dot--3 { animation-delay: -1.2s; }
+/* Break × badge — centered on line */
+.ngd-signal__break {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%) scale(0);
+ width: 18px; height: 18px;
+ opacity: 0;
+ animation: ngd-break-show 5s ease-in-out infinite;
+ filter: drop-shadow(0 0 4px rgba(239,68,68,.5));
+}
+
+/* ═══════════════════════════════════════════════════════════
+ KEYFRAMES (10 s cycle)
+ ═══════════════════════════════════════════════════════════ */
+
+/* Ticker scroll */
+@keyframes ngd-ticker {
+ from { transform: translateX(0); }
+ to { transform: translateX(-50%); }
+}
+
+/* Highlighted menu row pulsing */
+@keyframes ngd-hl-pulse {
+ 0%, 100% { background: rgba(76,175,80,.14); }
+ 50% { background: rgba(76,175,80,.28); }
+}
+
+/* Player LED: green → amber → red during disconnect → back to green */
+@keyframes ngd-led {
+ 0%, 29% { background: #4CAF50; box-shadow: 0 0 6px rgba(76,175,80,.8); }
+ 33% { background: #f59e0b; box-shadow: 0 0 5px rgba(245,158,11,.6); }
+ 38%, 71% { background: #ef4444; box-shadow: 0 0 4px rgba(239,68,68,.4); }
+ 75% { background: #4CAF50; box-shadow: 0 0 6px rgba(76,175,80,.8); }
+ 100% { background: #4CAF50; box-shadow: 0 0 6px rgba(76,175,80,.8); }
+}
+
+/* Cloud stroke: green → red → green */
+@keyframes ngd-cloud-color {
+ 0%, 29% { stroke: #4CAF50; opacity: .85; }
+ 36%, 71% { stroke: #ef4444; opacity: 1; }
+ 76%, 100% { stroke: #4CAF50; opacity: .85; }
+}
+
+/* Signal line colour */
+@keyframes ngd-line-col {
+ 0%, 29% { background: rgba(76,175,80,.35); }
+ 36%, 71% { background: rgba(239,68,68,.45); }
+ 76%, 100% { background: rgba(76,175,80,.35); }
+}
+
+/* Dots container: visible during connected phases only */
+@keyframes ngd-dots-vis {
+ 0%, 29% { opacity: 1; }
+ 33% { opacity: 0; }
+ 71% { opacity: 0; }
+ 75%, 100% { opacity: 1; }
+}
+
+/* Single dot travelling bottom → top */
+@keyframes ngd-dot-up {
+ 0% { bottom: 1px; opacity: 0; }
+ 8% { opacity: 1; }
+ 85% { opacity: 1; }
+ 100% { bottom: calc(100% - 5px); opacity: 0; }
+}
+
+/* Break × badge: appears when disconnected */
+@keyframes ngd-break-show {
+ 0%, 29% { opacity: 0; transform: translate(-50%,-50%) scale(0); }
+ 38%, 71% { opacity: 1; transform: translate(-50%,-50%) scale(1); }
+ 76%, 100% { opacity: 0; transform: translate(-50%,-50%) scale(0); }
+}
+
+/* Checkmark: appears when offline, confirming local playback */
+@keyframes ngd-check-show {
+ 0%, 44% { opacity: 0; transform: scale(0.4); }
+ 52%, 71% { opacity: 1; transform: scale(1); }
+ 77%, 100% { opacity: 0; transform: scale(0.4); }
+}
+
+/* ── Responsive ─────────────────────────────────────────────── */
+@media (max-width: 640px) {
+ .ngd-stage { max-width: 320px; }
+ /* Scale at 84% (320/380) */
+ .ngd-tv { left: 17px; top: 76px; }
+ .ngd-tv__body { width: 185px; height: 136px; }
+ .ngd-tv__screen { --ngd-menu-scale-x: 0.8409; --ngd-menu-scale-y: 0.8395; }
+ /* port at body midpoint: 136/2 − 7 = 61 */
+ .ngd-tv__port { top: 61px; }
+ .ngd-tv__feet { gap: 60px; }
+ .ngd-tv__foot { width: 24px; }
+ /* TV right: 17+4+185+4=210; port centre-y: 76+4+61+7=148; player top: 148−13=135 */
+ .ngd-player { left: 210px; top: 135px; }
+ .ngd-player__connector { width: 12px; height: 9px; }
+ .ngd-player__body { width: 68px; height: 24px; }
+ .ngd-player__body::before { top: 5px; left: 6px; width: 24px; height: 10px; }
+ .ngd-player__led { width: 3px; height: 3px; right: 6px; }
+ /* body centre-x: 210+12+34=256; globe 72px → half=36 → wrap left=220 */
+ .ngd-signal-wrap { left: 220px; top: 18px; width: 72px; }
+ /* line: wrap.top(18)+globe_h(~52)=70 to player.top(135) → 65px */
+ .ngd-signal-line { height: 65px; }
+}
+
+/* ── Reduced-motion overrides ───────────────────────────────── */
+@media (prefers-reduced-motion: reduce) {
+ .ngd-tv__screen::after,
+ .ngd-menu__ticker-inner,
+ .ngd-menu__row--hl,
+ .ngd-player__led,
+ .ngd-signal__dot,
+ .ngd-signal__dots,
+ .ngd-signal__break,
+ .ngd-cloud__path,
+ .ngd-signal-line,
+ .ngd-player__check { animation: none !important; }
+ /* Static fallback states */
+ .ngd-player__led { background: #4CAF50; box-shadow: 0 0 5px rgba(76,175,80,.6); }
+ .ngd-cloud__path { stroke: #4CAF50; opacity: .8; }
+ .ngd-signal__dots { opacity: 1; }
+}
+
+/* ═══════════════════════════════════════════════════════════
+ BRANDED DISPLAY ANIMATION (.platform-visual.has-branded)
+ Sequence (8 s loop per screen, staggered by 0.5 s):
+ 0 – 25 % : Boot splash — logo fades in centred on dark screen
+ 25 – 40 % : Transition — logo shrinks to header, brand bar grows
+ 40 – 90 % : Content — UI blocks slide in beneath brand header
+ 90 – 100% : Reset — fade out, loop
+ ═══════════════════════════════════════════════════════════ */
+
+/* ── Wrapper overrides ─────────────────────────────────────── */
+.platform-visual.has-branded {
+ background: none !important;
+ border: none !important;
+ border-radius: 0;
+ aspect-ratio: unset;
+ padding: 0;
+ overflow: visible;
+ position: relative;
+ font-size: inherit;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ align-self: center;
+}
+
+/* ── Stage ─────────────────────────────────────────────────── */
+.bd-stage {
+ position: relative;
+ width: 100%;
+ max-width: 500px;
+ aspect-ratio: 4/3;
+ margin: 0 auto;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 22px;
+}
+
+/* ── Shared device styles ─────────────────────────────────── */
+.bd-device {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ position: relative;
+}
+.bd-device__body {
+ background: #111;
+ border: 3px solid #111;
+ border-radius: 5px;
+ outline: 1px solid #000;
+ padding: 2px;
+ display: flex;
+ align-items: stretch;
+ position: relative;
+ box-shadow: 0 10px 32px rgba(0,0,0,.50);
+}
+.bd-device__screen {
+ width: 100%;
+ height: 100%;
+ border-radius: 2px;
+ position: relative;
+ overflow: hidden;
+ background: linear-gradient(135deg, #0c1016 0%, #151c28 60%, #0c1016 100%);
+}
+.bd-device__label {
+ font-size: 10px;
+ color: rgba(255,255,255,.45);
+ margin-bottom: 6px;
+ letter-spacing: .5px;
+ text-transform: uppercase;
+ order: -1;
+}
+
+/* ── Tablet (portrait kiosk) ──────────────────────────────── */
+.bd-device--tablet .bd-device__body {
+ width: 96px;
+ height: 144px;
+ border-radius: 8px;
+}
+.bd-device--tablet .bd-device__screen { border-radius: 4px; }
+.bd-device--tablet { animation-delay: 0s; }
+
+/* ── Wall display (wide landscape) ────────────────────────── */
+.bd-device--wall .bd-device__body {
+ width: 216px;
+ height: 130px;
+}
+.bd-mount {
+ width: 7px;
+ height: 22px;
+ background: #222;
+ margin-top: -1px;
+ border-radius: 0 0 2px 2px;
+}
+.bd-device--wall { animation-delay: 0.5s; }
+
+/* ── Interactive tablet on table ───────────────────────────── */
+.bd-device--interactive .bd-device__body {
+ width: 132px;
+ height: 89px;
+ border-radius: 6px;
+ transform: perspective(400px) rotateX(25deg);
+ transform-origin: bottom center;
+}
+.bd-device--interactive .bd-device__screen { border-radius: 3px; }
+.bd-table {
+ width: 156px;
+ height: 10px;
+ background: linear-gradient(180deg, #2a2a2a, #1a1a1a);
+ border-radius: 3px;
+ margin-top: -2px;
+ box-shadow: 0 4px 12px rgba(0,0,0,.4);
+}
+.bd-device--interactive { animation-delay: 1s; }
+
+/* ── Boot splash overlay ──────────────────────────────────── */
+.bd-splash {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 2;
+ animation: bd-splash 8s ease-in-out infinite;
+}
+.bd-device--wall .bd-splash { animation-delay: 0.5s; }
+.bd-device--interactive .bd-splash { animation-delay: 1s; }
+
+.bd-splash__logo {
+ width: 28px;
+ height: 28px;
+ background: var(--color-primary);
+ border-radius: 6px;
+ box-shadow: 0 0 20px rgba(var(--color-primary-rgb),.5), 0 0 50px rgba(var(--color-primary-rgb),.15);
+ animation: bd-logo-pulse 8s ease-in-out infinite;
+}
+.bd-device--wall .bd-splash__logo {
+ width: 32px;
+ height: 32px;
+ animation-delay: 0.5s;
+}
+.bd-device--interactive .bd-splash__logo {
+ animation-delay: 1s;
+}
+
+/* ── Branded UI chrome ────────────────────────────────────── */
+.bd-ui {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ padding: 0;
+ opacity: 0;
+ z-index: 1;
+ animation: bd-ui-show 8s ease-in-out infinite;
+}
+.bd-device--wall .bd-ui { animation-delay: 0.5s; }
+.bd-device--interactive .bd-ui { animation-delay: 1s; }
+
+/* Brand header bar */
+.bd-ui__header {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 4px 5px;
+ background: rgba(var(--color-primary-rgb),.15);
+ border-bottom: 1px solid rgba(var(--color-primary-rgb),.25);
+ flex-shrink: 0;
+}
+.bd-ui__logo {
+ width: 10px;
+ height: 10px;
+ background: var(--color-primary);
+ border-radius: 3px;
+ flex-shrink: 0;
+}
+.bd-ui__brand-bar {
+ flex: 1;
+ height: 4px;
+ background: rgba(var(--color-primary-rgb),.4);
+ border-radius: 2px;
+ max-width: 50px;
+ animation: bd-bar-grow 8s ease-in-out infinite;
+}
+.bd-device--wall .bd-ui__brand-bar { animation-delay: 0.5s; }
+.bd-device--interactive .bd-ui__brand-bar { animation-delay: 1s; }
+
+/* Content area */
+.bd-ui__content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ padding: 6px 5px;
+ animation: bd-content-slide 8s ease-in-out infinite;
+}
+.bd-device--wall .bd-ui__content { animation-delay: 0.5s; }
+.bd-device--interactive .bd-ui__content { animation-delay: 1s; }
+
+.bd-ui__block {
+ border-radius: 2px;
+}
+.bd-ui__block--txt {
+ height: 4px;
+ background: rgba(255,255,255,.18);
+}
+.bd-ui__block--short {
+ width: 60%;
+}
+.bd-ui__block--img {
+ flex: 1;
+ min-height: 16px;
+ background: linear-gradient(
+ 135deg,
+ rgba(var(--color-primary-rgb),.10) 0%,
+ rgba(var(--color-primary-rgb),.05) 100%
+ );
+ border: 1px solid rgba(var(--color-primary-rgb),.12);
+}
+
+/* ── Promotional content layouts ─────────────────────── */
+.bd-promo {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+}
+
+/* ── Kiosk: Welcome / check-in screen ── */
+.bd-promo--welcome {
+ align-items: center;
+ text-align: center;
+ gap: 4px;
+}
+.bd-promo__hero {
+ width: 100%;
+ flex: 1;
+ min-height: 28px;
+ background: linear-gradient(135deg, rgba(var(--color-primary-rgb),.18) 0%, rgba(var(--color-primary-rgb),.06) 100%);
+ border-radius: 2px;
+}
+.bd-promo__heading {
+ width: 70%;
+ height: 5px;
+ background: rgba(255,255,255,.3);
+ border-radius: 1px;
+}
+.bd-promo__text {
+ width: 85%;
+ height: 3px;
+ background: rgba(255,255,255,.14);
+ border-radius: 1px;
+}
+.bd-promo__btn {
+ width: 45%;
+ height: 8px;
+ background: var(--color-primary);
+ border-radius: 3px;
+ margin-top: 2px;
+}
+
+/* ── Wall display: Sale / featured product ── */
+.bd-promo--sale {
+ gap: 0;
+}
+.bd-promo__cols {
+ display: flex;
+ gap: 5px;
+ flex: 1;
+}
+.bd-promo__visual {
+ flex: 1;
+ background: linear-gradient(160deg, rgba(var(--color-primary-rgb),.20) 0%, rgba(var(--color-primary-rgb),.06) 100%);
+ border-radius: 2px;
+ min-height: 24px;
+}
+.bd-promo__info {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ justify-content: center;
+}
+.bd-promo__badge {
+ width: 28px;
+ height: 6px;
+ background: rgba(239,68,68,.7);
+ border-radius: 2px;
+}
+.bd-promo--sale .bd-promo__heading {
+ width: 90%;
+ height: 4px;
+}
+.bd-promo--sale .bd-promo__text {
+ width: 100%;
+ height: 3px;
+}
+.bd-promo__text--short {
+ width: 65% !important;
+}
+.bd-promo__price {
+ width: 36px;
+ height: 6px;
+ background: rgba(255,200,80,.6);
+ border-radius: 1px;
+ margin-top: 1px;
+}
+
+/* ── Interactive: Touch menu / category grid ── */
+.bd-promo--menu {
+ gap: 3px;
+}
+.bd-promo--menu .bd-promo__heading {
+ width: 55%;
+ height: 4px;
+}
+.bd-promo__grid {
+ flex: 1;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 3px;
+}
+.bd-promo__tile {
+ background: rgba(255,255,255,.06);
+ border-radius: 2px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+.bd-promo__tile-img {
+ flex: 1;
+ background: linear-gradient(135deg, rgba(var(--color-primary-rgb),.14) 0%, rgba(var(--color-primary-rgb),.04) 100%);
+}
+.bd-promo__tile-lbl {
+ height: 4px;
+ margin: 2px 3px;
+ background: rgba(255,255,255,.18);
+ border-radius: 1px;
+}
+
+/* ═══════════════════════════════════════════════════════════
+ KEYFRAMES (8 s cycle)
+ ═══════════════════════════════════════════════════════════ */
+
+/* Splash: visible 0–30%, fades out 30–40%, hidden rest */
+@keyframes bd-splash {
+ 0% { opacity: 0; }
+ 5% { opacity: 1; }
+ 25% { opacity: 1; }
+ 35% { opacity: 0; }
+ 100% { opacity: 0; }
+}
+
+/* Logo pulse glow during splash */
+@keyframes bd-logo-pulse {
+ 0%, 25% { transform: scale(1); box-shadow: 0 0 20px rgba(var(--color-primary-rgb),.5), 0 0 50px rgba(var(--color-primary-rgb),.15); }
+ 12% { transform: scale(1.08); box-shadow: 0 0 28px rgba(var(--color-primary-rgb),.7), 0 0 60px rgba(var(--color-primary-rgb),.25); }
+ 35%, 100% { transform: scale(0.6); opacity: 0; }
+}
+
+/* UI chrome: hidden 0–28%, fades in 28–38%, visible until 88%, fades out */
+@keyframes bd-ui-show {
+ 0%, 28% { opacity: 0; }
+ 38% { opacity: 1; }
+ 88% { opacity: 1; }
+ 96%, 100% { opacity: 0; }
+}
+
+/* Brand bar grows in from 0 width */
+@keyframes bd-bar-grow {
+ 0%, 30% { transform: scaleX(0); transform-origin: left; }
+ 42% { transform: scaleX(1); transform-origin: left; }
+ 88% { transform: scaleX(1); }
+ 96%, 100% { transform: scaleX(0); }
+}
+
+/* Content blocks slide up into view */
+@keyframes bd-content-slide {
+ 0%, 35% { opacity: 0; transform: translateY(10px); }
+ 48% { opacity: 1; transform: translateY(0); }
+ 88% { opacity: 1; transform: translateY(0); }
+ 96%, 100% { opacity: 0; transform: translateY(4px); }
+}
+
+/* ── Responsive ─────────────────────────────────────────────── */
+@media (max-width: 900px) {
+ .bd-stage { max-width: 430px; gap: 14px; }
+ .bd-device--tablet .bd-device__body { width: 76px; height: 114px; }
+ .bd-device--wall .bd-device__body { width: 170px; height: 102px; }
+ .bd-device--interactive .bd-device__body { width: 101px; height: 67px; }
+ .bd-table { width: 120px; }
+}
+@media (max-width: 640px) {
+ .bd-stage { max-width: 340px; gap: 10px; }
+ .bd-device--tablet .bd-device__body { width: 60px; height: 90px; }
+ .bd-device--wall .bd-device__body { width: 138px; height: 83px; }
+ .bd-device--interactive .bd-device__body { width: 83px; height: 55px; }
+ .bd-device__label { font-size: 9px; }
+ .bd-table { width: 98px; height: 7px; }
+}
+
+/* ── Reduced-motion overrides ───────────────────────────────── */
+@media (prefers-reduced-motion: reduce) {
+ .bd-splash,
+ .bd-splash__logo,
+ .bd-ui,
+ .bd-ui__brand-bar,
+ .bd-ui__content { animation: none !important; }
+ /* Static fallback: show branded UI */
+ .bd-splash { opacity: 0; }
+ .bd-ui { opacity: 1; }
+ .bd-ui__brand-bar { transform: scaleX(1); }
+ .bd-ui__content { opacity: 1; transform: translateY(0); }
+}
+
+/* ═══════════════════════════════════════════════════════════════
+ GALLERY TV SLIDESHOW (.platform-visual.has-gallery-tv)
+ ═══════════════════════════════════════════════════════════════ */
+
+.platform-visual.has-gallery-tv {
+ background: none !important;
+ border: none !important;
+ border-radius: 0;
+ aspect-ratio: unset;
+ padding: 0;
+ overflow: visible;
+ box-shadow: none;
+ font-size: inherit;
+}
+
+.gtv-stage {
+ width: 100%;
+ max-width: 520px;
+ margin: 0 auto;
+}
+
+/* TV frame (mirrors dashboard-tv pattern) */
+.gtv-tv {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 100%;
+}
+.gtv-tv__body {
+ width: 100%;
+ background: #111;
+ border: 5px solid #1a1a1a;
+ border-radius: 8px 8px 4px 4px;
+ outline: 2px solid #000;
+ padding: 4px;
+ position: relative;
+ box-shadow:
+ 0 14px 48px rgba(0,0,0,0.6),
+ 0 0 0 1px rgba(255,255,255,0.04),
+ inset 0 1px 0 rgba(255,255,255,0.06);
+}
+.gtv-tv__body::after {
+ content: '\25CF';
+ position: absolute;
+ bottom: -14px;
+ left: 50%;
+ transform: translateX(-50%);
+ font-size: 7px;
+ color: rgba(74,222,128,0.8);
+ filter: drop-shadow(0 0 3px rgba(74,222,128,0.5));
+}
+.gtv-tv__screen {
+ width: 100%;
+ aspect-ratio: 16/9;
+ background: var(--color-bg);
+ border-radius: 2px;
+ overflow: hidden;
+ position: relative;
+}
+.gtv-tv__feet {
+ display: flex;
+ justify-content: space-between;
+ width: 60%;
+ max-width: 300px;
+}
+.gtv-tv__foot {
+ width: 12px;
+ height: 8px;
+ background: #111;
+ border: 1px solid #000;
+ border-radius: 0 0 4px 4px;
+}
+
+/* Slides */
+.gtv-slides {
+ position: relative;
+ width: 100%;
+ height: 100%;
+}
+.gtv-slide {
+ position: absolute;
+ inset: 0;
+ opacity: 0;
+ transition: opacity 0.8s ease;
+}
+.gtv-slide.is-active {
+ opacity: 1;
+}
+.gtv-slide img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+}
+
+/* ── Reduced-motion overrides for gallery TV ── */
+@media (prefers-reduced-motion: reduce) {
+ .gtv-slide {
+ transition: none !important;
+ }
+}
+
+/* ══════════════════════════════════════════════════════════════════════════════
+ VIDEO EDITOR ANIMATOR (.platform-visual.has-video-editor)
+ Laptop frame with dark editor UI, animated timeline playhead and preview.
+ ══════════════════════════════════════════════════════════════════════════════ */
+.platform-visual.has-video-editor {
+ background: none !important;
+ border: none !important;
+ border-radius: 0;
+ aspect-ratio: unset;
+ padding: 0;
+ overflow: visible;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 200px;
+}
+
+.ve-stage {
+ width: 100%;
+ max-width: 560px;
+}
+
+.ve-svg {
+ width: 100%;
+ height: auto;
+ display: block;
+ filter: drop-shadow(0 8px 28px rgba(0, 0, 0, 0.18));
+}
diff --git a/theme/assets/js/industry-animator.js b/theme/assets/js/industry-animator.js
new file mode 100644
index 0000000..45e6ae5
--- /dev/null
+++ b/theme/assets/js/industry-animator.js
@@ -0,0 +1,61 @@
+/**
+ * Gallery TV Slideshow
+ * Cycles through images inside gallery-TV blocks.
+ * Pauses off-screen via IntersectionObserver for performance.
+ * Respects prefers-reduced-motion.
+ */
+(function () {
+ 'use strict';
+
+ var INTERVAL = 4000; // ms between slides
+
+ function boot() {
+ var stages = document.querySelectorAll('[data-gtv-slideshow]');
+ if (!stages.length) return;
+
+ /* Honour reduced-motion – show first slide only */
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
+
+ for (var i = 0; i < stages.length; i++) {
+ initSlideshow(stages[i]);
+ }
+ }
+
+ function initSlideshow(stage) {
+ var slides = stage.querySelectorAll('.gtv-slide');
+ if (slides.length < 2) return;
+
+ var state = { current: 0, paused: false, timer: null };
+
+ /* IntersectionObserver – pause when off-screen */
+ if ('IntersectionObserver' in window) {
+ new IntersectionObserver(function (entries) {
+ for (var j = 0; j < entries.length; j++) {
+ state.paused = !entries[j].isIntersecting;
+ }
+ if (!state.paused && !state.timer) {
+ state.timer = setInterval(function () { advance(slides, state); }, INTERVAL);
+ } else if (state.paused && state.timer) {
+ clearInterval(state.timer);
+ state.timer = null;
+ }
+ }, { rootMargin: '200px', threshold: 0.05 }).observe(stage);
+ }
+
+ /* Start cycling */
+ state.timer = setInterval(function () { advance(slides, state); }, INTERVAL);
+ }
+
+ function advance(slides, state) {
+ if (state.paused) return;
+ slides[state.current].classList.remove('is-active');
+ state.current = (state.current + 1) % slides.length;
+ slides[state.current].classList.add('is-active');
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', boot);
+ } else {
+ boot();
+ }
+})();
diff --git a/theme/assets/js/main.js b/theme/assets/js/main.js
index 91b6773..80f324f 100644
--- a/theme/assets/js/main.js
+++ b/theme/assets/js/main.js
@@ -17,6 +17,19 @@ document.addEventListener('DOMContentLoaded', () => {
window.addEventListener('scroll', () => {
header.classList.toggle('scrolled', window.scrollY > 40);
}, { passive: true });
+
+ /* Detect whether the hero beneath the header has a light background.
+ .hero (homepage) is white in light mode; .page-hero stays dark.
+ Re-evaluate when the theme toggle changes data-theme. */
+ function updateHeroContrast() {
+ const isLight = document.documentElement.getAttribute('data-theme') !== 'dark';
+ const hasLightHero = isLight && document.querySelector('.hero') && !document.querySelector('.page-hero');
+ header.classList.toggle('over-light-hero', !!hasLightHero);
+ }
+ updateHeroContrast();
+ new MutationObserver(updateHeroContrast).observe(document.documentElement, {
+ attributes: true, attributeFilter: ['data-theme']
+ });
}
/* ── Mobile nav toggle ──────────────────────────────────── */
@@ -26,6 +39,7 @@ document.addEventListener('DOMContentLoaded', () => {
toggle.addEventListener('click', () => {
toggle.classList.toggle('open');
nav.classList.toggle('open');
+ document.body.classList.toggle('menu-open');
const expanded = toggle.getAttribute('aria-expanded') === 'true';
toggle.setAttribute('aria-expanded', !expanded);
});
@@ -119,18 +133,33 @@ document.addEventListener('DOMContentLoaded', () => {
/* ── Animate cards on scroll ────────────────────────────── */
const cards = document.querySelectorAll('.oribi-card, .feature-card, .industry-card, .pricing-card, .value-card, .platform-row');
- if (cards.length && 'IntersectionObserver' in window) {
- cards.forEach(c => { c.style.opacity = '0'; c.style.transform = 'translateY(24px)'; c.style.transition = 'opacity .5s ease, transform .5s ease'; });
- const io = new IntersectionObserver((entries) => {
- entries.forEach(entry => {
- if (entry.isIntersecting) {
- entry.target.style.opacity = '1';
- entry.target.style.transform = 'translateY(0)';
- io.unobserve(entry.target);
+ if (cards.length && 'IntersectionObserver' in window &&
+ !window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
+ cards.forEach(c => c.classList.add('scroll-hidden'));
+ /* Use rAF to ensure the class is applied before observing – avoids
+ Safari quirk where elements already in-viewport don't fire. */
+ requestAnimationFrame(() => {
+ const io = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ entry.target.classList.remove('scroll-hidden');
+ entry.target.classList.add('scroll-visible');
+ io.unobserve(entry.target);
+ }
+ });
+ }, { threshold: 0.05, rootMargin: '0px 0px 80px 0px' });
+ cards.forEach(c => io.observe(c));
+ });
+ /* Safety net: reveal any still-hidden elements after 4 s so content
+ is never permanently invisible (e.g. iOS Safari edge-cases). */
+ setTimeout(() => {
+ cards.forEach(c => {
+ if (c.classList.contains('scroll-hidden')) {
+ c.classList.remove('scroll-hidden');
+ c.classList.add('scroll-visible');
}
});
- }, { threshold: 0.1 });
- cards.forEach(c => io.observe(c));
+ }, 4000);
}
});
@@ -685,6 +714,7 @@ document.addEventListener('DOMContentLoaded', () => {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
stages.forEach(function (stage) {
stage.classList.add('is-plugged');
+ startTsSlides(stage);
});
return;
}
@@ -698,6 +728,10 @@ document.addEventListener('DOMContentLoaded', () => {
// Add plugged state after slide-in completes (1.4s)
setTimeout(function () {
stage.classList.add('is-plugged');
+ // Start promotional slide cycling after screen glow (0.9s)
+ setTimeout(function () {
+ startTsSlides(stage);
+ }, 900);
}, 1400);
io.unobserve(stage);
}
@@ -705,4 +739,17 @@ document.addEventListener('DOMContentLoaded', () => {
}, { threshold: 0.3 });
stages.forEach(function (stage) { io.observe(stage); });
}
+
+ function startTsSlides(stage) {
+ var slides = stage.querySelectorAll('.ts-slide');
+ if (!slides.length) return;
+ var current = 0;
+ slides[0].classList.add('is-active');
+ stage.classList.add('is-playing');
+ setInterval(function () {
+ slides[current].classList.remove('is-active');
+ current = (current + 1) % slides.length;
+ slides[current].classList.add('is-active');
+ }, 3000);
+ }
})();
diff --git a/theme/assets/js/video-editor-animator.js b/theme/assets/js/video-editor-animator.js
new file mode 100644
index 0000000..21939f0
--- /dev/null
+++ b/theme/assets/js/video-editor-animator.js
@@ -0,0 +1,110 @@
+/**
+ * Video Editor Timeline Animator
+ * Animates playhead scrubbing across the timeline and video preview crossfades.
+ * Mirrors the structure and conventions of dashboard-animator.js.
+ */
+(function () {
+ 'use strict';
+
+ var DURATION = 10000; // ms for one full playhead sweep (left → right, then loop)
+ var X_MIN = 104; // leftmost playhead centre (SVG units)
+ var X_MAX = 504; // rightmost playhead centre (end of clip area)
+
+ function makeState(svg) {
+ return {
+ svg: svg,
+ playheadLine: svg.querySelector('#ve-playhead-line'),
+ playheadHead: svg.querySelector('#ve-playhead-head'),
+ scene1: svg.querySelector('#ve-scene-1'),
+ scene2: svg.querySelector('#ve-scene-2'),
+ scene3: svg.querySelector('#ve-scene-3'),
+ innerScreen: svg.querySelector('#ve-inner-screen'),
+ timecode: svg.querySelector('#ve-timecode'),
+ scrubPct: 0,
+ lastTime: performance.now(),
+ paused: false
+ };
+ }
+
+ function lerp(a, b, t) { return a + (b - a) * t; }
+
+ function updatePlayhead(st) {
+ var xC = lerp(X_MIN, X_MAX, st.scrubPct);
+ if (st.playheadLine) st.playheadLine.setAttribute('x', (xC - 1).toFixed(1));
+ if (st.playheadHead) st.playheadHead.setAttribute('transform', 'translate(' + xC.toFixed(1) + ',234)');
+ if (st.timecode) {
+ var s = Math.floor(st.scrubPct * 10);
+ st.timecode.textContent = '0:' + (s < 10 ? '0' + s : s);
+ }
+ }
+
+ function updateScenes(st) {
+ var p = st.scrubPct;
+ var o1, o2, o3, fade;
+ if (p < 0.30) {
+ o1 = 1; o2 = 0; o3 = 0;
+ } else if (p < 0.40) {
+ fade = (p - 0.30) / 0.10; o1 = 1 - fade; o2 = fade; o3 = 0;
+ } else if (p < 0.65) {
+ o1 = 0; o2 = 1; o3 = 0;
+ } else if (p < 0.75) {
+ fade = (p - 0.65) / 0.10; o1 = 0; o2 = 1 - fade; o3 = fade;
+ } else {
+ o1 = 0; o2 = 0; o3 = 1;
+ }
+ if (st.scene1) st.scene1.setAttribute('opacity', o1.toFixed(3));
+ if (st.scene2) st.scene2.setAttribute('opacity', o2.toFixed(3));
+ if (st.scene3) st.scene3.setAttribute('opacity', o3.toFixed(3));
+ if (st.innerScreen) {
+ st.innerScreen.setAttribute('fill',
+ p < 0.38 ? 'url(#ve-scr-warm)' :
+ p < 0.72 ? 'url(#ve-scr-cold)' :
+ 'url(#ve-scr-go)'
+ );
+ }
+ }
+
+ function loop(st, now) {
+ if (!st.paused) {
+ var delta = now - st.lastTime;
+ st.lastTime = now;
+ st.scrubPct += delta / DURATION;
+ if (st.scrubPct >= 1) st.scrubPct -= 1;
+ updatePlayhead(st);
+ updateScenes(st);
+ } else {
+ st.lastTime = now; // keep fresh so there is no jump on resume
+ }
+ requestAnimationFrame(function (t) { loop(st, t); });
+ }
+
+ 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.svg);
+ }
+
+ function boot() {
+ var svgs = document.querySelectorAll('.ve-svg');
+ if (!svgs.length) return;
+ if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
+ for (var i = 0; i < svgs.length; i++) {
+ (function (svg) {
+ if (svg._veAnim) return;
+ var st = makeState(svg);
+ svg._veAnim = st;
+ observe(st);
+ requestAnimationFrame(function (t) { loop(st, t); });
+ })(svgs[i]);
+ }
+ }
+
+ if (document.readyState === 'loading') {
+ document.addEventListener('DOMContentLoaded', boot);
+ } else {
+ boot();
+ }
+})();
diff --git a/theme/blocks/editor.js b/theme/blocks/editor.js
index 4fda89c..a8c8bdc 100644
--- a/theme/blocks/editor.js
+++ b/theme/blocks/editor.js
@@ -1170,28 +1170,105 @@ reg('oribi/platform-row', {
parent: ['oribi/platform-section'],
supports: { html: false, reusable: false },
attributes: {
- heading: { type: 'string', default: '' },
- description: { type: 'string', default: '' },
- btnText: { type: 'string', default: 'Learn More' },
- btnUrl: { type: 'string', default: '' },
- visual: { type: 'string', default: '' },
- reversed: { type: 'boolean', default: false },
- imgId: { type: 'number', default: 0 },
- imgUrl: { type: 'string', default: '' },
- imgAlt: { type: 'string', default: '' },
- imgWidth: { type: 'number', default: 300 },
- cameraAnim: { type: 'boolean', default: false },
+ heading: { type: 'string', default: '' },
+ description: { type: 'string', default: '' },
+ btnText: { type: 'string', default: 'Learn More' },
+ btnUrl: { type: 'string', default: '' },
+ visual: { type: 'string', default: '' },
+ reversed: { type: 'boolean', default: false },
+ imgId: { type: 'number', default: 0 },
+ imgUrl: { type: 'string', default: '' },
+ imgAlt: { type: 'string', default: '' },
+ imgWidth: { type: 'number', default: 300 },
+ isDashboard: { type: 'boolean', default: false },
+ deviceAnim: { type: 'boolean', default: false },
+ tvStick: { type: 'boolean', default: false },
+ cameraAnim: { type: 'boolean', default: false },
+ neverGoesDark: { type: 'boolean', default: false },
+ brandedAnim: { type: 'boolean', default: false },
+ galleryIds: { type: 'array', default: [] },
},
edit: function (props) {
var a = props.attributes, s = props.setAttributes;
var imgW = a.imgWidth || 300;
+
+ /* ── Animation HTML strings (mirror PHP render, used via dangerouslySetInnerHTML) ── */
+ var DA_SCREEN = '
';
+ var DA_HTML = '' +
+ '
' +
+ '
' + DA_SCREEN + '
Small Monitor ' +
+ '
' + DA_SCREEN + '
Large Monitor ' +
+ '
' +
+ '
' +
+ '
' + DA_SCREEN + '
' + DA_SCREEN + '
' + DA_SCREEN + '
' + DA_SCREEN + '
Video Wall ' +
+ '
';
+
+ var TS_MI = '';
+ var TS_COL = '';
+ var TS_HTML = '' +
+ '
' +
+ '' +
+ '
' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+
+ var NGD_ROW = '';
+ var NGD_ROWH = '';
+ var NGD_HTML = '' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+
+ var BD_SPLASH = '';
+ var BD_HDR = '';
+ var BD_HTML = '' +
+ '
' +
+ '
' +
+ '
' +
+ '
';
+
+ var DB_HTML = 'Performance API Cache DB Queue Worker Requests/sec Read Write Update Delete Traffic Trend Distribution
';
+
return el(Frag, null,
el(IC, null,
el(PB, { title: 'Row Settings' },
el(TC, { label: 'Visual (emoji)', value: a.visual, onChange: function(v){s({visual:v});} }),
el(TC, { label: 'Button URL', value: a.btnUrl, onChange: function(v){s({btnUrl:v});} }),
el(TG, { label: 'Reversed', checked: !!a.reversed, onChange: function(v){s({reversed:v});} }),
- el(TG, { label: 'Camera Animation', checked: !!a.cameraAnim, onChange: function(v){s({cameraAnim:v});} })
+ el(TG, { label: 'Dashboard Animation', checked: !!a.isDashboard, onChange: function(v){s({isDashboard:v});} }),
+ el(TG, { label: 'Device Animation', checked: !!a.deviceAnim, onChange: function(v){s({deviceAnim:v});} }),
+ el(TG, { label: 'TV Stick Animation', checked: !!a.tvStick, onChange: function(v){s({tvStick:v});} }),
+ el(TG, { label: 'Camera Animation', checked: !!a.cameraAnim, onChange: function(v){s({cameraAnim:v});} }),
+ el(TG, { label: 'Never Goes Dark', checked: !!a.neverGoesDark, onChange: function(v){s({neverGoesDark:v});} }),
+ el(TG, { label: 'Branded Display', checked: !!a.brandedAnim, onChange: function(v){s({brandedAnim:v});} })
+ ),
+ el(PB, { title: 'Gallery TV Slideshow', initialOpen: false },
+ el(MUC, null,
+ el(MU, {
+ onSelect: function(media) {
+ s({ galleryIds: media.map(function(m){ return m.id; }) });
+ },
+ allowedTypes: ['image'],
+ gallery: true,
+ multiple: true,
+ value: a.galleryIds || [],
+ render: function(ref) {
+ return el(Frag, null,
+ a.galleryIds && a.galleryIds.length
+ ? el('div', { style: { marginBottom: '8px' } },
+ el('p', { style: { margin: '0 0 4px' } }, a.galleryIds.length + ' image(s) selected'),
+ el(Btn, { variant: 'link', isDestructive: true, onClick: function(){ s({ galleryIds: [] }); } }, 'Clear gallery')
+ )
+ : null,
+ el(Btn, { onClick: ref.open, variant: 'secondary', __next40pxDefaultSize: true },
+ a.galleryIds && a.galleryIds.length ? 'Edit gallery' : 'Select images for TV slideshow')
+ );
+ }
+ })
+ )
),
el(PB, { title: 'Visual Image', initialOpen: false },
el(MUC, null,
@@ -1222,7 +1299,9 @@ reg('oribi/platform-row', {
a.btnUrl ? el(RT, { tagName: 'span', className: 'btn btn-outline mt-3',
value: a.btnText, onChange: function(v){s({btnText:v});}, placeholder: 'Button...' }) : null
),
- a.cameraAnim
+ a.isDashboard
+ ? el('div', { className: 'platform-visual has-dashboard', dangerouslySetInnerHTML: { __html: DB_HTML } })
+ : a.cameraAnim
? el('div', { className: 'platform-visual has-camera' },
el('div', { className: 'cam-stage', 'aria-hidden': 'true' },
// Photo camera (left)
@@ -1282,6 +1361,14 @@ reg('oribi/platform-row', {
)
)
)
+ : a.deviceAnim
+ ? el('div', { className: 'platform-visual has-anim', dangerouslySetInnerHTML: { __html: DA_HTML } })
+ : a.tvStick
+ ? el('div', { className: 'platform-visual has-tv-stick', dangerouslySetInnerHTML: { __html: TS_HTML } })
+ : a.neverGoesDark
+ ? el('div', { className: 'platform-visual has-ngd', dangerouslySetInnerHTML: { __html: NGD_HTML } })
+ : a.brandedAnim
+ ? el('div', { className: 'platform-visual has-branded', dangerouslySetInnerHTML: { __html: BD_HTML } })
: a.imgUrl
? el('div', { className: 'platform-visual has-img' },
el('img', { src: a.imgUrl, style: { width: imgW + 'px', maxWidth: '100%', height: 'auto', borderRadius: '4px', objectFit: 'contain', display: 'block', marginInline: 'auto' } })
@@ -1618,6 +1705,74 @@ reg('oribi/comparison-table', {
var a = props.attributes, s = props.setAttributes;
var cols = a.columns || [];
var rows = a.rows || [];
+
+ /* ── Column helpers ─────────────────────────────────────── */
+ function updateCol(idx, val) {
+ var c = cols.slice(); c[idx] = val; s({ columns: c });
+ }
+ function addCol() {
+ var newRows = rows.map(function(r) {
+ if (r.group) return r;
+ return Object.assign({}, r, { values: (r.values || []).concat([false]) });
+ });
+ s({ columns: cols.concat(['Plan']), rows: newRows });
+ }
+ function removeCol(idx) {
+ var c = cols.slice(); c.splice(idx, 1);
+ var newRows = rows.map(function(r) {
+ if (r.group) return r;
+ var v = (r.values || []).slice(); v.splice(idx, 1);
+ return Object.assign({}, r, { values: v });
+ });
+ s({ columns: c, rows: newRows });
+ }
+
+ /* ── Row helpers ────────────────────────────────────────── */
+ function updateRow(idx, key, val) {
+ var r = rows.slice();
+ r[idx] = Object.assign({}, r[idx]);
+ r[idx][key] = val;
+ s({ rows: r });
+ }
+ function updateCell(ri, ci, val) {
+ var r = rows.slice();
+ r[ri] = Object.assign({}, r[ri]);
+ var v = (r[ri].values || []).slice();
+ v[ci] = val;
+ r[ri].values = v;
+ s({ rows: r });
+ }
+ function toggleCell(ri, ci) {
+ var val = (rows[ri].values || [])[ci];
+ updateCell(ri, ci, val === true ? false : val === false ? true : true);
+ }
+ function switchCellToText(ri, ci) { updateCell(ri, ci, ''); }
+ function addFeatureRow() {
+ var vals = cols.map(function() { return false; });
+ s({ rows: rows.concat([{ feature: 'New feature', values: vals }]) });
+ }
+ function addGroupRow() {
+ s({ rows: rows.concat([{ group: 'New Group' }]) });
+ }
+ function removeRow(idx) {
+ var r = rows.slice(); r.splice(idx, 1); s({ rows: r });
+ }
+ function moveRow(idx, dir) {
+ var t = idx + dir;
+ if (t < 0 || t >= rows.length) return;
+ var r = rows.slice();
+ var tmp = r[idx]; r[idx] = r[t]; r[t] = tmp;
+ s({ rows: r });
+ }
+
+ /* ── Inline styles for editor controls ──────────────────── */
+ var inputStyle = { width: '100%', padding: '4px 6px', border: '1px solid #ddd', borderRadius: '3px', fontSize: '13px', background: 'transparent', boxSizing: 'border-box' };
+ var thInputStyle = Object.assign({}, inputStyle, { fontWeight: 600, textAlign: 'center' });
+ var smallBtnStyle = { background: 'none', border: 'none', cursor: 'pointer', padding: '2px 4px', fontSize: '11px', lineHeight: 1, opacity: 0.6, verticalAlign: 'middle' };
+ var rowCtrlStyle = { whiteSpace: 'nowrap', width: '1%', padding: '4px', verticalAlign: 'middle', border: 'none', background: 'transparent' };
+ var cellBtnStyle = { background: 'none', border: '1px solid #ddd', borderRadius: '3px', cursor: 'pointer', padding: '2px 6px', fontSize: '13px', lineHeight: '1.4', margin: '0 1px' };
+
+ /* ── Render ─────────────────────────────────────────────── */
return el(Frag, null,
el(IC, null,
el(PB, { title: 'Table Settings' },
@@ -1625,6 +1780,21 @@ reg('oribi/comparison-table', {
{ label: 'Normal', value: 'normal' }, { label: 'Alternate', value: 'alt' }
], onChange: function(v){s({variant:v});} }),
el(TC, { label: 'Label', value: a.label, onChange: function(v){s({label:v});} })
+ ),
+ el(PB, { title: 'Columns', initialOpen: false },
+ cols.map(function(col, i) {
+ return el('div', { key: i, style: { display: 'flex', gap: '4px', marginBottom: '8px', alignItems: 'center' } },
+ el(TC, { label: '', value: col, onChange: function(v){ updateCol(i, v); }, style: { flex: 1 } }),
+ el(Btn, { isDestructive: true, isSmall: true, onClick: function(){ removeCol(i); } }, '\u2715')
+ );
+ }),
+ el(Btn, { isSecondary: true, isSmall: true, onClick: addCol }, '+ Add Column')
+ ),
+ el(PB, { title: 'Add Rows', initialOpen: false },
+ el('div', { style: { display: 'flex', gap: '8px' } },
+ el(Btn, { isSecondary: true, isSmall: true, onClick: addFeatureRow }, '+ Feature Row'),
+ el(Btn, { isSecondary: true, isSmall: true, onClick: addGroupRow }, '+ Group Row')
+ )
)
),
el('section', { className: a.variant === 'alt' ? 'section section-alt' : 'section' },
@@ -1639,26 +1809,62 @@ reg('oribi/comparison-table', {
el('thead', null,
el('tr', null,
el('th', { className: 'comparison-feature-col' }, 'Feature'),
- cols.map(function(col, i) { return el('th', { key: i }, col); })
+ cols.map(function(col, i) {
+ return el('th', { key: i },
+ el('input', { type: 'text', value: col, style: thInputStyle, onChange: function(e){ updateCol(i, e.target.value); } })
+ );
+ }),
+ el('th', { style: rowCtrlStyle })
)
),
el('tbody', null,
- rows.map(function(row, i) {
+ rows.map(function(row, ri) {
if (row.group) {
- return el('tr', { key: i, className: 'comparison-group-row' },
- el('td', { colSpan: cols.length + 1 }, row.group)
+ return el('tr', { key: ri, className: 'comparison-group-row' },
+ el('td', { colSpan: cols.length + 1 },
+ el('input', { type: 'text', value: row.group, style: Object.assign({}, inputStyle, { fontWeight: 700 }), onChange: function(e){ updateRow(ri, 'group', e.target.value); } })
+ ),
+ el('td', { style: rowCtrlStyle },
+ el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, -1); }, title: 'Move up' }, '\u25B2'),
+ el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, 1); }, title: 'Move down' }, '\u25BC'),
+ el('button', { style: Object.assign({}, smallBtnStyle, { color: '#b00' }), onClick: function(){ removeRow(ri); }, title: 'Remove row' }, '\u2715')
+ )
);
}
- return el('tr', { key: i },
- el('td', { className: 'comparison-feature-name' }, row.feature || ''),
- (row.values || []).map(function(val, j) {
- return el('td', { key: j, className: 'comparison-cell' },
- val === true ? '\u2713' : val === false ? '\u2014' : String(val)
+ return el('tr', { key: ri },
+ el('td', { className: 'comparison-feature-name' },
+ el('input', { type: 'text', value: row.feature || '', style: inputStyle, placeholder: 'Feature name\u2026', onChange: function(e){ updateRow(ri, 'feature', e.target.value); } })
+ ),
+ (row.values || []).map(function(val, ci) {
+ if (typeof val === 'boolean') {
+ return el('td', { key: ci, className: 'comparison-cell', style: { textAlign: 'center' } },
+ el('button', { style: Object.assign({}, cellBtnStyle, { color: val ? '#2e7d32' : '#c62828' }), onClick: function(){ toggleCell(ri, ci); }, title: 'Toggle \u2713/\u2717' },
+ val ? '\u2713' : '\u2717'
+ ),
+ el('button', { style: Object.assign({}, smallBtnStyle, { fontSize: '10px' }), onClick: function(){ switchCellToText(ri, ci); }, title: 'Switch to text' }, 'Aa')
+ );
+ }
+ return el('td', { key: ci, className: 'comparison-cell' },
+ el('div', { style: { display: 'flex', alignItems: 'center', gap: '2px' } },
+ el('input', { type: 'text', value: String(val), style: Object.assign({}, inputStyle, { flex: 1, minWidth: '60px' }), placeholder: 'Value\u2026', onChange: function(e){ updateCell(ri, ci, e.target.value); } }),
+ el('button', { style: Object.assign({}, smallBtnStyle, { color: '#2e7d32' }), onClick: function(){ updateCell(ri, ci, true); }, title: 'Set as \u2713' }, '\u2713'),
+ el('button', { style: Object.assign({}, smallBtnStyle, { color: '#c62828' }), onClick: function(){ updateCell(ri, ci, false); }, title: 'Set as \u2717' }, '\u2717')
+ )
);
- })
+ }),
+ el('td', { style: rowCtrlStyle },
+ el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, -1); }, title: 'Move up' }, '\u25B2'),
+ el('button', { style: smallBtnStyle, onClick: function(){ moveRow(ri, 1); }, title: 'Move down' }, '\u25BC'),
+ el('button', { style: Object.assign({}, smallBtnStyle, { color: '#b00' }), onClick: function(){ removeRow(ri); }, title: 'Remove row' }, '\u2715')
+ )
);
})
)
+ ),
+ el('div', { style: { display: 'flex', gap: '8px', marginTop: '12px', justifyContent: 'center' } },
+ el(Btn, { isSecondary: true, isSmall: true, onClick: addFeatureRow }, '+ Feature Row'),
+ el(Btn, { isSecondary: true, isSmall: true, onClick: addGroupRow }, '+ Group Row'),
+ el(Btn, { isSecondary: true, isSmall: true, onClick: addCol }, '+ Column')
)
)
)
diff --git a/theme/blocks/index.php b/theme/blocks/index.php
index 9f4bab8..cf382cb 100644
--- a/theme/blocks/index.php
+++ b/theme/blocks/index.php
@@ -553,9 +553,13 @@ add_action( 'init', function () {
'imgUrl' => [ 'type' => 'string', 'default' => '' ],
'imgAlt' => [ 'type' => 'string', 'default' => '' ],
'imgWidth' => [ 'type' => 'number', 'default' => 300 ],
- 'deviceAnim' => [ 'type' => 'boolean', 'default' => false ],
- 'tvStick' => [ 'type' => 'boolean', 'default' => false ],
- 'cameraAnim' => [ 'type' => 'boolean', 'default' => false ],
+ 'isDashboard' => [ 'type' => 'boolean', 'default' => false ],
+ 'deviceAnim' => [ 'type' => 'boolean', 'default' => false ],
+ 'tvStick' => [ 'type' => 'boolean', 'default' => false ],
+ 'cameraAnim' => [ 'type' => 'boolean', 'default' => false ],
+ 'neverGoesDark'=> [ 'type' => 'boolean', 'default' => false ],
+ 'brandedAnim' => [ 'type' => 'boolean', 'default' => false ],
+ 'galleryIds' => [ 'type' => 'array', 'default' => [], 'items' => [ 'type' => 'number' ] ],
],
'supports' => $block_supports,
'render_callback' => 'oribi_render_platform_row',
@@ -671,9 +675,8 @@ function oribi_render_site_header() {
@@ -1344,6 +1347,208 @@ function oribi_render_platform_section( $a, $content ) {
}
/* ── Platform Row (child - renders one service row) ────────────────────────── */
+function oribi_render_camera_animation() {
+ return <<<'HTML'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0:00
+
+ 0:02
+
+ 0:04
+
+ 0:06
+
+ 0:08
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0:00
+
+HTML;
+}
+
function oribi_render_platform_row( $a ) {
$rev = ! empty( $a['reversed'] ) ? ' reverse' : '';
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
@@ -1364,7 +1569,7 @@ function oribi_render_platform_row( $a ) {
-
+
@@ -1442,7 +1647,7 @@ function oribi_render_platform_row( $a ) {
Distribution
-
+
@@ -1457,7 +1662,7 @@ function oribi_render_platform_row( $a ) {
100%
-
+
Service A
Service B
@@ -1481,13 +1686,14 @@ function oribi_render_platform_row( $a ) {
}
$visual_cls = 'platform-visual has-img';
} elseif ( ! empty( $a['deviceAnim'] ) ) {
+ $da_screen = '';
$da = '';
- $da .= '
';
- $da .= '
';
- $da .= '
';
- $da .= '
';
- $da .= '
';
- $da .= '
';
+ $da .= '
';
+ $da .= '
' . $da_screen . '
Small Monitor ';
+ $da .= '
' . $da_screen . '
Large Monitor ';
+ $da .= '
';
+ $da .= '
';
+ $da .= '
' . $da_screen . '
' . $da_screen . '
' . $da_screen . '
' . $da_screen . '
Video Wall ';
$da .= '
';
$visual_html = $da;
$visual_cls = 'platform-visual has-anim';
@@ -1495,7 +1701,59 @@ function oribi_render_platform_row( $a ) {
$ts = '';
$ts .= '
';
$ts .= '
';
- $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+
+ // Slide 1 — Menu Board
+ $ts .= '';
+
+ // Slide 2 — Wayfinding Sign
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+
+ // Slide 3 — Schedule / Timetable
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+ $ts .= '
';
+
+ $ts .= '
'; // ts-slides
+ $ts .= '
'; // ts-tv__screen
$ts .= '
';
$ts .= '
';
$ts .= '
';
@@ -1509,59 +1767,210 @@ function oribi_render_platform_row( $a ) {
$ts .= '
';
$visual_html = $ts;
$visual_cls = 'platform-visual has-tv-stick';
+ } elseif ( ! empty( $a['neverGoesDark'] ) ) {
+ /* ── Never Goes Dark: player + TV + cloud connection/break animation ── */
+ $ngd = '
';
+
+ /* TV */
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= ''; /* ngd-menu */
+ $ngd .= '
'; /* ngd-tv__screen */
+ $ngd .= '
';
+ $ngd .= '
'; /* ngd-tv__body */
+ $ngd .= '
';
+ $ngd .= '
'; /* ngd-tv */
+
+ /* Player device (stick style, plugged into TV right-side HDMI port) */
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= '
';
+ $ngd .= '
'; /* ngd-player */
+
+ /* Signal wrap: vertical line connecting player to globe above */
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '
';
+ $ngd .= '';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= ' ';
+ $ngd .= '
';
+ $ngd .= '
'; /* ngd-signal-line */
+ $ngd .= '
'; /* ngd-signal-wrap */
+
+ $ngd .= '
'; /* ngd-stage */
+
+ $visual_html = $ngd;
+ $visual_cls = 'platform-visual has-ngd';
+ } elseif ( ! empty( $a['brandedAnim'] ) ) {
+ /* ── Custom Display Solutions: branded screens cascade animation ── */
+ $bd = '
';
+
+ /* ── Screen 1: Tablet (portrait kiosk) ── */
+ $bd .= '
';
+ $bd .= '
Kiosk ';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+
+ /* ── Screen 2: Wide wall-mount (landscape) ── */
+ $bd .= '
';
+ $bd .= '
Wall Display ';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+
+ /* ── Screen 3: Interactive tablet on table ── */
+ $bd .= '
';
+ $bd .= '
Interactive ';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '';
+ $bd .= '
';
+ $bd .= '';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+ $bd .= '
';
+
+ $bd .= '
'; /* bd-stage */
+ $visual_html = $bd;
+ $visual_cls = 'platform-visual has-branded';
} elseif ( ! empty( $a['cameraAnim'] ) ) {
- $ca = '
';
+ $visual_html = oribi_render_camera_animation();
+ $visual_cls = 'platform-visual has-video-editor';
- // ── Left: compact photo camera ──
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
'; // pc-body
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
'; // pc-prints
- $ca .= '
'; // pc-wrap
+ /* ── Gallery TV Slideshow ───────────────────────────────── */
+ } elseif ( ! empty( $a['galleryIds'] ) && is_array( $a['galleryIds'] ) && count( $a['galleryIds'] ) > 0 ) {
+ $slides = '';
+ $count = 0;
+ foreach ( $a['galleryIds'] as $gid ) {
+ $gid = intval( $gid );
+ if ( ! $gid ) continue;
+ $url = wp_get_attachment_url( $gid );
+ $alt = get_post_meta( $gid, '_wp_attachment_image_alt', true );
+ if ( ! $url ) continue;
+ $active = $count === 0 ? ' is-active' : '';
+ $slides .= '
';
+ $slides .= '
';
+ $slides .= '
';
+ $count++;
+ }
+ if ( $count > 0 ) {
+ $visual_html = '
';
+ $visual_html .= '
';
+ $visual_html .= '
';
+ $visual_html .= '
';
+ $visual_html .= '
' . $slides . '
';
+ $visual_html .= '
'; // screen
+ $visual_html .= '
'; // body
+ $visual_html .= '
';
+ $visual_html .= '
'; // tv
+ $visual_html .= '
'; // stage
+ $visual_cls = 'platform-visual has-gallery-tv';
+ } else {
+ $visual_html = oribi_render_icon( $a['visual'] ?? '' );
+ $visual_cls = 'platform-visual';
+ }
- // ── Centre: product scene both cameras shoot ──
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
'; // cam-scene
-
- // ── Right: retro VHS video camera on tripod ──
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
'; // vc-body
- $ca .= '
'; // vc-camera
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
';
- $ca .= '
'; // vc-legs
- $ca .= '
'; // vc-tripod
- $ca .= '
'; // vc-wrap
-
- $ca .= '
'; // cam-stage
- $visual_html = $ca;
- $visual_cls = 'platform-visual has-camera';
} else {
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
$visual_cls = 'platform-visual';
@@ -1580,7 +1989,6 @@ function oribi_render_platform_row( $a ) {
@@ -1772,3 +2180,107 @@ function oribi_render_page_hero_animated( $a ) {
+
+
+
+
+
+
+
+';
+ case 'event':
+ return '
+
+
+
+
+
9:00
+
Keynote Speech
+
+
+
10:30
+
Panel Discussion
+
+
+
+
12:30
+
Networking Lunch
+
+
';
+ case 'dashboard':
+ return '
+';
+ case 'wayfinding':
+ return '
+';
+ default:
+ return '';
+ }
+}
+
+function oribi_render_use_cases( $a ) {
+ $cases = [
+ [ 'title' => $a['case1Title'], 'desc' => $a['case1Desc'], 'mod' => 'menu' ],
+ [ 'title' => $a['case2Title'], 'desc' => $a['case2Desc'], 'mod' => 'event' ],
+ [ 'title' => $a['case3Title'], 'desc' => $a['case3Desc'], 'mod' => 'dashboard' ],
+ [ 'title' => $a['case4Title'], 'desc' => $a['case4Desc'], 'mod' => 'wayfinding' ],
+ ];
+ ob_start(); ?>
+
+ admin_url( 'admin-ajax.php' ),
diff --git a/theme/inc/theme-defaults.php b/theme/inc/theme-defaults.php
index 2cf9836..e9401a5 100644
--- a/theme/inc/theme-defaults.php
+++ b/theme/inc/theme-defaults.php
@@ -24,9 +24,9 @@ function oribi_get_theme_defaults() {
return [
/* ── Light-mode colour palette ──────────────────────── */
- 'color_primary' => '#004225',
- 'color_primary_dk' => '#002E1A',
- 'color_primary_lt' => '#E8F5E9',
+ 'color_primary' => '#D83302',
+ 'color_primary_dk' => '#A22702',
+ 'color_primary_lt' => '#FFF0EB',
'color_accent' => '#4CAF50',
'color_accent_dk' => '#388E3C',
'color_accent_lt' => '#E8F5E9',
@@ -39,9 +39,9 @@ function oribi_get_theme_defaults() {
'color_bg_alt' => '#F5F5F5',
/* ── Dark-mode colour palette ───────────────────────── */
- 'dark_primary' => '#4CAF50',
- 'dark_primary_dk' => '#004225',
- 'dark_primary_lt' => 'rgba(0,66,37,0.15)',
+ 'dark_primary' => '#FF6B3D',
+ 'dark_primary_dk' => '#D83302',
+ 'dark_primary_lt' => 'rgba(216,51,2,0.15)',
'dark_accent' => '#66BB6A',
'dark_accent_dk' => '#4CAF50',
'dark_accent_lt' => 'rgba(76,175,80,0.15)',
diff --git a/theme/inc/theme-settings.php b/theme/inc/theme-settings.php
index ccf732f..f4e4c10 100644
--- a/theme/inc/theme-settings.php
+++ b/theme/inc/theme-settings.php
@@ -636,7 +636,7 @@ document.addEventListener('DOMContentLoaded', function() {
if (heroText) heroText.style.color = 'rgba(255,255,255,.8)';
}
if (btnP) {
- btnP.style.backgroundColor = get('oribi_color_primary') || '#004225';
+ btnP.style.backgroundColor = get('oribi_color_primary') || '#D83302';
btnP.style.borderRadius = (get('oribi_radius_sm') || '6') + 'px';
}
if (btnA) {
diff --git a/theme/theme.json b/theme/theme.json
index ca551c0..a560961 100644
--- a/theme/theme.json
+++ b/theme/theme.json
@@ -32,9 +32,9 @@
"customDuotone": false,
"customGradient": false,
"palette": [
- { "slug": "primary", "color": "#004225", "name": "Primary" },
- { "slug": "primary-dk", "color": "#002E1A", "name": "Primary Dark" },
- { "slug": "primary-lt", "color": "#E8F5E9", "name": "Primary Light" },
+ { "slug": "primary", "color": "#D83302", "name": "Primary" },
+ { "slug": "primary-dk", "color": "#A22702", "name": "Primary Dark" },
+ { "slug": "primary-lt", "color": "#FFF0EB", "name": "Primary Light" },
{ "slug": "accent", "color": "#4CAF50", "name": "Accent" },
{ "slug": "accent-dk", "color": "#388E3C", "name": "Accent Dark" },
{ "slug": "accent-lt", "color": "#E8F5E9", "name": "Accent Light" },
@@ -85,9 +85,9 @@
},
"custom": {
"dark": {
- "primary": "#4CAF50",
- "primary-dk": "#004225",
- "primary-lt": "rgba(0,66,37,0.15)",
+ "primary": "#FF6B3D",
+ "primary-dk": "#D83302",
+ "primary-lt": "rgba(216,51,2,0.15)",
"accent": "#66BB6A",
"accent-dk": "#388E3C",
"accent-lt": "rgba(76,175,80,0.12)",