/* =========================================== VIEWPORT FITTING: MANDATORY BASE STYLES Include this ENTIRE file in every presentation. These styles ensure slides fit exactly in the viewport. =========================================== */ /* 1. Lock html/body to viewport */ html, body { height: 100%; overflow-x: hidden; } html { scroll-snap-type: y mandatory; scroll-behavior: smooth; } /* =========================================== CJK TYPOGRAPHY BASE Chinese text rendering and spacing defaults =========================================== */ /* CJK-aware line height: Chinese characters need more vertical room */ :lang(zh), :lang(zh-CN), :lang(zh-Hans) { line-height: 1.7; word-break: break-all; overflow-wrap: break-word; } /* Headings tighter line-height for CJK */ h1:lang(zh), h2:lang(zh), h3:lang(zh), h1:lang(zh-CN), h2:lang(zh-CN), h3:lang(zh-CN) { line-height: 1.3; letter-spacing: 0.02em; } /* Tabular numbers for financial data */ .num, .kpi-value, [data-count], td.num, th.col-num { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; } /* Financial color semantics — A-share convention as GLOBAL DEFAULT */ /* All themes inherit. Override in preset :root ONLY if intentional. */ :root { --color-positive: #dc2626; /* Red = Up (A-share) */ --color-negative: #16a34a; /* Green = Down (A-share) */ } .positive, .up { color: var(--color-positive); } .negative, .down { color: var(--color-negative); } /* Trend arrows — CSS only, never emoji */ .trend-up::before { content: ''; display: inline-block; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-bottom: 5px solid var(--color-positive); margin-right: 0.25em; vertical-align: middle; } .trend-down::before { content: ''; display: inline-block; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 5px solid var(--color-negative); margin-right: 0.25em; vertical-align: middle; } /* 2. Each slide = exact viewport height */ .slide { width: 100vw; height: 100vh; height: 100dvh; /* Dynamic viewport height for mobile browsers */ overflow: hidden; /* CRITICAL: Prevent ANY overflow */ scroll-snap-align: start; display: flex; flex-direction: column; position: relative; } /* 3. Content container with flex for centering */ .slide-content { flex: 1; display: flex; flex-direction: column; justify-content: center; max-height: 100%; overflow: hidden; /* Double-protection against overflow */ padding: var(--slide-padding); } /* 4. ALL typography uses clamp() for responsive scaling */ :root { /* Titles scale from mobile to desktop */ --title-size: clamp(1.5rem, 5vw, 4rem); --h2-size: clamp(1.25rem, 3.5vw, 2.5rem); --h3-size: clamp(1rem, 2.5vw, 1.75rem); /* Body text */ --body-size: clamp(0.75rem, 1.5vw, 1.125rem); --small-size: clamp(0.65rem, 1vw, 0.875rem); /* Spacing scales with viewport */ --slide-padding: clamp(1rem, 4vw, 4rem); --content-gap: clamp(0.5rem, 2vw, 2rem); --element-gap: clamp(0.25rem, 1vw, 1rem); } /* 5. Cards/containers use viewport-relative max sizes */ .card, .container, .content-box { max-width: min(90vw, 1000px); max-height: min(80vh, 700px); } /* 6. Lists auto-scale with viewport */ .feature-list, .bullet-list { gap: clamp(0.4rem, 1vh, 1rem); } .feature-list li, .bullet-list li { font-size: var(--body-size); line-height: 1.4; } /* 7. Grids adapt to available space */ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)); gap: clamp(0.5rem, 1.5vw, 1rem); } /* 8. Images constrained to viewport */ img, .image-container { max-width: 100%; max-height: min(50vh, 400px); object-fit: contain; } /* =========================================== RESPONSIVE BREAKPOINTS Aggressive scaling for smaller viewports =========================================== */ /* Short viewports (< 700px height) */ @media (max-height: 700px) { :root { --slide-padding: clamp(0.75rem, 3vw, 2rem); --content-gap: clamp(0.4rem, 1.5vw, 1rem); --title-size: clamp(1.25rem, 4.5vw, 2.5rem); --h2-size: clamp(1rem, 3vw, 1.75rem); } } /* Very short viewports (< 600px height) */ @media (max-height: 600px) { :root { --slide-padding: clamp(0.5rem, 2.5vw, 1.5rem); --content-gap: clamp(0.3rem, 1vw, 0.75rem); --title-size: clamp(1.1rem, 4vw, 2rem); --body-size: clamp(0.7rem, 1.2vw, 0.95rem); } /* Hide non-essential elements */ .nav-dots, .keyboard-hint, .decorative { display: none; } } /* Extremely short (landscape phones, < 500px height) */ @media (max-height: 500px) { :root { --slide-padding: clamp(0.4rem, 2vw, 1rem); --title-size: clamp(1rem, 3.5vw, 1.5rem); --h2-size: clamp(0.9rem, 2.5vw, 1.25rem); --body-size: clamp(0.65rem, 1vw, 0.85rem); } } /* Narrow viewports (< 600px width) */ @media (max-width: 600px) { :root { --title-size: clamp(1.25rem, 7vw, 2.5rem); } /* Stack grids vertically */ .grid { grid-template-columns: 1fr; } } /* =========================================== REDUCED MOTION Respect user preferences =========================================== */ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.2s !important; } html { scroll-behavior: auto; } }