feat: refine trade-pro variant pages (brand/service/faq/search/notfound)

Task 11 (layout port finale): rebuild the five thin variant pages in the
sf-tp design language, informed by upstream industrial/automotive
1.3.0/1.4.0 information architecture.

- brand: page-hero (breadcrumb Home > Brands > name, cover bg, anchor
  button) + related-product card grid (fields.brand == page title) +
  brand profile body only when authored; derived placeholder summary
  excluded, empty brands get an empty state, never fabricated intros.
- service: page-hero + 1.2/0.8 detail grid (article-body typography +
  sticky CTA card with contact/back links); empty body collapses to a
  centered solo column with the CTA card kept.
- faq: page-hero + article-body for the rich-text body (platform has no
  faq content type; sanitize strips details/summary so the typography
  layer carries it, block-driven details coexist via sf-canvas) +
  dark contact-guidance card; empty body swaps to an empty state.
- search: adopts the same platform mechanism as all four upstream
  themes (site-runtime.js ?q= client search over dist-root
  search-index.json); #sf-search/#sf-search-results/#sf-search-count
  hooks and .sf-search-page kept as JS contract, panel and injected
  result cards restyled via scoped cms-token overrides.
- notfound: branded dark-band 404 (icon macro, giant 404 h1, English
  copy, back-home + browse-products buttons); no end-cta.

CSS: Task 11 block appended to pro.css (new sf-tp-* classes only, own
900/620 media queries; shared hero/grid/typography responsive rules
come from existing 10a/10c/10d blocks; search overrides beat
factory.css by specificity without touching hooks).

Tests: test_trade_pro_variant_pages_structure covers brand fixture
(related filtering, empty forms), service/faq body-vs-empty, search
mechanism contract + noindex + index asset, 404 structure, v3 spot
checks (single h1, chrome, SVG arrows) and clean build report.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-26 16:32:15 +08:00
parent e21dbb6518
commit 391d22f1a8
7 changed files with 499 additions and 8 deletions
+47 -2
View File
@@ -1,2 +1,47 @@
<section class="pro-inner-hero pro-info-hero"><div class="pro-wrap"><span class="pro-eyebrow">OUR SERVICES</span><h1>{{page.title}}</h1><p>{{page.summary}}</p></div></section>
<section class="pro-section pro-info-section"><div class="pro-wrap pro-info-grid"><div><span class="pro-eyebrow">SERVICE / SUPPORT</span><h2>{{page.title}}</h2><p class="pro-muted">Working process, service scope and support commitments.</p></div><div class="pro-info-copy">{{body_copy(content,page)}}{% if page.cover %}<img class="pro-info-photo" src="{{safe_image(page.cover)}}" alt="{{page.title}}">{% endif %}</div></div></section>
{# trade-pro service detail — 服务详情精修(Task 11)。
设计参照(本轮无 cms 源对应):上游 industrial/automotive 1.3.0/1.4.0 的
service 页为通用信息页薄形态(hero + 双栏正文 + 封面图);本模板以
sf-tp 设计语言重组为「详情页」口径:sf-tp-page-hero(10c:封面底图 +
面包屑)→ detail 双栏(10g 案例页同构 1.2fr/0.8fr:文案列 = 眉题 + h2 +
正文排版层;侧列 = sticky CTA 卡 + 返回服务列表)。
数据事实(make_context 对 service kind):仅页面条目上下文(title/
summary/body/cover),无服务专属集合;正文 = 单一富文本 body,小节结构
由正文自身 h2 承担(10g/10h 同决策),sf-tp-article-body 排版层双挂
(10d)。body 为空 → 正文区块整段隐藏,双栏退化为居中单列(CTA 卡
保留——真实动作位,非虚构内容)。
面包屑/返回链接指向 /services/(required_sections 恒保证该路由存在;
当前页恰为 /services/ 时自指链接隐藏,面包屑降级为 Home › 标题)。 #}
<section class="sf-tp-page-hero sf-tp-service-hero">
{% if safe_image(page.cover) %}<img class="sf-tp-page-hero-bg" src="{{ safe_image(page.cover) }}" alt="" width="1600" height="900" fetchpriority="high" decoding="async">{% endif %}
<div class="sf-tp-page-hero-overlay" aria-hidden="true"></div>
<div class="wrap">
<nav class="sf-tp-breadcrumb" aria-label="Breadcrumb" data-reveal>
<a href="/">Home</a>{% if route != '/services/' %}<a href="/services/">Services</a>{% endif %}<span class="sf-tp-breadcrumb-current">{{ page.title }}</span>
</nav>
<div class="sf-tp-page-hero-copy" data-reveal style="--reveal-i: 1">
<span class="eyebrow">SERVICE / SUPPORT</span>
<h1>{{ page.title }}</h1>
{% if page.summary %}<p class="sf-tp-page-hero-lead">{{ page.summary }}</p>{% endif %}
</div>
</div>
</section>
<section class="section sf-tp-service">
<div class="wrap sf-tp-service-grid{{ '' if content else ' sf-tp-service-grid--solo' }}">
{% if content %}
<div class="sf-tp-service-copy" data-reveal>
<span class="eyebrow">SERVICE DETAIL</span>
<h2>{{ page.title }}</h2>
<div class="sf-tp-service-body sf-tp-article-body" data-reveal style="--reveal-i: 1">{{ body_copy(content, page) }}</div>
</div>
{% endif %}
<aside class="sf-tp-service-aside" data-reveal style="--reveal-i: 1">
<div class="sf-tp-service-cta">
<span class="eyebrow">NEXT STEP</span>
<h3>Request this service</h3>
<p>Send your requirements and the team replies within one business day.</p>
<a class="sf-tp-btn" href="/contact/">Contact us {{ icon('arrow-right') }}</a>
</div>
{% if route != '/services/' %}<a class="sf-tp-service-back" href="/services/">{{ icon('arrow-left', cls='sf-tp-icon--sm') }} All services</a>{% endif %}
</aside>
</div>
</section>