@hagicode/hagilight-starlight 0.5.3-dev.70.1.7faab38 → 0.5.3-dev.71.1.f32e5d4

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.
@@ -43,43 +43,34 @@ const gallery = copy.gallery.flatMap((item) => {
43
43
  ---
44
44
 
45
45
  <section class="hagilight-article-promotion" aria-labelledby="hagilight-article-promotion-title">
46
- <div class="hagilight-article-promotion__intro">
47
- <h2 id="hagilight-article-promotion-title">{copy.title}</h2>
48
- <p>{copy.lead}</p>
49
- <p>{copy.subheadline}</p>
50
- </div>
51
-
52
- <div class="hagilight-article-promotion__actions">
53
- <a class="hagilight-article-promotion__cta hagilight-article-promotion__cta--primary" href={homeHref}>
54
- {copy.visitLabel}
55
- </a>
56
- <a class="hagilight-article-promotion__cta hagilight-article-promotion__cta--secondary" href={docsHref}>
57
- {copy.docsLabel}
58
- </a>
59
- <div class="hagilight-article-promotion__windows">
60
- <div class="hagilight-article-promotion__windows-header">
61
- <span class="hagilight-article-promotion__windows-label">{copy.windowsLabel}</span>
62
- <a class="hagilight-article-promotion__downloads" href={downloadsHref}>{copy.allDownloadsLabel}</a>
46
+ <div class="hagilight-article-promotion__pitch">
47
+ <div class="hagilight-article-promotion__intro">
48
+ <h2 id="hagilight-article-promotion-title">{copy.title}</h2>
49
+ <p class="hagilight-article-promotion__lead">{copy.lead}</p>
50
+ <p class="hagilight-article-promotion__tagline">{copy.subheadline}</p>
51
+ <div class="hagilight-article-promotion__actions">
52
+ <a class="hagilight-article-promotion__cta hagilight-article-promotion__cta--primary" href={homeHref}>
53
+ {copy.visitLabel}
54
+ </a>
55
+ <a class="hagilight-article-promotion__cta hagilight-article-promotion__cta--secondary" href={docsHref}>
56
+ {copy.docsLabel}
57
+ </a>
63
58
  </div>
64
- <ms-store-badge
65
- productid={storeProductId}
66
- productname="HagiCode"
67
- window-mode="direct"
68
- theme="auto"
69
- size="large"
70
- animation="on"
71
- language={badgeLanguage}
72
- aria-label={copy.windowsStoreAriaLabel}
73
- title={copy.windowsStoreAriaLabel}
74
- >
75
- <a
76
- class="hagilight-article-promotion__store-fallback"
77
- href={storeHref}
78
- aria-label={copy.windowsStoreAriaLabel}
79
- title={copy.windowsStoreAriaLabel}
80
- >{copy.windowsStoreLabel}</a>
81
- </ms-store-badge>
82
59
  </div>
60
+
61
+ <ul class="hagilight-article-promotion__features" aria-label={copy.title}>
62
+ {copy.features.map((feature) => (
63
+ <li>
64
+ <span
65
+ class="hagilight-article-promotion__icon"
66
+ aria-hidden="true"
67
+ style={`--hagilight-pillar-icon: url(${pillarIcons[feature.id]?.src})`}
68
+ ></span>
69
+ <strong>{feature.label}</strong>
70
+ <span class="hagilight-article-promotion__feature-text">{feature.description}</span>
71
+ </li>
72
+ ))}
73
+ </ul>
83
74
  </div>
84
75
 
85
76
  <div class="hagilight-article-promotion__gallery-block">
@@ -94,7 +85,7 @@ const gallery = copy.gallery.flatMap((item) => {
94
85
  width={item.image.width}
95
86
  height={item.image.height}
96
87
  widths={[480, 800, item.image.width]}
97
- sizes="(min-width: 50rem) 720px, 100vw"
88
+ sizes="(min-width: 50rem) 560px, 100vw"
98
89
  loading="lazy"
99
90
  decoding="async"
100
91
  fetchpriority="low"
@@ -106,33 +97,54 @@ const gallery = copy.gallery.flatMap((item) => {
106
97
  </ul>
107
98
  </div>
108
99
 
109
- <ul class="hagilight-article-promotion__features" aria-label={copy.title}>
110
- {copy.features.map((feature) => (
111
- <li>
112
- <span
113
- class="hagilight-article-promotion__icon"
114
- aria-hidden="true"
115
- style={`--hagilight-pillar-icon: url(${pillarIcons[feature.id]?.src})`}
116
- ></span>
117
- <strong>{feature.label}</strong>
118
- <span>{feature.description}</span>
119
- </li>
120
- ))}
121
- </ul>
122
-
123
- <div class="hagilight-article-promotion__share">
124
- <h3 id="hagilight-article-promotion-share-title">{copy.shareLabel}</h3>
125
- <p class="hagilight-article-promotion__share-text">{copy.shareText}</p>
100
+ <div class="hagilight-article-promotion__closing">
101
+ <div class="hagilight-article-promotion__windows">
102
+ <h3 id="hagilight-article-promotion-windows-title" class="hagilight-article-promotion__windows-label">{copy.windowsLabel}</h3>
103
+ <div class="hagilight-article-promotion__windows-actions">
104
+ <ms-store-badge
105
+ productid={storeProductId}
106
+ productname="HagiCode"
107
+ window-mode="direct"
108
+ theme="auto"
109
+ size="large"
110
+ animation="on"
111
+ language={badgeLanguage}
112
+ aria-label={copy.windowsStoreAriaLabel}
113
+ title={copy.windowsStoreAriaLabel}
114
+ >
115
+ <a
116
+ class="hagilight-article-promotion__store-fallback"
117
+ href={storeHref}
118
+ aria-label={copy.windowsStoreAriaLabel}
119
+ title={copy.windowsStoreAriaLabel}
120
+ >{copy.windowsStoreLabel}</a>
121
+ </ms-store-badge>
122
+ <a class="hagilight-article-promotion__downloads" href={downloadsHref}>{copy.allDownloadsLabel}</a>
123
+ </div>
124
+ </div>
125
+
126
+ <div class="hagilight-article-promotion__share">
127
+ <h3 id="hagilight-article-promotion-share-title">{copy.shareLabel}</h3>
128
+ <p class="hagilight-article-promotion__share-text">{copy.shareText}</p>
129
+ </div>
126
130
  </div>
127
131
  </section>
128
132
  <script type="module" src="https://get.microsoft.com/badge/ms-store-badge.bundled.js" is:inline></script>
129
133
 
130
134
  <style>
135
+ /*
136
+ * Zones, top to bottom: pitch (what it is, where to go, the three pillars), gallery (proof),
137
+ * closing (get it, share it). Zones are separated by space and hairlines rather than nested
138
+ * boxes. The topology follows the section's own width, so the wide-content toggle and the
139
+ * sidebar layouts reflow it, not just the viewport. Mobile-first: the base rules are the
140
+ * single-column layout, which is also what a browser without container queries renders.
141
+ */
131
142
  .hagilight-article-promotion {
143
+ container-type: inline-size;
132
144
  display: grid;
133
145
  grid-template-columns: minmax(0, 1fr);
134
- gap: 1.5rem;
135
- margin: 2rem auto;
146
+ gap: 2rem;
147
+ margin: 3rem auto 2rem;
136
148
  padding: clamp(1rem, 3vw, 1.75rem);
137
149
  border: 1px solid var(--sl-color-gray-5);
138
150
  border-radius: var(--sl-radius-lg, 0.75rem);
@@ -147,12 +159,16 @@ const gallery = copy.gallery.flatMap((item) => {
147
159
  line-height: 1.25;
148
160
  }
149
161
 
162
+ .hagilight-article-promotion h2 {
163
+ font-size: var(--sl-text-2xl, 1.5rem);
164
+ }
165
+
150
166
  .hagilight-article-promotion h3 {
151
167
  font-size: var(--sl-text-lg, 1.125rem);
152
168
  }
153
169
 
154
170
  .hagilight-article-promotion p {
155
- margin: 0.5rem 0;
171
+ margin: 0;
156
172
  line-height: 1.6;
157
173
  }
158
174
 
@@ -167,11 +183,35 @@ const gallery = copy.gallery.flatMap((item) => {
167
183
  outline-offset: 3px;
168
184
  }
169
185
 
186
+ /* Pitch: headline, definition, promise, then the way in. */
187
+ .hagilight-article-promotion__pitch {
188
+ display: grid;
189
+ gap: 1.75rem;
190
+ }
191
+
192
+ .hagilight-article-promotion__intro {
193
+ display: grid;
194
+ align-content: start;
195
+ justify-items: start;
196
+ gap: 0.75rem;
197
+ }
198
+
199
+ .hagilight-article-promotion__lead,
200
+ .hagilight-article-promotion__tagline {
201
+ max-inline-size: 68ch;
202
+ }
203
+
204
+ .hagilight-article-promotion__tagline {
205
+ color: var(--sl-color-white);
206
+ font-weight: 600;
207
+ }
208
+
170
209
  .hagilight-article-promotion__actions {
171
210
  display: flex;
172
211
  flex-wrap: wrap;
173
212
  align-items: center;
174
- gap: 0.75rem 1rem;
213
+ gap: 0.75rem;
214
+ margin-block-start: 0.5rem;
175
215
  }
176
216
 
177
217
  .hagilight-article-promotion__cta {
@@ -200,61 +240,56 @@ const gallery = copy.gallery.flatMap((item) => {
200
240
  filter: brightness(1.08);
201
241
  }
202
242
 
203
- .hagilight-article-promotion__windows {
243
+ /* Pillars: one hairline-topped row each, icon and word on a line, description under it. */
244
+ .hagilight-article-promotion__features {
204
245
  display: grid;
205
- gap: 0.25rem;
206
- width: 100%;
207
- padding: 0.25rem 0.75rem 0.75rem;
208
- border: 1px solid var(--sl-color-gray-5);
209
- border-radius: var(--sl-radius-md, 0.5rem);
210
- background: var(--sl-color-gray-6);
246
+ gap: 1rem 1.5rem;
211
247
  }
212
248
 
213
- .hagilight-article-promotion__windows-header {
214
- display: flex;
215
- flex-wrap: wrap;
249
+ .hagilight-article-promotion__features li {
250
+ display: grid;
251
+ grid-template-columns: auto minmax(0, 1fr);
252
+ align-content: start;
216
253
  align-items: center;
217
- justify-content: space-between;
218
- gap: 0 1rem;
219
- }
220
-
221
- .hagilight-article-promotion__windows-label {
222
- font-weight: 600;
254
+ gap: 0.5rem 0.625rem;
255
+ min-width: 0;
256
+ padding-block-start: 0.875rem;
257
+ border-block-start: 1px solid var(--sl-color-gray-5);
223
258
  }
224
259
 
225
- /* Reserve the large badge's height (104px) so it replaces the fallback link without a layout jump. */
226
- .hagilight-article-promotion__windows ms-store-badge {
227
- display: inline-flex;
228
- align-items: center;
229
- justify-self: start;
230
- max-width: 100%;
231
- min-height: 6.5rem;
260
+ .hagilight-article-promotion__features strong {
261
+ color: var(--sl-color-text-accent);
262
+ font-size: var(--sl-text-lg, 1.125rem);
263
+ line-height: 1.25;
232
264
  }
233
265
 
234
- /* Keep the badge's fixed height and shrink it to the slot on narrow screens without distortion. */
235
- .hagilight-article-promotion__windows ms-store-badge::part(img) {
236
- max-width: 100%;
237
- object-fit: contain;
238
- object-position: left center;
266
+ .hagilight-article-promotion__feature-text {
267
+ grid-column: 1 / -1;
268
+ font-size: var(--sl-text-sm, 0.875rem);
269
+ line-height: 1.55;
239
270
  }
240
271
 
241
- .hagilight-article-promotion__store-fallback,
242
- .hagilight-article-promotion__downloads {
243
- display: inline-flex;
244
- align-items: center;
245
- min-height: 2.75rem;
246
- color: var(--sl-color-text-accent);
247
- font-weight: 600;
272
+ .hagilight-article-promotion__icon {
273
+ width: 1.5rem;
274
+ height: 1.5rem;
275
+ background: var(--sl-color-text-accent);
276
+ mask: var(--hagilight-pillar-icon) center / contain no-repeat;
277
+ -webkit-mask: var(--hagilight-pillar-icon) center / contain no-repeat;
248
278
  }
249
279
 
280
+ /* Gallery: three audited screenshots, kept in the catalog's narrative order. */
250
281
  .hagilight-article-promotion__gallery-block {
251
282
  display: grid;
252
- gap: 0.75rem;
283
+ gap: 1rem;
253
284
  }
254
285
 
255
286
  .hagilight-article-promotion__gallery {
256
287
  display: grid;
257
- gap: 1.25rem;
288
+ gap: 1.25rem 1rem;
289
+ }
290
+
291
+ .hagilight-article-promotion__gallery li {
292
+ min-width: 0;
258
293
  }
259
294
 
260
295
  .hagilight-article-promotion figure {
@@ -277,41 +312,57 @@ const gallery = copy.gallery.flatMap((item) => {
277
312
  line-height: 1.5;
278
313
  }
279
314
 
280
- .hagilight-article-promotion__features {
315
+ /* Closing: the practical next steps, as two parallel headed blocks. */
316
+ .hagilight-article-promotion__closing {
281
317
  display: grid;
282
- grid-template-columns: repeat(3, minmax(0, 1fr));
283
- gap: 0.75rem;
318
+ gap: 1.5rem;
319
+ padding-block-start: 1.5rem;
320
+ border-block-start: 1px solid var(--sl-color-gray-5);
284
321
  }
285
322
 
286
- .hagilight-article-promotion__features li {
323
+ .hagilight-article-promotion__windows,
324
+ .hagilight-article-promotion__share {
287
325
  display: grid;
288
326
  align-content: start;
327
+ justify-items: start;
289
328
  gap: 0.5rem;
290
329
  min-width: 0;
291
- padding: 0.75rem;
292
- border: 1px solid var(--sl-color-gray-5);
293
- border-radius: var(--sl-radius-md, 0.5rem);
294
330
  }
295
331
 
296
- .hagilight-article-promotion__features strong {
297
- color: var(--sl-color-text-accent);
332
+ /* Reserve the large badge's height (104px) so it replaces the fallback link without a layout jump. */
333
+ .hagilight-article-promotion__windows-actions {
334
+ display: flex;
335
+ flex-wrap: wrap;
336
+ align-items: center;
337
+ gap: 0 1.25rem;
338
+ max-width: 100%;
298
339
  }
299
340
 
300
- .hagilight-article-promotion__icon {
301
- width: 2rem;
302
- height: 2rem;
303
- background: var(--sl-color-text-accent);
304
- mask: var(--hagilight-pillar-icon) center / contain no-repeat;
305
- -webkit-mask: var(--hagilight-pillar-icon) center / contain no-repeat;
341
+ .hagilight-article-promotion__windows ms-store-badge {
342
+ display: inline-flex;
343
+ align-items: center;
344
+ max-width: 100%;
345
+ min-height: 6.5rem;
306
346
  }
307
347
 
308
- .hagilight-article-promotion__share {
309
- display: grid;
310
- gap: 0.5rem;
348
+ /* Keep the badge's fixed height and shrink it to the slot on narrow screens without distortion. */
349
+ .hagilight-article-promotion__windows ms-store-badge::part(img) {
350
+ max-width: 100%;
351
+ object-fit: contain;
352
+ object-position: left center;
353
+ }
354
+
355
+ .hagilight-article-promotion__store-fallback,
356
+ .hagilight-article-promotion__downloads {
357
+ display: inline-flex;
358
+ align-items: center;
359
+ min-height: 2.75rem;
360
+ color: var(--sl-color-text-accent);
361
+ font-weight: 600;
311
362
  }
312
363
 
313
364
  .hagilight-article-promotion__share-text {
314
- margin: 0;
365
+ justify-self: stretch;
315
366
  padding: 0.75rem 1rem;
316
367
  border: 1px dashed var(--sl-color-gray-4);
317
368
  border-radius: var(--sl-radius-md, 0.5rem);
@@ -320,15 +371,63 @@ const gallery = copy.gallery.flatMap((item) => {
320
371
  user-select: all;
321
372
  }
322
373
 
323
- @media (max-width: 30rem) {
374
+ /* Medium: pillars become a three-up row, the gallery a mosaic, the closing two columns. */
375
+ @container (min-width: 36rem) {
324
376
  .hagilight-article-promotion__features {
325
- grid-template-columns: 1fr;
377
+ grid-template-columns: repeat(3, minmax(0, 1fr));
326
378
  }
327
379
 
380
+ /*
381
+ * Mosaic in reading order: the workbench and the proposal strip stack in the left column
382
+ * beside the tall Hero Dungeon panel. The 1.1fr split lands the image bottoms of both columns within
383
+ * a caption's height of each other for the current screenshots; the placement assumes exactly
384
+ * three gallery images.
385
+ */
386
+ .hagilight-article-promotion__gallery {
387
+ grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
388
+ align-items: start;
389
+ }
390
+
391
+ .hagilight-article-promotion__gallery li:nth-child(1) {
392
+ grid-column: 1;
393
+ grid-row: 1;
394
+ }
395
+
396
+ .hagilight-article-promotion__gallery li:nth-child(2) {
397
+ grid-column: 1;
398
+ grid-row: 2;
399
+ }
400
+
401
+ .hagilight-article-promotion__gallery li:nth-child(3) {
402
+ grid-column: 2;
403
+ grid-row: 1 / span 2;
404
+ }
405
+
406
+ .hagilight-article-promotion__closing {
407
+ grid-template-columns: repeat(2, minmax(0, 1fr));
408
+ gap: 2rem;
409
+ }
410
+ }
411
+
412
+ /* Wide: the pitch takes the left column and the pillars stack beside it. */
413
+ @container (min-width: 56rem) {
414
+ .hagilight-article-promotion__pitch {
415
+ grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
416
+ gap: 3rem;
417
+ align-items: start;
418
+ }
419
+
420
+ .hagilight-article-promotion__features {
421
+ grid-template-columns: minmax(0, 1fr);
422
+ }
423
+ }
424
+
425
+ @media (max-width: 30rem) {
328
426
  .hagilight-article-promotion__actions {
329
427
  flex-direction: column;
330
428
  flex-wrap: nowrap;
331
429
  align-items: stretch;
430
+ justify-self: stretch;
332
431
  }
333
432
  }
334
433
  </style>
package/README.md CHANGED
@@ -39,7 +39,7 @@ hagilight({ themes: { enabled: false } })
39
39
 
40
40
  ### HagiCode showcase
41
41
 
42
- After the body (and any translation notice) of every documentation article, the plugin renders a static HagiCode showcase: a headline and lead, calls to action to the website and the documentation, a Windows download button, a three-image gallery with captions, three pillar cards (Smart, Efficient, Fun), and a selectable, copy-ready share sentence. All text is localized for the ten published locales (`en-US`, `zh-CN`, `zh-Hant`, `ja-JP`, `ko-KR`, `de-DE`, `fr-FR`, `es-ES`, `pt-BR`, `ru-RU`) and falls back to English for any other language. Links come from the same locale-aware catalog as the footer.
42
+ After the body (and any translation notice) of every documentation article, the plugin renders a static HagiCode showcase: a headline, lead, and tagline with calls to action to the website and the documentation, three pillars (Smart, Efficient, Fun), a three-image gallery with captions, and a closing row with the Windows download button beside a selectable, copy-ready share sentence. The layout follows the showcase's own width: one column when narrow, a three-up pillar row, a gallery mosaic, and a two-column closing row from 36rem, and the pillars beside the pitch from 56rem (for example in the wide content mode). All text is localized for the ten published locales (`en-US`, `zh-CN`, `zh-Hant`, `ja-JP`, `ko-KR`, `de-DE`, `fr-FR`, `es-ES`, `pt-BR`, `ru-RU`) and falls back to English for any other language. Links come from the same locale-aware catalog as the footer.
43
43
 
44
44
  Turn it off for the whole site, or override it per article:
45
45
 
@@ -88,7 +88,7 @@ Budgets, enforced by `npm test`: 768 KiB for all showcase images together, 200 K
88
88
  The copy and assets mirror `repos/web` and `repos/docs` in the HagiCode monorepo, which this package never edits.
89
89
 
90
90
  - **Copy:** edit `src/article-promotion-copy/<locale>.ts` (every locale must keep the same fields, feature ids, and gallery ids). Terminology is pinned in `GLOSSARY` in `src/article-promotion-copy/index.ts`, seeded from the product locale files in `repos/web/src/locales/<locale>/`. `HagiCode`, `OpenSpec`, `Hero Dungeon`, `Microsoft Store`, and `Windows` are never translated.
91
- - **Images:** audit the candidate, crop and convert it to WebP, add or update its `manifest.json` entry, register it in the `galleryImages` map in `ArticlePromotion.astro`, and add a caption and text alternative in every locale. `npm test` checks that the manifest, the files, the component registry, and the copy agree.
91
+ - **Images:** audit the candidate, crop and convert it to WebP, add or update its `manifest.json` entry, register it in the `galleryImages` map in `ArticlePromotion.astro`, and add a caption and text alternative in every locale. The gallery mosaic places the first, second, and third catalog entries as the left top, left bottom, and right tall slot, so keep the gallery at three images or revisit the placement in the component's `@container (min-width: 36rem)` block. `npm test` checks that the manifest, the files, the component registry, and the copy agree.
92
92
  - **Badge:** the product id is parsed from the Store URL and the badge language map lives in `src/windows-download.ts`. Re-check both against `repos/docs/src/components/MicrosoftStoreBadge.tsx` and the official site when the Store listing or the supported languages change.
93
93
 
94
94
  The plugin footer and direct `/Footer` and `/PromotoFooter` components append
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hagicode/hagilight-starlight",
3
- "version": "0.5.3-dev.70.1.7faab38",
3
+ "version": "0.5.3-dev.71.1.f32e5d4",
4
4
  "type": "module",
5
5
  "description": "Starlight plugin and components for HagiCode documentation",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "assets/showcase/*"
54
54
  ],
55
55
  "dependencies": {
56
- "@hagicode/hagilight-core": "0.5.3-dev.70.1.7faab38"
56
+ "@hagicode/hagilight-core": "0.5.3-dev.71.1.f32e5d4"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "@astrojs/starlight": "^0.42.4",