|
798 | 798 | margin: 0 auto; |
799 | 799 | overflow: hidden; |
800 | 800 | } |
| 801 | + .mockup-stage { |
| 802 | + position: relative; |
| 803 | + max-width: 940px; |
| 804 | + margin: 0 auto; |
| 805 | + padding-inline: 58px; |
| 806 | + } |
801 | 807 | .mockup-stack > .browser-mockup { |
802 | 808 | grid-column: 1; |
803 | 809 | grid-row: 1; |
|
818 | 824 | transform: scale(1); |
819 | 825 | pointer-events: auto; |
820 | 826 | } |
| 827 | + .scene-arrow { |
| 828 | + appearance: none; |
| 829 | + -webkit-appearance: none; |
| 830 | + position: absolute; |
| 831 | + top: 50%; |
| 832 | + z-index: 3; |
| 833 | + display: inline-flex; |
| 834 | + align-items: center; |
| 835 | + justify-content: center; |
| 836 | + width: 42px; |
| 837 | + height: 42px; |
| 838 | + padding: 0; |
| 839 | + border: 1px solid var(--border); |
| 840 | + border-radius: 999px; |
| 841 | + background: var(--surface); |
| 842 | + color: var(--text); |
| 843 | + box-shadow: 0 12px 30px var(--shadow); |
| 844 | + cursor: pointer; |
| 845 | + transform: translateY(-50%); |
| 846 | + transition: background 0.2s, border-color 0.2s, color 0.2s, transform 0.2s, box-shadow 0.2s; |
| 847 | + } |
| 848 | + .scene-arrow:hover { |
| 849 | + background: var(--bg-card-hover); |
| 850 | + border-color: var(--accent); |
| 851 | + color: var(--text); |
| 852 | + transform: translateY(-50%) scale(1.04); |
| 853 | + box-shadow: 0 16px 36px var(--shadow-strong); |
| 854 | + } |
| 855 | + .scene-arrow:focus-visible { outline: 2px solid var(--accent2); outline-offset: 3px; } |
| 856 | + .scene-arrow svg { |
| 857 | + width: 20px; |
| 858 | + height: 20px; |
| 859 | + display: block; |
| 860 | + } |
| 861 | + .scene-arrow-prev { inset-inline-start: 0; } |
| 862 | + .scene-arrow-next { inset-inline-end: 0; } |
821 | 863 |
|
822 | 864 | .scene-nav { |
823 | 865 | display: flex; |
|
1872 | 1914 | ================================================================ */ |
1873 | 1915 | @media (max-width: 768px) { |
1874 | 1916 | body { overflow-x: hidden; } |
| 1917 | + .mockup-stage { padding-inline: 0; } |
| 1918 | + .scene-arrow { display: none; } |
1875 | 1919 | .browser-body { flex-direction: column; } |
1876 | 1920 | .side-panel { width: 100%; border-inline-start: none; border-top: 1px solid var(--border); min-height: 260px; } |
1877 | 1921 | .modes-grid { grid-template-columns: 1fr; } |
@@ -2013,7 +2057,11 @@ <h1><span class="gradient">وكيل تصفّح ذكي</span> مفتوح المص |
2013 | 2057 | carries .is-active on load so its messages animate in immediately; |
2014 | 2058 | the rotation script swaps the class on a timer / on click. --> |
2015 | 2059 | <div class="hero-visual"> |
2016 | | - <div class="mockup-stack" id="mockup-stack"> |
| 2060 | + <div class="mockup-stage"> |
| 2061 | + <button class="scene-arrow scene-arrow-prev" type="button" data-scene-step="-1" aria-label="سيناريو العرض التوضيحي السابق" aria-controls="mockup-stack"> |
| 2062 | + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M15 18l-6-6 6-6"/></svg> |
| 2063 | + </button> |
| 2064 | + <div class="mockup-stack" id="mockup-stack"> |
2017 | 2065 |
|
2018 | 2066 | <!-- Scene 1: Follow-up question (two-turn conversation) — Ask mode --> |
2019 | 2067 | <div class="browser-mockup is-active" data-scene="0"> |
@@ -2266,6 +2314,10 @@ <h3>كتالوج المنتجات</h3> |
2266 | 2314 | </div> |
2267 | 2315 | </div> |
2268 | 2316 |
|
| 2317 | + </div> |
| 2318 | + <button class="scene-arrow scene-arrow-next" type="button" data-scene-step="1" aria-label="سيناريو العرض التوضيحي التالي" aria-controls="mockup-stack"> |
| 2319 | + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.3" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 18l6-6-6-6"/></svg> |
| 2320 | + </button> |
2269 | 2321 | </div> |
2270 | 2322 |
|
2271 | 2323 | <div class="scene-nav" role="tablist" aria-label="تبديل سيناريو العرض التوضيحي"> |
@@ -2778,11 +2830,6 @@ <h4>تنبيه أمان مهم</h4> |
2778 | 2830 | </a> |
2779 | 2831 | <a href="/blog">المدونة</a> |
2780 | 2832 | <a href="/docs/">Docs</a> |
2781 | | - <a href="#features">المزايا</a> |
2782 | | - <a href="#security">الأمان</a> |
2783 | | - <a href="#compare">المقارنة</a> |
2784 | | - <a href="#faq">الأسئلة الشائعة</a> |
2785 | | - <a href="#safety">تنبيه أمان</a> |
2786 | 2833 | <a href="/privacy">سياسة الخصوصية</a> |
2787 | 2834 | <a href="https://github.com/webbrain-one/webbrain/issues" target="_blank" rel="noopener">أبلغ عن خلل</a> |
2788 | 2835 | <a href="https://github.com/webbrain-one/webbrain/blob/main/LICENSE" target="_blank" rel="noopener">رخصة MIT</a> |
@@ -2873,23 +2920,25 @@ <h4>تنبيه أمان مهم</h4> |
2873 | 2920 | })(); |
2874 | 2921 | </script> |
2875 | 2922 |
|
2876 | | -<!-- Hero mockup rotation: cross-fade through 4 demo scenes. Click a dot to |
2877 | | - jump (and freeze the auto-rotate so a hand-picked scene stays put). |
| 2923 | +<!-- Hero mockup rotation: cross-fade through 5 demo scenes. Click a dot or |
| 2924 | + arrow to jump (and freeze the auto-rotate so a hand-picked scene stays put). |
2878 | 2925 | Auto-rotate pauses on hover and when the tab is hidden. Skipped |
2879 | 2926 | entirely under prefers-reduced-motion — the first scene just stays. --> |
2880 | 2927 | <script> |
2881 | 2928 | (function () { |
2882 | 2929 | const stack = document.getElementById('mockup-stack'); |
2883 | 2930 | if (!stack) return; |
| 2931 | + const stage = stack.closest('.mockup-stage') || stack; |
2884 | 2932 | const scenes = stack.querySelectorAll(':scope > .browser-mockup'); |
2885 | 2933 | const dots = document.querySelectorAll('.scene-nav .scene-dot'); |
| 2934 | + const arrows = document.querySelectorAll('.scene-arrow'); |
2886 | 2935 | if (scenes.length < 2) return; |
2887 | 2936 |
|
2888 | 2937 | const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; |
2889 | 2938 | const INTERVAL_MS = 6000; |
2890 | 2939 | let current = 0; |
2891 | 2940 | let timer = null; |
2892 | | - let userLocked = false; // set true once the visitor clicks a dot |
| 2941 | + let userLocked = false; // set true once the visitor uses a manual control |
2893 | 2942 |
|
2894 | 2943 | function activate(idx) { |
2895 | 2944 | idx = ((idx % scenes.length) + scenes.length) % scenes.length; |
@@ -2937,8 +2986,18 @@ <h4>تنبيه أمان مهم</h4> |
2937 | 2986 | }); |
2938 | 2987 | }); |
2939 | 2988 |
|
2940 | | - stack.addEventListener('mouseenter', stop); |
2941 | | - stack.addEventListener('mouseleave', start); |
| 2989 | + arrows.forEach((arrow) => { |
| 2990 | + arrow.addEventListener('click', function () { |
| 2991 | + const step = parseInt(arrow.dataset.sceneStep, 10); |
| 2992 | + if (Number.isNaN(step)) return; |
| 2993 | + userLocked = true; |
| 2994 | + stop(); |
| 2995 | + activate(current + step); |
| 2996 | + }); |
| 2997 | + }); |
| 2998 | + |
| 2999 | + stage.addEventListener('mouseenter', stop); |
| 3000 | + stage.addEventListener('mouseleave', start); |
2942 | 3001 | document.addEventListener('visibilitychange', function () { |
2943 | 3002 | if (document.hidden) stop(); else start(); |
2944 | 3003 | }); |
|
0 commit comments