art of war reader

D David Veksler · 1 year ago e7a30bbbb95a7877021381fb51f9fda4af0d45f2
Parent: 6eea24f77

2 files changed +1216 −0

Diff

diff --git a/art-of-war-sun-tzu-claude.html b/art-of-war-sun-tzu-claude.html
new file mode 100644
index 0000000..38b5915
--- /dev/null
+++ b/art-of-war-sun-tzu-claude.html
@@ -0,0 +1,668 @@
+<!DOCTYPE html>
+<!-- saved from url=(0057)file:///C:/Users/veksl/Downloads/bamboo_reader%20(2).html -->
+<html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Bamboo Slip Reader - Dual Mode</title>
+    <style>
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+        }
+
+        body {
+            background: 
+                radial-gradient(circle at 20% 50%, rgba(76, 44, 26, 0.3) 0%, transparent 50%),
+                radial-gradient(circle at 80% 20%, rgba(139, 90, 43, 0.2) 0%, transparent 50%),
+                radial-gradient(circle at 40% 80%, rgba(61, 37, 26, 0.3) 0%, transparent 50%),
+                linear-gradient(135deg, #2c1810 0%, #4a2c1a 50%, #3d251a 100%);
+            font-family: 'Georgia', serif;
+            overflow: hidden;
+            height: 100vh;
+            padding: 20px;
+        }
+
+        .reader-container {
+            display: flex;
+            height: calc(100vh - 40px);
+            perspective: 1200px;
+            justify-content: center;
+            align-items: flex-start;
+            transition: all 1.2s cubic-bezier(0.4, 0.0, 0.2, 1);
+            transform-style: preserve-3d;
+            overflow: hidden;
+        }
+
+        .reader-container.transitioning {
+            transform: rotateY(90deg);
+        }
+
+        /* Vertical Mode (Chinese) */
+        .vertical-mode .bamboo-strip {
+            width: 80px;
+            height: 600px;
+            margin: 0 1px;
+            flex-direction: column;
+        }
+
+        .vertical-mode .strip-content {
+            writing-mode: vertical-rl;
+            text-orientation: upright;
+            font-size: 12px;
+            line-height: 1.4;
+            padding: 40px 8px;
+            letter-spacing: 2px;
+            width: 100%;
+            height: 100%;
+        }
+
+        .vertical-mode .title-strip {
+            width: 100px;
+        }
+
+        .vertical-mode .title-strip .strip-content {
+            font-size: 16px;
+            font-weight: bold;
+        }
+
+        /* Horizontal Mode (English) */
+        .horizontal-mode {
+            flex-direction: column;
+            gap: 4px;
+            overflow-y: auto;
+            overflow-x: hidden;
+            padding: 20px;
+        }
+
+        .horizontal-mode .bamboo-strip {
+            width: min(95vw, 1200px);
+            height: auto;
+            min-height: 50px;
+            margin: 2px 0;
+            flex-shrink: 0;
+        }
+
+        .horizontal-mode .strip-content {
+            writing-mode: horizontal-tb;
+            text-orientation: mixed;
+            font-size: 15px;
+            line-height: 1.5;
+            padding: 12px 20px;
+            letter-spacing: 0.3px;
+            width: 100%;
+            height: auto;
+            display: block;
+            text-align: left;
+            word-wrap: break-word;
+            hyphens: auto;
+        }
+
+        .horizontal-mode .title-strip {
+            width: min(95vw, 1200px);
+            height: auto;
+            min-height: 70px;
+        }
+
+        .horizontal-mode .title-strip .strip-content {
+            font-size: 20px;
+            font-weight: bold;
+            text-align: center;
+            padding: 15px 20px;
+        }
+
+        /* Base Bamboo Strip Styles */
+        .bamboo-strip {
+            background: 
+                linear-gradient(135deg, rgba(255,255,255,0.15) 0%, transparent 50%),
+                linear-gradient(45deg, 
+                    #d4a574 0%, #c19653 25%, #d4a574 50%, #b8954d 75%, #d4a574 100%);
+            position: relative;
+            transform-style: preserve-3d;
+            transition: all 0.4s ease;
+            cursor: pointer;
+            border-radius: 4px;
+            box-shadow: 
+                inset 0 1px 0 rgba(255,255,255,0.2),
+                inset 0 0 20px rgba(0,0,0,0.1), 
+                0 4px 12px rgba(0,0,0,0.3),
+                0 1px 3px rgba(0,0,0,0.2);
+        }
+
+        .bamboo-strip::before {
+            content: '';
+            position: absolute;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background: repeating-linear-gradient(90deg,
+                transparent 0px,
+                rgba(139, 85, 47, 0.1) 1px,
+                transparent 2px,
+                transparent 12px
+            );
+            border-radius: 3px;
+        }
+
+        .horizontal-mode .bamboo-strip::before {
+            background: repeating-linear-gradient(0deg,
+                transparent 0px,
+                rgba(139, 85, 47, 0.06) 1px,
+                transparent 2px,
+                transparent 20px
+            );
+        }
+
+        .bamboo-strip::after {
+            content: '';
+            position: absolute;
+            background: linear-gradient(
+                rgba(101, 67, 33, 0.15) 20%,
+                rgba(101, 67, 33, 0.08) 50%,
+                rgba(101, 67, 33, 0.15) 80%
+            );
+        }
+
+        .vertical-mode .bamboo-strip::after {
+            top: 10%;
+            left: 50%;
+            transform: translateX(-50%);
+            width: 2px;
+            height: 80%;
+        }
+
+        .horizontal-mode .bamboo-strip::after {
+            left: 15px;
+            top: 50%;
+            transform: translateY(-50%);
+            height: 2px;
+            width: calc(100% - 30px);
+        }
+
+        .strip-content {
+            position: absolute;
+            top: 0;
+            left: 0;
+            color: #2c1810;
+            font-weight: 600;
+            text-align: center;
+            transition: all 0.4s ease;
+        }
+
+        .bamboo-strip:hover {
+            transform: scale(1.03) translateZ(10px);
+            z-index: 5;
+            box-shadow: 
+                inset 0 1px 0 rgba(255,255,255,0.3),
+                inset 0 0 25px rgba(0,0,0,0.15), 
+                0 8px 20px rgba(0,0,0,0.4),
+                0 2px 6px rgba(0,0,0,0.3);
+        }
+
+        .bamboo-strip.selected {
+            transform: scale(1.08) translateZ(20px);
+            z-index: 10;
+            background: 
+                linear-gradient(135deg, rgba(255,255,255,0.25) 0%, transparent 50%),
+                linear-gradient(45deg, 
+                    #e6c080 0%, #d4a574 25%, #e6c080 50%, #c9a366 75%, #e6c080 100%);
+            box-shadow: 
+                inset 0 2px 0 rgba(255,255,255,0.4),
+                inset 0 0 30px rgba(255,204,102,0.2), 
+                0 12px 25px rgba(0,0,0,0.5),
+                0 4px 10px rgba(0,0,0,0.3);
+        }
+
+        .bamboo-strip.selected .strip-content {
+            color: #1a0f08;
+            font-weight: bold;
+        }
+
+        .title-strip {
+            background: 
+                linear-gradient(135deg, rgba(255,255,255,0.2) 0%, transparent 50%),
+                linear-gradient(45deg, 
+                    #e6c080 0%, #d4a574 25%, #e6c080 50%, #c9a366 75%, #e6c080 100%);
+            box-shadow: 
+                inset 0 2px 0 rgba(255,255,255,0.3),
+                inset 0 0 25px rgba(255,204,102,0.1), 
+                0 6px 15px rgba(0,0,0,0.4),
+                0 2px 5px rgba(0,0,0,0.2);
+        }
+
+        .title-strip .strip-content {
+            color: #8b2635;
+        }
+
+        .binding-cord {
+            position: absolute;
+            background: linear-gradient(to bottom,
+                #8b5a2b 0%,
+                #654021 50%,
+                #8b5a2b 100%
+            );
+            border-radius: 2px;
+            z-index: 10;
+            box-shadow: 1px 1px 3px rgba(0,0,0,0.4);
+            transition: all 1.2s ease;
+        }
+
+        .vertical-mode .binding-cord {
+            width: 4px;
+            height: 600px;
+        }
+
+        .horizontal-mode .binding-cord {
+            height: 4px;
+            width: 800px;
+        }
+
+        .controls {
+            position: fixed;
+            bottom: 20px;
+            left: 50%;
+            transform: translateX(-50%);
+            display: flex;
+            gap: 15px;
+            z-index: 100;
+        }
+
+        .control-btn {
+            padding: 10px 20px;
+            background: rgba(212, 165, 116, 0.9);
+            border: 2px solid #8b5a2b;
+            border-radius: 8px;
+            color: #2c1810;
+            font-weight: bold;
+            cursor: pointer;
+            transition: all 0.3s ease;
+        }
+
+        .control-btn:hover {
+            background: rgba(230, 192, 128, 1);
+            transform: translateY(-2px);
+        }
+
+        .control-btn.active {
+            background: rgba(139, 38, 53, 0.9);
+            color: #e6c080;
+            border-color: #8b2635;
+        }
+
+        .chapter-indicator {
+            position: fixed;
+            top: 20px;
+            right: 20px;
+            background: rgba(212, 165, 116, 0.9);
+            padding: 10px 15px;
+            border-radius: 8px;
+            color: #2c1810;
+            font-weight: bold;
+            border: 2px solid #8b5a2b;
+        }
+
+        .mode-toggle {
+            position: fixed;
+            top: 20px;
+            left: 20px;
+            background: rgba(212, 165, 116, 0.9);
+            padding: 12px 18px;
+            border-radius: 8px;
+            color: #2c1810;
+            font-weight: bold;
+            border: 3px solid #8b5a2b;
+            cursor: pointer;
+            transition: all 0.3s ease;
+            font-size: 14px;
+            z-index: 1000;
+            user-select: none;
+        }
+
+        .mode-toggle:hover {
+            background: rgba(230, 192, 128, 1);
+            transform: translateY(-2px);
+            border-color: #654021;
+        }
+
+        .mode-toggle:active {
+            transform: translateY(0px);
+            background: rgba(200, 150, 100, 1);
+        }
+
+        .loading-indicator {
+            position: fixed;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            background: rgba(212, 165, 116, 0.95);
+            padding: 20px 30px;
+            border-radius: 12px;
+            color: #2c1810;
+            font-weight: bold;
+            border: 3px solid #8b5a2b;
+            z-index: 2000;
+            box-shadow: 0 8px 25px rgba(0,0,0,0.4);
+        }
+
+        .error-message {
+            position: fixed;
+            top: 50%;
+            left: 50%;
+            transform: translate(-50%, -50%);
+            background: rgba(139, 38, 53, 0.95);
+            padding: 20px 30px;
+            border-radius: 12px;
+            color: #e6c080;
+            font-weight: bold;
+            border: 3px solid #8b2635;
+            z-index: 2000;
+            box-shadow: 0 8px 25px rgba(0,0,0,0.4);
+        }
+
+        @keyframes fadeInUp {
+            from {
+                opacity: 0;
+                transform: translateY(30px);
+            }
+            to {
+                opacity: 1;
+                transform: translateY(0);
+            }
+        }
+
+        .bamboo-strip {
+            animation: fadeInUp 0.6s ease-out forwards;
+        }
+
+        .bamboo-strip:nth-child(even) {
+            animation-delay: 0.1s;
+        }
+
+        .bamboo-strip:nth-child(3n) {
+            animation-delay: 0.2s;
+        }
+    </style>
+</head>
+<body>
+    <div class="loading-indicator" id="loadingIndicator" style="display: none;">Loading Chinese version...</div>
+
+    <div class="mode-toggle" onclick="toggleMode()" id="modeToggle" style="display: block;">
+        中文 ⟷ English
+    </div>
+
+    <div class="reader-container horizontal-mode" id="readerContainer"><div class="bamboo-strip title-strip" style="transform: rotateX(-0.349693deg) rotateZ(0.303864deg);"><div class="strip-content">IV. Tactical Dispositions</div></div><div class="bamboo-strip" data-index="0" style="transform: rotateX(-0.0496933deg) rotateZ(0.303864deg);"><div class="strip-content">1. Sun Tzu said: The good fighters of old first put themselves beyond the possibility of defeat, and then waited for an opportunity of defeating the enemy.</div></div><div class="bamboo-strip" data-index="1" style="transform: rotateX(0.250307deg) rotateZ(0.303864deg);"><div class="strip-content">2. To secure ourselves against defeat lies in our own hands, but the opportunity of defeating the enemy is provided by the enemy himself.</div></div><div class="bamboo-strip" data-index="2" style="transform: rotateX(0.550307deg) rotateZ(0.303864deg);"><div class="strip-content">3. Thus the good fighter is able to secure himself against defeat, but cannot make certain of defeating the enemy.</div></div><div class="bamboo-strip" data-index="3" style="transform: rotateX(0.850307deg) rotateZ(0.303864deg);"><div class="strip-content">4. Hence the saying: One may know how to conquer without being able to do it.</div></div><div class="bamboo-strip" data-index="4" style="transform: rotateX(1.15031deg) rotateZ(0.303864deg);"><div class="strip-content">5. Security against defeat implies defensive tactics; ability to defeat the enemy means taking the offensive.</div></div><div class="bamboo-strip" data-index="5" style="transform: rotateX(1.45031deg) rotateZ(0.303864deg);"><div class="strip-content">6. Standing on the defensive indicates insufficient strength; attacking, a superabundance of strength.</div></div><div class="bamboo-strip" data-index="6" style="transform: rotateX(1.75031deg) rotateZ(0.303864deg);"><div class="strip-content">7. The general who is skilled in defense hides in the most secret recesses of the earth; he who is skilled in attack flashes forth from the topmost heights of heaven. Thus on the one hand we have ability to protect ourselves; on the other, a victory that is complete.</div></div><div class="bamboo-strip" data-index="7" style="transform: rotateX(2.05031deg) rotateZ(0.303864deg);"><div class="strip-content">8. To see victory only when it is within the ken of the common herd is not the acme of excellence.</div></div><div class="bamboo-strip" data-index="8" style="transform: rotateX(2.35031deg) rotateZ(0.303864deg);"><div class="strip-content">9. Neither is it the acme of excellence if you fight and conquer and the whole Empire says, "Well done!"</div></div><div class="bamboo-strip" data-index="9" style="transform: rotateX(2.65031deg) rotateZ(0.303864deg);"><div class="strip-content">10. To lift an autumn hair is no sign of great strength; to see the sun and moon is no sign of sharp sight; to hear the noise of thunder is no sign of a quick ear.</div></div><div class="bamboo-strip" data-index="10" style="transform: rotateX(2.95031deg) rotateZ(0.303864deg);"><div class="strip-content">11. What the ancients called a clever fighter is one who not only wins, but excels in winning with ease.</div></div><div class="bamboo-strip" data-index="11" style="transform: rotateX(3.25031deg) rotateZ(0.303864deg);"><div class="strip-content">12. Hence his victories bring him neither reputation for wisdom nor credit for courage.</div></div><div class="bamboo-strip" data-index="12" style="transform: rotateX(3.55031deg) rotateZ(0.303864deg);"><div class="strip-content">13. He wins his battles by making no mistakes. Making no mistakes is what establishes the certainty of victory, for it means conquering an enemy that is already defeated.</div></div><div class="bamboo-strip" data-index="13" style="transform: rotateX(3.85031deg) rotateZ(0.303864deg);"><div class="strip-content">14. Hence the skillful fighter puts himself into a position which makes defeat impossible, and does not miss the moment for defeating the enemy.</div></div><div class="bamboo-strip" data-index="14" style="transform: rotateX(4.15031deg) rotateZ(0.303864deg);"><div class="strip-content">15. Thus it is that in war the victorious strategist only seeks battle after the victory has been won, whereas he who is destined to defeat first fights and afterwards looks for victory.</div></div><div class="bamboo-strip" data-index="15" style="transform: rotateX(4.45031deg) rotateZ(0.303864deg);"><div class="strip-content">16. The consummate leader cultivates the moral law, and strictly adheres to method and discipline; thus it is in his power to control success.</div></div><div class="bamboo-strip" data-index="16" style="transform: rotateX(4.75031deg) rotateZ(0.303864deg);"><div class="strip-content">17. In respect of military method, we have, firstly, Measurement; secondly, Estimation of quantity; thirdly, Calculation; fourthly, Balancing of chances; fifthly, Victory.</div></div><div class="bamboo-strip" data-index="17" style="transform: rotateX(5.05031deg) rotateZ(0.303864deg);"><div class="strip-content">18. Measurement owes its existence to Earth; Estimation of quantity to Measurement; Calculation to Estimation of quantity; Balancing of chances to Calculation; and Victory to Balancing of chances.</div></div><div class="bamboo-strip" data-index="18" style="transform: rotateX(5.35031deg) rotateZ(0.303864deg);"><div class="strip-content">19. A victorious army opposed to a routed one, is as a pound's weight placed in the scale against a single grain.</div></div><div class="bamboo-strip" data-index="19" style="transform: rotateX(5.65031deg) rotateZ(0.303864deg);"><div class="strip-content">20. The onrush of a conquering force is like the bursting of pent-up waters into a chasm a thousand fathoms deep.</div></div><div class="binding-cord" style="top: 100px; left: 50px;"></div><div class="binding-cord" style="top: 250px; left: 50px;"></div><div class="binding-cord" style="top: 400px; left: 50px;"></div><div class="binding-cord" style="top: 550px; left: 50px;"></div><div class="binding-cord" style="top: 700px; left: 50px;"></div><div class="binding-cord" style="top: 850px; left: 50px;"></div><div class="binding-cord" style="top: 1000px; left: 50px;"></div></div>
+
+    <div class="controls">
+        <button class="control-btn" onclick="previousChapter()">◀ Previous</button>
+        <button class="control-btn" onclick="resetView()">Reset View</button>
+        <button class="control-btn" onclick="nextChapter()">Next ▶</button>
+    </div>
+
+    <div class="chapter-indicator" id="chapterIndicator">Chapter 4: IV. Tactical Dispositions</div>
+
+    <script>
+        let chapters = {
+            chinese: [],
+            english: []
+        };
+        let currentChapter = 0;
+        let selectedStrip = -1;
+        let isChineseMode = true;
+        let isTransitioning = false;
+        let isLoaded = false;
+
+        // Fetch book content from JSON URLs
+        async function loadBookContent() {
+            const loadingEl = document.getElementById('loadingIndicator');
+            const modeToggle = document.getElementById('modeToggle');
+            
+            try {
+                loadingEl.textContent = 'Loading English version...';
+                const englishResponse = await fetch('https://cheatsheets.davidveksler.com/art-of-war-sun-tzu-english.json');
+                if (!englishResponse.ok) throw new Error('Failed to load English content');
+                const englishData = await englishResponse.json();
+
+                loadingEl.textContent = 'Loading Chinese version...';
+                const chineseResponse = await fetch('https://cheatsheets.davidveksler.com/art-of-war-sun-tzu-chinese.json');
+                if (!chineseResponse.ok) throw new Error('Failed to load Chinese content');
+                const chineseData = await chineseResponse.json();
+
+                // Process and structure the data
+                chapters.english = processBookData(englishData);
+                chapters.chinese = processBookData(chineseData);
+
+                loadingEl.style.display = 'none';
+                modeToggle.style.display = 'block';
+                isLoaded = true;
+                
+                createBambooStrips();
+            } catch (error) {
+                console.error('Error loading book content:', error);
+                loadingEl.innerHTML = `
+                    <div class="error-message">
+                        Failed to load The Art of War content.<br>
+                        Please check your internet connection and try again.
+                    </div>
+                `;
+            }
+        }
+
+        // Process JSON data into chapter format
+        function processBookData(data) {
+            // Handle the specific structure from your JSON files
+            if (data.chapters && Array.isArray(data.chapters)) {
+                return data.chapters.map(chapter => ({
+                    title: chapter.title || `Chapter ${chapter.roman_numeral || ''}`,
+                    content: chapter.paragraphs || []
+                }));
+            }
+            
+            // Fallback for other structures
+            if (Array.isArray(data)) {
+                return data.map((chapter, index) => ({
+                    title: chapter.title || chapter.name || `Chapter ${index + 1}`,
+                    content: chapter.paragraphs || chapter.content || 
+                        (chapter.text || chapter.verses || [chapter.content]).filter(Boolean)
+                }));
+            }
+            
+            // Handle nested content
+            if (data.content) {
+                return processBookData(data.content);
+            }
+            
+            // Fallback structure
+            return Object.keys(data).map(key => ({
+                title: key,
+                content: Array.isArray(data[key]) ? data[key] : [data[key]]
+            }));
+        }
+
+        function getCurrentChapters() {
+            return isChineseMode ? chapters.chinese : chapters.english;
+        }
+
+        function createBambooStrips() {
+            if (!isLoaded) return;
+            
+            const container = document.getElementById('readerContainer');
+            container.innerHTML = '';
+
+            const currentChapters = getCurrentChapters();
+            if (!currentChapters || currentChapters.length === 0) return;
+            
+            const chapter = currentChapters[currentChapter];
+            if (!chapter) return;
+            
+            // Create title strip
+            const titleStrip = document.createElement('div');
+            titleStrip.className = 'bamboo-strip title-strip';
+            titleStrip.innerHTML = `<div class="strip-content">${chapter.title}</div>`;
+            container.appendChild(titleStrip);
+
+            // Create content strips
+            if (chapter.content && Array.isArray(chapter.content)) {
+                chapter.content.forEach((text, index) => {
+                    if (text && text.trim()) { // Only create strips for non-empty content
+                        const strip = document.createElement('div');
+                        strip.className = 'bamboo-strip';
+                        strip.setAttribute('data-index', index);
+                        strip.innerHTML = `<div class="strip-content">${text}</div>`;
+                        
+                        strip.addEventListener('click', () => selectStrip(index));
+                        container.appendChild(strip);
+                    }
+                });
+            }
+
+            // Add binding cords
+            const contentLength = chapter.content ? chapter.content.filter(text => text && text.trim()).length : 0;
+            if (isChineseMode) {
+                // Vertical binding cords
+                for (let i = 0; i < Math.ceil(contentLength / 4); i++) {
+                    const cord = document.createElement('div');
+                    cord.className = 'binding-cord';
+                    cord.style.left = `${120 + i * 320}px`;
+                    cord.style.top = '50px';
+                    container.appendChild(cord);
+                }
+            } else {
+                // Horizontal binding cords
+                for (let i = 0; i < Math.ceil(contentLength / 3); i++) {
+                    const cord = document.createElement('div');
+                    cord.className = 'binding-cord';
+                    cord.style.top = `${100 + i * 150}px`;
+                    cord.style.left = '50px';
+                    container.appendChild(cord);
+                }
+            }
+
+            document.getElementById('chapterIndicator').textContent = 
+                `Chapter ${currentChapter + 1}: ${chapter.title}`;
+        }
+
+        function toggleMode() {
+            if (isTransitioning || !isLoaded) return;
+            
+            isTransitioning = true;
+            const container = document.getElementById('readerContainer');
+            
+            // Start rotation
+            container.classList.add('transitioning');
+            
+            setTimeout(() => {
+                // Switch mode at halfway point
+                isChineseMode = !isChineseMode;
+                container.className = `reader-container ${isChineseMode ? 'vertical-mode' : 'horizontal-mode'}`;
+                selectedStrip = -1;
+                createBambooStrips();
+            }, 600);
+            
+            setTimeout(() => {
+                // Complete rotation
+                container.classList.remove('transitioning');
+                isTransitioning = false;
+            }, 1200);
+        }
+
+        function selectStrip(index) {
+            if (!isLoaded) return;
+            
+            document.querySelectorAll('.bamboo-strip').forEach(strip => {
+                strip.classList.remove('selected');
+            });
+
+            if (selectedStrip === index) {
+                selectedStrip = -1;
+                return;
+            }
+
+            selectedStrip = index;
+            const strip = document.querySelector(`[data-index="${index}"]`);
+            if (strip) {
+                strip.classList.add('selected');
+            }
+        }
+
+        function nextChapter() {
+            if (!isLoaded) return;
+            
+            const currentChapters = getCurrentChapters();
+            if (currentChapter < currentChapters.length - 1) {
+                currentChapter++;
+                selectedStrip = -1;
+                createBambooStrips();
+            }
+        }
+
+        function previousChapter() {
+            if (!isLoaded) return;
+            
+            if (currentChapter > 0) {
+                currentChapter--;
+                selectedStrip = -1;
+                createBambooStrips();
+            }
+        }
+
+        function resetView() {
+            if (!isLoaded) return;
+            
+            selectedStrip = -1;
+            document.querySelectorAll('.bamboo-strip').forEach(strip => {
+                strip.classList.remove('selected');
+            });
+        }
+
+        // Keyboard navigation
+        document.addEventListener('keydown', (e) => {
+            if (isTransitioning || !isLoaded) return;
+            
+            switch(e.key) {
+                case 'ArrowLeft':
+                    previousChapter();
+                    break;
+                case 'ArrowRight':
+                    nextChapter();
+                    break;
+                case 'Escape':
+                    resetView();
+                    break;
+                case ' ':
+                    e.preventDefault();
+                    toggleMode();
+                    break;
+            }
+        });
+
+        // Initialize - Load content from JSON URLs
+        loadBookContent();
+
+        // Add explicit event listener as backup
+        document.getElementById('modeToggle').addEventListener('click', function(e) {
+            e.preventDefault();
+            e.stopPropagation();
+            toggleMode();
+        });
+
+        // Subtle parallax effect
+        document.addEventListener('mousemove', (e) => {
+            if (isTransitioning || !isLoaded) return;
+            
+            const strips = document.querySelectorAll('.bamboo-strip:not(.selected)');
+            const mouseX = (e.clientX / window.innerWidth - 0.5) * 2;
+            const mouseY = (e.clientY / window.innerHeight - 0.5) * 2;
+
+            strips.forEach((strip, index) => {
+                const offset = index * 0.3;
+                if (isChineseMode) {
+                    strip.style.transform = `rotateY(${mouseX * 1 + offset}deg) rotateX(${mouseY * 0.5}deg)`;
+                } else {
+                    strip.style.transform = `rotateX(${mouseY * 1 + offset}deg) rotateZ(${mouseX * 0.5}deg)`;
+                }
+            });
+        });
+    </script>
+
+</body></html>
\ No newline at end of file
diff --git a/art-of-war-sun-tzu-gemini.html b/art-of-war-sun-tzu-gemini.html
new file mode 100644
index 0000000..3d0f2f6
--- /dev/null
+++ b/art-of-war-sun-tzu-gemini.html
@@ -0,0 +1,548 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>Art of War - Dual View Reader</title>
+    <style>
+      @import url("https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;700&display=swap");
+
+      * {
+        margin: 0;
+        padding: 0;
+        box-sizing: border-box;
+      }
+
+      body {
+        background: radial-gradient(circle at 20% 50%, rgba(76, 44, 26, 0.3) 0%, transparent 50%),
+          radial-gradient(circle at 80% 20%, rgba(139, 90, 43, 0.2) 0%, transparent 50%),
+          radial-gradient(circle at 40% 80%, rgba(61, 37, 26, 0.3) 0%, transparent 50%),
+          linear-gradient(135deg, #2c1810 0%, #4a2c1a 50%, #3d251a 100%);
+        font-family: "Georgia", serif; /* Base font from inspiration */
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        justify-content: center;
+        min-height: 100vh;
+        color: #3a2b20; /* Default text color, will be overridden */
+        padding: 20px;
+        overflow: hidden;
+      }
+
+      .header-title {
+        font-weight: 700;
+        font-size: 2.2em;
+        margin-bottom: 5px;
+        color: #e6c080; /* Lighter color for dark bg */
+        text-shadow: 1px 1px 3px rgba(0, 0, 0, 0.7);
+        text-align: center;
+      }
+
+      .subtitle {
+        font-size: 1.1em;
+        margin-bottom: 20px;
+        color: #d4a574; /* Lighter color */
+        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
+        text-align: center;
+      }
+
+      .reader-frame {
+        width: 90vw;
+        max-width: 1000px;
+        height: 70vh;
+        max-height: 600px; /* Increased max-height for new strip style */
+        /* background-color: #6f4e37; Old background */
+        border: 3px solid #654021; /* Darker, richer border */
+        box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5), inset 0 0 15px rgba(0, 0, 0, 0.3);
+        position: relative;
+        border-radius: 8px;
+        perspective: 1500px;
+        overflow: hidden;
+        /* Add a subtle inner texture or darker background for the frame itself */
+        background: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)),
+          url("data:image/svg+xml,%3Csvg width='52' height='26' viewBox='0 0 52 26' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23503020' fill-opacity='0.1'%3E%3Cpath d='M10 10c0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6h2c0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4 3.314 0 6 2.686 6 6 0 2.21 1.79 4 4 4v2c-3.314 0-6-2.686-6-6 0-2.21-1.79-4-4-4-3.314 0-6-2.686-6-6zm25.464-1.95l8.486 8.486-1.414 1.414-8.486-8.486 1.414-1.414z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E"),
+          #4a2c1a;
+      }
+
+      .view-container {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+        padding: 20px;
+        box-sizing: border-box;
+        transition: transform 0.9s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.7s ease-in-out;
+        transform-style: preserve-3d;
+        backface-visibility: hidden;
+        overflow: hidden;
+      }
+
+      /* --- Base Strip Styling (Common for Chinese and English) --- */
+      .bamboo-slip,
+      .english-strip {
+        background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 40%),
+          /* Subtle highlight */ linear-gradient(45deg, #d4a574 0%, #c19653 25%, #d4a574 50%, #b8954d 75%, #d4a574 100%);
+        position: relative;
+        transform-style: preserve-3d;
+        transition: all 0.4s ease;
+        cursor: default; /* Changed from pointer as they are not clickable yet */
+        border-radius: 3px; /* Slightly less rounding */
+        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), /* Inner highlight */ inset 0 0 10px rgba(0, 0, 0, 0.1),
+          /* Inner shadow for depth */ 0 3px 8px rgba(0, 0, 0, 0.3), /* Outer shadow */ 0 1px 2px rgba(0, 0, 0, 0.2);
+        color: #2c1810; /* Dark brown text for readability */
+        font-weight: 600;
+        overflow: hidden; /* Ensure pseudo elements don't bleed out awkwardly */
+        animation: fadeInUp 0.6s ease-out forwards;
+      }
+      .bamboo-slip:nth-child(even),
+      .english-strip:nth-child(even) {
+        animation-delay: 0.05s;
+      }
+      .bamboo-slip:nth-child(3n),
+      .english-strip:nth-child(3n) {
+        animation-delay: 0.1s;
+      }
+
+      .bamboo-slip::before,
+      .english-strip::before {
+        /* Grain effect */
+        content: "";
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        border-radius: 2px; /* Match parent's rounding slightly tighter */
+        pointer-events: none;
+      }
+      .bamboo-slip::after,
+      .english-strip::after {
+        /* Center line/crease */
+        content: "";
+        position: absolute;
+        background: linear-gradient(
+          rgba(101, 67, 33, 0.1) 20%,
+          rgba(101, 67, 33, 0.05) 50%,
+          rgba(101, 67, 33, 0.1) 80%
+        );
+        pointer-events: none;
+      }
+
+      .bamboo-slip:hover,
+      .english-strip:hover {
+        transform: scale(1.02) translateZ(8px); /* Subtle hover */
+        z-index: 5; /* Ensure hovered strip is above others */
+        box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), inset 0 0 15px rgba(0, 0, 0, 0.12),
+          0 6px 15px rgba(0, 0, 0, 0.35), 0 2px 5px rgba(0, 0, 0, 0.25);
+      }
+
+      /* --- Chinese View (Vertical Slips) --- */
+      #chinese-view-container {
+        transform: rotateY(0deg);
+        opacity: 1;
+        z-index: 2;
+        overflow-x: auto;
+        overflow-y: hidden;
+        display: flex;
+        white-space: nowrap;
+        padding: 25px 15px; /* Padding around the slips */
+      }
+      #chinese-view-container.hidden-view {
+        transform: rotateY(-90deg) translateX(-50%);
+        opacity: 0;
+        z-index: 1;
+      }
+
+      #chinese-view-container::-webkit-scrollbar {
+        height: 12px;
+      }
+      #chinese-view-container::-webkit-scrollbar-track {
+        background: rgba(140, 109, 82, 0.5);
+        border-radius: 6px;
+      }
+      #chinese-view-container::-webkit-scrollbar-thumb {
+        background-color: rgba(92, 58, 33, 0.7);
+        border-radius: 6px;
+        border: 2px solid rgba(140, 109, 82, 0.5);
+      }
+
+      .bamboo-slip {
+        flex: 0 0 auto;
+        width: 55px; /* Slightly wider for aesthetics */
+        height: calc(100% - 10px); /* Accommodate padding within container */
+        margin: 0 2px; /* Tighter margin */
+        writing-mode: vertical-rl;
+        text-orientation: upright; /* From inspiration for Chinese */
+        font-family: "Noto Serif SC", serif;
+        font-size: 14px; /* Adjusted from inspiration */
+        line-height: 1.5;
+        padding: 35px 6px; /* Top/bottom padding for threads, L/R for text */
+        letter-spacing: 1px; /* From inspiration */
+      }
+      .bamboo-slip::before {
+        /* Vertical Grain */
+        background: repeating-linear-gradient(
+          90deg,
+          transparent 0px,
+          rgba(139, 85, 47, 0.08) 1px,
+          transparent 1px,
+          transparent 10px
+        );
+      }
+      .bamboo-slip::after {
+        /* Vertical Center Line */
+        top: 8%;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 1px;
+        height: 84%; /* Slightly inset */
+      }
+      .bamboo-slip.chapter-title-slip {
+        width: 70px; /* Wider for title */
+        font-size: 16px;
+        font-weight: bold;
+        background: linear-gradient(45deg, #e6c080 0%, #d4a574 25%, #e6c080 50%, #c9a366 75%, #e6c080 100%);
+        color: #8b2635; /* Inspired title color */
+        letter-spacing: 2px;
+        align-items: center;
+        justify-content: center;
+        display: flex; /* For text centering */
+      }
+
+      /* Binding threads for Chinese view (on container) */
+      #chinese-view-container.active-view::before,
+      #chinese-view-container.active-view::after {
+        content: "";
+        position: absolute;
+        left: 10px;
+        right: 10px; /* Inset slightly */
+        height: 4px; /* Thicker */
+        background: linear-gradient(to bottom, #8b5a2b 0%, #654021 50%, #8b5a2b 100%);
+        border-radius: 2px;
+        z-index: 3; /* Above slips but below potential hover scale */
+        pointer-events: none;
+        box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.5);
+      }
+      #chinese-view-container.active-view::before {
+        top: 40px;
+      }
+      #chinese-view-container.active-view::after {
+        bottom: 40px;
+      }
+
+      /* --- English View (Horizontal Strips) --- */
+      #english-view-container {
+        transform: rotateY(90deg) translateX(50%);
+        opacity: 0;
+        z-index: 1;
+        overflow-y: auto;
+        overflow-x: hidden;
+        /* background-color: #c7bcae;  Old bg */
+        font-family: Georgia, "Times New Roman", serif;
+        padding: 20px;
+        position: relative;
+      }
+      #english-view-container.active-view {
+        transform: rotateY(0deg) translateX(0%);
+        opacity: 1;
+        z-index: 2;
+      }
+
+      /* Decorative "binding threads" for the English view background */
+      #english-view-container.active-view::before,
+      #english-view-container.active-view::after {
+        content: "";
+        position: absolute;
+        left: 15%;
+        right: 15%; /* Positioned more centrally */
+        height: 4px; /* Thicker */
+        background: linear-gradient(to right, #8b5a2b 0%, #654021 50%, #8b5a2b 100%);
+        border-radius: 2px;
+        z-index: 0;
+        pointer-events: none;
+        box-shadow: 1px 0px 2px rgba(0, 0, 0, 0.5);
+      }
+      #english-view-container.active-view::before {
+        top: 20%;
+      }
+      #english-view-container.active-view::after {
+        bottom: 20%;
+      }
+
+      #english-view-container::-webkit-scrollbar {
+        width: 12px;
+      }
+      #english-view-container::-webkit-scrollbar-track {
+        background: rgba(184, 174, 159, 0.5);
+        border-radius: 6px;
+      }
+      #english-view-container::-webkit-scrollbar-thumb {
+        background-color: rgba(122, 93, 66, 0.7);
+        border-radius: 6px;
+        border: 2px solid rgba(184, 174, 159, 0.5);
+      }
+
+      .english-strip {
+        width: calc(100% - 10px); /* Responsive width */
+        min-height: 40px; /* Minimum height */
+        margin: 0 auto 5px auto; /* Centered, tighter margin */
+        padding: 10px 35px; /* L/R padding for threads, T/B for text */
+        font-size: 14px; /* From inspiration */
+        line-height: 1.4; /* Adjusted */
+        letter-spacing: 0.5px; /* From inspiration */
+        display: flex;
+        align-items: center; /* For vertical centering of text */
+      }
+
+      .english-strip::before {
+        /* Horizontal Grain */
+        background: repeating-linear-gradient(
+          0deg,
+          transparent 0px,
+          rgba(139, 85, 47, 0.06) 1px,
+          /* Softer grain */ transparent 1px,
+          transparent 12px
+        );
+      }
+      .english-strip::after {
+        /* Horizontal Center Line */
+        left: 8%;
+        top: 50%;
+        transform: translateY(-50%);
+        height: 1px;
+        width: 84%; /* Slightly inset */
+      }
+      .english-strip.chapter-title {
+        min-height: 50px; /* Taller for title */
+        font-size: 16px;
+        font-weight: bold;
+        justify-content: center; /* Center title text */
+        background: linear-gradient(45deg, #e6c080 0%, #d4a574 25%, #e6c080 50%, #c9a366 75%, #e6c080 100%);
+        color: #8b2635; /* Inspired title color */
+      }
+
+      /* Toggle Button */
+      .toggle-button {
+        margin-top: 25px;
+        padding: 10px 20px; /* Adjusted from inspiration */
+        background: rgba(212, 165, 116, 0.85); /* Inspired */
+        border: 2px solid #8b5a2b; /* Inspired */
+        border-radius: 8px;
+        color: #2c1810;
+        font-weight: bold;
+        cursor: pointer;
+        transition: all 0.3s ease;
+        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
+        font-size: 15px;
+        text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.2);
+      }
+      .toggle-button:hover {
+        background: rgba(230, 192, 128, 0.95);
+        transform: translateY(-1px);
+        border-color: #654021;
+        box-shadow: 0 3px 7px rgba(0, 0, 0, 0.35);
+      }
+      .toggle-button:disabled {
+        background: rgba(150, 130, 110, 0.7);
+        color: #705040;
+        border-color: #705040;
+        cursor: not-allowed;
+      }
+
+      .instructions {
+        margin-top: 15px;
+        font-size: 0.9em;
+        color: #d4a574;
+        text-align: center;
+        text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
+      }
+      .loading-message,
+      .error-message {
+        /* Combined for similar styling */
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%, -50%);
+        background: rgba(212, 165, 116, 0.9);
+        padding: 15px 25px;
+        border-radius: 10px;
+        color: #2c1810;
+        font-weight: bold;
+        border: 2px solid #8b5a2b;
+        box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
+        text-align: center;
+      }
+      .error-message {
+        background: rgba(139, 38, 53, 0.9); /* Error specific color */
+        color: #e6c080;
+        border: 2px solid #801f2a;
+      }
+
+      @keyframes fadeInUp {
+        from {
+          opacity: 0;
+          transform: translateY(15px) scale(0.98);
+        }
+        to {
+          opacity: 1;
+          transform: translateY(0) scale(1);
+        }
+      }
+    </style>
+  </head>
+  <body>
+    <div class="header-title" id="mainBookTitle">孫子兵法 / The Art of War</div>
+    <div class="subtitle" id="mainBookAuthor">Dual Language Reader Concept</div>
+
+    <div class="reader-frame">
+      <div id="chinese-view-container" class="view-container active-view">
+        <div class="loading-message">Loading Chinese Content...</div>
+      </div>
+
+      <div id="english-view-container" class="view-container hidden-view">
+        <div class="loading-message">Loading English Content...</div>
+      </div>
+    </div>
+
+    <button id="toggleViewButton" class="toggle-button" disabled>Switch Language</button>
+    <div class="instructions">Chinese view: Use mouse wheel or touchpad to scroll horizontally.</div>
+
+    <script>
+      const chineseViewContainer = document.getElementById("chinese-view-container");
+      const englishViewContainer = document.getElementById("english-view-container");
+      const toggleButton = document.getElementById("toggleViewButton");
+      const mainBookTitle = document.getElementById("mainBookTitle");
+      const mainBookAuthor = document.getElementById("mainBookAuthor");
+
+      let isChineseViewActive = true;
+      let chineseData = null;
+      let englishData = null;
+
+      const chineseJsonUrl = "https://cheatsheets.davidveksler.com/art-of-war-sun-tzu-chinese.json";
+      const englishJsonUrl = "https://cheatsheets.davidveksler.com/art-of-war-sun-tzu-english.json";
+
+      function populateChineseView(data) {
+        chineseViewContainer.innerHTML = "";
+        if (!data || !data.chapters) {
+          chineseViewContainer.innerHTML = '<div class="error-message">Error loading Chinese content.</div>';
+          return;
+        }
+
+        data.chapters.forEach((chapter) => {
+          const titleSlip = document.createElement("div");
+          titleSlip.classList.add("bamboo-slip", "chapter-title-slip");
+          let formattedTitle = chapter.title; // Keep as is for now, or apply more complex vertical formatting
+          if (formattedTitle.length > 5) {
+            // Simple attempt to break longer titles
+            formattedTitle = formattedTitle.split("").join("\n");
+          }
+          titleSlip.textContent = formattedTitle;
+          chineseViewContainer.appendChild(titleSlip);
+
+          chapter.paragraphs.forEach((para) => {
+            const slip = document.createElement("div");
+            slip.classList.add("bamboo-slip");
+            slip.textContent = para;
+            chineseViewContainer.appendChild(slip);
+          });
+        });
+      }
+
+      function populateEnglishView(data) {
+        englishViewContainer.innerHTML = "";
+        if (!data || !data.chapters) {
+          englishViewContainer.innerHTML = '<div class="error-message">Error loading English content.</div>';
+          return;
+        }
+
+        data.chapters.forEach((chapter) => {
+          const titleStrip = document.createElement("div");
+          titleStrip.classList.add("english-strip", "chapter-title");
+          titleStrip.textContent = `${chapter.title}`;
+          englishViewContainer.appendChild(titleStrip);
+
+          chapter.paragraphs.forEach((para) => {
+            const strip = document.createElement("div");
+            strip.classList.add("english-strip");
+            strip.textContent = para;
+            englishViewContainer.appendChild(strip);
+          });
+        });
+      }
+
+      async function loadContent() {
+        toggleButton.textContent = "Loading...";
+        try {
+          const [chineseResponse, englishResponse] = await Promise.all([fetch(chineseJsonUrl), fetch(englishJsonUrl)]);
+
+          if (!chineseResponse.ok) throw new Error(`Failed to fetch Chinese data (Status: ${chineseResponse.status})`);
+          if (!englishResponse.ok) throw new Error(`Failed to fetch English data (Status: ${englishResponse.status})`);
+
+          chineseData = await chineseResponse.json();
+          englishData = await englishResponse.json();
+
+          populateChineseView(chineseData);
+          populateEnglishView(englishData);
+
+          mainBookTitle.textContent = `${chineseData.title} / ${englishData.title}`;
+          mainBookAuthor.textContent = `By ${chineseData.author || englishData.author}`;
+
+          toggleButton.disabled = false;
+          toggleButton.textContent = "Switch to English";
+        } catch (error) {
+          console.error("Error loading content:", error);
+          const errorMessage = `<div class="error-message">Failed to load book content.<br><small>${error.message}</small></div>`;
+          chineseViewContainer.innerHTML = errorMessage;
+          englishViewContainer.innerHTML = errorMessage;
+          toggleButton.disabled = true;
+          toggleButton.textContent = "Load Failed";
+        }
+      }
+
+      if (chineseViewContainer) {
+        chineseViewContainer.addEventListener("wheel", (event) => {
+          if (isChineseViewActive && event.deltaY !== 0 && chineseViewContainer.classList.contains("active-view")) {
+            event.preventDefault();
+            chineseViewContainer.scrollLeft += event.deltaY * 2.5; // Slightly faster scroll
+          }
+        });
+      }
+
+      toggleButton.addEventListener("click", () => {
+        if (!chineseData || !englishData) return;
+
+        isChineseViewActive = !isChineseViewActive;
+        // Add a class to the frame for the overall rotation
+        document.querySelector(".reader-frame").classList.add("transitioning");
+
+        // The actual view swap happens after the rotation animation is expected to be part way
+        setTimeout(() => {
+          if (isChineseViewActive) {
+            chineseViewContainer.classList.remove("hidden-view");
+            chineseViewContainer.classList.add("active-view");
+            englishViewContainer.classList.remove("active-view");
+            englishViewContainer.classList.add("hidden-view");
+            toggleButton.textContent = "Switch to English";
+          } else {
+            englishViewContainer.classList.remove("hidden-view");
+            englishViewContainer.classList.add("active-view");
+            chineseViewContainer.classList.remove("active-view");
+            chineseViewContainer.classList.add("hidden-view");
+            toggleButton.textContent = "Switch to Chinese";
+          }
+          // Remove the transitioning class to allow rotation back
+          setTimeout(() => {
+            // Ensure it's removed after the new view is set
+            document.querySelector(".reader-frame").classList.remove("transitioning");
+          }, 50); // Small delay
+        }, 350); // Half of the view-container transition duration (0.7s / 2)
+      });
+
+      englishViewContainer.classList.add("hidden-view");
+      englishViewContainer.classList.remove("active-view");
+
+      document.addEventListener("DOMContentLoaded", loadContent);
+    </script>
+  </body>
+</html>