Files
cms-SiteForge/themes/trade-pro/pages/home.html
T
浅念 c318829ff3 feat: port cms home layout into trade-pro (hero/features/cards/cta + reveal JS)
Task 10a (Phase 3 first layout task). home.html now mirrors the cms
astro-site-runtime homepage section sequence: full-bleed hero (single
active slide; the platform has no multi-slide config, so the carousel
dots/JS are not ported), trustbar, two-col about with floating stats,
soft products band (4-card grid), dark applications band (2x2 case
tiles), advantages feature grid, soft news band (3-card grid), and the
closing cta band. Data maps to SiteForge context (page.cover/summary,
showcase, cases, stories, category/brand counts); empty sections hide
instead of rendering shells. All new component classes are sf-tp-*
prefixed and compose on the Task 8 base utilities in theme.css
(.wrap/.section/.eyebrow/.icon-circle/.sf-tp-btn).

CSS: the five cms components' scoped styles (PageHero, FeatureGrid,
CardGrid, Cta, SectionHead + the inline homepage bands) are extracted
into pro.css as the sf-tp-* component layer, tokens rewritten to
--sf-tp-*, breakpoints 900/767/620 preserved. theme.css accordingly
drops the superseded generic .cards/.card/.feature mobile baselines
and the .pro-home-hero em bridge, and retargets the dark-surface ghost
button hook from .cta-band to .sf-tp-cta.

Reveal: cms uses data-reveal everywhere; a ~15-line inline script at
the pro.html tail adds html.js + an IntersectionObserver that toggles
is-visible (the reduced-motion/no-JS exemptions already live in
theme.css from Task 8).

Tests: test_theme_registry gains test_trade_pro_home_layout_structure
(preview-render contract: sf-tp-hero, card grid, feature grid, cta,
no pro-industrial-hero residue, reveal script). The distinct-markup
tripwire in test_theme_pro_v3 is legitimately updated 4 -> 5 (renamed
to drop the stale "four"): with trade-pro now carrying its own
sf-tp-hero class, five themes yield five distinct hero signatures,
which is what the test always meant to enforce.

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-23 09:23:30 +08:00

167 lines
8.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{# trade-pro home — cms 首页设计移植(Task 10a)。
区块序列对照 D:/project/cms/runtimes/astro-site-runtime/src/pages/[locale]/index.astro
(像素基准 dist/hesupipe/en/index.html):
hero 大图叠加白字 → trustbar 信任条 → about 两栏 + 悬浮数据 →
products 浅底 4 卡 → applications 深色带 + 2×2 案例瓦片 →
advantages 特性网格 → news 浅底 3 卡 → cta 收尾横幅。
数据接 SiteForge 上下文:page.cover/summary、showcase(产品)、cases、
stories、分类/品牌计数;空数据区块整段隐藏,避免空壳布局。
轮播简化为单 active slide(平台首页无多图配置),dots/轮播 JS 不移植。 #}
<section class="sf-tp-hero" aria-label="{{ site.name }}">
<div class="sf-tp-hero-slides">
<div class="sf-tp-hero-slide active">{% if safe_image(page.cover) %}<img src="{{ safe_image(page.cover) }}" alt="{{ page.title or site.name }}" width="1600" height="800" loading="eager" fetchpriority="high" decoding="async">{% endif %}</div>
</div>
<div class="sf-tp-hero-overlay" aria-hidden="true"></div>
<div class="wrap sf-tp-hero-content">
<div class="sf-tp-hero-copy" data-reveal>
<span class="eyebrow">GLOBAL SOURCING · MADE RELIABLE</span>
<h1>{{ page.title if page.title and page.title not in (site.name,'首页','Home') else site.name }}</h1>
<p class="sf-tp-lead">{{ page.summary or site.tagline or 'Reliable products, transparent specifications and responsive export service.' }}</p>
<a class="sf-tp-btn" href="/products/">Browse products {{ icon('arrow-right') }}</a>
</div>
</div>
</section>
<div class="sf-tp-trustbar">
<div class="wrap sf-tp-trust-grid">
{% set tp_trust = [
('check', 'Certified quality', 'Inspected before every shipment'),
('location', 'Global export', 'Delivering to worldwide markets'),
('download', 'Full documentation', 'Specs and export files on hand'),
('mail', 'Responsive service', 'Replies within one business day'),
] %}
{% for tp_icon, tp_title, tp_sub in tp_trust %}
<div class="sf-tp-trust-item" data-reveal style="--reveal-i: {{ loop.index0 }}">
<div class="icon-circle" aria-hidden="true">{{ icon(tp_icon) }}</div>
<strong>{{ tp_title }}</strong><span>{{ tp_sub }}</span>
</div>
{% endfor %}
</div>
</div>
<section class="section">
<div class="wrap sf-tp-two-col">
<div class="sf-tp-copy" data-reveal>
<span class="eyebrow">ABOUT US</span>
<h2>One partner from inquiry to delivery.</h2>
<p>{{ page.summary or site.tagline or 'Product specifications, quality control and export documentation in one place.' }}</p>
<a class="sf-tp-btn" href="/about/">About our company {{ icon('arrow-right') }}</a>
</div>
<div data-reveal style="--reveal-i: 1">
<div class="sf-tp-photo">{% if safe_image(page.cover) %}<img src="{{ safe_image(page.cover) }}" alt="{{ site.name }} facility" width="800" height="600" loading="lazy" decoding="async">{% else %}<div class="sf-tp-photo-plain" aria-hidden="true"><span>EXPORT · B2B</span></div>{% endif %}</div>
{% if groups['product'] or groups['vehicle'] or categories or brands or cases %}
<div class="sf-tp-stats">
{% if groups['product'] or groups['vehicle'] %}<div class="sf-tp-stat"><strong class="mono">{{ groups['product']|length + groups['vehicle']|length }}</strong><span>Products</span></div>{% endif %}
{% if categories %}<div class="sf-tp-stat"><strong class="mono">{{ categories|length }}</strong><span>Categories</span></div>{% endif %}
{% if brands %}<div class="sf-tp-stat"><strong class="mono">{{ brands|length }}</strong><span>Brands</span></div>{% endif %}
{% if cases %}<div class="sf-tp-stat"><strong class="mono">{{ cases|length }}</strong><span>Case studies</span></div>{% endif %}
</div>
{% endif %}
</div>
</div>
</section>
{% if showcase %}
<section class="section section--soft">
<div class="wrap">
<div class="sf-tp-section-head" data-reveal>
<div>
<span class="eyebrow">TRADE CATALOGUE</span>
<h2>Featured products</h2>
</div>
<p class="sf-tp-intro">Specifications, certification and packaging details are published with every listing.</p>
<a class="sf-tp-more" href="/products/">Browse all products {{ icon('arrow-right', cls='sf-tp-icon--sm') }}</a>
</div>
<div class="sf-tp-card-grid">
{% for tp_item in showcase[:4] %}
{% set tp_desc = tp_item.summary or 'Published specifications available on request.' %}
<article class="sf-tp-card" data-reveal style="--reveal-i: {{ loop.index0 % 4 }}">
<div class="sf-tp-card-media">{{ cover(tp_item, 'product') }}</div>
<div class="sf-tp-card-body">
<h3>{{ tp_item.title }}</h3>
<p>{{ tp_desc.split('.')[0] }}.</p>
<a class="sf-tp-more" href="{{ safe_href(tp_item.route) }}">View details {{ icon('arrow-right', cls='sf-tp-icon--sm') }}</a>
</div>
</article>
{% endfor %}
</div>
</div>
</section>
{% endif %}
{% if cases %}
<section class="sf-tp-applications">
<div class="wrap sf-tp-applications-grid">
<div class="sf-tp-applications-copy" data-reveal>
<span class="eyebrow">APPLICATIONS</span>
<h2>Built for real-world projects.</h2>
<p>Case studies from export programmes: municipal supply, industrial plants and OEM partnerships.</p>
<a class="sf-tp-btn" href="/cases/">Explore case studies {{ icon('arrow-right') }}</a>
</div>
<div class="sf-tp-application-tiles">
{% for tp_case in cases[:4] %}
<a class="sf-tp-app-tile" href="{{ safe_href(tp_case.route) }}" data-reveal style="--reveal-i: {{ loop.index0 }}">
{% if safe_image(tp_case.cover) %}<img src="{{ safe_image(tp_case.cover) }}" alt="{{ tp_case.title }}" width="600" height="450" loading="lazy" decoding="async">{% else %}<div class="sf-tp-tile-art" aria-hidden="true"></div>{% endif %}
<span>{{ tp_case.title }}</span>
</a>
{% endfor %}
</div>
</div>
</section>
{% endif %}
<section class="section">
<div class="wrap">
<div class="sf-tp-section-head" data-reveal>
<div>
<span class="eyebrow">OUR ADVANTAGES</span>
<h2>Why buyers stay with us</h2>
</div>
</div>
<div class="sf-tp-feature-grid">
{% set tp_features = [
('search', 'Verified sourcing', 'Suppliers audited against your specifications before the first sample.'),
('check', 'Strict quality control', 'Pre-shipment inspection with photographic evidence for every batch.'),
('download', 'Export documentation', 'Certification, packing lists and customs papers prepared in-house.'),
('phone', 'Dedicated support', 'One trade desk contact from inquiry to container loading.'),
] %}
{% for tp_icon, tp_title, tp_desc in tp_features %}
<div class="sf-tp-feature" data-reveal style="--reveal-i: {{ loop.index0 }}">
<div class="icon-circle" aria-hidden="true">{{ icon(tp_icon) }}</div>
<h3>{{ tp_title }}</h3>
<p>{{ tp_desc }}</p>
</div>
{% endfor %}
</div>
</div>
</section>
{% if stories %}
<section class="section section--soft">
<div class="wrap">
<div class="sf-tp-section-head" data-reveal>
<div>
<span class="eyebrow">COMPANY NEWS</span>
<h2>Latest updates</h2>
</div>
<a class="sf-tp-more" href="/news/">View all news {{ icon('arrow-right', cls='sf-tp-icon--sm') }}</a>
</div>
<div class="sf-tp-card-grid sf-tp-card-grid--news">
{% for tp_post in stories[:3] %}
<article class="sf-tp-card" data-reveal style="--reveal-i: {{ loop.index0 }}">
<div class="sf-tp-card-media">{{ cover(tp_post, 'post') }}</div>
<div class="sf-tp-card-body">
<h3><a href="{{ safe_href(tp_post.route) }}">{{ tp_post.title }}</a></h3>
<span class="sf-tp-tag">{{ fields_of(tp_post).get('category') or 'UPDATE' }}</span>
</div>
</article>
{% endfor %}
</div>
</div>
</section>
{% endif %}
<section class="sf-tp-cta">
<div class="wrap sf-tp-cta-inner">
<div data-reveal>
<span class="eyebrow">GET A QUOTATION</span>
<h2>Send one inquiry, get a matched quote.</h2>
<p>Share your specifications and target market; our trade desk replies with pricing and lead time within one business day.</p>
</div>
<a class="sf-tp-btn sf-tp-btn--ghost" href="/contact/" data-reveal style="--reveal-i: 1">Request a quote {{ icon('arrow-right') }}</a>
</div>
</section>