Compare commits

...

87 Commits

Author SHA1 Message Date
Matt Batchelder
c91975db12 Add column and row management features to comparison table block 2026-02-21 22:52:38 -05:00
Matt Batchelder
5ea06c2332 Update logo text styling for improved visibility in dark mode 2026-02-21 21:53:52 -05:00
Matt Batchelder
59295b15db Update gap size in layout and change logo text color for improved aesthetics 2026-02-21 21:51:30 -05:00
Matt Batchelder
82d6ecba1e Update logo dimensions and change logo text to 'OTS Signs' for improved branding 2026-02-21 21:48:45 -05:00
Matt Batchelder
e90e644b62 Update platform features and home pages to reflect new service offerings and improve clarity 2026-02-21 21:42:30 -05:00
Matt Batchelder
afccdca783 Update features page content for improved clarity and detail on platform capabilities 2026-02-21 21:36:20 -05:00
Matt Batchelder
d88070949c Enhance transition effects for form elements and comparison table components 2026-02-21 20:05:44 -05:00
Matt Batchelder
2a0b949ea9 Add video editor timeline animator with animated playhead and scene transitions 2026-02-21 19:55:47 -05:00
Matt Batchelder
2c82b2e432 Enhance platform-row block with new animation attributes for improved visual effects 2026-02-21 18:55:04 -05:00
Matt Batchelder
97bbe90ed1 Fix scroll-reveal animation flicker by adding !important and disabling transitions 2026-02-21 18:44:58 -05:00
668c92aff6 Sync: update about from WordPress 2026-02-21 18:29:44 -05:00
a8ba4a1fef Sync: update contact from WordPress 2026-02-21 18:29:43 -05:00
edacab26b3 Sync: update pricing from WordPress 2026-02-21 18:29:41 -05:00
0a18e35943 Sync: update home from WordPress 2026-02-21 18:29:40 -05:00
b264511d34 Sync: update features from WordPress 2026-02-21 18:29:38 -05:00
6254fff0c0 Sync: update faq from WordPress 2026-02-21 18:29:37 -05:00
3c07a4733c Sync: update devices from WordPress 2026-02-21 18:29:35 -05:00
e54b94222a Sync: update demo from WordPress 2026-02-21 18:29:34 -05:00
44b501b4da Sync: update solutions from WordPress 2026-02-21 18:29:33 -05:00
4f596dbf30 Sync: update resources from WordPress 2026-02-21 18:29:33 -05:00
Matt Batchelder
a7d6623eec Fix: add missing animation properties to platform row components 2026-02-21 18:09:27 -05:00
Matt Batchelder
985ba72212 Fix: adjust positioning and border radius of lens barrel and eyepiece components 2026-02-21 18:02:46 -05:00
Matt Batchelder
cfb216f73e Sync: update camera animation subjects to include shoe, food, and laptop 2026-02-21 18:00:51 -05:00
Matt Batchelder
ce163d25e3 Fix: adjust vertical positioning of the lens barrel in the visual component 2026-02-21 17:59:10 -05:00
Matt Batchelder
6b8b6b2328 Sync: implement camera animation rendering function and refactor platform row logic 2026-02-21 17:55:50 -05:00
Matt Batchelder
f9f15708e3 Sync: add promotional animation styles and integrate into device rendering 2026-02-21 17:53:14 -05:00
Matt Batchelder
80b36032e8 small 2026-02-21 17:47:49 -05:00
Matt Batchelder
7b4caa1267 Sync: update button styles for light and dark themes in homepage hero 2026-02-21 17:44:41 -05:00
a69521ab25 Sync: update contact from WordPress 2026-02-21 17:40:20 -05:00
e03b6e150e Sync: update about from WordPress 2026-02-21 17:40:19 -05:00
8eea9d95ce Sync: update features from WordPress 2026-02-21 17:40:18 -05:00
0fd40020b0 Sync: update faq from WordPress 2026-02-21 17:40:16 -05:00
afd49f2165 Sync: update devices from WordPress 2026-02-21 17:40:15 -05:00
c476a79cee Sync: update demo from WordPress 2026-02-21 17:40:14 -05:00
369da66d4c Sync: update pricing from WordPress 2026-02-21 17:40:12 -05:00
402804018a Sync: update home from WordPress 2026-02-21 17:40:11 -05:00
93e1c59e29 Sync: update solutions from WordPress 2026-02-21 17:40:10 -05:00
170f134927 Sync: update resources from WordPress 2026-02-21 17:40:10 -05:00
Matt Batchelder
5be6eae083 Sync: add devices split card section and styles for improved presentation of player options 2026-02-21 17:36:46 -05:00
Matt Batchelder
7bb9a0bdd3 bigger 2026-02-21 17:33:04 -05:00
Matt Batchelder
3027f3da40 Sync: update ngd-signal-wrap SVG paths for improved visual representation 2026-02-21 17:30:18 -05:00
Matt Batchelder
c50087d669 Sync: update ngd-signal-wrap styles and SVG structure for improved visual representation 2026-02-21 17:28:35 -05:00
Matt Batchelder
8c3c7a1d8a Sync: update ngd-tv component styles for improved layout and dimensions 2026-02-21 17:26:19 -05:00
Matt Batchelder
4e4549e865 Sync: adjust layout styles for improved alignment and centering of elements 2026-02-21 17:22:35 -05:00
Matt Batchelder
25da755378 Sync: enhance platform text styles and adjust layout for improved responsiveness 2026-02-21 17:20:19 -05:00
Matt Batchelder
dc89009cfa Sync: update site navigation styles to manage overflow and enhance usability 2026-02-21 17:12:28 -05:00
Matt Batchelder
21d41b24d8 Sync: implement menu toggle functionality to manage body overflow state 2026-02-21 17:06:47 -05:00
Matt Batchelder
8f43b6c584 Sync: implement scroll-reveal animations for cards with responsive visibility adjustments 2026-02-21 16:47:11 -05:00
Matt Batchelder
66b6b9cbfb Sync: refine glow animations and adjust particle sizes for enhanced visual dynamics 2026-02-21 15:02:25 -05:00
Matt Batchelder
018928dd9b Sync: enhance glow animations and adjust particle effects for improved visual appeal 2026-02-21 15:01:06 -05:00
Matt Batchelder
78065e0143 Sync: update stat-card descriptions with new research links for improved accuracy 2026-02-21 14:54:09 -05:00
Matt Batchelder
131ef8448c Sync: update stat-card descriptions with external study links for enhanced credibility 2026-02-21 14:47:55 -05:00
Matt Batchelder
a89f9067e2 Sync: enhance header behavior for light hero backgrounds with dynamic class toggling 2026-02-21 14:42:45 -05:00
Matt Batchelder
8926a9b071 Sync: update header styles for scrolled state to improve visibility and consistency 2026-02-21 14:38:18 -05:00
Matt Batchelder
1540aa9f13 Sync: enhance styling for gtv-tv__body with improved borders, padding, and shadow effects 2026-02-21 14:30:42 -05:00
Matt Batchelder
3dcffaeb06 Sync: update pricing comparison table with new features and contractual SLA guarantee 2026-02-21 14:29:11 -05:00
7aee3eab85 Sync: update contact from WordPress 2026-02-21 14:18:25 -05:00
20b655d490 Sync: update about from WordPress 2026-02-21 14:18:24 -05:00
3e3578823d Sync: update pricing from WordPress 2026-02-21 14:18:22 -05:00
b96bdfe355 Sync: update home from WordPress 2026-02-21 14:18:21 -05:00
dcb8acb1e5 Sync: update features from WordPress 2026-02-21 14:18:20 -05:00
a2821b4c2c Sync: update faq from WordPress 2026-02-21 14:18:18 -05:00
f12928690e Sync: update devices from WordPress 2026-02-21 14:18:17 -05:00
6ddd3ba399 Sync: update demo from WordPress 2026-02-21 14:18:15 -05:00
4fe3f6e283 Sync: update solutions from WordPress 2026-02-21 14:18:15 -05:00
4e5ab8b3fa Sync: update resources from WordPress 2026-02-21 14:18:14 -05:00
Matt Batchelder
48432c1931 Update comparison group row styles for improved visibility and layout 2026-02-21 14:14:59 -05:00
Matt Batchelder
2826a3ec4a Update script handle and description for gallery TV slideshow in enqueue.php 2026-02-21 14:11:56 -05:00
Matt Batchelder
2edbf9732b Add industry mockup animator script for solutions page
- Enqueued new script `industry-animator.js` for animated device mockups.
- Implemented animation logic for various industries including hospitality, retail, corporate, education, outdoor, and live data displays.
- Utilized IntersectionObserver for performance optimization by pausing animations when off-screen.
2026-02-21 13:59:57 -05:00
Matt Batchelder
82a2dacbef Refactor splash and promotional elements to use CSS variables for primary color 2026-02-21 13:46:21 -05:00
Matt Batchelder
75588a5151 Refactor platform row to implement promotional content layouts for welcome, sale, and menu displays 2026-02-21 13:43:07 -05:00
Matt Batchelder
624a5c2d4e Update platform row to include labels for interactive and wall display devices; adjust device types for clarity 2026-02-21 13:37:23 -05:00
Matt Batchelder
61a7070b0f Add branded display animation and custom display solutions to platform row 2026-02-21 13:33:53 -05:00
Matt Batchelder
bb30f38090 Update color palette to use new orange primary and green accent colors for improved branding 2026-02-21 13:26:59 -05:00
Matt Batchelder
d8c12e3f3b Update CSS will-change property and add min-height to hero section; enhance JS card animation with reduced motion support 2026-02-21 13:22:07 -05:00
Matt Batchelder
ebb4b7668c Update event display styles and replace event time element with cursor for improved visibility 2026-02-21 13:14:41 -05:00
Matt Batchelder
5783fa7ebc Rename event cursor to event time display and update styles for improved visibility 2026-02-21 13:13:03 -05:00
Matt Batchelder
df794be0d8 Refactor event display structure and styles for improved readability and consistency 2026-02-21 13:05:58 -05:00
Matt Batchelder
150fe5a291 Update feature descriptions and keywords for clarity and consistency 2026-02-21 13:02:27 -05:00
Matt Batchelder
b0167f2505 Adjust TV and player positioning and dimensions for improved layout 2026-02-21 12:52:54 -05:00
Matt Batchelder
0407269e79 Adjust TV and player dimensions for improved layout and responsiveness 2026-02-21 12:45:48 -05:00
Matt Batchelder
ecba27595c Refactor player device structure and styles for HDMI connection representation 2026-02-21 12:41:45 -05:00
Matt Batchelder
c4f3d7e881 Reduce animation durations for menu highlight, ticker, LED, and signal effects 2026-02-21 12:36:59 -05:00
Matt Batchelder
e5c3be6ec5 Add 'Never Goes Dark' feature with animations for player and TV connection status 2026-02-21 12:35:28 -05:00
Matt Batchelder
201e4e4606 Refactor slide structure to enhance menu board, wayfinding sign, and schedule display 2026-02-21 12:18:48 -05:00
Matt Batchelder
ef0532ef9b Add promotional slides with animations to TV stick component 2026-02-21 12:13:10 -05:00
Matt Batchelder
1d49929ed3 Reverse scale transformation for animation effects in the ts-stick component 2026-02-21 12:07:06 -05:00
21 changed files with 2962 additions and 399 deletions

View File

@@ -1,27 +1,30 @@
<?php
/**
/*
* Title: About
* Slug: ots-signs/page-about
* Categories: oribi-pages
* Keywords: about, company, mission, team, digital signage
* Post Types: page
* Slug: about
* Post Type: page
*/
?>
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"About Us","title":"Digital Signage, Done Properly","description":"OTS Signs is the digital signage arm of Oribi Technology Services. We combine deep IT expertise with creative production to deliver signage that businesses can genuinely rely on."} /-->
<!-- wp:oribi/intro-section {"variant":"normal","label":"Our Story","heading":"Born from Infrastructure, Built for Signage","description":"OTS Signs grew out of a gap we kept seeing: businesses wanted digital signage but were stuck choosing between complex enterprise platforms and unreliable consumer tools. As part of Oribi Technology Services, we already understood networks, uptime, and security at a deep level. We took that foundation and built a signage platform that is powerful enough for large deployments yet simple enough for a single-site café. Every decision we make from hardware selection to CMS design is grounded in real-world infrastructure experience.","visual":""} /-->
<!-- wp:oribi/intro-section {"label":"Our Story","heading":"Born from Infrastructure, Built for Signage","description":"OTS Signs grew out of a gap we kept seeing: businesses wanted digital signage but were stuck choosing between complex enterprise platforms and unreliable consumer tools. As part of Oribi Technology Services, we already understood networks, uptime, and security at a deep level. We took that foundation and built a signage platform that is powerful enough for large deployments yet simple enough for a single-site café. Every decision we make, from hardware selection to Command Center design, is grounded in real-world infrastructure experience."} /-->
<!-- wp:oribi/intro-section {"variant":"alt","label":"Our Mission","heading":"Making Professional Signage Accessible to Everyone","description":"Too many signage providers lock essential features behind enterprise price tags. We took a different approach. Our platform gives every customer — from a neighbourhood restaurant to a national retailer — access to the same professional-grade tools: cloud content management, intelligent scheduling, live data integration, and content that looks outstanding on screen. We handle the complexity so you can focus on running your business.","visual":"","reversed":true} /-->
<!-- wp:oribi/intro-section {"variant":"alt","label":"Our Mission","heading":"Making Professional Signage Accessible to Everyone","description":"Too many signage providers lock essential features behind enterprise price tags. We took a different approach. Our platform gives every customer access to the same professional-grade tools: \u003cbr\u003e- Cloud Content Management\u003cbr\u003e- Intelligent Scheduling\u003cbr\u003e- Live Data Integration \u003cbr\u003e- Content that looks outstanding on screen\u003cbr\u003e\u003cbr\u003eWe handle the complexity so you can focus on running your business.","reversed":true} /-->
<!-- wp:oribi/value-section {"variant":"normal","label":"What Sets Us Apart","heading":"A Full-Service Signage Partner","lead":"Software alone isn\u0027t enough. We pair our platform with hands-on services that make the difference.","columns":3} -->
<!-- wp:oribi/value-section {"label":"What Sets Us Apart","heading":"A Full-Service Signage Partner","lead":"Software alone isn't enough. We pair our platform with hands-on services that make the difference."} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-camera","title":"Studio-Quality Creative","description":"Photography, videography, and motion graphics produced in-house. Your screens always look polished, on-brand, and impossible to ignore."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-server","title":"IT-Grade Infrastructure","description":"Our roots are in enterprise IT. That means proper networking, redundancy, and security baked into every layer of the platform."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Genuine Partnership","description":"Dedicated onboarding, a named point of contact, and ongoing optimisation. We operate as an extension of your own team."} /-->
<!-- /wp:oribi/value-section -->
<!-- wp:oribi/trust-section {"label":"Our Commitment","heading":"Promises We Actually Keep","lead":"Every screen in your network reflects on your business. We take that responsibility seriously.","btnText":"Start a Conversation","btnUrl":"/contact","btnSub":"Tell us what you need and we'll take it from there"} -->
<!-- wp:oribi/trust-item {"heading":"Uptime You Can Count On","description":"99.9% platform availability, end-to-end encryption, and intelligent offline playback mean your message stays on screen no matter what."} /-->
<!-- wp:oribi/trust-item {"heading":"A Platform That Keeps Improving","description":"Regular feature releases, new integrations, and expanded content tools ensure you're always working with the latest capabilities — at no extra cost."} /-->
<!-- wp:oribi/trust-item {"heading":"Uptime You Can Count On","description":"99.9% platform availability, and intelligent offline playback mean your message stays on screen no matter what."} /-->
<!-- wp:oribi/trust-item {"heading":"A Platform That Keeps Improving","description":"Regular feature releases, new integrations, and expanded content tools ensure you're always working with the latest capabilities, at no extra cost."} /-->
<!-- /wp:oribi/trust-section -->
<!-- wp:oribi/cta-banner {"heading":"Ready to See What We Can Do?","text":"Whether you're planning your first screen or scaling to hundreds, we'd love to hear about your project.","btnText":"Get in Touch","btnUrl":"/contact"} /-->
ORIBI_SYNC_CONTENT;

View File

@@ -1,20 +1,22 @@
<?php
/**
/*
* Title: Contact
* Slug: ots-signs/page-contact
* Categories: oribi-pages
* Keywords: contact, sales, support, inquiry, get in touch
* Post Types: page
* Slug: contact
* Post Type: page
*/
?>
<!-- wp:oribi/page-hero-animated {"label":"Contact Us","title":"Let\u0027s Start a Conversation","description":"Whether you\u0027re researching digital signage for the first time or ready to roll out screens next week, we\u0027re here to help you move forward."} /-->
<!-- wp:oribi/contact-section {"heading":"Send Us a Message","lead":"Tell us what you're working on. We respond within one business day — usually faster.","email":"hello@ots-signs.com","supportUrl":"https://ots-signs.com/support","portalUrl":"https://ots-signs.com/portal","location":"An Oribi Technology Services Company","formHeading":"How Can We Help?"} /-->
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Contact Us","title":"Let's Start a Conversation","description":"Whether you're researching digital signage for the first time or ready to roll out screens next week, we're here to help you move forward."} /-->
<!-- wp:oribi/contact-section {"heading":"Send Us a Message","lead":"Tell us what you're working on. We respond within one business day, usually faster.","email":"hello@ots-signs.com","supportUrl":"https://ots-signs.com/support","portalUrl":"https://ots-signs.com/portal","location":"An Oribi Technology Services Company","formHeading":"How Can We Help?"} /-->
<!-- wp:oribi/value-section {"variant":"alt","label":"How We Can Help","heading":"Whatever You Need, We're Here","lead":"From your first question to ongoing support, our team has you covered."} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-comments","title":"Sales \u0026 Quotes","description":"Talk through your requirements, get a custom quote, or simply learn how digital signage fits your business."} /-->
<!-- wp:oribi/value-section {"variant":"alt","label":"How We Can Help","heading":"Whatever You Need, We\u0027re Here","lead":"From your first question to ongoing support, our team has you covered.","columns":3} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-comments","title":"Sales & Quotes","description":"Talk through your requirements, get a custom quote, or simply learn how digital signage fits your business."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Technical Support","description":"Already a customer? Our support team is ready to troubleshoot, advise, and resolve any issue quickly."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Partnerships","description":"Interested in reselling, white-labelling, or integrating our platform into your own offering? Let\u0027s talk."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-handshake","title":"Partnerships","description":"Interested in reselling, white-labelling, or integrating our platform into your own offering? Let's talk."} /-->
<!-- /wp:oribi/value-section -->
<!-- wp:oribi/cta-banner {"heading":"Rather See It First?","text":"Get hands-on with our platform before committing. Request a live demo and explore at your own pace.","btnText":"Request Demo","btnUrl":"/demo"} /-->
ORIBI_SYNC_CONTENT;

View File

@@ -1,25 +1,30 @@
<?php
/**
/*
* Title: Demo
* Slug: ots-signs/page-demo
* Categories: oribi-pages
* Keywords: demo, trial, try, preview, platform
* Post Types: page
* Slug: demo
* Post Type: page
*/
?>
<!-- wp:oribi/page-hero-animated {"label":"Try It","title":"Hands-On in Minutes, Not Weeks","description":"Skip the slideshow. Request access to a live instance of our platform and explore every feature at your own pace — no sales call required."} /-->
<!-- wp:oribi/intro-section {"variant":"normal","label":"Live Demo","heading":"Your Own Sandbox to Explore","description":"We'll set you up with full access to the OTS Signs CMS — the same platform our paying customers use. Build playlists, schedule content, connect data feeds, and preview exactly how your signage will look in production. No credit card, no time limit on the trial. Fill in the form below and we'll send you credentials within 24 hours.","visual":""} /-->
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Try It","title":"Hands-On in Minutes, Not Weeks","description":"Skip the slideshow. Request access to a live instance of our platform and explore every feature at your own pace, no sales call required."} /-->
<!-- wp:oribi/intro-section {"label":"Live Demo","heading":"Your Own Sandbox to Explore","description":"We'll set you up with full access to the OTS Signs Command Center, the same platform our paying customers use. Build playlists, schedule content, connect data feeds, and preview exactly how your signage will look in production. No credit card, no time limit on the trial. Fill in the form below and we'll send you credentials within 24 hours."} /-->
<!-- wp:oribi/feature-section {"variant":"alt","label":"What Youu0027ll See","heading":"Full Pro-Tier Access","lead":"The demo includes every feature available, nothing held back."} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-desktop","title":"Content Management","description":"Upload images, videos, and HTML. Organize media, create playlists, and preview how content looks on screen."} /-->
<!-- wp:oribi/feature-section {"variant":"alt","label":"What You\u0027ll See","heading":"Full Pro-Tier Access","lead":"The demo includes every feature available on our Pro plan — nothing held back.","columns":3} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-desktop","title":"Content Management","description":"Upload images, videos, and HTML. Organise media, create playlists, and preview how content looks on screen."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Smart Scheduling","description":"Build day-parted schedules, set date ranges, and see how automated playback works across multiple screens."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-line","title":"Live Data Feeds","description":"Connect sample data sources to experience real-time information flowing directly onto display layouts."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-th-large","title":"Template Library","description":"Browse and customise professional templates for menus, promotions, announcements, and informational displays."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users-cog","title":"Team & Permissions","description":"Test role-based access, invite collaborators, and see how multi-user management works across your network."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-th-large","title":"Template Library","description":"Browse and customize professional templates for menus, promotions, announcements, and informational displays."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users-cog","title":"Team \u0026 Permissions","description":"Test role-based access, invite collaborators, and see how multi-user management works across your network."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-pie","title":"Playback Analytics","description":"Explore screen health monitoring, content playback logs, and performance dashboards."} /-->
<!-- /wp:oribi/feature-section -->
<!-- wp:oribi/contact-section {"heading":"Request Demo Access","lead":"Fill in your details below. We'll have your login credentials ready within 24 hours.","email":"hello@ots-signs.com","supportUrl":"https://demo.ots-signs.com/","portalUrl":"https://demo.ots-signs.com/","location":"Online Demo Available 24/7","formHeading":"Get Your Demo Login"} /-->
<!-- wp:oribi/cta-banner {"heading":"Already Convinced?","text":"If you've seen enough and want to get started, jump straight to our plans.","btnText":"View Pricing","btnUrl":"/pricing"} /-->
ORIBI_SYNC_CONTENT;

46
pages/design.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
/*
* Title: Design
* Slug: design
* Post Type: page
*/
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Creative Services","title":"Content That Demands Attention","description":"Great signage starts with great content. Our in-house creative team produces photography, video, motion graphics, and branded layouts — so every screen in your network looks polished, professional, and impossible to ignore."} /-->
<!-- wp:oribi/platform-section {"label":"What We Create","heading":"Professional Content for Every Screen","lead":"We handle the entire creative process — from concept to screen-ready assets — so you can focus on running your business."} -->
<!-- wp:oribi/platform-row {"heading":"Photography That Sells","description":"Our photographers capture your products, venues, and team in the best possible light. Whether it's plated dishes for a digital menu board, hero shots for a retail promotion, or environmental photography for a hotel lobby — every image is composed, lit, and retouched specifically for screen display. No stock photos, no compromises.","btnText":"Get a Quote","btnUrl":"/contact","cameraAnim":true} /-->
<!-- wp:oribi/platform-row {"heading":"Video \u0026amp; Motion Graphics","description":"Short-form video content grabs attention like nothing else. We produce promotional videos, product loops, animated backgrounds, and kinetic typography — all optimised for digital signage playback. From scripting and shooting to editing and export, we deliver files ready to drop straight into your CMS.","btnText":"See Examples","btnUrl":"/contact","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Branded Layout Design","description":"Your screens should feel like a natural extension of your brand. We design custom layouts that match your visual identity — fonts, colours, logo placement, and spacing — across every display format. Whether you need a single hero layout or a full library of templates for your team to reuse, we build it to your spec.","btnUrl":"/features"} /-->
<!-- wp:oribi/platform-row {"heading":"Digital Menu Boards","description":"Menu boards that update in seconds, not hours. We design structured menu layouts with clear categories, pricing, and imagery — then connect them to the platform so you can change a price, swap a photo, or add a seasonal item without touching the design. One update, every screen, instantly.","btnText":"View Platform","btnUrl":"/features","reversed":true} /-->
<!-- /wp:oribi/platform-section -->
<!-- wp:oribi/feature-section {"variant":"alt","label":"How We Work","heading":"From Brief to Screen in Days, Not Weeks","lead":"A straightforward process that gets professional content onto your displays quickly — with revisions built in and no surprises on cost.","columns":3} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-comments","title":"1. Discovery \u0026amp; Brief","description":"We learn about your brand, your audience, and your goals. You tell us what you need — we'll recommend what works best on screen and scope the project."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-pencil","title":"2. Create \u0026amp; Review","description":"We produce your content — photography, video, layouts, or all three — and share drafts for your feedback. Revisions are included until you're completely happy."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"3. Publish \u0026amp; Go Live","description":"Approved content goes straight into your CMS, scheduled and ready to play. We handle the upload so you don't have to lift a finger."} /-->
<!-- /wp:oribi/feature-section -->
<!-- wp:oribi/value-section {"label":"Why In-House","heading":"The Advantage of a Single Partner","lead":"When your creative team and your signage platform are under the same roof, everything moves faster and fits better."} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-display","title":"Designed for Screen","description":"Every asset is created specifically for digital display — correct resolutions, aspect ratios, colour profiles, and file formats. No guesswork, no re-exporting."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-layer-group","title":"Platform-Native Layouts","description":"We design directly within the CMS layout engine, so what you approve in the draft is exactly what plays on screen. No design-to-development handoff."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-arrows-rotate","title":"Ongoing Content Refresh","description":"Screens that never change get ignored. We offer ongoing content packages — monthly or quarterly — to keep your displays fresh, seasonal, and relevant."} /-->
<!-- /wp:oribi/value-section -->
<!-- wp:oribi/stat-section {"variant":"alt","label":"Content Impact","heading":"Why Content Quality Matters","lead":"The difference between signage that works and signage that gets ignored almost always comes down to the content on screen."} -->
<!-- wp:oribi/stat-card {"value":"400%","label":"More Views","description":"Digital displays capture 400% more eyeballs than static signage — but only when the content is worth looking at."} /-->
<!-- wp:oribi/stat-card {"value":"80%","label":"Content Recall","description":"Eight out of ten people remember what they see on a digital display. Professional visuals make that memory count."} /-->
<!-- wp:oribi/stat-card {"value":"30%","label":"Sales Uplift","description":"Retail locations with well-designed digital signage report up to 30% higher in-store sales."} /-->
<!-- /wp:oribi/stat-section -->
<!-- wp:oribi/cta-banner {"heading":"Let's Make Your Screens Look Outstanding","text":"Tell us about your brand, your locations, and what you want your screens to do. We'll put together a creative plan and a clear quote — no obligation.","btnText":"Start a Project","btnUrl":"/contact"} /-->
ORIBI_SYNC_CONTENT;

View File

@@ -1,29 +1,47 @@
<?php
/**
* Title: Player Devices
* Slug: ots-signs/page-devices
* Categories: oribi-pages
* Keywords: devices, hardware, player, screens, HDMI, commercial display
* Post Types: page
/*
* Title: Devices
* Slug: devices
* Post Type: page
*/
?>
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Hardware","title":"Signage Players Engineered for the Real World","description":"Compact, silent, and built for 24/7 operation. Plug into any HDMI screen, connect to your network, and your content is live in minutes."} /-->
<!-- wp:oribi/platform-section {"label":"Our Devices","heading":"Commercial-Grade Hardware, Consumer-Level Simplicity","lead":"No IT degree required. Our players are designed to be set up in minutes and forgotten about for years."} -->
<!-- wp:oribi/platform-row {"heading":"Works With Your Existing Screens","description":"Our player devices connect to any screen with an HDMI port no proprietary hardware required. Already have displays? Plug in and go. Need a full setup? We offer bundled player-and-display packages too.","btnText":"Get a Quote","btnUrl":"/contact","tvStick":true} /-->
<!-- wp:oribi/platform-row {"heading":"Never Goes Dark","description":"Every player caches content locally. If your internet connection drops, your displays continue running seamlessly with the latest synced content. When connectivity returns, new content pulls down automatically — no manual steps, no reboots.","btnText":"See Features","btnUrl":"/features","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Locked Down by Default","description":"Secure boot, encrypted storage, and encrypted communications come standard on every device. Remote management lets you monitor, update, and troubleshoot from anywhere. Firmware updates roll out over the air with zero downtime.","btnText":"Learn More","btnUrl":"/about"} /-->
<!-- wp:oribi/platform-section {"label":"Our Devices","heading":"Commercial-Grade Hardware, Consumer-Level Simplicity","lead":"Our players are designed to be set up in minutes and forgotten about for years. No IT degree required. "} -->
<!-- wp:oribi/platform-row {"heading":"Works With Your Existing Screens","description":"Our player devices connect to any screen with an HDMI port, no proprietary hardware required. Already have displays? Plug in and go. Need a full setup? We offer bundled player-and-display packages too.","btnText":"Get a Quote","btnUrl":"/contact","deviceAnim":true} /-->
<!-- wp:oribi/platform-row {"heading":"Never Goes Dark","description":"Every player caches content locally. If your internet connection drops, your displays continue running seamlessly with the latest synced content. When connectivity returns, new content pulls down automatically. No manual steps, no reboots.","btnText":"See Features","btnUrl":"/features","reversed":true,"neverGoesDark":true} /-->
<!-- wp:oribi/platform-row {"heading":"Custom Display Solutions","description":"Create a polished, on-brand experience with our Custom Display Platform. Seamlessly integrated with your interactive signage, it ensures your logo and branding appear consistently across every screen, reinforcing recognition at every touchpoint. Ideal for businesses looking to elevate their presence and deliver a professional, cohesive visual identity.","btnText":"Get a Quote","btnUrl":"/contact","brandedAnim":true} /-->
<!-- /wp:oribi/platform-section -->
<!-- wp:oribi/feature-section {"variant":"alt","label":"Device Specifications","heading":"What\u0027s Inside Every Player","lead":"Purpose-built components selected for reliability, performance, and silent operation in any environment.","columns":3} -->
<!-- wp:oribi/feature-section {"variant":"alt","label":"Device Specifications","heading":"What's Inside Every Player","lead":"Purpose-built components selected for reliability, performance, and silent operation in any environment."} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-display","title":"4K Output","description":"Crisp 4K resolution over HDMI for stunning visuals on any display size, from 32-inch panels to 75-inch video walls."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Dual Connectivity","description":"Wi-Fi and Ethernet built in. Choose the connection that suits your environment, or use both for redundancy."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Dual Connectivity","description":"We offer players with Wi-Fi and Ethernet connectivity. Choose the connection that suits your environment, or use both for redundancy."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-hard-drive","title":"Local Storage","description":"On-device storage caches your full content library for instant startup and uninterrupted offline playback."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-shield-halved","title":"Secure Boot","description":"Hardware-level security with encrypted storage prevents tampering and ensures only verified software runs."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rotate","title":"Over-the-Air Updates","description":"Firmware updates deploy remotely and automatically. Your devices stay current without site visits or manual intervention."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-temperature-low","title":"Silent & Fanless","description":"Passive cooling means zero noise. Ideal for quiet spaces like hotel lobbies, meeting rooms, and restaurants."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-temperature-low","title":"Silent \u0026amp; Fanless","description":"Passive cooling means zero noise. Ideal for quiet spaces like hotel lobbies, meeting rooms, and restaurants."} /-->
<!-- /wp:oribi/feature-section -->
<!-- wp:oribi/intro-section {"variant":"normal","label":"Bundles Available","heading":"Player + Display Packages","description":"Don\u0027t have screens yet? We offer turnkey bundles pairing our player device with a commercial-grade display rated for 24/7 operation — brighter, tougher, and longer-lasting than consumer TVs. Available from 32\" to 75\". Contact us for volume pricing and custom configurations.","visual":""} /-->
<!-- wp:oribi/cta-banner {"heading":"Not Sure What You Need?","text":"Tell us about your space and we'll recommend the right player, display, and mounting solution for your environment.","btnText":"Request a Quote","btnUrl":"/contact"} /-->
<!-- wp:html -->
<section class="section">
<div class="container">
<div class="devices-split-card">
<div class="devices-split-card__panel">
<h3>Pre-Configured OTS Players</h3>
<p>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.</p>
</div>
<div class="devices-split-card__panel devices-split-card__panel--brand">
<h3>Bring Your Own Player (BYO)</h3>
<p>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.</p>
</div>
</div>
</div>
</section>
<!-- /wp:html -->
ORIBI_SYNC_CONTENT;

View File

@@ -1,33 +1,42 @@
<?php
/**
* Title: FAQ
* Slug: ots-signs/page-faq
* Categories: oribi-pages
* Keywords: faq, questions, answers, support, help
* Post Types: page
/*
* Title: Faq
* Slug: faq
* Post Type: page
*/
?>
<!-- wp:oribi/page-hero-animated {"label":"FAQ","title":"Your Questions, Answered","description":"Everything you need to know about our platform, pricing, setup, and support — in plain language."} /-->
<!-- wp:oribi/faq-section {"label":"Platform \u0026 Pricing","heading":"Plans, Pricing \u0026 What\u0027s Included","lead":"Straightforward answers about what you get and what it costs."} -->
<!-- wp:oribi/faq-item {"question":"What\u0027s included in the Essentials plan?","answer":"Essentials gives you up to 50 screens on a shared CMS instance with a custom subdomain. You get full content scheduling with day-parting, DataSets, RSS feeds, social widgets, embedded HTML, menu boards, interactive layouts, Canva integration, offline playback, Proof of Play analytics with 30-day retention, unlimited users with standard roles, and two-factor authentication. Pricing is $7 per screen per month, or $70 per screen if you pay annually."} /-->
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"FAQ","title":"Your Questions, Answered","description":"Everything you need to know about our platform, pricing, setup, and support, in plain language."} /-->
<!-- wp:oribi/faq-section {"label":"Platform u0026 Pricing","heading":"Plans, Pricing \u0026amp; What's Included","lead":"Straightforward answers about what you get and what it costs."} -->
<!-- wp:oribi/faq-item {"question":"What's included in the Essentials plan?","answer":"Essentials gives you up to 50 screens on a shared CMS instance with a custom subdomain. You get full content scheduling with day-parting, DataSets, RSS feeds, social widgets, embedded HTML, menu boards, interactive layouts, Canva integration, offline playback, Proof of Play analytics with 30-day retention, unlimited users with standard roles, and two-factor authentication. Pricing is $7 per screen per month, or $70 per screen if you pay annually."} /-->
<!-- wp:oribi/faq-item {"question":"What extra do I get with Pro?","answer":"Pro gives you unlimited screens on a dedicated CMS instance with a custom domain. On top of everything in Essentials, you get geo-location and weather-triggered scheduling, video wall support, ad campaigns with SSP monetisation, Dashboard Connector and custom API integrations, Audience Reporting with scheduled PDF reports, Proof of Play with 12+ month retention, SSO via SAML or CAS, custom user roles, extended audit trails, display map view, shell commands, in-house creative services, white-glove onboarding, priority support with a 4-hour SLA, a dedicated account manager, and a contractual SLA guarantee. Contact us for a tailored quote."} /-->
<!-- wp:oribi/faq-item {"question":"Are there any hidden fees?","answer":"None. Your per-screen fee covers the CMS, cloud hosting, software updates, and standard support. Content creation services and hardware are quoted separately and always upfront."} /-->
<!-- wp:oribi/faq-item {"question":"Can I upgrade later?","answer":"Yes — at any time. Moving from Essentials to Pro is seamless. We handle the migration behind the scenes with no disruption to your live displays."} /-->
<!-- wp:oribi/faq-item {"question":"Can I upgrade later?","answer":"Yes, at any time. Moving from Essentials to Pro is seamless. We handle the migration behind the scenes with no disruption to your live displays."} /-->
<!-- /wp:oribi/faq-section -->
<!-- wp:oribi/faq-section {"variant":"alt","label":"Setup \u0026 Integration","heading":"Getting Up and Running","lead":"What to expect when you set up your first screen and connect your systems."} -->
<!-- wp:oribi/faq-item {"question":"How quickly can I be up and running?","answer":"Most installations go live within a day. Plug in the player device, connect it to your network, and your content appears on screen. We configure your CMS in advance and can have your first content loaded and ready before the hardware arrives."} /-->
<!-- wp:oribi/faq-item {"question":"Do I need to buy new screens?","answer":"No. Our players work with any display that has an HDMI port — consumer TVs, commercial panels, or monitors you already own. If you do need screens, we offer bundled player-and-display packages built for commercial use."} /-->
<!-- wp:oribi/faq-item {"question":"How do live data integrations work?","answer":"Every plan includes DataSets, RSS feeds, social widgets, and embedded HTML — data updates appear on screen in real time. Pro adds the Dashboard Connector for secure third-party service connections, custom API integrations for bespoke data sources, and the SSP Connector for ad monetisation."} /-->
<!-- wp:oribi/faq-item {"question":"Do I need to buy new screens?","answer":"No. Our players work with any display that has an HDMI port, consumer TVs, commercial panels, or monitors you already own. If you do need screens, we offer bundled player-and-display packages built for commercial use."} /-->
<!-- wp:oribi/faq-item {"question":"How do live data integrations work?","answer":"Every plan includes DataSets, RSS feeds, social widgets, and embedded HTML, data updates appear on screen in real time. Pro adds the Dashboard Connector for secure third-party service connections, custom API integrations for bespoke data sources, and the SSP Connector for ad monetisation."} /-->
<!-- wp:oribi/faq-item {"question":"What kind of internet connection do I need?","answer":"A standard business broadband connection is more than enough. Our players sync content incrementally and cache everything locally, so bandwidth usage is minimal. For locations with unreliable connectivity, offline playback ensures your displays never go dark."} /-->
<!-- /wp:oribi/faq-section -->
<!-- wp:oribi/faq-section {"label":"Support \u0026 Security","heading":"Keeping Your Network Secure and Supported","lead":"How we protect your content, keep your screens online, and support you when you need us."} -->
<!-- wp:oribi/faq-section {"label":"Support u0026 Security","heading":"Keeping Your Network Secure and Supported","lead":"How we protect your content, keep your screens online, and support you when you need us."} -->
<!-- wp:oribi/faq-item {"question":"What happens if the internet goes down?","answer":"Your displays carry on. Every player caches content locally and keeps playing even without a connection. When the internet returns, new content syncs automatically. Your screens will never go dark because of a network blip."} /-->
<!-- wp:oribi/faq-item {"question":"How secure is the platform?","answer":"Security runs through every layer: end-to-end encryption for all communications, secure boot and encrypted storage on player devices, role-based access control in the CMS, and SOC 2-aligned cloud infrastructure. Your content and your network stay protected."} /-->
<!-- wp:oribi/faq-item {"question":"What support is available?","answer":"Essentials customers get email support with next-business-day response. Pro customers get priority support, a dedicated account manager, phone access, and guaranteed SLA response times."} /-->
<!-- wp:oribi/faq-item {"question":"Can I create my own content or do you handle it?","answer":"Both. The CMS is designed for self-service content creation with drag-and-drop simplicity. If you'd prefer polished visuals, our in-house creative team offers professional photography, video production, and graphic design services."} /-->
<!-- /wp:oribi/faq-section -->
<!-- wp:oribi/cta-banner {"heading":"Something Not Covered Here?","text":"Drop us a message and we'll get back to you with a clear answer usually within one business day.","btnText":"Contact Us","btnUrl":"/contact"} /-->
<!-- wp:oribi/cta-banner {"heading":"Something Not Covered Here?","text":"Drop us a message and we'll get back to you with a clear answer, usually within one business day.","btnText":"Contact Us","btnUrl":"/contact"} /-->
ORIBI_SYNC_CONTENT;

View File

@@ -1,33 +1,72 @@
<?php
/**
/*
* Title: Features
* Slug: ots-signs/page-features
* Categories: oribi-pages
* Keywords: features, platform, content scheduling, cloud CMS, real-time data
* Post Types: page
* Slug: features
* Post Type: page
*/
?>
<!-- wp:oribi/page-hero-animated {"label":"Platform","title":"Powerful Signage, Refreshingly Simple","description":"A cloud-native CMS that lets you publish content to any screen in seconds. Built-in scheduling, live data feeds, and real-time analytics — all wrapped in an interface your whole team can use."} /-->
<!-- wp:oribi/platform-section {"label":"Core Features","heading":"Everything You Need, Nothing You Don\u0027t","lead":"Create, schedule, and manage digital signage content from a single dashboard — whether you have one screen or one thousand."} -->
<!-- wp:oribi/platform-row {"heading":"One Dashboard for Every Display","description":"Manage your entire signage network from a single cloud-based console. Organise screens by location, group, or purpose. Push content updates across your whole estate in one click — no matter how many sites you operate.","btnText":"Get Started","btnUrl":"/contact"} /-->
<!-- wp:oribi/platform-row {"heading":"Scheduling That Runs Itself","description":"Set content to appear at the right time, in the right place, automatically. Day-parting, date ranges, and event-triggered playback let you plan weeks ahead while the platform handles the execution.","btnText":"See Pricing","btnUrl":"/pricing","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Live Data, Straight to Screen","description":"Pull in web dashboards, social feeds, KPIs, and real-time APIs directly to your displays. Content updates automatically — no manual refreshing, no extra steps. Turn any screen into a live information hub.","btnText":"Learn More","btnUrl":"/solutions","reversed":true} /-->
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Platform Features","title":"Create It. Schedule It. Forget It.","description":"Design content in minutes, automate your schedule, and let your screens run themselves. One cloud dashboard for every display in your network — with live data, real-time analytics, and the tools your whole team can use from day one."} /-->
<!-- wp:oribi/platform-section {"label":"Create \u0026amp; Publish","heading":"From Idea to Screen in Minutes","lead":"A drag-and-drop layout designer, a built-in media library, and instant publishing — so your content goes live the moment it's ready."} -->
<!-- wp:oribi/platform-row {"heading":"Design for Any Screen","description":"Build layouts visually with a drag-and-drop editor that works in any browser. Use ready-made stencils or start from scratch. Layer text, images, video, tickers, and data widgets across multiple zones — then preview exactly how it will look on screen before you publish. Save any layout as a reusable template for your team.","btnText":"Request Demo","btnUrl":"/demo"} /-->
<!-- wp:oribi/platform-row {"heading":"Every Media Type, One Library","description":"Upload images, video (including H.265 and HLS streams), PDFs, PowerPoint files, and audio to a centralised media library. Tag, organise, and reuse assets across layouts and playlists. Set expiration dates on media so outdated content removes itself automatically. Need polished creative? Our in-house team handles photography, video production, and graphic design.","btnText":"Creative Services","btnUrl":"/design","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Publish Without the Wait","description":"Content goes live the moment you hit publish. A draft/publish workflow lets you edit layouts safely without affecting what's already on screen — then push updates across your entire network in one click. Schedule a layout to auto-publish at a specific date and time, or push it immediately. No queues, no approval chains, no delays.","btnUrl":"/pricing"} /-->
<!-- /wp:oribi/platform-section -->
<!-- wp:oribi/feature-section {"variant":"alt","label":"Capabilities","heading":"The Tools Behind Great Signage","lead":"From content creation to performance tracking, every feature is designed to save you time and keep your screens looking sharp.","columns":3} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-cloud","title":"Cloud-Native CMS","description":"Log in from any browser, anywhere. No software to install, no servers to maintain. Your content is always accessible and backed up."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Intelligent Scheduling","description":"Day-parting, date-based playlists, and event triggers let you automate content rotation down to the minute."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-wifi","title":"Offline Playback","description":"Content is cached on the player device. If your connection drops, your displays keep running seamlessly until it returns."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited Users","description":"Invite your entire team at no extra cost. No per-seat charges, no access restrictions — on any plan."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-pie","title":"Playback Analytics","description":"Track what\u0027s playing, where, and when. Proof of Play reporting, screen health monitoring, and content logs give you full visibility — with retention depth that scales with your plan."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-shield-halved","title":"Enterprise Security","description":"End-to-end encryption, two-factor authentication, secure boot hardware, and predefined user roles on every plan. Pro adds SSO via SAML or CAS, custom role definitions, and extended audit trails."} /-->
<!-- wp:oribi/feature-section {"variant":"alt","label":"Smart Scheduling","heading":"Automate Your Entire Schedule","lead":"Set it once and let the platform handle the rest. Day-parting, recurring events, location-based triggers, and weather-driven rules keep the right content on the right screen at the right time."} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Day-Part Scheduling","description":"Assign content to specific times of day — breakfast menus in the morning, happy hour promos in the evening. Set it once and it repeats automatically."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-arrows-rotate","title":"Recurring Campaigns","description":"Schedule campaigns with daily, weekly, or custom recurrence patterns. Plan weeks of content ahead and let the platform execute on time, every time."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-location-dot","title":"Location \u0026amp; Weather Triggers","description":"Show region-specific promotions based on player location. Trigger content automatically when weather conditions change — sunscreen ads when it's sunny, hot drinks when it rains."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-bolt","title":"Interrupt \u0026amp; Priority Content","description":"Push emergency alerts or time-sensitive content to any screen instantly. Interrupt layouts override the schedule without disrupting your planned campaigns."} /-->
<!-- /wp:oribi/feature-section -->
<!-- wp:oribi/value-section {"variant":"normal","label":"Why Choose Us","heading":"Beyond the Software","lead":"Great signage takes more than a CMS. Here\u0027s what you get when you work with OTS Signs.","columns":3} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-camera","title":"In-House Creative","description":"Professional photography, video production, and graphic design — so every screen looks polished and on-brand from day one."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"Instant Publishing","description":"Upload your content and push it live across your entire network in seconds. No queues, no waiting, no complex approval chains."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-headset","title":"Support That\u0027s There","description":"From initial setup to ongoing optimisation, our team is available when you need us — not hidden behind a ticket queue."} /-->
<!-- wp:oribi/platform-section {"label":"Display Management","heading":"One Dashboard for Every Screen","lead":"Group, monitor, and control your entire display network — whether that's three screens in one venue or three hundred across the country."} -->
<!-- wp:oribi/platform-row {"heading":"Group, Target, Update","description":"Organise displays into groups by location, department, or purpose. Use dynamic groups that auto-populate based on tags or criteria. Push a content update to one screen, a group, or your whole network — all from one place. Nested groups let you build multi-level hierarchies that mirror your real-world structure.","btnText":"View Devices","btnUrl":"/devices"} /-->
<!-- wp:oribi/platform-row {"heading":"Monitor \u0026amp; Control Remotely","description":"See which screens are online at a glance. Take on-demand or periodic screenshots to verify content is playing correctly. Control screen power, volume, and brightness remotely. Get email alerts the moment a player goes offline. Map view shows every display's location so you always know what's where.","btnUrl":"/contact","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Runs on Your Hardware","description":"Our player software runs on Android, Windows, Linux, Samsung Tizen, LG webOS, and Chrome OS. Portrait or landscape. Single screen or synchronised video wall. Content is cached locally, so your displays keep running seamlessly even when the internet drops. Not sure which hardware to choose? We'll recommend and configure the right player for your setup.","btnText":"See Devices","btnUrl":"/devices"} /-->
<!-- /wp:oribi/platform-section -->
<!-- wp:oribi/feature-section {"variant":"alt","label":"Content Toolkit","heading":"Connect Your World to Screen","lead":"Pull in live data, social feeds, menus, dashboards, and third-party content. Everything updates automatically — no manual refreshing, no extra steps.","columns":3} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-database","title":"Live Data Feeds","description":"Connect DataSets, remote JSON sources, and CSV imports directly to your layouts. Data refreshes automatically so your screens always show the latest information."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-utensils","title":"Digital Menu Boards","description":"Build product categories and pricing lists that update across every location. Change a price once and it's live everywhere — no screen-by-screen editing."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-code","title":"Web Pages \u0026amp; Dashboards","description":"Embed any web page, internal dashboard, or HTML content directly on screen. Show operational KPIs, analytics dashboards, or custom web apps in real time."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-rss","title":"Tickers \u0026amp; Social Feeds","description":"Display RSS news tickers, social media feeds, and live notifications. Keep your audience informed with auto-updating content streams."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-palette","title":"Canva \u0026amp; Stock Images","description":"Design in Canva and publish straight to your displays — no export/import steps. Browse Pixabay's stock image library directly from the CMS."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-hand-pointer","title":"Interactive Touchscreens","description":"Add buttons, navigation, and actions to your layouts. Let your audience browse products, find directions, or explore content on touch-enabled displays."} /-->
<!-- /wp:oribi/feature-section -->
<!-- wp:oribi/feature-section {"label":"Analytics \u0026amp; Reporting","heading":"Prove Every Play","lead":"Know exactly what's playing, where, and when. Export reports, automate delivery, and monitor the health of every screen in your network."} -->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-chart-pie","title":"Proof of Play","description":"Track every piece of content at the layout, media, and widget level. Configurable retention depth lets you store as much history as you need."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-file-pdf","title":"Scheduled Reports","description":"Set up automated PDF reports and have them emailed to stakeholders on your schedule. Export raw data as CSV for deeper analysis."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-heart-pulse","title":"Display Health","description":"Monitor connection status, storage usage, and player performance in real time. Spot issues before they affect your audience."} /-->
<!-- wp:oribi/feature-card {"iconType":"fontawesome","faIcon":"fas fa-box-archive","title":"Content Usage","description":"See which media is assigned to layouts and which is unused. Library usage reports by user help you manage storage and keep your library clean."} /-->
<!-- /wp:oribi/feature-section -->
<!-- wp:oribi/value-section {"variant":"alt","label":"Secure \u0026amp; Scalable","heading":"Enterprise Trust, Simple Setup","lead":"Every plan includes the security foundations your business needs. Scale your team and your network without worrying about per-user fees or access limits.","columns":4} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-lock","title":"Two-Factor Auth","description":"Secure every login with 2FA on every plan. TLS/HTTPS encryption protects all connections between your CMS and player devices."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-user-shield","title":"Roles \u0026amp; Permissions","description":"Predefined admin, editor, and viewer roles on every plan. Pro adds SSO via SAML or CAS, custom role definitions, and feature-level access control."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-clipboard-list","title":"Audit Trail","description":"Full activity logging with configurable retention. Know who changed what, when — for compliance, accountability, and peace of mind."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited Users","description":"Invite your entire team at no extra cost. No per-seat charges, no access restrictions, no gatekeeping — on any plan."} /-->
<!-- /wp:oribi/value-section -->
<!-- wp:oribi/cta-banner {"heading":"Try the Platform Yourself","text":"Get hands-on access to a live demo instance and see every feature in action — no commitment, no credit card.","btnText":"Request Demo","btnUrl":"/demo"} /-->
<!-- wp:oribi/cta-banner {"heading":"More Than Just Software","text":"Our in-house creative team produces professional photography, video, and graphic design for your screens. Our support team is available when you need us — not hidden behind a ticket queue. Get hands-on access to a live demo and see every feature in action.","btnText":"Request Demo","btnUrl":"/demo"} /-->
ORIBI_SYNC_CONTENT;

View File

@@ -8,14 +8,14 @@
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/hero-animated {"label":"● Digital Signage Solutions","title":"Turn any screen into a dynamic communication tool.","highlightWord":"dynamic","description":"Digital signage is the modern way to connect with your audience. From eye-catching retail displays to dynamic informational screens, we craft tailored solutions that capture attention and deliver your message.","secondaryBtnText":"Request Demo","secondaryBtnUrl":"/demo","stat1Value":"4K","stat1Label":"Resolution Supported","stat2Value":"500+","stat2Label":"Screens Supported","stat3Value":"99.9%","stat3Label":"Uptime"} /-->
<!-- wp:oribi/use-cases {"label":"● Use Cases","heading":"Built for Every Scenario","lead":"From menus to meeting-room dashboards, digital signage adapts to your environment.","case1Title":"Menu Boards","case1Desc":"Showcase food, drinks, and daily specials with dynamic, always-current displays.","case2Title":"Event Displays","case2Desc":"Promote schedules, speakers, and live countdowns across lobbies and venues.","case3Title":"Office Dashboards","case3Desc":"Surface KPIs, occupancy data, and team alerts on screens throughout your workspace.","case4Title":"Wayfinding","case4Desc":"Guide visitors through complex buildings with interactive maps and directional signs."} /-->
<!-- wp:oribi/use-cases /-->
<!-- wp:oribi/platform-section {"label":"The Complete Package","heading":"Everything You Need for Engaging Digital Signage","lead":"High-quality visuals, real-time data, and reliable playback all managed from one powerful platform."} -->
<!-- wp:oribi/platform-row {"heading":"Professional Content Creation","description":"Our in-house photography and video production services showcase your products, services, and environment with polished, engaging visuals. From digital menu boards to branded promotions, we create content that captures attention.","btnText":"See Features","btnUrl":"/features","cameraAnim":true} /-->
<!-- wp:oribi/platform-section {"label":"The Complete Package","heading":"Everything You Need for Engaging Digital Signage","lead":"High-quality visuals, real-time data, and reliable playback, all managed from one powerful platform."} -->
<!-- wp:oribi/platform-row {"heading":"Professional Content Creation","description":"Our in-house photography and video production services showcase your products, services, and environment with polished, engaging visuals. From digital menu boards to branded promotions, we create content that captures attention.","btnText":"Creative Services","btnUrl":"/design","cameraAnim":true} /-->
<!-- wp:oribi/platform-row {"heading":"Live Data \u0026amp; Web Dashboards","description":"Integrate your existing web dashboards, social feeds, and real-time data sources directly to your displays. Bring your most important information to life on screen, automatically and effortlessly.","btnUrl":"/features","reversed":true,"isDashboard":true} /-->
<!-- wp:oribi/platform-row {"heading":"Reliable on Any Screen","description":"Our intelligent player devices work on any screen with HDMI, and keep your message running even when the internet goes down. Enterprise-grade hardware designed for uninterrupted, always-on signage.","btnText":"View Devices","btnUrl":"/devices","deviceAnim":true} /-->
<!-- wp:oribi/platform-row {"heading":"Reliable on Any Screen","description":"Our intelligent player devices work on any screen with HDMI, and keep your message running even when the internet goes down. Enterprise-grade hardware designed for uninterrupted, always-on signage.","btnText":"View Devices","btnUrl":"/devices","tvStick":true} /-->
<!-- /wp:oribi/platform-section -->
<!-- wp:oribi/feature-section {"variant":"alt","label":"Who It's For","heading":"Solutions for Every Industry","lead":"Modern businesses need real-time communication. Digital signage helps you connect, inform, and engage.","columns":4} -->

View File

@@ -9,22 +9,22 @@ return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Pricing","title":"Straightforward Pricing, No Surprises","description":"Every plan includes the full content engine. Scale your infrastructure, integrations, and support as you grow. No hidden fees, no per-user charges."} /-->
<!-- wp:oribi/value-section {"label":"Included on Every Plan","heading":"The Full Content Engine, From Day One","lead":"Whether you choose Essentials or Pro, your team gets the same powerful tools to create, schedule, and publish.","columns":4} -->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Automated Scheduling","description":"Day-parting, date ranges, and recurring schedules — your content plays at exactly the right time, automatically."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-clock","title":"Automated Scheduling","description":"Day-parting, date ranges, and recurring schedules. Your content plays at exactly the right time, automatically."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rss","title":"Live Data to Screen","description":"Pull DataSets, RSS feeds, social widgets, and embedded HTML directly to your displays updated in real time."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rss","title":"Live Data to Screen","description":"Pull DataSets, RSS feeds, social widgets, and embedded HTML directly to your displays, updated in real time."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-users","title":"Unlimited Team Access","description":"Invite everyone who needs access. No per-user fees, no seat limits, no gatekeeping."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"Instant Publishing","description":"Upload content and push it live across your network in seconds not hours."} /-->
<!-- wp:oribi/value-card {"iconType":"fontawesome","faIcon":"fas fa-rocket","title":"Instant Publishing","description":"Upload content and push it live across your network in seconds, not hours."} /-->
<!-- /wp:oribi/value-section -->
<!-- wp:oribi/pricing-section {"variant":"alt","label":"Choose Your Plan","heading":"Scale When Youu0027re Ready","lead":"Start with Essentials and upgrade seamlessly as your network grows. No disruption, no data loss."} -->
<!-- wp:oribi/pricing-card {"name":"Essentials","tagline":"The full content engine for growing networks","price":"$7","pricePer":"per screen / month · or $70/screen annually","features":["Up to 50 screens","Custom subdomain","Shared CMS instance","Content scheduling \u0026 day-parting","DataSets, RSS, social \u0026 embedded widgets","Menu boards \u0026 interactive layouts","Unlimited users with standard roles","Canva integration","Offline playback","Proof of Play analytics (30-day retention)","Email support (next-business-day)"]} /-->
<!-- wp:oribi/pricing-section {"variant":"alt","label":"Choose Your Plan","heading":"Scale When You're Ready","lead":"Start with Essentials and upgrade seamlessly as your network grows. No disruption, no data loss."} -->
<!-- wp:oribi/pricing-card {"name":"Essentials","tagline":"The full content engine for growing networks","price":"$7","pricePer":"per screen / month · or $70/screen annually","features":["Up to 50 screens","Custom subdomain","Shared CMS instance","Content scheduling \u0026amp; day-parting","DataSets, RSS, social embedded widgets","Menu boards \u0026amp; interactive layouts","Unlimited users with standard roles","Canva integration","Offline playback","Proof of Play analytics (30-day retention)","Email support (next-business-day)"]} /-->
<!-- wp:oribi/pricing-card {"name":"Pro","tagline":"Dedicated infrastructure, enterprise integrations \u0026 white-glove service","price":"Custom","pricePer":"tailored to your network size","features":["Unlimited screens","Custom domain","Dedicated CMS instance","Geo-location \u0026 weather-triggered scheduling","Dashboard Connector \u0026 custom API integrations","Video wall support","Ad campaigns \u0026 SSP monetisation","SSO (SAML/CAS) \u0026 custom user roles","Proof of Play analytics (12+ month retention)","Audience Reporting \u0026 scheduled PDF reports","Priority support (4-hour SLA) \u0026 account manager","Contractual SLA guarantee"],"btnText":"Contact Sales","featured":true,"badge":"Enterprise"} /-->
<!-- wp:oribi/pricing-card {"name":"Pro","tagline":"Dedicated infrastructure, enterprise integrations u0026 white-glove service","price":"Custom","pricePer":"tailored to your network size","features":["Unlimited screens","Custom domain","Dedicated CMS instance","Geo-location \u0026amp; weather-triggered scheduling","Dashboard Connector \u0026amp; custom API integrations","Video wall support","Ad campaigns \u0026amp; SSP monetisation","SSO (SAML/CAS) \u0026amp; custom user roles","Proof of Play analytics (12+ month retention)","Audience Reporting \u0026amp; scheduled PDF reports","Priority support (4-hour SLA)","Contractual SLA guarantee","Custom Live Data Integrations"],"btnText":"Contact Sales","featured":true,"badge":"Enterprise"} /-->
<!-- /wp:oribi/pricing-section -->
<!-- wp:oribi/comparison-table {"label":"Plan Comparison","heading":"See Exactly Whatu0027s Included","lead":"A full breakdown of what you get on each plan — so there are no surprises.","columns":["Essentials","Pro"],"rows":[{"group":"Scale \u0026 Infrastructure"},{"feature":"Screen limit","values":["Up to 50","Unlimited"]},{"feature":"CMS instance","values":["Shared","Dedicated"]},{"feature":"Custom subdomain","values":[true,true]},{"feature":"Custom domain","values":[false,true]},{"group":"Content \u0026 Scheduling"},{"feature":"Day-parting \u0026 date scheduling","values":[true,true]},{"feature":"Playlists \u0026 campaigns","values":[true,true]},{"feature":"Menu boards","values":[true,true]},{"feature":"Interactive touchscreen actions","values":[true,true]},{"feature":"Overlay layouts","values":[true,true]},{"feature":"Geo-location scheduling","values":[false,true]},{"feature":"Weather-triggered scheduling","values":[false,true]},{"feature":"Video wall","values":[false,true]},{"feature":"Ad campaigns \u0026 plays-per-hour control","values":[false,true]},{"group":"Data \u0026 Integrations"},{"feature":"DataSets, RSS \u0026 tickers","values":[true,true]},{"feature":"Embedded HTML \u0026 web pages","values":[true,true]},{"feature":"Social feeds","values":[true,true]},{"feature":"Canva integration","values":[true,true]},{"feature":"Dashboard Connector","values":[false,true]},{"feature":"Custom API integrations","values":[false,true]},{"feature":"SSP Connector (ad monetisation)","values":[false,true]},{"group":"Analytics \u0026 Reporting"},{"feature":"Proof of Play reporting","values":["30-day retention","12+ month retention"]},{"feature":"Scheduled PDF reports","values":[false,true]},{"feature":"Audience Reporting","values":[false,true]},{"feature":"Display health monitoring","values":[true,true]},{"group":"Users \u0026 Security"},{"feature":"Unlimited user seats","values":[true,true]},{"feature":"Predefined roles (admin/editor/viewer)","values":[true,true]},{"feature":"Custom user roles \u0026 feature access","values":[false,true]},{"feature":"Two-factor authentication","values":[true,true]},{"feature":"SSO (SAML / CAS)","values":[false,true]},{"feature":"Audit trail","values":["7-day retention","Extended retention"]},{"group":"Display Management"},{"feature":"Screen power on/off control","values":[true,true]},{"feature":"Offline playback","values":[true,true]},{"feature":"Portrait / landscape","values":[true,true]},{"feature":"Email alerts (player offline)","values":[true,true]},{"feature":"Periodic screenshots","values":[false,true]},{"feature":"Display map view","values":[false,true]},{"feature":"Shell commands \u0026 RS232","values":[false,true]},{"group":"Support \u0026 Services"},{"feature":"Email support","values":["Next-business-day",true]},{"feature":"Priority support","values":[false,"4-hour SLA"]},{"feature":"Dedicated account manager","values":[false,true]},{"feature":"In-house creative services","values":[false,"Included hours"]},{"feature":"White-glove onboarding","values":[false,true]}]} /-->
<!-- wp:oribi/comparison-table {"label":"Plan Comparison","heading":"See Exactly What's Included","lead":"A full breakdown of what you get on each plan — so there are no surprises.","columns":["Essentials","Pro"],"rows":[{"group":"Scale u0026 Infrastructure"},{"feature":"Screen limit","values":["Up to 50","Unlimited"]},{"feature":"CMS instance","values":["Shared","Dedicated"]},{"feature":"Custom subdomain","values":[true,true]},{"feature":"Custom domain","values":[false,true]},{"group":"Content u0026 Scheduling"},{"feature":"Day-parting u0026 date scheduling","values":[true,true]},{"feature":"Playlists u0026 campaigns","values":[true,true]},{"feature":"Menu boards","values":[true,true]},{"feature":"Interactive touchscreen actions","values":[true,true]},{"feature":"Overlay layouts","values":[true,true]},{"feature":"Geo-location scheduling","values":[false,true]},{"feature":"Weather-triggered scheduling","values":[false,true]},{"feature":"Video wall","values":[false,true]},{"feature":"Ad campaigns u0026 plays-per-hour control","values":[false,true]},{"group":"Data u0026 Integrations"},{"feature":"DataSets, RSS u0026 tickers","values":[true,true]},{"feature":"Embedded HTML u0026 web pages","values":[true,true]},{"feature":"Social feeds","values":[true,true]},{"feature":"Canva integration","values":[true,true]},{"feature":"Dashboard Connector","values":[false,true]},{"feature":"Custom API integrations","values":[false,true]},{"feature":"SSP Connector (ad monetisation)","values":[false,true]},{"feature":"Custom Live Data Integrations","values":[false,true]},{"group":"Analytics u0026 Reporting"},{"feature":"Proof of Play reporting","values":["30-day retention","12+ month retention"]},{"feature":"Scheduled PDF reports","values":[false,true]},{"feature":"Audience Reporting","values":[false,true]},{"feature":"Display health monitoring","values":[true,true]},{"group":"Users u0026 Security"},{"feature":"Unlimited user seats","values":[true,true]},{"feature":"Predefined roles (admin/editor/viewer)","values":[true,true]},{"feature":"Custom user roles u0026 feature access","values":[false,true]},{"feature":"Two-factor authentication","values":[true,true]},{"feature":"SSO (SAML / CAS)","values":[false,true]},{"feature":"Audit trail","values":["7-day retention","Extended retention"]},{"group":"Display Management"},{"feature":"Screen power on/off control","values":[true,true]},{"feature":"Offline playback","values":[true,true]},{"feature":"Portrait / landscape","values":[true,true]},{"feature":"Email alerts (player offline)","values":[true,true]},{"feature":"Periodic screenshots","values":[false,true]},{"feature":"Display map view","values":[false,true]},{"feature":"Shell commands u0026 RS232","values":[false,true]},{"group":"Support u0026 Services"},{"feature":"Email support","values":["Next-business-day",true]},{"feature":"Priority support","values":[false,"4-hour SLA"]},{"feature":"Dedicated account manager","values":[false,true]},{"feature":"In-house creative services","values":[false,"Included hours"]},{"feature":"White-glove onboarding","values":[false,true]},{"feature":"Contractual SLA guarantee","values":[false,true]}]} /-->
<!-- wp:oribi/intro-section {"label":"Try Before You Commit","heading":"Want to Explore the Platform First?","description":"Request access to our live demo instance and take the full CMS for a spin — create content, set up schedules, and see exactly how it works. No credit card, no obligation."} /-->

View File

@@ -1,13 +1,12 @@
<?php
/**
/*
* Title: Resources
* Slug: ots-signs/page-resources
* Categories: oribi-pages
* Keywords: resources, documentation, guides, knowledge base, support
* Post Types: page
* Slug: resources
* Post Type: page
*/
?>
<!-- wp:oribi/page-hero-animated {"label":"Resources","title":"Guides, Docs \u0026 Tools","description":"Everything you need to set up, manage, and get the most out of your digital signage — all in one place."} /-->
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Resources","title":"Guides, Docs u0026 Tools","description":"Everything you need to set up, manage, and get the most out of your digital signage — all in one place."} /-->
<!-- wp:oribi/link-section {"variant":"normal","label":"Getting Started","heading":"Hit the Ground Running","lead":"From first login to first screen, these resources walk you through every step.","columns":3} -->
<!-- wp:oribi/link-card {"iconType":"fontawesome","faIcon":"fas fa-book","title":"Quick Start Guide","description":"Set up your first screen, configure your CMS, and publish content — step by step, start to finish.","linkText":"Read the Guide","linkUrl":"/contact"} /-->
@@ -28,3 +27,4 @@
<!-- /wp:oribi/link-section -->
<!-- wp:oribi/cta-banner {"heading":"Need a Hand?","text":"Our team is happy to walk you through any part of the platform, help with content, or answer questions one-on-one.","btnText":"Contact Us","btnUrl":"/contact"} /-->
ORIBI_SYNC_CONTENT;

View File

@@ -1,28 +1,36 @@
<?php
/**
* Title: Industry Solutions
* Slug: ots-signs/page-solutions
* Categories: oribi-pages
* Keywords: solutions, industries, hospitality, retail, corporate, education, marketplace
* Post Types: page
/*
* Title: Solutions
* Slug: solutions
* Post Type: page
*/
?>
return <<<'ORIBI_SYNC_CONTENT'
<!-- wp:oribi/page-hero-animated {"label":"Industry Solutions","title":"Built for the Way You Work","description":"Every industry communicates differently. Our platform adapts to your environment — whether that's a hotel lobby, a shop floor, a boardroom, or a lecture hall."} /-->
<!-- wp:oribi/platform-section {"label":"Industries We Serve","heading":"One Platform, Tailored to Your Sector","lead":"We've worked with businesses across six key industries. Here's how our platform fits into each one."} -->
<!-- wp:oribi/platform-row {"heading":"Hospitality","description":"Digital menu boards that update with your POS, lobby displays that guide guests, and promotional screens that drive upsells in bars and restaurants. Create a polished guest experience from the moment they walk in — and keep it fresh without touching a single printed sign.","btnText":"Get Started","btnUrl":"/contact"} /-->
<!-- wp:oribi/platform-row {"heading":"Hospitality","description":"Digital menu boards that update with your POS, lobby displays that guide guests, and promotional screens that drive upsells in bars and restaurants. Create a polished guest experience from the moment they walk in — and keep it fresh without touching a single printed sign.","btnText":"Get Started","btnUrl":"/contact","galleryIds":[418,417]} /-->
<!-- wp:oribi/platform-row {"heading":"Retail","description":"Launch promotions across every store instantly, spotlight seasonal products, and guide shoppers with in-store wayfinding. Retailers using digital signage see up to 30% more sales. Our platform makes it simple to keep content current, targeted, and data-driven across every location.","btnText":"See Pricing","btnUrl":"/pricing","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Corporate Office","description":"Meeting room displays with native Microsoft Teams integration, company-wide announcement boards, and live KPI dashboards in common areas. Turn your office into a connected, well-informed workplace where important information is always visible.","btnText":"Learn More","btnUrl":"/features"} /-->
<!-- wp:oribi/platform-row {"heading":"Corporate Office","description":"Meeting room displays with native Microsoft Teams integration, company-wide announcement boards, and live KPI dashboards in common areas. Turn your office into a connected, well-informed workplace where important information is always visible.","btnUrl":"/features"} /-->
<!-- wp:oribi/platform-row {"heading":"Education","description":"Timetable displays, campus wayfinding, emergency alerts, and event boards — all managed centrally. Keep students, faculty, and visitors informed across multiple buildings without the overhead of maintaining individual screens.","btnText":"Contact Us","btnUrl":"/contact","reversed":true} /-->
<!-- wp:oribi/platform-row {"heading":"Outdoor Marketplace","description":"From farmers' markets to seasonal fairs, digital signage adds a professional edge without losing the character of your venue. Weather-resistant display options and built-in offline playback ensure your screens perform reliably, rain or shine.","btnText":"Get a Quote","btnUrl":"/contact"} /-->
<!-- wp:oribi/platform-row {"heading":"Live Data Displays","description":"Bring your web dashboards, real-time KPIs, and operational data to large-format screens. Ideal for operations centres, trading floors, and management war rooms where critical information needs to be visible to the entire team at a glance.","btnText":"See Features","btnUrl":"/features","reversed":true} /-->
<!-- /wp:oribi/platform-section -->
<!-- wp:oribi/stat-section {"variant":"alt","label":"By the Numbers","heading":"The Results Speak for Themselves","lead":"Businesses that invest in digital signage see measurable returns across every metric that matters.","columns":4} -->
<!-- wp:oribi/stat-card {"value":"400%","label":"More Views","description":"Digital displays capture 400% more attention than traditional static signage."} /-->
<!-- wp:oribi/stat-card {"value":"30%","label":"Revenue Uplift","description":"Retail locations with digital signage report up to 30% higher in-store sales."} /-->
<!-- wp:oribi/stat-card {"value":"80%","label":"Content Recall","description":"Eight out of ten customers remember what they see on a digital display."} /-->
<!-- wp:oribi/stat-card {"value":"50%","label":"Shorter Perceived Waits","description":"Engaging displays cut perceived wait times in half for customers in queues."} /-->
<!-- wp:oribi/stat-card {"value":"400%","label":"More Views","description":"Digital displays capture 400% more attention than traditional static signage. <a href='https://mvix.com/blog/digital-signage-statistics/' target='_blank' rel='noopener'>Mvix Research →</a>"} /-->
<!-- wp:oribi/stat-card {"value":"30%","label":"Revenue Uplift","description":"Retail locations with digital signage report up to 30% higher in-store sales. <a href='https://www.digitalsignagetoday.com/news/nielsen-study-dooh-increases-revenue-at-the-point-of-sale-2/' target='_blank' rel='noopener'>Nielsen DOOH Study →</a>"} /-->
<!-- wp:oribi/stat-card {"value":"80%","label":"Content Recall","description":"Eight out of ten customers remember what they see on a digital display. <a href='https://www.databeat.net/databeatblog/15-surprising-statistics-about-digital-signage' target='_blank' rel='noopener'>Databeat Research →</a>"} /-->
<!-- wp:oribi/stat-card {"value":"50%","label":"Shorter Perceived Waits","description":"Engaging displays cut perceived wait times in half for customers in queues. <a href='https://www.digitalsignagetoday.com/articles/the-business-case-for-digital-signage-in-the-waiting-line/' target='_blank' rel='noopener'>Digital Signage Today →</a>"} /-->
<!-- /wp:oribi/stat-section -->
<!-- wp:oribi/cta-banner {"heading":"Let Us Match You to the Right Setup","text":"Tell us about your industry, your locations, and what you want your screens to do. We'll recommend the ideal configuration.","btnText":"Talk to an Expert","btnUrl":"/contact"} /-->
ORIBI_SYNC_CONTENT;

File diff suppressed because it is too large Load Diff

View File

@@ -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();
}
})();

View File

@@ -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);
}
})();

View File

@@ -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();
}
})();

View File

@@ -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 = '<div class="da-screen"><div class="da-promo"><div class="da-promo__top"><span class="da-promo__dot"></span><span class="da-promo__brand"></span></div><div class="da-promo__hero"></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--lg"></span><span class="da-promo__line da-promo__line--sm"></span></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--md"></span><span class="da-promo__line da-promo__line--xs"></span></div><div class="da-promo__ticker"><span class="da-promo__chip"></span><span class="da-promo__chip"></span><span class="da-promo__chip"></span></div></div></div>';
var DA_HTML = '<div class="da-stage" aria-hidden="true">' +
'<div class="da-device da-tablet"><div class="da-body">' + DA_SCREEN + '</div><span class="da-label">Tablet</span></div>' +
'<div class="da-device da-monitor-sm"><div class="da-body">' + DA_SCREEN + '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Small Monitor</span></div>' +
'<div class="da-device da-monitor-lg"><div class="da-body">' + DA_SCREEN + '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Large Monitor</span></div>' +
'<div class="da-device da-tv"><div class="da-body">' + DA_SCREEN + '</div><div class="da-feet"><div class="da-foot"></div><div class="da-foot"></div></div><span class="da-label">TV</span></div>' +
'<div class="da-device da-projector"><div class="da-proj-layout"><div class="da-proj-body"><div class="da-lens"></div></div><div class="da-beam"></div><div class="da-proj-screen">' + DA_SCREEN + '</div></div><span class="da-label">Projector</span></div>' +
'<div class="da-device da-vwall"><div class="da-vwall-grid"><div class="da-panel">' + DA_SCREEN + '</div><div class="da-panel">' + DA_SCREEN + '</div><div class="da-panel">' + DA_SCREEN + '</div><div class="da-panel">' + DA_SCREEN + '</div></div><span class="da-label">Video Wall</span></div>' +
'</div>';
var TS_MI = '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
var TS_COL = '<div class="ts-menu__col"><div class="ts-menu__cat"></div>' + TS_MI + TS_MI + TS_MI + '</div>';
var TS_HTML = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">' +
'<div class="ts-tv"><div class="ts-tv__body"><div class="ts-tv__screen"><div class="ts-slides">' +
'<div class="ts-slide ts-slide--menu"><div class="ts-menu"><div class="ts-menu__header"><div class="ts-menu__logo"></div><div class="ts-menu__title"></div></div><div class="ts-menu__cols">' + TS_COL + TS_COL + '</div></div></div>' +
'<div class="ts-slide ts-slide--wayfind"><div class="ts-wf"><div class="ts-wf__header"><div class="ts-wf__building"></div></div><div class="ts-wf__rows"><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w1"></span><span class="ts-wf__floor"></span></div><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--right"></span><span class="ts-wf__label ts-wf__label--w2"></span><span class="ts-wf__floor"></span></div><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--up"></span><span class="ts-wf__label ts-wf__label--w3"></span><span class="ts-wf__floor"></span></div><div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w4"></span><span class="ts-wf__floor"></span></div></div></div></div>' +
'<div class="ts-slide ts-slide--sched"><div class="ts-sched"><div class="ts-sched__header"><div class="ts-sched__title"></div><div class="ts-sched__date"></div></div><div class="ts-sched__table"><div class="ts-sched__hrow"><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--c"></span></div><div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div></div></div></div>' +
'</div></div><div class="ts-tv__port"></div></div><div class="ts-tv__feet"><div class="ts-tv__foot"></div><div class="ts-tv__foot"></div></div></div>' +
'<div class="ts-stick"><div class="ts-stick__body"><div class="ts-stick__led"></div></div><div class="ts-stick__connector"></div></div>' +
'</div>';
var NGD_ROW = '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
var NGD_ROWH = '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
var NGD_HTML = '<div class="ngd-stage" aria-hidden="true">' +
'<div class="ngd-tv"><div class="ngd-tv__body"><div class="ngd-tv__screen"><div class="ngd-menu"><div class="ngd-menu__hd"><div class="ngd-menu__logo"></div><div class="ngd-menu__ttl"></div></div><div class="ngd-menu__cols"><div class="ngd-menu__col"><div class="ngd-menu__cat"></div>' + NGD_ROW + NGD_ROWH + NGD_ROW + '</div><div class="ngd-menu__col"><div class="ngd-menu__cat"></div>' + NGD_ROW + NGD_ROW + NGD_ROWH + '</div></div><div class="ngd-menu__ticker"><div class="ngd-menu__ticker-inner"></div></div></div></div><div class="ngd-tv__port"></div></div><div class="ngd-tv__feet"><div class="ngd-tv__foot"></div><div class="ngd-tv__foot"></div></div></div>' +
'<div class="ngd-player"><div class="ngd-player__connector"></div><div class="ngd-player__body"><div class="ngd-player__led"></div></div><div class="ngd-player__check"><svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="11" cy="11" r="10" stroke="#4CAF50" stroke-width="1.5"/><polyline points="6,11 9.5,14.5 16,7.5" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></div></div>' +
'<div class="ngd-signal-wrap"><div class="ngd-cloud"><svg class="ngd-cloud__svg" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg"><circle class="ngd-cloud__path" cx="32" cy="23" r="14" stroke-width="2.2" fill="none"/><path class="ngd-cloud__path" d="M18.5 23C23 20 41 20 45.5 23" stroke-width="1.9" stroke-linecap="round" fill="none"/><path class="ngd-cloud__path" d="M20.5 29C25.5 31 38.5 31 43.5 29" stroke-width="1.9" stroke-linecap="round" fill="none"/><path class="ngd-cloud__path" d="M24.5 12C21.5 16.5 21.5 29.5 24.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/><path class="ngd-cloud__path" d="M39.5 12C42.5 16.5 42.5 29.5 39.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/></svg></div><div class="ngd-signal-line"><div class="ngd-signal__dots"><div class="ngd-signal__dot ngd-signal__dot--1"></div><div class="ngd-signal__dot ngd-signal__dot--2"></div><div class="ngd-signal__dot ngd-signal__dot--3"></div></div><div class="ngd-signal__break"><svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="9" cy="9" r="8" fill="rgba(239,68,68,0.12)" stroke="#ef4444" stroke-width="1.2"/><line x1="5.5" y1="5.5" x2="12.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/><line x1="12.5" y1="5.5" x2="5.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/></svg></div></div></div>' +
'</div>';
var BD_SPLASH = '<div class="bd-splash"><div class="bd-splash__logo"></div></div>';
var BD_HDR = '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
var BD_HTML = '<div class="bd-stage" aria-hidden="true">' +
'<div class="bd-device bd-device--tablet"><span class="bd-device__label">Kiosk</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--welcome"><div class="bd-promo__hero"></div><div class="bd-promo__heading"></div><div class="bd-promo__text"></div><div class="bd-promo__btn"></div></div></div></div></div></div></div>' +
'<div class="bd-device bd-device--wall"><span class="bd-device__label">Wall Display</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--sale"><div class="bd-promo__cols"><div class="bd-promo__visual"></div><div class="bd-promo__info"><div class="bd-promo__badge"></div><div class="bd-promo__heading"></div><div class="bd-promo__text"></div><div class="bd-promo__text bd-promo__text--short"></div><div class="bd-promo__price"></div></div></div></div></div></div></div></div><div class="bd-mount"></div></div>' +
'<div class="bd-device bd-device--interactive"><span class="bd-device__label">Interactive</span><div class="bd-device__body"><div class="bd-device__screen">' + BD_SPLASH + '<div class="bd-ui">' + BD_HDR + '<div class="bd-ui__content"><div class="bd-promo bd-promo--menu"><div class="bd-promo__heading"></div><div class="bd-promo__grid"><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div><div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div></div></div></div></div></div></div><div class="bd-table"></div></div>' +
'</div>';
var DB_HTML = '<div class="dashboard-tv" data-dashboard-container="true"><div class="dashboard-tv__body"><div class="dashboard-tv__screen"><svg viewBox="0 0 800 450" xmlns="http://www.w3.org/2000/svg" class="dashboard-chart" role="img" aria-label="Animated dashboard charts"><defs><linearGradient id="dbe-barGrad" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#D83302" stop-opacity="1"/><stop offset="100%" stop-color="#4CAF50" stop-opacity=".8"/></linearGradient><linearGradient id="dbe-lineGrad" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#4CAF50" stop-opacity=".3"/><stop offset="100%" stop-color="#4CAF50" stop-opacity="0"/></linearGradient></defs><g transform="translate(35,20)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Performance</text><g id="dbe-bars1" transform="translate(0,25)"><rect x="0" y="60" width="28" height="60" fill="url(#dbe-barGrad)"/><rect x="40" y="80" width="28" height="40" fill="url(#dbe-barGrad)"/><rect x="80" y="40" width="28" height="80" fill="url(#dbe-barGrad)"/><rect x="120" y="70" width="28" height="50" fill="url(#dbe-barGrad)"/><rect x="160" y="50" width="28" height="70" fill="url(#dbe-barGrad)"/></g><g transform="translate(0,152)"><text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#aaa">API</text><text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#aaa">Cache</text><text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#aaa">DB</text><text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#aaa">Queue</text><text class="cl" x="174" y="0" font-size="10" text-anchor="middle" fill="#aaa">Worker</text></g></g><g transform="translate(430,20)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Requests/sec</text><g transform="translate(0,25)"><rect x="0" y="50" width="28" height="70" fill="url(#dbe-barGrad)"/><rect x="40" y="30" width="28" height="90" fill="url(#dbe-barGrad)"/><rect x="80" y="65" width="28" height="55" fill="url(#dbe-barGrad)"/><rect x="120" y="45" width="28" height="75" fill="url(#dbe-barGrad)"/></g><g transform="translate(0,152)"><text class="cl" x="14" y="0" font-size="10" text-anchor="middle" fill="#aaa">Read</text><text class="cl" x="54" y="0" font-size="10" text-anchor="middle" fill="#aaa">Write</text><text class="cl" x="94" y="0" font-size="10" text-anchor="middle" fill="#aaa">Update</text><text class="cl" x="134" y="0" font-size="10" text-anchor="middle" fill="#aaa">Delete</text></g></g><g transform="translate(35,245)"><text class="ct" x="0" y="0" font-size="14" font-weight="600" fill="#888">Traffic Trend</text><g transform="translate(0,25)"><line class="grid-line" x1="0" y1="0" x2="340" y2="0" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="40" x2="340" y2="40" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="80" x2="340" y2="80" stroke="#ddd" stroke-width=".5"/><line class="grid-line" x1="0" y1="120" x2="340" y2="120" stroke="#ddd" stroke-width=".5"/><path d="M0,90 L42,70 L85,50 L127,80 L170,45 L212,65 L255,55 L297,75 L340,60 L340,145 L0,145 Z" fill="url(#dbe-lineGrad)"/><path d="M0,90 L42,70 L85,50 L127,80 L170,45 L212,65 L255,55 L297,75 L340,60" stroke="#4CAF50" stroke-width="2.5" fill="none" stroke-linecap="round"/></g></g><g transform="translate(490,245)"><text class="ct" x="100" y="0" font-size="14" font-weight="600" text-anchor="middle" fill="#888">Distribution</text><g transform="translate(100,90)"><path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#D83302" opacity=".9"/><path d="M0,0 L38.89,-38.89 A55,55 0 0,1 55,0 Z" fill="#4CAF50" opacity=".8"/><path d="M0,0 L55,0 A55,55 0 0,1 0,55 Z" fill="#f59e0b" opacity=".7"/><path d="M0,0 L0,55 A55,55 0 1,1 0,-55 Z" fill="#ef4444" opacity=".7"/><circle cx="0" cy="0" r="22" fill="#f5f5f5" stroke="#ddd" stroke-width="1"/></g></g></svg></div></div><div class="dashboard-tv__feet"><div class="dashboard-tv__foot"></div><div class="dashboard-tv__foot"></div></div></div>';
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')
)
)
)

View File

@@ -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',
@@ -690,9 +694,8 @@ function oribi_render_site_header() {
<div class="site-logo">
<?php if ( $has_logo ) : ?>
<?php the_custom_logo(); ?>
<?php else : ?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="logo-text"><strong>Oribi</strong> Tech</a>
<?php endif; ?>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" class="logo-text"><strong>OTS</strong> Signs</a>
</div>
<button class="nav-toggle" id="nav-toggle" aria-expanded="false" aria-label="<?php esc_attr_e( 'Toggle navigation', 'ots-theme' ); ?>">
<span></span><span></span><span></span>
@@ -1353,6 +1356,208 @@ function oribi_render_platform_section( $a, $content ) {
}
/* ── Platform Row (child - renders one service row) ────────────────────────── */
function oribi_render_camera_animation() {
return <<<'HTML'
<div class="ve-stage" aria-hidden="true"><svg viewBox="0 0 540 360" xmlns="http://www.w3.org/2000/svg" class="ve-svg" role="img" aria-label="Animated video editor timeline">
<defs>
<clipPath id="ve-preview-clip">
<rect x="54" y="36" width="256" height="184"/>
</clipPath>
<linearGradient id="ve-sg-warm" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#3d0800"/>
<stop offset="50%" stop-color="#a02500"/>
<stop offset="100%" stop-color="#1d0400"/>
</linearGradient>
<linearGradient id="ve-sg-cold" x1="100%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#0a1f3d"/>
<stop offset="50%" stop-color="#0e3d6e"/>
<stop offset="100%" stop-color="#06111e"/>
</linearGradient>
<linearGradient id="ve-sg-go" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#07180d"/>
<stop offset="50%" stop-color="#1c6038"/>
<stop offset="100%" stop-color="#040e07"/>
</linearGradient>
<linearGradient id="ve-scr-warm" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#ff9500"/>
<stop offset="100%" stop-color="#ff4500"/>
</linearGradient>
<linearGradient id="ve-scr-cold" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#1a8aff"/>
<stop offset="100%" stop-color="#0055cc"/>
</linearGradient>
<linearGradient id="ve-scr-go" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#00cc66"/>
<stop offset="100%" stop-color="#008844"/>
</linearGradient>
<pattern id="ve-scanlines" x="0" y="0" width="1" height="3" patternUnits="userSpaceOnUse">
<rect width="1" height="1" fill="rgba(0,0,0,0.18)"/>
</pattern>
</defs>
<!-- Laptop lid outer shell -->
<rect x="20" y="5" width="500" height="300" rx="12" fill="#d2d2d0" stroke="#b0aca8" stroke-width="1.5"/>
<rect x="28" y="12" width="484" height="280" rx="8" fill="#1c1c1c"/>
<rect x="32" y="16" width="476" height="272" rx="5" fill="#0e1117"/>
<!-- Laptop base -->
<rect x="10" y="305" width="520" height="26" rx="5" fill="#c8c8c8" stroke="#b0ada8" stroke-width="0.8"/>
<rect x="80" y="301" width="380" height="5" rx="2" fill="#a8a6a2"/>
<rect x="205" y="311" width="130" height="13" rx="5" fill="#b8b5b0" stroke="#a0a09a" stroke-width="0.7"/>
<rect x="38" y="306" width="155" height="18" rx="2" fill="#bcbab6" opacity="0.45"/>
<rect x="347" y="306" width="155" height="18" rx="2" fill="#bcbab6" opacity="0.45"/>
<!-- Editor title bar -->
<rect x="32" y="16" width="476" height="20" rx="4" fill="#1e2229"/>
<circle cx="50" cy="26" r="5" fill="#FF5F56"/>
<circle cx="66" cy="26" r="5" fill="#FFBD2E"/>
<circle cx="82" cy="26" r="5" fill="#27C93F"/>
<rect x="180" y="21" width="180" height="10" rx="3" fill="#3a3f48"/>
<rect x="100" y="22" width="28" height="8" rx="2" fill="#2e333c"/>
<rect x="132" y="22" width="24" height="8" rx="2" fill="#2e333c"/>
<rect x="160" y="22" width="16" height="8" rx="2" fill="#2e333c"/>
<!-- Left toolbar -->
<rect x="32" y="36" width="22" height="184" fill="#181c22"/>
<line x1="54" y1="36" x2="54" y2="220" stroke="#2a2e38" stroke-width="1"/>
<rect x="36" y="46" width="14" height="14" rx="2" fill="#3a4152"/>
<rect x="36" y="66" width="14" height="14" rx="2" fill="#3a4152"/>
<rect x="36" y="86" width="14" height="14" rx="2" fill="#3a4152"/>
<rect x="36" y="106" width="14" height="14" rx="2" fill="#3a4152"/>
<rect x="36" y="126" width="14" height="14" rx="2" fill="#3a4152"/>
<rect x="33" y="46" width="3" height="14" rx="1" fill="#D83302"/>
<!-- Preview pane -->
<rect x="54" y="36" width="256" height="184" fill="#0a0b0e"/>
<g clip-path="url(#ve-preview-clip)">
<rect id="ve-scene-1" x="54" y="36" width="256" height="184" fill="url(#ve-sg-warm)" opacity="1"/>
<rect id="ve-scene-2" x="54" y="36" width="256" height="184" fill="url(#ve-sg-cold)" opacity="0"/>
<rect id="ve-scene-3" x="54" y="36" width="256" height="184" fill="url(#ve-sg-go)" opacity="0"/>
<!-- Laptop in the preview video -->
<rect x="102" y="52" width="156" height="106" rx="5" fill="#1c1c1c" stroke="#2e2e2e" stroke-width="1"/>
<rect x="106" y="56" width="148" height="98" rx="3" fill="#111111"/>
<rect id="ve-inner-screen" x="108" y="58" width="144" height="94" rx="1" fill="url(#ve-scr-warm)"/>
<polygon points="108,58 160,58 108,88" fill="white" opacity="0.04"/>
<rect x="108" y="58" width="144" height="94" fill="url(#ve-scanlines)" opacity="0.45"/>
<circle cx="180" cy="55" r="2.5" fill="#232323" stroke="#2e2e2e" stroke-width="0.5"/>
<rect x="92" y="158" width="176" height="17" rx="2" fill="#222222" stroke="#2d2d2d" stroke-width="0.5"/>
<rect x="150" y="162" width="60" height="9" rx="3" fill="#2a2a2a" stroke="#353535" stroke-width="0.5"/>
<rect x="97" y="159" width="166" height="1" fill="#2c2c2c"/>
<line x1="54" y1="175" x2="310" y2="175" stroke="#1c1c1c" stroke-width="2"/>
<rect x="54" y="175" width="256" height="45" fill="#040507" opacity="0.75"/>
<rect x="54" y="36" width="256" height="184" fill="url(#ve-scanlines)" opacity="0.25"/>
</g>
<rect x="54" y="36" width="256" height="184" fill="none" stroke="#2a2e38" stroke-width="0.5"/>
<line x1="310" y1="36" x2="310" y2="220" stroke="#2a2e38" stroke-width="1"/>
<!-- Inspector / Properties panel -->
<rect x="310" y="36" width="198" height="184" fill="#141619"/>
<rect x="310" y="36" width="198" height="20" fill="#1a1e25"/>
<rect x="318" y="42" width="80" height="8" rx="2" fill="#3a3f48"/>
<rect x="318" y="64" width="50" height="7" rx="2" fill="#2a2e38"/>
<rect x="378" y="64" width="82" height="7" rx="2" fill="#333a45"/>
<rect x="318" y="78" width="45" height="7" rx="2" fill="#2a2e38"/>
<rect x="378" y="78" width="96" height="7" rx="2" fill="#333a45"/>
<rect x="318" y="92" width="35" height="7" rx="2" fill="#2a2e38"/>
<rect x="378" y="92" width="62" height="7" rx="2" fill="#333a45"/>
<rect x="318" y="106" width="55" height="7" rx="2" fill="#2a2e38"/>
<rect x="378" y="106" width="72" height="7" rx="2" fill="#333a45"/>
<rect x="318" y="120" width="40" height="7" rx="2" fill="#2a2e38"/>
<rect x="378" y="120" width="54" height="7" rx="2" fill="#333a45"/>
<line x1="318" y1="136" x2="498" y2="136" stroke="#2a2e38" stroke-width="0.5"/>
<rect x="310" y="136" width="198" height="12" fill="#1a1e25"/>
<rect x="318" y="140" width="60" height="6" rx="2" fill="#2a2e38"/>
<rect x="318" y="150" width="32" height="24" rx="1" fill="#C0390A" opacity="0.8"/>
<rect x="354" y="150" width="32" height="24" rx="1" fill="#1a52c8" opacity="0.8"/>
<rect x="390" y="150" width="32" height="24" rx="1" fill="#1a7a3d" opacity="0.8"/>
<rect x="426" y="150" width="32" height="24" rx="1" fill="#c07800" opacity="0.8"/>
<rect x="462" y="150" width="32" height="24" rx="1" fill="#7030d0" opacity="0.8"/>
<!-- Timeline section -->
<rect x="32" y="220" width="476" height="68" fill="#161616"/>
<line x1="32" y1="220" x2="508" y2="220" stroke="#2a2e38" stroke-width="1"/>
<rect x="32" y="220" width="476" height="14" fill="#1a1e24"/>
<rect x="32" y="220" width="72" height="68" fill="#1a1e24"/>
<line x1="104" y1="220" x2="104" y2="288" stroke="#2a2e38" stroke-width="1"/>
<!-- Ruler ticks and labels -->
<line x1="104" y1="220" x2="104" y2="232" stroke="#4a4e58" stroke-width="1"/>
<text x="105" y="231" fill="#565a64" font-size="8" font-family="monospace">0:00</text>
<line x1="184" y1="220" x2="184" y2="232" stroke="#4a4e58" stroke-width="1"/>
<text x="185" y="231" fill="#565a64" font-size="8" font-family="monospace">0:02</text>
<line x1="264" y1="220" x2="264" y2="232" stroke="#4a4e58" stroke-width="1"/>
<text x="265" y="231" fill="#565a64" font-size="8" font-family="monospace">0:04</text>
<line x1="344" y1="220" x2="344" y2="232" stroke="#4a4e58" stroke-width="1"/>
<text x="345" y="231" fill="#565a64" font-size="8" font-family="monospace">0:06</text>
<line x1="424" y1="220" x2="424" y2="232" stroke="#4a4e58" stroke-width="1"/>
<text x="425" y="231" fill="#565a64" font-size="8" font-family="monospace">0:08</text>
<line x1="144" y1="220" x2="144" y2="226" stroke="#2e3240" stroke-width="0.5"/>
<line x1="224" y1="220" x2="224" y2="226" stroke="#2e3240" stroke-width="0.5"/>
<line x1="304" y1="220" x2="304" y2="226" stroke="#2e3240" stroke-width="0.5"/>
<line x1="384" y1="220" x2="384" y2="226" stroke="#2e3240" stroke-width="0.5"/>
<line x1="464" y1="220" x2="464" y2="226" stroke="#2e3240" stroke-width="0.5"/>
<!-- Track label colour strips -->
<rect x="36" y="237" width="56" height="14" rx="2" fill="#283040"/>
<rect x="36" y="255" width="56" height="14" rx="2" fill="#203020"/>
<rect x="36" y="273" width="56" height="14" rx="2" fill="#302818"/>
<!-- Track 1: VIDEO clips -->
<rect x="104" y="234" width="404" height="18" fill="#1a1a22"/>
<rect x="104" y="235" width="88" height="16" rx="2" fill="#2563EB"/>
<rect x="104" y="235" width="88" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<rect x="196" y="235" width="66" height="16" rx="2" fill="#1D4ED8"/>
<rect x="196" y="235" width="66" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<rect x="266" y="235" width="106" height="16" rx="2" fill="#2563EB"/>
<rect x="266" y="235" width="106" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<rect x="376" y="235" width="88" height="16" rx="2" fill="#1E40AF"/>
<rect x="376" y="235" width="88" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<!-- Track 2: AUDIO/MUSIC clips -->
<rect x="104" y="252" width="404" height="18" fill="#141c12"/>
<rect x="104" y="253" width="178" height="16" rx="2" fill="#15803D"/>
<rect x="104" y="253" width="178" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
<!-- Inline waveform bars -->
<rect x="108" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
<rect x="112" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
<rect x="116" y="260" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
<rect x="120" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
<rect x="124" y="260" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
<rect x="128" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
<rect x="132" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
<rect x="136" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
<rect x="140" y="260" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
<rect x="144" y="258" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
<rect x="148" y="261" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
<rect x="152" y="258" width="2" height="6" fill="rgba(255,255,255,0.22)"/>
<rect x="156" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
<rect x="160" y="257" width="2" height="7" fill="rgba(255,255,255,0.22)"/>
<rect x="164" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
<rect x="168" y="257" width="2" height="8" fill="rgba(255,255,255,0.22)"/>
<rect x="172" y="261" width="2" height="4" fill="rgba(255,255,255,0.22)"/>
<rect x="176" y="259" width="2" height="5" fill="rgba(255,255,255,0.22)"/>
<rect x="286" y="253" width="148" height="16" rx="2" fill="#166534"/>
<rect x="286" y="253" width="148" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
<rect x="438" y="253" width="66" height="16" rx="2" fill="#15803D"/>
<rect x="438" y="253" width="66" height="5" rx="2" fill="rgba(255,255,255,0.06)"/>
<!-- Track 3: GFX / TEXT clips -->
<rect x="104" y="270" width="404" height="18" fill="#181710"/>
<rect x="120" y="271" width="60" height="16" rx="2" fill="#D97706"/>
<rect x="120" y="271" width="60" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<rect x="226" y="271" width="52" height="16" rx="2" fill="#B45309"/>
<rect x="226" y="271" width="52" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<rect x="334" y="271" width="78" height="16" rx="2" fill="#D97706"/>
<rect x="334" y="271" width="78" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<rect x="452" y="271" width="50" height="16" rx="2" fill="#B45309"/>
<rect x="452" y="271" width="50" height="5" rx="2" fill="rgba(255,255,255,0.07)"/>
<!-- Animated playhead -->
<polygon id="ve-playhead-head" points="0,-8 -6,-2 6,-2" transform="translate(104,234)" fill="#FF4500"/>
<rect id="ve-playhead-line" x="103" y="220" width="2" height="68" fill="#FF4500" opacity="0.92"/>
<!-- Timecode display -->
<text id="ve-timecode" x="36" y="230" fill="#8a8e98" font-size="8" font-family="monospace">0:00</text>
</svg></div>
HTML;
}
function oribi_render_platform_row( $a ) {
$rev = ! empty( $a['reversed'] ) ? ' reverse' : '';
$img_id = ! empty( $a['imgId'] ) ? intval( $a['imgId'] ) : 0;
@@ -1373,7 +1578,7 @@ function oribi_render_platform_row( $a ) {
<svg viewBox="0 0 800 450" xmlns="http://www.w3.org/2000/svg" class="dashboard-chart" role="img" aria-label="Animated dashboard charts">
<defs>
<linearGradient id="barGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#004225" stop-opacity="1"/>
<stop offset="0%" stop-color="#D83302" stop-opacity="1"/>
<stop offset="100%" stop-color="#4CAF50" stop-opacity=".8"/>
</linearGradient>
<linearGradient id="lineGradient" x1="0%" y1="0%" x2="0%" y2="100%">
@@ -1451,7 +1656,7 @@ function oribi_render_platform_row( $a ) {
<text class="ct" x="100" y="0" font-size="14" font-weight="600" text-anchor="middle" fill="#333">Distribution</text>
<g transform="translate(100,90)">
<g class="pie-segment" transform="rotate(0)">
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#004225" opacity=".9"/>
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#D83302" opacity=".9"/>
</g>
<g class="pie-segment" transform="rotate(90)">
<path d="M0,0 L0,-55 A55,55 0 0,1 38.89,-38.89 Z" fill="#4CAF50" opacity=".8"/>
@@ -1466,7 +1671,7 @@ function oribi_render_platform_row( $a ) {
<text id="pie-center-text" x="0" y="5" text-anchor="middle" font-size="13" font-weight="600" fill="#333">100%</text>
</g>
<g transform="translate(30,170)">
<rect x="0" y="0" width="8" height="8" fill="#004225"/>
<rect x="0" y="0" width="8" height="8" fill="#D83302"/>
<text class="cl" x="12" y="8" font-size="11" fill="#666">Service A</text>
<rect x="0" y="15" width="8" height="8" fill="#4CAF50"/>
<text class="cl" x="12" y="23" font-size="11" fill="#666">Service B</text>
@@ -1490,13 +1695,14 @@ function oribi_render_platform_row( $a ) {
}
$visual_cls = 'platform-visual has-img';
} elseif ( ! empty( $a['deviceAnim'] ) ) {
$da_screen = '<div class="da-screen"><div class="da-promo"><div class="da-promo__top"><span class="da-promo__dot"></span><span class="da-promo__brand"></span></div><div class="da-promo__hero"></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--lg"></span><span class="da-promo__line da-promo__line--sm"></span></div><div class="da-promo__row"><span class="da-promo__line da-promo__line--md"></span><span class="da-promo__line da-promo__line--xs"></span></div><div class="da-promo__ticker"><span class="da-promo__chip"></span><span class="da-promo__chip"></span><span class="da-promo__chip"></span></div></div></div>';
$da = '<div class="da-stage" aria-hidden="true">';
$da .= '<div class="da-device da-tablet"><div class="da-body"><div class="da-screen"></div></div><span class="da-label">Tablet</span></div>';
$da .= '<div class="da-device da-monitor-sm"><div class="da-body"><div class="da-screen"></div></div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Small Monitor</span></div>';
$da .= '<div class="da-device da-monitor-lg"><div class="da-body"><div class="da-screen"></div></div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Large Monitor</span></div>';
$da .= '<div class="da-device da-tv"><div class="da-body"><div class="da-screen"></div></div><div class="da-feet"><div class="da-foot"></div><div class="da-foot"></div></div><span class="da-label">TV</span></div>';
$da .= '<div class="da-device da-projector"><div class="da-proj-layout"><div class="da-proj-body"><div class="da-lens"></div></div><div class="da-beam"></div><div class="da-proj-screen"><div class="da-screen"></div></div></div><span class="da-label">Projector</span></div>';
$da .= '<div class="da-device da-vwall"><div class="da-vwall-grid"><div class="da-panel"><div class="da-screen"></div></div><div class="da-panel"><div class="da-screen"></div></div><div class="da-panel"><div class="da-screen"></div></div><div class="da-panel"><div class="da-screen"></div></div></div><span class="da-label">Video Wall</span></div>';
$da .= '<div class="da-device da-tablet"><div class="da-body">' . $da_screen . '</div><span class="da-label">Tablet</span></div>';
$da .= '<div class="da-device da-monitor-sm"><div class="da-body">' . $da_screen . '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Small Monitor</span></div>';
$da .= '<div class="da-device da-monitor-lg"><div class="da-body">' . $da_screen . '</div><div class="da-stand"><div class="da-stem"></div><div class="da-base"></div></div><span class="da-label">Large Monitor</span></div>';
$da .= '<div class="da-device da-tv"><div class="da-body">' . $da_screen . '</div><div class="da-feet"><div class="da-foot"></div><div class="da-foot"></div></div><span class="da-label">TV</span></div>';
$da .= '<div class="da-device da-projector"><div class="da-proj-layout"><div class="da-proj-body"><div class="da-lens"></div></div><div class="da-beam"></div><div class="da-proj-screen">' . $da_screen . '</div></div><span class="da-label">Projector</span></div>';
$da .= '<div class="da-device da-vwall"><div class="da-vwall-grid"><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div><div class="da-panel">' . $da_screen . '</div></div><span class="da-label">Video Wall</span></div>';
$da .= '</div>';
$visual_html = $da;
$visual_cls = 'platform-visual has-anim';
@@ -1504,7 +1710,59 @@ function oribi_render_platform_row( $a ) {
$ts = '<div class="ts-stage" data-tv-stick-anim aria-hidden="true">';
$ts .= '<div class="ts-tv">';
$ts .= '<div class="ts-tv__body">';
$ts .= '<div class="ts-tv__screen"></div>';
$ts .= '<div class="ts-tv__screen">';
$ts .= '<div class="ts-slides">';
// Slide 1 — Menu Board
$ts .= '<div class="ts-slide ts-slide--menu">';
$ts .= '<div class="ts-menu">';
$ts .= '<div class="ts-menu__header"><div class="ts-menu__logo"></div><div class="ts-menu__title"></div></div>';
$ts .= '<div class="ts-menu__cols">';
$ts .= '<div class="ts-menu__col">';
$ts .= '<div class="ts-menu__cat"></div>';
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
$ts .= '</div>';
$ts .= '<div class="ts-menu__col">';
$ts .= '<div class="ts-menu__cat"></div>';
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
$ts .= '<div class="ts-menu__item"><span class="ts-menu__name"></span><span class="ts-menu__dots"></span><span class="ts-menu__price"></span></div>';
$ts .= '</div>';
$ts .= '</div>';
$ts .= '</div>';
$ts .= '</div>';
// Slide 2 — Wayfinding Sign
$ts .= '<div class="ts-slide ts-slide--wayfind">';
$ts .= '<div class="ts-wf">';
$ts .= '<div class="ts-wf__header"><div class="ts-wf__building"></div></div>';
$ts .= '<div class="ts-wf__rows">';
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w1"></span><span class="ts-wf__floor"></span></div>';
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--right"></span><span class="ts-wf__label ts-wf__label--w2"></span><span class="ts-wf__floor"></span></div>';
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--up"></span><span class="ts-wf__label ts-wf__label--w3"></span><span class="ts-wf__floor"></span></div>';
$ts .= '<div class="ts-wf__row"><span class="ts-wf__arrow ts-wf__arrow--left"></span><span class="ts-wf__label ts-wf__label--w4"></span><span class="ts-wf__floor"></span></div>';
$ts .= '</div>';
$ts .= '</div>';
$ts .= '</div>';
// Slide 3 — Schedule / Timetable
$ts .= '<div class="ts-slide ts-slide--sched">';
$ts .= '<div class="ts-sched">';
$ts .= '<div class="ts-sched__header"><div class="ts-sched__title"></div><div class="ts-sched__date"></div></div>';
$ts .= '<div class="ts-sched__table">';
$ts .= '<div class="ts-sched__hrow"><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span><span class="ts-sched__hcell"></span></div>';
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span></div>';
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div>';
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__cell"></span><span class="ts-sched__cell"></span><span class="ts-sched__event ts-sched__event--c"></span></div>';
$ts .= '<div class="ts-sched__row"><span class="ts-sched__time"></span><span class="ts-sched__event ts-sched__event--a"></span><span class="ts-sched__event ts-sched__event--b"></span><span class="ts-sched__cell"></span></div>';
$ts .= '</div>';
$ts .= '</div>';
$ts .= '</div>';
$ts .= '</div>'; // ts-slides
$ts .= '</div>'; // ts-tv__screen
$ts .= '<div class="ts-tv__port"></div>';
$ts .= '</div>';
$ts .= '<div class="ts-tv__feet"><div class="ts-tv__foot"></div><div class="ts-tv__foot"></div></div>';
@@ -1518,59 +1776,210 @@ function oribi_render_platform_row( $a ) {
$ts .= '</div>';
$visual_html = $ts;
$visual_cls = 'platform-visual has-tv-stick';
} elseif ( ! empty( $a['neverGoesDark'] ) ) {
/* ── Never Goes Dark: player + TV + cloud connection/break animation ── */
$ngd = '<div class="ngd-stage" aria-hidden="true">';
/* TV */
$ngd .= '<div class="ngd-tv">';
$ngd .= '<div class="ngd-tv__body">';
$ngd .= '<div class="ngd-tv__screen">';
$ngd .= '<div class="ngd-menu">';
$ngd .= '<div class="ngd-menu__hd">';
$ngd .= '<div class="ngd-menu__logo"></div>';
$ngd .= '<div class="ngd-menu__ttl"></div>';
$ngd .= '</div>';
$ngd .= '<div class="ngd-menu__cols">';
$ngd .= '<div class="ngd-menu__col">';
$ngd .= '<div class="ngd-menu__cat"></div>';
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
$ngd .= '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
$ngd .= '</div>';
$ngd .= '<div class="ngd-menu__col">';
$ngd .= '<div class="ngd-menu__cat"></div>';
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
$ngd .= '<div class="ngd-menu__row"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
$ngd .= '<div class="ngd-menu__row ngd-menu__row--hl"><span class="ngd-menu__name"></span><span class="ngd-menu__price"></span></div>';
$ngd .= '</div>';
$ngd .= '</div>'; /* cols */
$ngd .= '<div class="ngd-menu__ticker"><div class="ngd-menu__ticker-inner"></div></div>';
$ngd .= '</div>'; /* ngd-menu */
$ngd .= '</div>'; /* ngd-tv__screen */
$ngd .= '<div class="ngd-tv__port"></div>';
$ngd .= '</div>'; /* ngd-tv__body */
$ngd .= '<div class="ngd-tv__feet"><div class="ngd-tv__foot"></div><div class="ngd-tv__foot"></div></div>';
$ngd .= '</div>'; /* ngd-tv */
/* Player device (stick style, plugged into TV right-side HDMI port) */
$ngd .= '<div class="ngd-player">';
$ngd .= '<div class="ngd-player__connector"></div>';
$ngd .= '<div class="ngd-player__body">';
$ngd .= '<div class="ngd-player__led"></div>';
$ngd .= '</div>';
$ngd .= '<div class="ngd-player__check">';
$ngd .= '<svg viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">';
$ngd .= '<circle cx="11" cy="11" r="10" stroke="#4CAF50" stroke-width="1.5"/>';
$ngd .= '<polyline points="6,11 9.5,14.5 16,7.5" stroke="#4CAF50" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>';
$ngd .= '</svg>';
$ngd .= '</div>';
$ngd .= '</div>'; /* ngd-player */
/* Signal wrap: vertical line connecting player to globe above */
$ngd .= '<div class="ngd-signal-wrap">';
$ngd .= '<div class="ngd-cloud">';
$ngd .= '<svg class="ngd-cloud__svg" viewBox="0 0 64 46" fill="none" xmlns="http://www.w3.org/2000/svg">';
$ngd .= '<circle class="ngd-cloud__path" cx="32" cy="23" r="14" stroke-width="2.2" fill="none"/>';
$ngd .= '<path class="ngd-cloud__path" d="M18.5 23C23 20 41 20 45.5 23" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
$ngd .= '<path class="ngd-cloud__path" d="M20.5 29C25.5 31 38.5 31 43.5 29" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
$ngd .= '<path class="ngd-cloud__path" d="M24.5 12C21.5 16.5 21.5 29.5 24.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
$ngd .= '<path class="ngd-cloud__path" d="M39.5 12C42.5 16.5 42.5 29.5 39.5 34" stroke-width="1.9" stroke-linecap="round" fill="none"/>';
$ngd .= '</svg>';
$ngd .= '</div>';
$ngd .= '<div class="ngd-signal-line">';
$ngd .= '<div class="ngd-signal__dots">';
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--1"></div>';
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--2"></div>';
$ngd .= '<div class="ngd-signal__dot ngd-signal__dot--3"></div>';
$ngd .= '</div>';
$ngd .= '<div class="ngd-signal__break">';
$ngd .= '<svg viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">';
$ngd .= '<circle cx="9" cy="9" r="8" fill="rgba(239,68,68,0.12)" stroke="#ef4444" stroke-width="1.2"/>';
$ngd .= '<line x1="5.5" y1="5.5" x2="12.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>';
$ngd .= '<line x1="12.5" y1="5.5" x2="5.5" y2="12.5" stroke="#ef4444" stroke-width="2" stroke-linecap="round"/>';
$ngd .= '</svg>';
$ngd .= '</div>';
$ngd .= '</div>'; /* ngd-signal-line */
$ngd .= '</div>'; /* ngd-signal-wrap */
$ngd .= '</div>'; /* ngd-stage */
$visual_html = $ngd;
$visual_cls = 'platform-visual has-ngd';
} elseif ( ! empty( $a['brandedAnim'] ) ) {
/* ── Custom Display Solutions: branded screens cascade animation ── */
$bd = '<div class="bd-stage" aria-hidden="true">';
/* ── Screen 1: Tablet (portrait kiosk) ── */
$bd .= '<div class="bd-device bd-device--tablet">';
$bd .= '<span class="bd-device__label">Kiosk</span>';
$bd .= '<div class="bd-device__body">';
$bd .= '<div class="bd-device__screen">';
$bd .= '<div class="bd-splash">';
$bd .= '<div class="bd-splash__logo"></div>';
$bd .= '</div>';
$bd .= '<div class="bd-ui">';
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
$bd .= '<div class="bd-ui__content">';
$bd .= '<div class="bd-promo bd-promo--welcome">';
$bd .= '<div class="bd-promo__hero"></div>';
$bd .= '<div class="bd-promo__heading"></div>';
$bd .= '<div class="bd-promo__text"></div>';
$bd .= '<div class="bd-promo__btn"></div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
/* ── Screen 2: Wide wall-mount (landscape) ── */
$bd .= '<div class="bd-device bd-device--wall">';
$bd .= '<span class="bd-device__label">Wall Display</span>';
$bd .= '<div class="bd-device__body">';
$bd .= '<div class="bd-device__screen">';
$bd .= '<div class="bd-splash">';
$bd .= '<div class="bd-splash__logo"></div>';
$bd .= '</div>';
$bd .= '<div class="bd-ui">';
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
$bd .= '<div class="bd-ui__content">';
$bd .= '<div class="bd-promo bd-promo--sale">';
$bd .= '<div class="bd-promo__cols">';
$bd .= '<div class="bd-promo__visual"></div>';
$bd .= '<div class="bd-promo__info">';
$bd .= '<div class="bd-promo__badge"></div>';
$bd .= '<div class="bd-promo__heading"></div>';
$bd .= '<div class="bd-promo__text"></div>';
$bd .= '<div class="bd-promo__text bd-promo__text--short"></div>';
$bd .= '<div class="bd-promo__price"></div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '<div class="bd-mount"></div>';
$bd .= '</div>';
/* ── Screen 3: Interactive tablet on table ── */
$bd .= '<div class="bd-device bd-device--interactive">';
$bd .= '<span class="bd-device__label">Interactive</span>';
$bd .= '<div class="bd-device__body">';
$bd .= '<div class="bd-device__screen">';
$bd .= '<div class="bd-splash">';
$bd .= '<div class="bd-splash__logo"></div>';
$bd .= '</div>';
$bd .= '<div class="bd-ui">';
$bd .= '<div class="bd-ui__header"><div class="bd-ui__logo"></div><div class="bd-ui__brand-bar"></div></div>';
$bd .= '<div class="bd-ui__content">';
$bd .= '<div class="bd-promo bd-promo--menu">';
$bd .= '<div class="bd-promo__heading"></div>';
$bd .= '<div class="bd-promo__grid">';
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
$bd .= '<div class="bd-promo__tile"><div class="bd-promo__tile-img"></div><div class="bd-promo__tile-lbl"></div></div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '</div>';
$bd .= '<div class="bd-table"></div>';
$bd .= '</div>';
$bd .= '</div>'; /* bd-stage */
$visual_html = $bd;
$visual_cls = 'platform-visual has-branded';
} elseif ( ! empty( $a['cameraAnim'] ) ) {
$ca = '<div class="cam-stage" aria-hidden="true">';
$visual_html = oribi_render_camera_animation();
$visual_cls = 'platform-visual has-video-editor';
// ── Left: compact photo camera ──
$ca .= '<div class="pc-wrap">';
$ca .= '<div class="pc-body">';
$ca .= '<div class="pc-flash-unit"></div>';
$ca .= '<div class="pc-top"><div class="pc-shutter-btn"></div><div class="pc-viewfinder"></div></div>';
$ca .= '<div class="pc-front">';
$ca .= '<div class="pc-lens-ring"><div class="pc-lens-glass"><div class="pc-lens-reflex"></div></div></div>';
$ca .= '<div class="pc-grip"></div>';
$ca .= '</div>';
$ca .= '</div>'; // pc-body
$ca .= '<div class="pc-prints">';
$ca .= '<div class="pc-print pc-print--1"><div class="pc-print__img"></div></div>';
$ca .= '<div class="pc-print pc-print--2"><div class="pc-print__img"></div></div>';
$ca .= '<div class="pc-print pc-print--3"><div class="pc-print__img"></div></div>';
$ca .= '</div>'; // pc-prints
$ca .= '</div>'; // 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 .= '<div class="gtv-slide' . $active . '">';
$slides .= '<img src="' . esc_url( $url ) . '" alt="' . esc_attr( $alt ) . '" loading="lazy" />';
$slides .= '</div>';
$count++;
}
if ( $count > 0 ) {
$visual_html = '<div class="gtv-stage" data-gtv-slideshow aria-hidden="true">';
$visual_html .= '<div class="gtv-tv">';
$visual_html .= '<div class="gtv-tv__body">';
$visual_html .= '<div class="gtv-tv__screen">';
$visual_html .= '<div class="gtv-slides">' . $slides . '</div>';
$visual_html .= '</div>'; // screen
$visual_html .= '</div>'; // body
$visual_html .= '<div class="gtv-tv__feet"><div class="gtv-tv__foot"></div><div class="gtv-tv__foot"></div></div>';
$visual_html .= '</div>'; // tv
$visual_html .= '</div>'; // 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 .= '<div class="cam-scene">';
$ca .= '<div class="cam-subject cam-subject--1"></div>';
$ca .= '<div class="cam-subject cam-subject--2"></div>';
$ca .= '<div class="cam-subject cam-subject--3"></div>';
$ca .= '<div class="cam-flash-overlay"></div>';
$ca .= '<div class="cam-vid-overlay"></div>';
$ca .= '</div>'; // cam-scene
// ── Right: retro VHS video camera on tripod ──
$ca .= '<div class="vc-wrap">';
$ca .= '<div class="vc-camera">';
$ca .= '<div class="vc-handle"></div>';
$ca .= '<div class="vc-body">';
$ca .= '<div class="vc-lens-barrel"><div class="vc-lens-tip"><div class="vc-lens-glass"><div class="vc-lens-reflex"></div></div></div></div>';
$ca .= '<div class="vc-top-rail"></div>';
$ca .= '<div class="vc-rec-light"></div>';
$ca .= '<div class="vc-eyepiece"></div>';
$ca .= '</div>'; // vc-body
$ca .= '</div>'; // vc-camera
$ca .= '<div class="vc-tripod">';
$ca .= '<div class="vc-stem"></div>';
$ca .= '<div class="vc-legs">';
$ca .= '<div class="vc-leg vc-leg--l"></div>';
$ca .= '<div class="vc-leg vc-leg--c"></div>';
$ca .= '<div class="vc-leg vc-leg--r"></div>';
$ca .= '</div>'; // vc-legs
$ca .= '</div>'; // vc-tripod
$ca .= '</div>'; // vc-wrap
$ca .= '</div>'; // cam-stage
$visual_html = $ca;
$visual_cls = 'platform-visual has-camera';
} else {
$visual_html = oribi_render_icon( $a['visual'] ?? '' );
$visual_cls = 'platform-visual';
@@ -1589,7 +1998,6 @@ function oribi_render_platform_row( $a ) {
</div>
<?php return ob_get_clean();
}
/* ── Trust Section (parent - wraps child trust-item blocks) ────────────────── */
function oribi_render_trust_section( $a, $content ) {
ob_start(); ?>
@@ -1800,11 +2208,23 @@ function oribi_uc_anim_inner( $mod ) {
return '
<div class="uc-inner uc-inner--event" aria-hidden="true">
<div class="uc-event-cursor"></div>
<div class="uc-event-header"></div>
<div class="uc-event-row"><div class="uc-event-time"></div><div class="uc-event-bar uc-event-bar--active"></div></div>
<div class="uc-event-row"><div class="uc-event-time"></div><div class="uc-event-bar"></div></div>
<div class="uc-event-row"><div class="uc-event-time"></div><div class="uc-event-bar uc-event-bar--accent"></div></div>
<div class="uc-event-row"><div class="uc-event-time"></div><div class="uc-event-bar"></div></div>
<div class="uc-event-header">Schedule</div>
<div class="uc-event-row">
<div class="uc-event-time">9:00</div>
<div class="uc-event-title uc-event-title--active">Keynote Speech</div>
</div>
<div class="uc-event-row">
<div class="uc-event-time">10:30</div>
<div class="uc-event-title">Panel Discussion</div>
</div>
<div class="uc-event-row">
<div class="uc-event-time">11:45</div>
<div class="uc-event-title uc-event-title--accent">Coffee Break</div>
</div>
<div class="uc-event-row">
<div class="uc-event-time">12:30</div>
<div class="uc-event-title">Networking Lunch</div>
</div>
</div>';
case 'dashboard':
return '

View File

@@ -38,6 +38,24 @@ add_action( 'wp_enqueue_scripts', function () {
true
);
// Gallery TV slideshow - cycles images in TV-frame cards
wp_enqueue_script(
'oribi-gallery-tv',
ORIBI_URI . '/assets/js/industry-animator.js',
[],
ORIBI_VERSION . '.' . filemtime( ORIBI_DIR . '/assets/js/industry-animator.js' ),
true
);
// Video editor timeline animator - animated playhead and preview crossfades
wp_enqueue_script(
'oribi-video-editor-animator',
ORIBI_URI . '/assets/js/video-editor-animator.js',
[],
ORIBI_VERSION . '.' . filemtime( ORIBI_DIR . '/assets/js/video-editor-animator.js' ),
true
);
// Localize AJAX endpoint for the contact form
wp_localize_script( 'oribi-main', 'oribiAjax', [
'url' => admin_url( 'admin-ajax.php' ),

View File

@@ -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)',

View File

@@ -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) {

View File

@@ -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)",