@press2ai/theme-specialist-glossy 0.8.2 → 0.9.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@press2ai/theme-specialist-glossy",
3
- "version": "0.8.2",
3
+ "version": "0.9.0",
4
4
  "description": "Classless, AI-first theme inspired by Stripe. Framework-agnostic templates (Hono, Astro, raw HTML). Semantic HTML, Schema.org microdata, JSON-LD — built for LLM crawlers.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -57,12 +57,12 @@ body > header nav {
57
57
  body > header nav a { color: var(--ink-2); text-decoration: none; font-size: var(--t-sm); font-weight: 500; }
58
58
  body > header nav a strong { font-size: var(--t-md); font-weight: 700; color: var(--ink); }
59
59
 
60
- /* Main — no margin-bottom anywhere, only margin-top */
60
+ /* Main — each block carries its own margin-top, no position-dependent rules */
61
61
  main {
62
62
  max-width: var(--container); margin-inline: auto;
63
63
  padding-inline: var(--pad); padding-top: 0; padding-bottom: var(--g6);
64
64
  }
65
- main > h1:first-child, main > article:first-child { margin-top: var(--g5); }
65
+ main > h1 { margin-top: var(--g5); }
66
66
 
67
67
  /* Footer */
68
68
  body > footer {
@@ -75,25 +75,24 @@ body > footer > small {
75
75
  }
76
76
  body > footer a { color: var(--ink-2); transition: color var(--ease); }
77
77
  body > footer a:hover { color: var(--violet); }
78
- .footer-grid {
78
+ body > footer > small > nav {
79
79
  display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--g4);
80
- max-width: var(--container); margin-inline: auto; padding-inline: var(--pad);
81
80
  margin-bottom: var(--g4);
82
81
  }
83
- .footer-col strong {
82
+ body > footer > small > nav section { all: unset; display: block; }
83
+ body > footer > small > nav strong {
84
84
  display: block; font-size: var(--t-xs); font-weight: 600; color: var(--ink);
85
85
  text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: var(--g2);
86
86
  }
87
- .footer-col p { font-size: var(--t-xs); line-height: 1.6; color: var(--ink-3); margin: 0; max-width: 36ch; }
88
- .footer-col a { display: block; font-size: var(--t-xs); line-height: 2; color: var(--ink-3); }
89
- .footer-col a:hover { color: var(--violet); }
90
- .footer-meta {
91
- max-width: var(--container); margin: 0 auto; padding: var(--g3) var(--pad) 0;
92
- border-top: 1px solid var(--line);
87
+ body > footer > small > nav p { font-size: var(--t-xs); line-height: 1.6; color: var(--ink-3); margin: 0; max-width: 36ch; }
88
+ body > footer > small > nav a { display: block; font-size: var(--t-xs); line-height: 2; color: var(--ink-3); }
89
+ body > footer > small > nav a:hover { color: var(--violet); }
90
+ body > footer > small > p {
91
+ padding-top: var(--g3); border-top: 1px solid var(--line);
93
92
  font-size: var(--t-xs); color: var(--ink-3); text-align: left;
94
93
  }
95
94
 
96
- /* Hero — golden ratio: top g6, bottom g5 */
95
+ /* Hero */
97
96
  hgroup {
98
97
  position: relative; text-align: center; isolation: isolate; overflow: hidden;
99
98
  padding: var(--g6) var(--pad) var(--g5);
@@ -128,19 +127,22 @@ hgroup > p:first-child small::before { content: ''; width: 6px; height: 6px; bor
128
127
  hgroup h1 { max-width: 18ch; margin: 0 auto var(--g4); color: var(--ink); }
129
128
  hgroup p { font-size: var(--t-md); line-height: 1.55; color: var(--ink-2); max-width: var(--measure); margin: 0 auto var(--g4); }
130
129
 
131
- /* Hero CTAs */
132
- .hero-ctas {
130
+ /* Hero CTAs — <nav> inside hgroup, first link primary, rest secondary */
131
+ hgroup > nav {
133
132
  display: flex; gap: var(--g2); flex-wrap: wrap; justify-content: center;
134
133
  margin-top: var(--g4); margin-bottom: 0;
135
134
  }
136
- .cta-primary, .cta-secondary {
135
+ hgroup > nav > a {
137
136
  display: inline-flex; align-items: center; height: 44px; padding: 0 var(--g4);
138
137
  border-radius: var(--pill); font-weight: 600; font-size: var(--t-sm); transition: all var(--ease);
138
+ background: var(--white); color: var(--ink); border: 1px solid var(--line);
139
+ }
140
+ hgroup > nav > a:first-child {
141
+ background: var(--violet); color: var(--white); border-color: transparent;
142
+ box-shadow: 0 4px 14px var(--violet-glow);
139
143
  }
140
- .cta-primary { background: var(--violet); color: var(--white); box-shadow: 0 4px 14px var(--violet-glow); }
141
- .cta-primary:hover { background: var(--ink); color: var(--white); transform: translateY(-1px); box-shadow: 0 6px 20px rgba(26,26,46,.2); }
142
- .cta-secondary { background: var(--white); color: var(--ink); border: 1px solid var(--line); }
143
- .cta-secondary:hover { border-color: var(--line-h); background: var(--bg); }
144
+ hgroup > nav > a:first-child:hover { background: var(--ink); color: var(--white); transform: translateY(-1px); box-shadow: 0 6px 20px rgba(26,26,46,.2); }
145
+ hgroup > nav > a:not(:first-child):hover { border-color: var(--line-h); background: var(--bg); }
144
146
 
145
147
  /* Search */
146
148
  form[role="search"] {
@@ -163,34 +165,33 @@ form[role="search"] button {
163
165
  }
164
166
  form[role="search"] button:hover { background: var(--ink); }
165
167
 
166
- /* Stats — margin-top only, visually separated */
167
- section[aria-label="Statystyki"] { margin-top: var(--g6); }
168
- .stat-summary {
168
+ /* Stats — structural selector, no hardcoded aria-label */
169
+ section:has(> dl) { margin-top: var(--g6); }
170
+ section:has(> dl) > p {
169
171
  text-align: center; font-size: var(--t-md); font-weight: 500; line-height: 1.55;
170
172
  color: var(--ink); margin: 0 auto var(--g4); max-width: var(--measure);
171
173
  }
172
- section[aria-label="Statystyki"] > dl {
174
+ section:has(> dl) > dl {
173
175
  display: flex; justify-content: center; gap: var(--g5); margin: 0 auto; padding: 0;
174
176
  border: none; background: none; box-shadow: none;
175
177
  }
176
- section[aria-label="Statystyki"] > dl div { text-align: center; }
177
- .stat-icon { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; margin: 0 auto var(--g1); background: var(--violet-s); border-radius: 50%; color: var(--violet); }
178
- .stat-icon svg { width: 18px; height: 18px; }
179
- section[aria-label="Statystyki"] > dl dt { font-size: var(--t-lg); font-weight: 800; line-height: 1.2; color: var(--violet); }
180
- section[aria-label="Statystyki"] > dl dd { margin: 2px 0 0; font-size: var(--t-xs); line-height: 1.4; color: var(--ink-3); font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; }
178
+ section:has(> dl) > dl div { text-align: center; }
179
+ section:has(> dl) > dl div > span:has(> svg) {
180
+ display: flex; align-items: center; justify-content: center; width: 36px; height: 36px;
181
+ margin: 0 auto var(--g1); background: var(--violet-s); border-radius: 50%; color: var(--violet);
182
+ }
183
+ section:has(> dl) > dl div > span:has(> svg) > svg { width: 18px; height: 18px; }
184
+ section:has(> dl) > dl dt { font-size: var(--t-lg); font-weight: 800; line-height: 1.2; color: var(--violet); }
185
+ section:has(> dl) > dl dd { margin: 2px 0 0; font-size: var(--t-xs); line-height: 1.4; color: var(--ink-3); font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; }
181
186
 
182
- /* Category pills — margin-top only */
187
+ /* Category pills — single accent, no position-dependent colors */
183
188
  nav[aria-label] { display: flex; flex-wrap: wrap; gap: var(--g1); margin-top: var(--g5); }
184
189
  nav[aria-label] a {
185
190
  display: inline-flex; align-items: center; height: 32px; padding: 0 var(--g2);
186
191
  border-radius: var(--pill); font-size: var(--t-xs); font-weight: 500;
187
192
  background: var(--white); border: 1px solid var(--line); color: var(--ink-2); transition: all var(--ease);
188
193
  }
189
- nav[aria-label] a:nth-child(5n+1):hover { border-color: var(--violet); color: var(--violet); background: var(--violet-s); }
190
- nav[aria-label] a:nth-child(5n+2):hover { border-color: var(--teal); color: var(--teal); background: var(--teal-s); }
191
- nav[aria-label] a:nth-child(5n+3):hover { border-color: var(--rose); color: var(--rose); background: var(--rose-s); }
192
- nav[aria-label] a:nth-child(5n+4):hover { border-color: var(--amber); color: var(--amber); background: var(--amber-s); }
193
- nav[aria-label] a:nth-child(5n+5):hover { border-color: var(--sky); color: var(--sky); background: var(--sky-s); }
194
+ nav[aria-label] a:hover { border-color: var(--violet); color: var(--violet); background: var(--violet-s); }
194
195
 
195
196
  /* Steps — full-bleed white band */
196
197
  section:has(> ol) {
@@ -214,16 +215,12 @@ section > ol li::before {
214
215
  content: counter(steps); display: flex; align-items: center; justify-content: center;
215
216
  width: 40px; height: 40px; margin: 0 auto var(--g2);
216
217
  border-radius: 50%; font-size: var(--t-sm); font-weight: 700;
218
+ background: var(--violet-s); color: var(--violet);
217
219
  }
218
- section > ol li:nth-child(5n+1)::before { background: var(--violet-s); color: var(--violet); }
219
- section > ol li:nth-child(5n+2)::before { background: var(--teal-s); color: var(--teal); }
220
- section > ol li:nth-child(5n+3)::before { background: var(--amber-s); color: var(--amber); }
221
- section > ol li:nth-child(5n+4)::before { background: var(--rose-s); color: var(--rose); }
222
- section > ol li:nth-child(5n+5)::before { background: var(--sky-s); color: var(--sky); }
223
220
  section > ol li strong { display: block; font-size: var(--t-sm); line-height: 1.4; margin-bottom: 4px; color: var(--ink); }
224
221
  section > ol li span { font-size: var(--t-xs); line-height: 1.5; color: var(--ink-3); }
225
222
 
226
- /* Trainer cards — margin-top only */
223
+ /* Trainer cards — no position-dependent colors */
227
224
  section:has(> article[itemscope]) {
228
225
  margin-top: var(--g6);
229
226
  display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: var(--g3);
@@ -237,42 +234,40 @@ article[itemscope] {
237
234
  }
238
235
  article[itemscope]:hover { transform: translateY(-2px); box-shadow: var(--shadow-up); border-color: var(--line-h); }
239
236
 
240
- /* Card avatar */
241
- .card-avatar {
237
+ /* Card avatar — single accent color, position-independent */
238
+ article[itemscope] > div[aria-hidden] {
242
239
  width: 40px; height: 40px; border-radius: 50%;
243
240
  display: flex; align-items: center; justify-content: center;
244
241
  font-size: var(--t-xs); font-weight: 700; color: var(--white);
245
242
  margin-bottom: var(--g2); flex-shrink: 0;
243
+ background: var(--violet);
246
244
  }
247
- article[itemscope]:nth-child(5n+2) .card-avatar { background: var(--violet); }
248
- article[itemscope]:nth-child(5n+3) .card-avatar { background: var(--teal); }
249
- article[itemscope]:nth-child(5n+4) .card-avatar { background: var(--rose); }
250
- article[itemscope]:nth-child(5n+5) .card-avatar { background: var(--amber); }
251
- article[itemscope]:nth-child(5n+6) .card-avatar { background: var(--sky); }
252
- article[itemscope]:nth-child(5n+1) .card-avatar,
253
- article[itemscope]:first-child .card-avatar { background: var(--violet); }
254
245
  article[itemscope] header { margin-bottom: var(--g1); }
255
246
  article[itemscope] h2 { font-size: var(--t-sm); font-weight: 600; line-height: 1.3; margin: 0 0 2px; }
256
247
  article[itemscope] h2 a { color: var(--ink); }
257
248
  article[itemscope] h2 a:hover { color: var(--violet); }
258
249
  article[itemscope] header p { font-size: var(--t-xs); line-height: 1.4; color: var(--ink-3); margin: 0; }
259
- .card-city { display: inline-flex; align-items: center; gap: 4px; margin-top: 2px; color: var(--ink-3); font-size: var(--t-xs); }
260
- .card-city::before { content: ''; display: inline-block; width: 3px; height: 3px; border-radius: 50%; background: var(--ink-3); }
250
+ article[itemscope] header p:has([itemprop="address"]) {
251
+ display: inline-flex; align-items: center; gap: 4px; margin-top: 2px;
252
+ }
253
+ article[itemscope] header p:has([itemprop="address"])::before {
254
+ content: ''; display: inline-block; width: 3px; height: 3px; border-radius: 50%; background: var(--ink-3);
255
+ }
261
256
  article[itemscope] [itemprop="description"] { font-size: var(--t-xs); line-height: 1.5; margin: var(--g1) 0 0; color: var(--ink-2); }
262
257
  article[itemscope] ul { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; margin-top: var(--g1); }
263
258
  article[itemscope] ul li {
264
259
  background: var(--violet-s); color: var(--violet);
265
260
  padding: 1px var(--g1); border-radius: var(--pill); font-size: 0.7rem; font-weight: 500;
266
261
  }
267
- .card-cta {
262
+ article[itemscope] > a:last-child {
268
263
  display: inline-flex; align-items: center; margin-top: auto; padding-top: var(--g2);
269
264
  font-size: var(--t-xs); font-weight: 600; color: var(--violet); transition: all var(--ease);
270
265
  }
271
- .card-cta:hover { color: var(--ink); gap: 4px; }
266
+ article[itemscope] > a:last-child:hover { color: var(--ink); gap: 4px; }
272
267
 
273
268
  /* Single trainer */
274
269
  main > article {
275
- max-width: var(--w-8); margin: 0 auto; background: var(--card);
270
+ max-width: var(--w-8); margin: var(--g5) auto 0; background: var(--card);
276
271
  border: 1px solid var(--line); border-radius: var(--r-lg); padding: var(--g5); box-shadow: var(--shadow-md);
277
272
  }
278
273
  main > article > header { border-bottom: 1px solid var(--line); padding-bottom: var(--g3); margin-bottom: var(--g4); }
@@ -322,6 +317,9 @@ form:not([role="search"]) button[type="submit"] {
322
317
  }
323
318
  form:not([role="search"]) button[type="submit"]:hover { background: var(--ink); transform: translateY(-1px); }
324
319
 
320
+ /* Trust block */
321
+ aside:has(> ul) { margin-top: var(--g5); }
322
+
325
323
  /* Responsive */
326
324
  @media (max-width: 640px) {
327
325
  :root { --pad: var(--g3); }
@@ -329,12 +327,12 @@ form:not([role="search"]) button[type="submit"]:hover { background: var(--ink);
329
327
  hgroup { padding: var(--g5) var(--pad) var(--g4); }
330
328
  section:has(> article[itemscope]) { grid-template-columns: 1fr; }
331
329
  section > ol { grid-template-columns: 1fr; }
332
- section[aria-label="Statystyki"] > dl { gap: var(--g3); }
330
+ section:has(> dl) > dl { gap: var(--g3); }
333
331
  main > article { padding: var(--g3); }
334
332
  main > article dl { grid-template-columns: 1fr; gap: calc(var(--g1) / 2) 0; }
335
333
  main > article dt { margin-top: var(--g2); }
336
334
  form[role="search"] { height: 40px; }
337
335
  form[role="search"] input { font-size: var(--t-xs); }
338
336
  section:has(> ol) { padding: var(--g4) var(--pad); }
339
- .footer-grid { grid-template-columns: 1fr; gap: var(--g3); }
337
+ body > footer > small > nav { grid-template-columns: 1fr; gap: var(--g3); }
340
338
  }
@@ -17,9 +17,9 @@ export function catalogHero(p: CatalogHeroProps): string {
17
17
  <input type="search" name="q" placeholder="${esc(p.searchPlaceholder ?? 'Szukaj...')}" value="${esc(p.searchValue ?? '')}" />
18
18
  <button type="submit">Szukaj</button>
19
19
  </form>` : '';
20
- const ctas = p.ctas?.length ? `<p class="hero-ctas">${p.ctas.map(
21
- (c, i) => `<a href="${esc(c.href)}" class="${i === 0 ? 'cta-primary' : 'cta-secondary'}">${esc(c.label)}</a>`
22
- ).join('\n')}</p>` : '';
20
+ const ctas = p.ctas?.length ? `<nav>${p.ctas.map(
21
+ c => `<a href="${esc(c.href)}">${esc(c.label)}</a>`
22
+ ).join('\n')}</nav>` : '';
23
23
  return `<hgroup>
24
24
  ${badge}
25
25
  <h1>${p.title}</h1>
@@ -37,10 +37,10 @@ const STAT_ICONS: Record<string, string> = {
37
37
 
38
38
  export function statBar(items: { value: string; label: string; icon?: string }[], summary?: string): string {
39
39
  const divs = items.map(i => {
40
- const icon = i.icon && STAT_ICONS[i.icon] ? `<span class="stat-icon">${STAT_ICONS[i.icon]}</span>` : '';
40
+ const icon = i.icon && STAT_ICONS[i.icon] ? `<span>${STAT_ICONS[i.icon]}</span>` : '';
41
41
  return `<div>${icon}<dt>${esc(i.value)}</dt><dd>${esc(i.label)}</dd></div>`;
42
42
  }).join('\n');
43
- const summaryP = summary ? `<p class="stat-summary">${esc(summary)}</p>` : '';
43
+ const summaryP = summary ? `<p>${esc(summary)}</p>` : '';
44
44
  return `<section aria-label="Statystyki">${summaryP}<dl aria-hidden="true">\n${divs}\n</dl></section>`;
45
45
  }
46
46
 
@@ -57,7 +57,7 @@ export function steps(title: string, items: { title: string; description: string
57
57
 
58
58
  export function trustBlock(title: string, points: string[]): string {
59
59
  const items = points.map(p => `<li>${esc(p)}</li>`).join('\n');
60
- return `<aside class="trust">
60
+ return `<aside>
61
61
  <strong>${esc(title)}</strong>
62
62
  <ul>${items}</ul>
63
63
  </aside>`;
@@ -11,7 +11,7 @@ export function hero(p: Profile): string {
11
11
  const ctas: string[] = [];
12
12
  if (p.email) ctas.push(`<a href="mailto:${esc(p.email)}">Napisz wiadomość</a>`);
13
13
  if (p.phone) ctas.push(`<a href="tel:${esc(p.phone.replace(/\s/g, ''))}">Zadzwoń</a>`);
14
- const ctaBlock = ctas.length ? `<p>${ctas.join('\n')}</p>` : '';
14
+ const ctaBlock = ctas.length ? `<nav>${ctas.join('\n')}</nav>` : '';
15
15
 
16
16
  return `<hgroup>
17
17
  ${badge}
@@ -12,7 +12,7 @@ export interface LayoutProps {
12
12
  footerContent?: string;
13
13
  }
14
14
 
15
- const THEME_VERSION = '0.4.0';
15
+ const THEME_VERSION = '0.9.0';
16
16
 
17
17
  export function layout(props: LayoutProps, body: string): string {
18
18
  const {
@@ -14,14 +14,14 @@ export function profileCard(p: Profile, href: string): string {
14
14
  : '';
15
15
 
16
16
  return `<article itemscope itemtype="https://schema.org/Person">
17
- <div class="card-avatar" aria-hidden="true">${initials}</div>
17
+ <div aria-hidden="true">${initials}</div>
18
18
  <header>
19
19
  <h2><a href="${esc(href)}" itemprop="url"><span itemprop="name">${esc(name)}</span></a></h2>
20
20
  <p><span itemprop="jobTitle">${esc(p.jobTitle)}</span></p>
21
- ${city ? `<p class="card-city">${city}</p>` : ''}
21
+ ${city ? `<p>${city}</p>` : ''}
22
22
  </header>
23
23
  ${bio}
24
24
  ${specs}
25
- <a href="${esc(href)}" class="card-cta">Zobacz profil &rarr;</a>
25
+ <a href="${esc(href)}">Zobacz profil &rarr;</a>
26
26
  </article>`;
27
27
  }