skills/fund-slides/references/safe-base-template.html
wangyitong a65adcc2e5 Initial commit: merged, deduplicated, and vetted skill collection
Sources: extracted from two upstream archives (skill-repo, skills-main),
merged with the following policy:

- 15 broken symlinks (pointing to /Users/jameslee/.cc-switch/skills or
  ../../.agents/skills on a foreign machine) discarded
- 3 real name collisions with identical content (ai-pair, ifind-http-api,
  zhipu-websearch) kept as one copy
- Functional overlaps deduped keeping the strongest variant:
  - docx family: kept docx (official, full toolchain) + docx-cn
    (GB/T 9704 Chinese official-document constants),
    dropped docx_writer (no scripts, name collided with docx)
  - humanizer family: kept humanizer-zh (6 zh reference docs),
    dropped humanizer (en, redundant for CN workflow)
- Skills that only ran in a foreign environment removed:
  ablemind-ops, app-publish, hlb-design-system, openclaw-adj-skill,
  claude-driver
- alphapai excluded from this public repo because its SKILL.md hard-coded
  live credentials

Result: 25 skills, 572 files, ~7.5 MB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 14:47:12 +08:00

298 lines
12 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><!-- SLOT: TITLE --></title>
<!-- SLOT: FONTS — Replace with chosen preset's Google Fonts link -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&family=Noto+Serif+SC:wght@400;600;700&display=swap" rel="stylesheet">
<style>
/* ===========================================
SAFE BASE — DO NOT DELETE ANY SECTION BELOW
This is the defensive foundation layer.
All content above this line can be customized.
=========================================== */
* { margin: 0; padding: 0; box-sizing: border-box; }
/* --- VIEWPORT FITTING (MANDATORY) --- */
html, body { height: 100%; overflow-x: hidden; }
html { scroll-snap-type: y mandatory; scroll-behavior: smooth; }
.slide {
width: 100vw;
height: 100vh;
height: 100dvh;
overflow: hidden;
scroll-snap-align: start;
display: flex;
flex-direction: column;
position: relative;
}
.slide-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
max-height: 100%;
overflow: hidden;
padding: var(--slide-padding);
}
/* --- CJK TYPOGRAPHY --- */
:lang(zh), :lang(zh-CN), :lang(zh-Hans) {
line-height: 1.7;
word-break: break-all;
overflow-wrap: break-word;
}
h1:lang(zh-CN), h2:lang(zh-CN), h3:lang(zh-CN) {
line-height: 1.3;
letter-spacing: 0.02em;
}
.num, .kpi-value, [data-count], td.num, th.col-num {
font-variant-numeric: tabular-nums;
font-feature-settings: "tnum" 1;
}
/* --- GLOBAL FINANCIAL COLORS (A-SHARE DEFAULT) --- */
:root {
--color-positive: #dc2626; /* Red = Up (A-share convention) */
--color-negative: #16a34a; /* Green = Down */
/* SLOT: THEME COLORS — Override below with chosen preset */
--bg-primary: #ffffff;
--text-primary: #1a1a2e;
--text-secondary: #5a5a7a;
--accent: #2563eb;
--accent-secondary: #60a5fa;
--border-color: rgba(0, 0, 0, 0.08);
/* SLOT: FONTS — Override with chosen preset */
--font-display: 'Noto Serif SC', serif;
--font-body: 'Noto Sans SC', sans-serif;
/* Responsive typography — ALL sizes use clamp() */
--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-size: clamp(0.75rem, 1.5vw, 1.125rem);
--small-size: clamp(0.65rem, 1vw, 0.875rem);
/* Responsive spacing — ALL spacing uses clamp() */
--slide-padding: clamp(1rem, 4vw, 4rem);
--content-gap: clamp(0.5rem, 2vw, 2rem);
--element-gap: clamp(0.25rem, 1vw, 1rem);
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--duration-normal: 0.6s;
}
.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;
}
/* --- RESPONSIVE CONSTRAINTS --- */
.card, .container, .content-box {
max-width: min(90vw, 1000px);
max-height: min(80vh, 700px);
}
img, .image-container {
max-width: 100%;
max-height: min(50vh, 400px);
object-fit: contain;
}
.chart-container {
width: min(90vw, 800px);
height: min(50vh, 400px);
margin: 0 auto;
}
/* --- RESPONSIVE BREAKPOINTS --- */
@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);
}
.chart-container { height: min(40vh, 300px); }
}
@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);
}
.nav-dots, .keyboard-hint, .decorative { display: none; }
}
@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);
}
.chart-container { height: min(35vh, 250px); }
}
@media (max-width: 600px) {
:root { --title-size: clamp(1.25rem, 7vw, 2.5rem); }
.grid { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.2s !important;
}
html { scroll-behavior: auto; }
}
/* --- BASE ANIMATIONS --- */
.reveal {
opacity: 0;
transform: translateY(20px);
transition: opacity var(--duration-normal) var(--ease-out-expo),
transform var(--duration-normal) var(--ease-out-expo);
}
.slide.visible .reveal { opacity: 1; transform: translateY(0); }
.reveal:nth-child(1) { transition-delay: 0.1s; }
.reveal:nth-child(2) { transition-delay: 0.2s; }
.reveal:nth-child(3) { transition-delay: 0.3s; }
.reveal:nth-child(4) { transition-delay: 0.4s; }
.reveal:nth-child(5) { transition-delay: 0.5s; }
/* ===========================================
SLOT: THEME STYLES
Add preset-specific styles below this line.
=========================================== */
/* ===========================================
SLOT: COMPONENT STYLES
Add KPI cards, tables, charts, etc. below.
=========================================== */
</style>
</head>
<body>
<!-- SLOT: PROGRESS BAR (optional) -->
<div class="progress-bar" id="progressBar" style="position:fixed;top:0;left:0;height:3px;background:var(--accent);z-index:200;transition:width 0.3s ease;"></div>
<!-- ===========================================
SLOT: SLIDES
Add <section class="slide"> blocks here.
Each slide MUST have overflow: hidden (inherited from .slide class).
=========================================== -->
<!-- SLOT: ECHARTS INLINE (remove if no charts needed)
Read references/echarts.min.js and paste full content here.
DO NOT use <script src="..."> CDN — file must work offline. -->
<!-- <script>/* ECharts v5 - inline */ ...paste echarts.min.js content here... </script> -->
<script>
/* ===========================================
SAFE BASE JS — DO NOT DELETE
=========================================== */
/* Chinese number formatting */
function formatCN(num, decimals) {
if (decimals === undefined) decimals = 1;
if (num === null || num === undefined) return '--';
var abs = Math.abs(num);
var sign = num < 0 ? '-' : '';
if (abs >= 1e8) return sign + (abs / 1e8).toFixed(decimals).replace(/\.0$/, '') + '\u4ebf';
if (abs >= 1e4) return sign + (abs / 1e4).toFixed(decimals).replace(/\.0$/, '') + '\u4e07';
return sign + abs.toLocaleString('zh-CN');
}
function formatPct(num, decimals) {
if (decimals === undefined) decimals = 2;
if (num === null || num === undefined) return '--';
return (num * 100).toFixed(decimals) + '%';
}
/* Slide controller */
class SlidePresentation {
constructor() {
this.slides = document.querySelectorAll('.slide');
this.currentSlide = 0;
this.progressBar = document.getElementById('progressBar');
this.setupObserver();
this.setupKeyboard();
this.setupTouch();
}
setupObserver() {
var self = this;
var obs = new IntersectionObserver(function(entries) {
entries.forEach(function(e) {
if (e.isIntersecting) {
e.target.classList.add('visible');
self.currentSlide = Array.from(self.slides).indexOf(e.target);
if (self.progressBar) self.progressBar.style.width = ((self.currentSlide + 1) / self.slides.length * 100) + '%';
/* Init ECharts if present */
e.target.querySelectorAll('.chart-container').forEach(function(el) {
if (!el._echartInstance && typeof echarts !== 'undefined' && el.dataset.init) {
try { var fn = new Function(el.dataset.init); fn.call(el); } catch(err) {}
}
});
}
});
}, { threshold: 0.3 });
this.slides.forEach(function(s) { obs.observe(s); });
}
setupKeyboard() {
var self = this;
document.addEventListener('keydown', function(e) {
if (e.key === 'ArrowDown' || e.key === 'ArrowRight' || e.key === ' ') { e.preventDefault(); self.go(self.currentSlide + 1); }
if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') { e.preventDefault(); self.go(self.currentSlide - 1); }
});
}
setupTouch() {
var self = this, startY = 0;
document.addEventListener('touchstart', function(e) { startY = e.touches[0].clientY; });
document.addEventListener('touchend', function(e) {
var d = startY - e.changedTouches[0].clientY;
if (Math.abs(d) > 50) self.go(self.currentSlide + (d > 0 ? 1 : -1));
});
}
go(i) { if (i >= 0 && i < this.slides.length) this.slides[i].scrollIntoView({ behavior: 'smooth' }); }
}
document.addEventListener('DOMContentLoaded', function() { new SlidePresentation(); });
/* ===========================================
SLOT: CUSTOM JS
Add chart init functions, counters, etc.
=========================================== */
</script>
</body>
</html>