diff --git a/pages/features.php b/pages/features.php index b60db7c..d4aa1bd 100644 --- a/pages/features.php +++ b/pages/features.php @@ -12,7 +12,7 @@ - + diff --git a/pages/home.php b/pages/home.php index e4958af..762aa16 100644 --- a/pages/home.php +++ b/pages/home.php @@ -11,7 +11,7 @@ return <<<'ORIBI_SYNC_CONTENT' - + diff --git a/theme/assets/css/main.css b/theme/assets/css/main.css index 3869368..e4aab86 100644 --- a/theme/assets/css/main.css +++ b/theme/assets/css/main.css @@ -2396,6 +2396,236 @@ p:last-child { margin-bottom: 0; } .da-screen::after { animation: none; } } +/* ── 10c. TV Stick Plug Animation ──────────────────────────── */ +.platform-visual.has-tv-stick { + background: none !important; + border: none !important; + border-radius: 0; + aspect-ratio: unset; + padding: 0; + overflow: visible; + position: relative; + font-size: inherit; +} +.ts-stage { + position: relative; + width: 100%; + aspect-ratio: 4/3; + display: flex; + align-items: center; + justify-content: center; +} +/* ── TV ── */ +.ts-tv { + display: flex; + flex-direction: column; + align-items: center; + position: relative; +} +.ts-tv__body { + width: 320px; + height: 188px; + background: var(--color-bg-alt); + border: 4px solid var(--color-bg-alt); + border-radius: 6px 6px 4px 4px; + outline: 1px solid var(--color-border); + padding: 3px; + display: flex; + align-items: stretch; + position: relative; + box-shadow: 0 14px 48px rgba(0,0,0,0.55); +} +.ts-tv__screen { + width: 100%; + height: 100%; + border-radius: 2px; + position: relative; + overflow: hidden; + background: + repeating-linear-gradient( + 180deg, + transparent, + transparent 3px, + rgba(0,0,0,0.10) 3px, + rgba(0,0,0,0.10) 4px + ), + linear-gradient(135deg, #0c1016 0%, #151c28 60%, #0c1016 100%); +} +/* Subtle green ambient glow on screen */ +.ts-tv__screen::before { + content: ''; + position: absolute; + top: -20%; + left: -10%; + width: 60%; + height: 60%; + background: radial-gradient(ellipse, rgba(74,222,128,0.12) 0%, transparent 70%); + pointer-events: none; +} +/* Scan line on screen */ +.ts-tv__screen::after { + content: ''; + position: absolute; + left: 0; + width: 100%; + height: 3px; + background: linear-gradient(90deg, transparent, rgba(74,222,128,0.28), transparent); + animation: da-scan 3s linear infinite; + pointer-events: none; +} +/* Screen glow when stick plugs in */ +.ts-stage.is-plugged .ts-tv__screen { + animation: ts-screen-glow 0.8s ease 0.1s both; +} +@keyframes ts-screen-glow { + 0% { filter: brightness(1); } + 40% { filter: brightness(1.25); } + 100% { filter: brightness(1); } +} +/* HDMI port on back-right of TV */ +.ts-tv__port { + position: absolute; + right: -6px; + top: 50%; + transform: translateY(-50%); + width: 6px; + height: 14px; + background: #1a1a1a; + border: 1px solid var(--color-border); + border-left: none; + border-radius: 0 2px 2px 0; + z-index: 1; +} +.ts-tv__port::before { + content: ''; + position: absolute; + left: 0; + top: 2px; + width: 3px; + height: 8px; + background: #333; + border-radius: 0 1px 1px 0; +} +/* Feet */ +.ts-tv__feet { + display: flex; + justify-content: space-between; + width: 180px; +} +.ts-tv__foot { + width: 12px; + height: 8px; + background: var(--color-bg-alt); + border: 1px solid var(--color-border); + border-radius: 0 0 4px 4px; +} +/* ── Stick device ── */ +.ts-stick { + position: absolute; + right: -20px; + top: 50%; + transform: translateY(-50%) translateX(80px); + display: flex; + align-items: center; + opacity: 0; + z-index: 2; +} +.ts-stick__body { + width: 68px; + height: 26px; + background: linear-gradient(180deg, #f5f5f5, #e0e0e0); + border: 1px solid #ccc; + border-radius: 5px; + position: relative; + box-shadow: + 0 2px 8px rgba(0,0,0,0.25), + inset 0 1px 0 rgba(255,255,255,0.6); +} +/* Brand logo area subtle inset */ +.ts-stick__body::before { + content: ''; + position: absolute; + top: 6px; + left: 10px; + width: 28px; + height: 12px; + background: rgba(0,0,0,0.04); + border-radius: 2px; +} +/* LED indicator */ +.ts-stick__led { + position: absolute; + right: 8px; + top: 50%; + transform: translateY(-50%); + width: 4px; + height: 4px; + background: #999; + border-radius: 50%; + transition: background 0.4s ease, box-shadow 0.4s ease; +} +.ts-stage.is-plugged .ts-stick__led { + background: #4CAF50; + box-shadow: 0 0 6px rgba(76,175,80,0.8); +} +/* HDMI connector */ +.ts-stick__connector { + width: 14px; + height: 10px; + background: linear-gradient(180deg, #888, #666); + border-radius: 0 2px 2px 0; + margin-left: -1px; + position: relative; + box-shadow: 0 1px 3px rgba(0,0,0,0.3); +} +.ts-stick__connector::before { + content: ''; + position: absolute; + left: 2px; + top: 2px; + width: 6px; + height: 6px; + background: #555; + border-radius: 1px; +} +/* ── Plug-in animation ── */ +.ts-stage.is-animating .ts-stick { + animation: ts-slide-in 1.4s cubic-bezier(0.22, 0.61, 0.36, 1) forwards; +} +@keyframes ts-slide-in { + 0% { opacity: 0; transform: translateY(-50%) translateX(80px); } + 20% { opacity: 1; transform: translateY(-50%) translateX(60px); } + 70% { transform: translateY(-50%) translateX(8px); } + 85% { transform: translateY(-50%) translateX(12px); } + 100% { opacity: 1; transform: translateY(-50%) translateX(6px); } +} +/* Responsive scale-down */ +@media (max-width: 900px) { + .ts-tv__body { width: 260px; height: 152px; } + .ts-tv__feet { width: 140px; } + .ts-stick__body { width: 56px; height: 22px; } +} +@media (max-width: 640px) { + .ts-tv__body { width: 200px; height: 118px; } + .ts-tv__feet { width: 110px; } + .ts-stick__body { width: 46px; height: 18px; } + .ts-stick__connector { width: 10px; height: 8px; } + .ts-stick__body::before { top: 4px; left: 6px; width: 20px; height: 8px; } + .ts-stick__led { width: 3px; height: 3px; right: 5px; } +} +@media (prefers-reduced-motion: reduce) { + .ts-stage .ts-stick { + opacity: 1; + transform: translateY(-50%) translateX(6px); + } + .ts-stage.is-animating .ts-stick { animation: none; } + .ts-stage.is-plugged .ts-tv__screen { animation: none; } + .ts-stage.is-plugged .ts-stick__led { + background: #4CAF50; + box-shadow: 0 0 6px rgba(76,175,80,0.8); + } +} + /* ── 11. Page Hero (inner pages) ───────────────────────────── */ .page-hero { background: #111111; diff --git a/theme/assets/js/main.js b/theme/assets/js/main.js index 75b457c..91b6773 100644 --- a/theme/assets/js/main.js +++ b/theme/assets/js/main.js @@ -675,3 +675,34 @@ document.addEventListener('DOMContentLoaded', () => { } }); })(); + +/* ── TV Stick Plug Animation ─────────────────────────────────────────────── */ +(function () { + var stages = document.querySelectorAll('[data-tv-stick-anim]'); + if (!stages.length) return; + + // Honour reduced-motion: show plugged-in state immediately + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) { + stages.forEach(function (stage) { + stage.classList.add('is-plugged'); + }); + return; + } + + if ('IntersectionObserver' in window) { + var io = new IntersectionObserver(function (entries) { + entries.forEach(function (e) { + if (e.isIntersecting) { + var stage = e.target; + stage.classList.add('is-animating'); + // Add plugged state after slide-in completes (1.4s) + setTimeout(function () { + stage.classList.add('is-plugged'); + }, 1400); + io.unobserve(stage); + } + }); + }, { threshold: 0.3 }); + stages.forEach(function (stage) { io.observe(stage); }); + } +})(); diff --git a/theme/blocks/index.php b/theme/blocks/index.php index 1fa1d9e..8fc5595 100644 --- a/theme/blocks/index.php +++ b/theme/blocks/index.php @@ -554,6 +554,7 @@ add_action( 'init', function () { 'imgAlt' => [ 'type' => 'string', 'default' => '' ], 'imgWidth' => [ 'type' => 'number', 'default' => 300 ], 'deviceAnim' => [ 'type' => 'boolean', 'default' => false ], + 'tvStick' => [ 'type' => 'boolean', 'default' => false ], ], 'supports' => $block_supports, 'render_callback' => 'oribi_render_platform_row', @@ -1339,9 +1340,8 @@ function oribi_render_platform_row( $a ) { $img_alt = ! empty( $a['imgAlt'] ) ? $a['imgAlt'] : ''; $img_w = ! empty( $a['imgWidth'] ) ? intval( $a['imgWidth'] ) : 300; - // Check if this is a dashboard card (by heading content or dashboard flag) - $heading_text = $a['heading'] ?? ''; - $is_dashboard = ! empty( $a['isDashboard'] ) || stripos( $heading_text, 'dashboard' ) !== false || stripos( $heading_text, 'data' ) !== false; + // Only render animated dashboard when explicitly flagged + $is_dashboard = ! empty( $a['isDashboard'] ); if ( $is_dashboard ) { // Render animated dashboard chart SVG @@ -1480,6 +1480,24 @@ function oribi_render_platform_row( $a ) { $da .= ''; $visual_html = $da; $visual_cls = 'platform-visual has-anim'; + } elseif ( ! empty( $a['tvStick'] ) ) { + $ts = '
'; + $visual_html = $ts; + $visual_cls = 'platform-visual has-tv-stick'; } else { $visual_html = oribi_render_icon( $a['visual'] ?? '' ); $visual_cls = 'platform-visual';