hexo-bb-channel 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +4 -5
- package/README.zh-CN.md +4 -5
- package/package.json +2 -1
- package/src/render-client.js +127 -6
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.2 - 2026-07-20
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Prevented multi-image expand/collapse from shifting the page scroll position.
|
|
8
|
+
- Improved mobile card auto-selection so the card nearest the reading position is selected instead of a taller partially visible card.
|
|
9
|
+
- Restored the mobile active-card placeholder outline while keeping the selected card offset visible.
|
|
10
|
+
- Made bb title and content typography theme-driven through CSS variables, avoiding hard-coded theme font assumptions.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Mobile card active styling now works without hover and keeps the original dashed placeholder visible.
|
|
15
|
+
- Image carousel positioning uses non-smooth initial placement to avoid jumpy first-open behavior.
|
|
16
|
+
|
package/README.md
CHANGED
|
@@ -11,8 +11,6 @@ English | [Chinese](./README.zh-CN.md)
|
|
|
11
11
|
|
|
12
12
|
`hexo-bb-channel` is a small Hexo plugin that creates a `/bb/` page shell and loads posts from a separate API at runtime. Your blog stays static, while Telegram updates can appear without rebuilding the whole site.
|
|
13
13
|
|
|
14
|
-
Live sample: [https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
15
|
-
|
|
16
14
|
## Preview
|
|
17
15
|
|
|
18
16
|
Live demo: [https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
@@ -25,7 +23,7 @@ Live demo: [https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
|
25
23
|
- **Dynamic content on static blogs**: Telegram posts are fetched in the browser from the API backend.
|
|
26
24
|
- **No Telegram token in the blog**: the Hexo side only needs a public API URL.
|
|
27
25
|
- **Media-friendly timeline**: supports text, real Telegram hashtag entities, images, files, pagination, and image preview interactions.
|
|
28
|
-
- **
|
|
26
|
+
- **Theme comments remain available**: the generated page is a standard Hexo page with `comments: true`; whether comments render depends on your theme and comment system.
|
|
29
27
|
|
|
30
28
|
## Quick Start
|
|
31
29
|
|
|
@@ -40,6 +38,8 @@ Deploy the companion API first:
|
|
|
40
38
|
Backend repo: [Kaaaaai/kaaaaai.tools.channel-api](https://github.com/Kaaaaai/kaaaaai.tools.channel-api)
|
|
41
39
|
See the API README for detailed Telegram channel creation steps.
|
|
42
40
|
|
|
41
|
+
For production, set `ALLOWED_ORIGINS` to your blog's exact origin, for example `https://www.example.com`, so the API accepts requests from the generated page.
|
|
42
|
+
|
|
43
43
|
### 2. Install the Hexo plugin
|
|
44
44
|
|
|
45
45
|
Install the latest stable release from npm:
|
|
@@ -94,7 +94,7 @@ http://localhost:4000/bb/
|
|
|
94
94
|
| `route` | `bb/` | Output route, for example `moments/`. |
|
|
95
95
|
| `title` | `moments` | Page title inside the content area. |
|
|
96
96
|
| `description` | empty | Subtitle under the title. |
|
|
97
|
-
| `api_base` | empty | Base URL of `kaaaaai.tools.channel-api`. |
|
|
97
|
+
| `api_base` | empty | Required in client mode. Base URL of `kaaaaai.tools.channel-api`; when omitted, the page shows `Missing bb_channel.api_base`. |
|
|
98
98
|
| `page_size` | `20` | Posts requested per page. |
|
|
99
99
|
|
|
100
100
|
## How It Works
|
|
@@ -198,7 +198,6 @@ npm test
|
|
|
198
198
|
## Related
|
|
199
199
|
|
|
200
200
|
- API backend: [Kaaaaai/kaaaaai.tools.channel-api](https://github.com/Kaaaaai/kaaaaai.tools.channel-api)
|
|
201
|
-
- Live sample: [https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
202
201
|
|
|
203
202
|
## License
|
|
204
203
|
|
package/README.zh-CN.md
CHANGED
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
|
|
12
12
|
`hexo-bb-channel` 是一个轻量 Hexo 插件:它只生成 `/bb/` 页面壳,内容在浏览器端从独立 API 拉取。这样博客仍然是静态站,但 Telegram Channel 更新后不需要重新 `hexo generate`。
|
|
13
13
|
|
|
14
|
-
在线示例:[https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
15
|
-
|
|
16
14
|
## 效果预览
|
|
17
15
|
|
|
18
16
|
在线示例:[https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
@@ -25,7 +23,7 @@
|
|
|
25
23
|
- **静态博客里的动态内容**:页面访问时从 API 拉取 Telegram 内容。
|
|
26
24
|
- **博客侧不放 Telegram 凭证**:Hexo 只需要配置一个 API 地址。
|
|
27
25
|
- **适合碎片流展示**:支持正文、Telegram 原生 hashtag entity、图片、文件、分页、图片预览交互。
|
|
28
|
-
-
|
|
26
|
+
- **保留主题评论能力**:生成的是标准 Hexo page,并设置 `comments: true`;最终是否显示评论取决于主题和评论系统。
|
|
29
27
|
|
|
30
28
|
## 快速开始
|
|
31
29
|
|
|
@@ -40,6 +38,8 @@
|
|
|
40
38
|
后端仓库:[Kaaaaai/kaaaaai.tools.channel-api](https://github.com/Kaaaaai/kaaaaai.tools.channel-api)
|
|
41
39
|
详细的 Telegram 频道创建步骤见 API 仓库 README。
|
|
42
40
|
|
|
41
|
+
生产环境请将 `ALLOWED_ORIGINS` 设置为博客的完整 Origin,例如 `https://www.example.com`,确保生成页面能够请求 API。
|
|
42
|
+
|
|
43
43
|
### 2. 安装 Hexo 插件
|
|
44
44
|
|
|
45
45
|
从 npm 安装最新稳定版:
|
|
@@ -94,7 +94,7 @@ http://localhost:4000/bb/
|
|
|
94
94
|
| `route` | `bb/` | 页面路由,例如 `moments/`。 |
|
|
95
95
|
| `title` | `moments` | 页面内容区标题。 |
|
|
96
96
|
| `description` | 空 | 页面描述。 |
|
|
97
|
-
| `api_base` | 空 |
|
|
97
|
+
| `api_base` | 空 | client 模式必填。`kaaaaai.tools.channel-api` 的 API 根地址;未配置时页面会显示 `Missing bb_channel.api_base`。 |
|
|
98
98
|
| `page_size` | `20` | 每页拉取数量。 |
|
|
99
99
|
|
|
100
100
|
## 工作原理
|
|
@@ -198,7 +198,6 @@ npm test
|
|
|
198
198
|
## 相关项目
|
|
199
199
|
|
|
200
200
|
- API 后端:[Kaaaaai/kaaaaai.tools.channel-api](https://github.com/Kaaaaai/kaaaaai.tools.channel-api)
|
|
201
|
-
- 在线示例:[https://www.kaaaaai.cn/bb/](https://www.kaaaaai.cn/bb/)
|
|
202
201
|
|
|
203
202
|
## License
|
|
204
203
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hexo-bb-channel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Render Telegram channel microblog timelines in Hexo using a dynamic API backend.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"index.js",
|
|
8
8
|
"src",
|
|
9
|
+
"CHANGELOG.md",
|
|
9
10
|
"README.md",
|
|
10
11
|
"README.zh-CN.md",
|
|
11
12
|
"LICENSE"
|
package/src/render-client.js
CHANGED
|
@@ -26,6 +26,10 @@ function renderClientScript() {
|
|
|
26
26
|
const feed = root.querySelector('[data-bb-channel-feed]');
|
|
27
27
|
const pager = root.querySelector('[data-bb-channel-pagination]');
|
|
28
28
|
const status = root.querySelector('[data-bb-channel-status]');
|
|
29
|
+
let bbActiveCardObserver = null;
|
|
30
|
+
let bbActiveCardRaf = 0;
|
|
31
|
+
let bbActiveCardListening = false;
|
|
32
|
+
const bbActiveCardQuery = window.matchMedia ? window.matchMedia('(max-width: 640px)') : null;
|
|
29
33
|
|
|
30
34
|
const escapeHtml = (value = '') => String(value)
|
|
31
35
|
.replace(/&/g, '&')
|
|
@@ -114,6 +118,121 @@ function renderClientScript() {
|
|
|
114
118
|
});
|
|
115
119
|
};
|
|
116
120
|
|
|
121
|
+
const positionImageTrack = (track, index, useSmoothScroll) => {
|
|
122
|
+
const left = track.clientWidth * index;
|
|
123
|
+
track.scrollTo({ left, behavior: useSmoothScroll ? 'smooth' : 'auto' });
|
|
124
|
+
if (!useSmoothScroll) track.scrollLeft = left;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const clearMobileActiveCards = () => {
|
|
128
|
+
feed.querySelectorAll('.bb-channel-card[data-bb-card-active]').forEach((card) => {
|
|
129
|
+
delete card.dataset.bbCardActive;
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const calculateCardVisibleArea = (card) => {
|
|
134
|
+
const surface = card.querySelector('.bb-channel-card-surface') || card;
|
|
135
|
+
const rect = surface.getBoundingClientRect();
|
|
136
|
+
const viewportWidth = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
137
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
138
|
+
const width = Math.max(0, Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0));
|
|
139
|
+
const height = Math.max(0, Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0));
|
|
140
|
+
return width * height;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const calculateCardVisibleRatio = (card) => {
|
|
144
|
+
const surface = card.querySelector('.bb-channel-card-surface') || card;
|
|
145
|
+
const rect = surface.getBoundingClientRect();
|
|
146
|
+
const area = calculateCardVisibleArea(card);
|
|
147
|
+
const total = Math.max(1, rect.width * rect.height);
|
|
148
|
+
return area / total;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const calculateCardActiveDistance = (card) => {
|
|
152
|
+
const surface = card.querySelector('.bb-channel-card-surface') || card;
|
|
153
|
+
const rect = surface.getBoundingClientRect();
|
|
154
|
+
const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
|
|
155
|
+
const viewportActiveLine = viewportHeight * .52;
|
|
156
|
+
const visibleTop = Math.max(rect.top, 0);
|
|
157
|
+
const visibleBottom = Math.min(rect.bottom, viewportHeight);
|
|
158
|
+
const visibleCenter = (visibleTop + visibleBottom) / 2;
|
|
159
|
+
return Math.abs(visibleCenter - viewportActiveLine);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const activateLargestVisibleCard = () => {
|
|
163
|
+
bbActiveCardRaf = 0;
|
|
164
|
+
if (!bbActiveCardQuery || !bbActiveCardQuery.matches) {
|
|
165
|
+
clearMobileActiveCards();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
let activeCard = null;
|
|
169
|
+
let bestDistance = Infinity;
|
|
170
|
+
let bestRatio = 0;
|
|
171
|
+
feed.querySelectorAll('.bb-channel-card').forEach((card) => {
|
|
172
|
+
if (card.dataset.bbViewerOpen === 'true') return;
|
|
173
|
+
const visibleArea = calculateCardVisibleArea(card);
|
|
174
|
+
const visibleRatio = calculateCardVisibleRatio(card);
|
|
175
|
+
if (visibleArea <= 0 || visibleRatio < .08) return;
|
|
176
|
+
const distance = calculateCardActiveDistance(card);
|
|
177
|
+
if (distance < bestDistance || (Math.abs(distance - bestDistance) < 1 && visibleRatio > bestRatio)) {
|
|
178
|
+
bestDistance = distance;
|
|
179
|
+
bestRatio = visibleRatio;
|
|
180
|
+
activeCard = card;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
feed.querySelectorAll('.bb-channel-card').forEach((card) => {
|
|
184
|
+
if (card === activeCard) {
|
|
185
|
+
card.dataset.bbCardActive = 'true';
|
|
186
|
+
} else {
|
|
187
|
+
delete card.dataset.bbCardActive;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const scheduleMobileActiveCardUpdate = () => {
|
|
193
|
+
if (bbActiveCardRaf) return;
|
|
194
|
+
bbActiveCardRaf = window.requestAnimationFrame(activateLargestVisibleCard);
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const stopMobileActiveCardTracking = () => {
|
|
198
|
+
if (bbActiveCardObserver) {
|
|
199
|
+
bbActiveCardObserver.disconnect();
|
|
200
|
+
bbActiveCardObserver = null;
|
|
201
|
+
}
|
|
202
|
+
if (bbActiveCardRaf) {
|
|
203
|
+
window.cancelAnimationFrame(bbActiveCardRaf);
|
|
204
|
+
bbActiveCardRaf = 0;
|
|
205
|
+
}
|
|
206
|
+
if (bbActiveCardListening) {
|
|
207
|
+
window.removeEventListener('scroll', scheduleMobileActiveCardUpdate);
|
|
208
|
+
window.removeEventListener('resize', scheduleMobileActiveCardUpdate);
|
|
209
|
+
bbActiveCardListening = false;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const setupMobileActiveCard = () => {
|
|
214
|
+
stopMobileActiveCardTracking();
|
|
215
|
+
clearMobileActiveCards();
|
|
216
|
+
if (!bbActiveCardQuery || !bbActiveCardQuery.matches) return;
|
|
217
|
+
window.addEventListener('scroll', scheduleMobileActiveCardUpdate, { passive: true });
|
|
218
|
+
window.addEventListener('resize', scheduleMobileActiveCardUpdate);
|
|
219
|
+
bbActiveCardListening = true;
|
|
220
|
+
if ('IntersectionObserver' in window) {
|
|
221
|
+
bbActiveCardObserver = new IntersectionObserver(scheduleMobileActiveCardUpdate, { threshold: [0, .15, .3, .45, .6, .75, .9, 1] });
|
|
222
|
+
feed.querySelectorAll('.bb-channel-card').forEach((card) => bbActiveCardObserver.observe(card));
|
|
223
|
+
}
|
|
224
|
+
scheduleMobileActiveCardUpdate();
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
if (bbActiveCardQuery) {
|
|
228
|
+
const handleActiveCardQueryChange = () => setupMobileActiveCard();
|
|
229
|
+
if (typeof bbActiveCardQuery.addEventListener === 'function') {
|
|
230
|
+
bbActiveCardQuery.addEventListener('change', handleActiveCardQueryChange);
|
|
231
|
+
} else if (typeof bbActiveCardQuery.addListener === 'function') {
|
|
232
|
+
bbActiveCardQuery.addListener(handleActiveCardQueryChange);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
117
236
|
const openImageViewer = (card, index) => {
|
|
118
237
|
const viewer = card.querySelector('[data-bb-image-viewer]');
|
|
119
238
|
const track = card.querySelector('[data-bb-image-track]');
|
|
@@ -121,6 +240,7 @@ function renderClientScript() {
|
|
|
121
240
|
const count = card.querySelector('[data-bb-image-count]');
|
|
122
241
|
if (!viewer || !track || !slides.length) return;
|
|
123
242
|
const safeIndex = (Number(index) + slides.length) % slides.length;
|
|
243
|
+
const useSmoothScroll = card.dataset.bbViewerOpen === 'true';
|
|
124
244
|
card.dataset.bbImageIndex = String(safeIndex);
|
|
125
245
|
if (count) count.textContent = slides.length > 1 ? (safeIndex + 1) + ' / ' + slides.length : '';
|
|
126
246
|
preserveCardViewportPosition(card, () => {
|
|
@@ -130,7 +250,7 @@ function renderClientScript() {
|
|
|
130
250
|
hydrateImages(slides[safeIndex]);
|
|
131
251
|
requestAnimationFrame(() => {
|
|
132
252
|
card.dataset.bbViewerOpen = 'true';
|
|
133
|
-
|
|
253
|
+
positionImageTrack(track, safeIndex, useSmoothScroll);
|
|
134
254
|
focusWithoutScroll(track);
|
|
135
255
|
});
|
|
136
256
|
});
|
|
@@ -199,6 +319,7 @@ function renderClientScript() {
|
|
|
199
319
|
const data = await response.json();
|
|
200
320
|
feed.innerHTML = (data.posts || []).map(renderCard).join('');
|
|
201
321
|
hydrateImages(feed);
|
|
322
|
+
setupMobileActiveCard();
|
|
202
323
|
status.textContent = '';
|
|
203
324
|
pager.innerHTML = '';
|
|
204
325
|
if (data.pagination && data.pagination.total > 1) {
|
|
@@ -271,7 +392,7 @@ function renderClientContent(config) {
|
|
|
271
392
|
.bb-channel-portable{max-width:100%;margin:0 auto;color:#242424}
|
|
272
393
|
.bb-channel-portable *{box-sizing:border-box}
|
|
273
394
|
.bb-channel-portable .bb-channel-intro{position:relative;margin:0 0 1.55rem;padding:0;border-bottom:0}
|
|
274
|
-
.bb-channel-portable .bb-channel-title{margin:0 0 .45rem;color:#202020;font-family:inherit;font-size:1.72rem;font-weight:700;line-height:1.2;letter-spacing
|
|
395
|
+
.bb-channel-portable .bb-channel-title{margin:0 0 .45rem;color:#202020;font-family:var(--bb-channel-title-font,inherit);font-size:1.72rem;font-weight:700;line-height:1.2;letter-spacing:0}
|
|
275
396
|
.bb-channel-portable .bb-channel-intro-text{margin:0;color:#777;font-size:1rem;line-height:1.6;text-align:left}
|
|
276
397
|
.bb-channel-portable .bb-channel-status{min-height:1.2rem;margin:.4rem 0 .8rem;color:#999}
|
|
277
398
|
.bb-channel-portable .bb-channel-feed{position:relative;display:flex;flex-direction:column;gap:1.05rem;padding-left:2.1rem}
|
|
@@ -286,8 +407,8 @@ function renderClientContent(config) {
|
|
|
286
407
|
.bb-channel-portable .bb-channel-time{color:inherit;text-decoration:none;border-bottom:0;font-size:.96rem;line-height:1.3}
|
|
287
408
|
.bb-channel-portable .bb-channel-body-with-media{display:grid;grid-template-columns:minmax(0,1fr) minmax(10rem,13.5rem);gap:1.25rem;align-items:start}
|
|
288
409
|
.bb-channel-portable .bb-channel-main{min-width:0}
|
|
289
|
-
.bb-channel-portable .bb-channel-content{font-size:
|
|
290
|
-
.bb-channel-portable .bb-channel-content p{margin:0 0 .
|
|
410
|
+
.bb-channel-portable .bb-channel-content{font-family:var(--bb-channel-content-font,inherit);font-size:1.02rem;line-height:1.82;letter-spacing:.01em;text-rendering:optimizeLegibility;overflow-wrap:anywhere}
|
|
411
|
+
.bb-channel-portable .bb-channel-content p{margin:0 0 .82em}
|
|
291
412
|
.bb-channel-portable .bb-channel-content a{color:#e46f0a;border-bottom:1px solid rgba(228,111,10,.35);text-decoration:none}
|
|
292
413
|
.bb-channel-portable .bb-channel-media-rail{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.32rem;justify-self:end;width:min(13.5rem,100%);max-height:24rem;opacity:1;overflow:hidden;transform:translateY(0);filter:blur(0);transition:max-height 420ms cubic-bezier(.22,1,.36,1),opacity 420ms cubic-bezier(.22,1,.36,1),transform 420ms cubic-bezier(.22,1,.36,1),filter 420ms cubic-bezier(.22,1,.36,1);will-change:max-height,opacity,transform}
|
|
293
414
|
.bb-channel-portable .bb-channel-media-thumb{position:relative;display:grid;min-height:0;aspect-ratio:1/1;place-items:center;border:1px solid #e7e7e7;border-radius:8px;background:#f8f8f8;padding:0;overflow:hidden;cursor:pointer}
|
|
@@ -327,8 +448,8 @@ function renderClientContent(config) {
|
|
|
327
448
|
.bb-channel-portable .bb-channel-pagination span{min-width:2.15rem;background:#333;color:#fff;border-color:#333}
|
|
328
449
|
@media(max-width:720px){.bb-channel-portable .bb-channel-body-with-media{grid-template-columns:1fr}.bb-channel-portable .bb-channel-media-rail{justify-self:start;width:min(18rem,100%)}}
|
|
329
450
|
@keyframes bb-channel-shimmer{0%{background-position:180% 0}100%{background-position:-80% 0}}
|
|
330
|
-
@media(max-width:640px){.bb-channel-portable .bb-channel-intro{margin-bottom:1.2rem}.bb-channel-portable .bb-channel-title{font-size:1.45rem}.bb-channel-portable .bb-channel-intro-text{font-size:.94rem}.bb-channel-portable .bb-channel-feed{gap:.9rem;padding-left:1.15rem}.bb-channel-portable .bb-channel-feed::before{left:.06rem}.bb-channel-portable .bb-channel-dot{left:-1.32rem;top:1.42rem}.bb-channel-portable .bb-channel-card-surface{padding:1.05rem .95rem;border-radius:12px}.bb-channel-portable .bb-channel-card-placeholder{border-radius:12px}.bb-channel-portable .bb-channel-card:hover .bb-channel-card-surface{transform:none}.bb-channel-portable .bb-channel-meta{margin-bottom:.85rem}.bb-channel-portable .bb-channel-content{font-size:.96rem;line-height:1.72}.bb-channel-portable .bb-channel-media-rail{width:100%;max-width:20rem;grid-template-columns:repeat(3,minmax(0,1fr));justify-self:center;margin-top:.15rem}.bb-channel-portable .bb-channel-media-thumb{min-height:4.1rem}.bb-channel-portable .bb-channel-image-viewer{margin-top:.95rem;max-width:100%}.bb-channel-portable .bb-channel-image-slide{min-height:10rem}.bb-channel-portable .bb-channel-image-large{max-width:100%!important;max-height:68vh!important}.bb-channel-portable .bb-channel-image-nav{width:2.55rem;height:2.55rem}.bb-channel-portable .bb-channel-image-prev{left:.45rem}.bb-channel-portable .bb-channel-image-next{right:.45rem}.bb-channel-portable .bb-channel-attachment{align-items:flex-start;padding:.78rem .82rem}.bb-channel-portable .bb-channel-attachment-title{white-space:normal;overflow-wrap:anywhere}.bb-channel-portable .bb-channel-tags{gap:.42rem}.bb-channel-portable .bb-channel-pagination{gap:1rem}}
|
|
331
|
-
@media(prefers-reduced-motion:reduce){.bb-channel-portable .bb-channel-card-placeholder,.bb-channel-portable .bb-channel-card-surface,.bb-channel-portable .bb-channel-media-rail,.bb-channel-portable .bb-channel-image-viewer,.bb-channel-portable .bb-channel-image-large,.bb-channel-portable .bb-channel-attachment{transition:none}.bb-channel-portable .bb-channel-card:hover .bb-channel-card-surface{transform:none}}
|
|
451
|
+
@media(max-width:640px){.bb-channel-portable .bb-channel-intro{margin-bottom:1.2rem}.bb-channel-portable .bb-channel-title{font-size:1.45rem}.bb-channel-portable .bb-channel-intro-text{font-size:.94rem}.bb-channel-portable .bb-channel-feed{gap:.9rem;padding-left:1.15rem}.bb-channel-portable .bb-channel-feed::before{left:.06rem}.bb-channel-portable .bb-channel-dot{left:-1.32rem;top:1.42rem}.bb-channel-portable .bb-channel-card-surface{padding:1.05rem .95rem;border-radius:12px}.bb-channel-portable .bb-channel-card-placeholder{border-radius:12px}.bb-channel-portable .bb-channel-card:hover .bb-channel-card-surface{transform:none}.bb-channel-portable .bb-channel-card[data-bb-card-active="true"] .bb-channel-card-placeholder{opacity:1}.bb-channel-portable .bb-channel-card[data-bb-card-active="true"] .bb-channel-card-surface{transform:translate(4px,-5px);border-style:solid;border-color:#e7b99d;background:rgba(255,255,255,.86);box-shadow:0 12px 26px -24px rgba(15,23,42,.32)}.bb-channel-portable .bb-channel-card[data-bb-viewer-open="true"] .bb-channel-card-placeholder{opacity:0}.bb-channel-portable .bb-channel-card[data-bb-viewer-open="true"] .bb-channel-card-surface{transform:none}.bb-channel-portable .bb-channel-meta{margin-bottom:.85rem}.bb-channel-portable .bb-channel-content{font-size:.96rem;line-height:1.72}.bb-channel-portable .bb-channel-media-rail{width:100%;max-width:20rem;grid-template-columns:repeat(3,minmax(0,1fr));justify-self:center;margin-top:.15rem}.bb-channel-portable .bb-channel-media-thumb{min-height:4.1rem}.bb-channel-portable .bb-channel-image-viewer{margin-top:.95rem;max-width:100%}.bb-channel-portable .bb-channel-image-slide{min-height:10rem}.bb-channel-portable .bb-channel-image-large{max-width:100%!important;max-height:68vh!important}.bb-channel-portable .bb-channel-image-nav{width:2.55rem;height:2.55rem}.bb-channel-portable .bb-channel-image-prev{left:.45rem}.bb-channel-portable .bb-channel-image-next{right:.45rem}.bb-channel-portable .bb-channel-attachment{align-items:flex-start;padding:.78rem .82rem}.bb-channel-portable .bb-channel-attachment-title{white-space:normal;overflow-wrap:anywhere}.bb-channel-portable .bb-channel-tags{gap:.42rem}.bb-channel-portable .bb-channel-pagination{gap:1rem}}
|
|
452
|
+
@media(prefers-reduced-motion:reduce){.bb-channel-portable .bb-channel-card-placeholder,.bb-channel-portable .bb-channel-card-surface,.bb-channel-portable .bb-channel-media-rail,.bb-channel-portable .bb-channel-image-viewer,.bb-channel-portable .bb-channel-image-large,.bb-channel-portable .bb-channel-attachment{transition:none}.bb-channel-portable .bb-channel-card:hover .bb-channel-card-surface,.bb-channel-portable .bb-channel-card[data-bb-card-active="true"] .bb-channel-card-surface{transform:none}}
|
|
332
453
|
</style>
|
|
333
454
|
<div class="bb-channel-portable" data-bb-channel-root data-api-base="${escapeHtml(config.apiBase)}" data-page-size="${escapeHtml(config.pageSize)}">
|
|
334
455
|
<header class="bb-channel-intro">
|