pandorga 1.3.0 → 1.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19d2883dc4b29f8c6b614997004f69d32d2cacfa67ab83ef61544364a7d57cb3
4
- data.tar.gz: 73f29c402a3259ec374c2d15746f7a6898d10f24258c11d626e5afe561d6a2e5
3
+ metadata.gz: 4947a2b9a5122c400a00753c4833861bbc6217dfaf59850fa27f79dbd7d99f3a
4
+ data.tar.gz: 7baa3fdc30880e278c772c2a98229bbeca3cce8b91e897bb56f4bb52fcedef3b
5
5
  SHA512:
6
- metadata.gz: 692b1745fea99d185aaf2ed170a584fb83bf9c870eaa6e03b9567e9d9883930cc136b7e7821cb4746781d87c5131f688bc79f9b0d4cb8aa90208a4d47ef6462f
7
- data.tar.gz: e9a2698daffc89e5ee9502a1450dce6e736aad68ca500ed1e37dffa4e5c34ed9709ed0f724888959bee6bd680085d56d7beb7c80504610f2a04683a21d6386a7
6
+ metadata.gz: 060666c1506de360e6420c3b4cf77e5fe36a8180f1aa5e8ffc5f8e4c9de134d980f1c2ba336a799cd4ac19646dc3ec6bb4022c78f0291d9eca2640bdf63da17d
7
+ data.tar.gz: 2a305ce4521e205322f8d7329d25730b4593e42718c8becfb49eed02bf4c3e1b862cec55b55662d7d653ea47d668cf8d3b780a4bd17f4b4bfb4b43bc7f20974d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.1] — 2026-10-05
4
+
5
+ ### Changed
6
+
7
+ - Home portfolio band is a specimen + inventory bench (16:9 media) instead of
8
+ an equal card grid
9
+ - Projects listing lead shows a Featured chip
10
+
3
11
  ## [1.3.0] — 2026-10-05
4
12
 
5
13
  ### Fixed
data/DESIGN.md CHANGED
@@ -935,8 +935,9 @@ Letter-spacing in use, by frequency: `0.1em` (12), `0.08em` (10), `0.12em` (7),
935
935
  writing, rascunhos, systems, ideas graph. The featured band carries a 6rem ×
936
936
  3px `primary` rule at its top-left corner as a structural mark. The three
937
937
  writing cards take `primary` / `secondary` / `tertiary` 2px top rules in
938
- rotation. The systems grid is a 12-column asymmetric pair — 7/5 then 5/7 —
939
- from 1024px. Below 768px the hero portrait runs to the screen edge, pulled
938
+ rotation. The systems band is a specimen + inventory bench from 900px —
939
+ one large project plate (~7/12) beside a compact ledger rail (~5/12); both
940
+ keep 16:9 media. Below 768px the hero portrait runs to the screen edge, pulled
940
941
  out of the band's gutter by exactly `--gutter-mobile` on each side and losing
941
942
  its side hairlines, which at the edge would read as a frame cut off.
942
943
  * **Writing index.** Masthead over a hairline, then a `panelContrast` filter
@@ -947,9 +948,9 @@ Letter-spacing in use, by frequency: `0.1em` (12), `0.08em` (10), `0.12em` (7),
947
948
  rows beside a sticky marginalia column. Rows become two-column
948
949
  (`.rascunhos-row--illustrated`, a 7.5rem plate, 4rem on phones) only when an
949
950
  image is actually present.
950
- * **Projects.** A Tailwind `grid-cols-1 md:grid-cols-2` of system cards with
951
- `align-items: start`, so a card without a poster does not stretch to match
952
- one that has one.
951
+ * **Projects.** A session-featured lead plate (with a Featured chip) over a
952
+ `grid-cols-1 md:grid-cols-2` of system cards with `align-items: start`, so a
953
+ card without a poster does not stretch to match one that has one.
953
954
  * **Sources.** `.listing-card-grid--sources`: one column, two from 768px,
954
955
  three from 1024px, posters at `16 / 9` — the video frame, which is what most
955
956
  of the collection links to. Filtering hides pre-rendered cards with a class
@@ -324,6 +324,43 @@
324
324
  ].join('');
325
325
  }
326
326
 
327
+ /* Compact inventory row for the home portfolio bench — thumb + name +
328
+ * status only. Field-backed; no tagline or tag cloud. */
329
+ function renderProjectInventoryRow(item, options) {
330
+ options = options || {};
331
+ var f = blockFields(item);
332
+ var fm = f.fm;
333
+ var href = options.href || '#';
334
+ var name = fm.project || f.title;
335
+
336
+ var row = document.createElement('article');
337
+ row.className = 'home-project-inventory-row group';
338
+
339
+ var media = renderPosterMedia(fm.thumbnail, name);
340
+ if (!media && fm.icon) {
341
+ media = '<div class="home-project-inventory-mark" aria-hidden="true">' +
342
+ '<span class="material-symbols-outlined">' + escapeHtml(fm.icon) + '</span></div>';
343
+ }
344
+
345
+ var html = '';
346
+ if (media) {
347
+ html += '<div class="home-project-inventory-media">' + media + '</div>';
348
+ }
349
+ html += '<div class="home-project-inventory-body">';
350
+ html += '<h3 class="home-project-inventory-title card-title">' +
351
+ '<a class="ledger-card-stretch" href="' + escapeAttr(href) + '">' +
352
+ escapeHtml(name) + '</a></h3>';
353
+ var meta = renderMetaStrip([
354
+ fm.label ? escapeHtml(fm.label) : '',
355
+ fm.status ? '<span class="ledger-status">' + escapeHtml(fm.status) + '</span>' : ''
356
+ ]);
357
+ if (meta) html += meta;
358
+ html += '</div>';
359
+
360
+ row.innerHTML = html;
361
+ return row;
362
+ }
363
+
327
364
  /* System card — the project shape. Carries the fields projects actually
328
365
  * have: label, status, and a repository link. */
329
366
  function renderSystemCard(item, options) {
@@ -335,8 +372,20 @@
335
372
 
336
373
  var card = document.createElement('article');
337
374
  card.className = 'ledger-system-card group';
375
+ if (options.className) card.className += ' ' + options.className;
338
376
 
339
- var html = renderPosterMedia(fm.thumbnail, name);
377
+ var html = '';
378
+ if (options.frameCorners) {
379
+ html += '<span class="ledger-frame-corners" aria-hidden="true"></span>';
380
+ }
381
+ var poster = renderPosterMedia(fm.thumbnail, name);
382
+ if (poster) {
383
+ html += poster;
384
+ } else if (options.glyphFallback && fm.icon) {
385
+ html += '<div class="projects-plate projects-plate--mark" aria-hidden="true">' +
386
+ '<span class="material-symbols-outlined projects-plate-glyph">' +
387
+ escapeHtml(fm.icon) + '</span></div>';
388
+ }
340
389
  // Callers may supply their own strip parts; the default is whatever the
341
390
  // project declares about itself.
342
391
  var parts = options.metaParts || [
@@ -63,6 +63,7 @@
63
63
  renderLedgerRow: renderLedgerRow,
64
64
  renderArchiveCard: renderArchiveCard,
65
65
  renderSystemCard: renderSystemCard,
66
+ renderProjectInventoryRow: renderProjectInventoryRow,
66
67
  renderPosterMedia: renderPosterMedia,
67
68
  ensureBibliographyIndex: ensureBibliographyIndex,
68
69
  bibField: bibField,
@@ -39,11 +39,23 @@
39
39
  {%- if _featured -%}
40
40
  <div id="{{ _slot_id }}-featured" data-home-featured-slot data-tag-base="{{ _path }}"></div>
41
41
  {%- endif -%}
42
+ {%- if band.kind == 'portfolio' -%}
42
43
  <div
43
44
  id="{{ _slot_id }}"
44
- class="{% if band.kind == 'blog' %}home-draft-list{% elsif band.kind == 'portfolio' %}home-system-grid{% else %}home-card-grid{% endif %}"
45
+ class="home-projects-bench"
46
+ data-home-list
47
+ data-tag-base="{{ _path }}"
48
+ >
49
+ <div data-home-specimen></div>
50
+ <div class="home-project-inventory" data-home-inventory aria-label="Project inventory"></div>
51
+ </div>
52
+ {%- else -%}
53
+ <div
54
+ id="{{ _slot_id }}"
55
+ class="{% if band.kind == 'blog' %}home-draft-list{% else %}home-card-grid{% endif %}"
45
56
  data-home-list
46
57
  data-tag-base="{{ _path }}"
47
58
  ></div>
59
+ {%- endif -%}
48
60
  </div>
49
61
  </section>
data/_layouts/home.html CHANGED
@@ -208,13 +208,38 @@ layout: shell
208
208
  entries = entries.sort(function (a, b) {
209
209
  return Number(a.sort_order || 0) - Number(b.sort_order || 0);
210
210
  });
211
+ var specimenSlot = section.querySelector('[data-home-specimen]');
212
+ var inventorySlot = section.querySelector('[data-home-inventory]');
211
213
  var systemTagHref = tagHrefFrom(list);
212
- fill(list, entries.slice(0, limit), function (entry) {
213
- return runtime.renderSystemCard(asItem(entry), {
214
- href: entry.url || runtime.projectUrl(entry.slug),
215
- tagHref: systemTagHref
216
- });
217
- }, 'Projects could not be loaded right now.');
214
+ var portfolio = entries.slice(0, limit);
215
+ if (!portfolio.length) {
216
+ runtime.Listing.showErrorState(list, 'Projects could not be loaded right now.');
217
+ return;
218
+ }
219
+ if (specimenSlot) {
220
+ specimenSlot.innerHTML = '';
221
+ specimenSlot.appendChild(runtime.renderSystemCard(asItem(portfolio[0]), {
222
+ href: portfolio[0].url || runtime.projectUrl(portfolio[0].slug),
223
+ tagHref: systemTagHref,
224
+ className: 'home-project-specimen ledger-card--edge-primary',
225
+ frameCorners: true,
226
+ glyphFallback: true
227
+ }));
228
+ }
229
+ var rest = portfolio.slice(1);
230
+ if (inventorySlot) {
231
+ if (!rest.length) {
232
+ inventorySlot.hidden = true;
233
+ inventorySlot.innerHTML = '';
234
+ } else {
235
+ inventorySlot.hidden = false;
236
+ fill(inventorySlot, rest, function (entry) {
237
+ return runtime.renderProjectInventoryRow(asItem(entry), {
238
+ href: entry.url || runtime.projectUrl(entry.slug)
239
+ });
240
+ }, 'Projects could not be loaded right now.');
241
+ }
242
+ }
218
243
  return;
219
244
  }
220
245
 
@@ -235,7 +235,10 @@ layout: shell
235
235
  html += '<a class="projects-lead-media" href="' + escAttr(href) + '" tabindex="-1">' +
236
236
  plateHtml(item, 'projects-plate--lead') + '</a>';
237
237
  html += '<div class="projects-lead-body">';
238
+ html += '<div class="projects-lead-rail">';
239
+ html += '<span class="ledger-chip home-featured-badge">Featured</span>';
238
240
  if (line) html += line;
241
+ html += '</div>';
239
242
  html += '<h2 class="projects-lead-title"><a href="' + escAttr(href) + '">' + esc(name) + '</a></h2>';
240
243
  if (fm.title && fm.title !== name) {
241
244
  html += '<p class="projects-lead-subtitle">' + esc(fm.title) + '</p>';
@@ -710,8 +710,8 @@ html[data-theme="light"] .home-hero-plate {
710
710
  .home-card-grid .ledger-card-title,
711
711
  .home-card-grid .card-title,
712
712
  .home-draft-card .ledger-card-title,
713
- .home-system-grid .ledger-card-title,
714
- .home-system-grid .card-title {
713
+ .home-project-specimen .ledger-card-title,
714
+ .home-project-inventory-title {
715
715
  font-family: var(--font-content-title);
716
716
  font-weight: var(--weight-title);
717
717
  font-synthesis: none;
@@ -943,45 +943,57 @@ html[data-theme="light"] .home-hero-plate {
943
943
  }
944
944
  }
945
945
 
946
- /* ── Engineering artifacts ──
947
- Uniform dense cells (not the old 7/5 tension scale): four portfolio cards
948
- on the home band were reading as oversized panels. Equal columns + a short
949
- poster keep them catalogue-sized; the projects listing page is unchanged. */
950
- .home-system-grid {
946
+ /* ── Engineering artifacts: specimen + inventory bench ──
947
+ One large specimen plate (~7/12) beside a compact ledger rail (~5/12).
948
+ Covers stay 16:9 — hard requirement for home project media. */
949
+ .home-projects-bench {
951
950
  display: grid;
952
951
  grid-template-columns: minmax(0, 1fr);
953
- gap: var(--space-md);
954
- align-items: stretch;
952
+ gap: var(--space-lg);
953
+ align-items: start;
955
954
  }
956
955
 
957
- @media (min-width: 700px) {
958
- .home-system-grid {
959
- grid-template-columns: repeat(2, minmax(0, 1fr));
956
+ @media (min-width: 900px) {
957
+ .home-projects-bench {
958
+ grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
959
+ gap: var(--space-xl);
960
960
  }
961
961
  }
962
962
 
963
- .home-system-grid .ledger-system-card {
964
- gap: var(--space-xs);
965
- padding: var(--space-md);
963
+ .home-project-specimen {
964
+ position: relative;
965
+ gap: var(--space-sm);
966
+ padding: var(--space-lg);
966
967
  }
967
968
 
968
- .home-system-grid .ledger-system-card>.ledger-poster,
969
- .home-system-grid .ledger-system-card>.projects-plate {
969
+ .home-project-specimen>.ledger-poster,
970
+ .home-project-specimen>.projects-plate {
970
971
  width: auto;
971
- margin: calc(var(--space-md) * -1) calc(var(--space-md) * -1) 0;
972
- aspect-ratio: 2 / 1;
972
+ margin: calc(var(--space-lg) * -1) calc(var(--space-lg) * -1) 0;
973
+ aspect-ratio: 16 / 9;
973
974
  }
974
975
 
975
- .home-system-grid .ledger-system-card .ledger-card-title {
976
- font-size: var(--type-card);
977
- line-height: 1.2;
976
+ .home-project-specimen .projects-plate--mark {
977
+ display: flex;
978
+ align-items: center;
979
+ justify-content: center;
980
+ background: var(--color-panel-contrast);
981
+ color: var(--color-primary);
978
982
  }
979
983
 
980
- .home-system-grid .ledger-card-links {
981
- row-gap: var(--space-sm);
984
+ .home-project-specimen .projects-plate-glyph {
985
+ font-size: 3rem;
986
+ }
987
+
988
+ .home-project-specimen .ledger-card-title {
989
+ font-family: var(--font-content-title);
990
+ font-size: var(--type-card-lg);
991
+ font-weight: var(--weight-title);
992
+ font-synthesis: none;
993
+ line-height: 1.2;
982
994
  }
983
995
 
984
- .home-system-grid .ledger-card-copy {
996
+ .home-project-specimen .ledger-card-copy {
985
997
  font-family: var(--font-body);
986
998
  font-size: var(--type-subtitle);
987
999
  font-weight: var(--weight-body);
@@ -989,9 +1001,106 @@ html[data-theme="light"] .home-hero-plate {
989
1001
  color: var(--color-legend);
990
1002
  display: -webkit-box;
991
1003
  -webkit-box-orient: vertical;
992
- -webkit-line-clamp: 2;
993
- line-clamp: 2;
1004
+ -webkit-line-clamp: 3;
1005
+ line-clamp: 3;
1006
+ overflow: hidden;
1007
+ }
1008
+
1009
+ .home-project-specimen .ledger-card-links {
1010
+ row-gap: var(--space-sm);
1011
+ }
1012
+
1013
+ .home-project-inventory {
1014
+ display: flex;
1015
+ flex-direction: column;
1016
+ min-width: 0;
1017
+ border-top: 1px solid var(--border-gentle-divider);
1018
+ }
1019
+
1020
+ .home-project-inventory-row {
1021
+ position: relative;
1022
+ display: grid;
1023
+ grid-template-columns: minmax(0, 1fr);
1024
+ gap: var(--space-md);
1025
+ align-items: center;
1026
+ padding: var(--space-sm) 0;
1027
+ border-bottom: 1px solid var(--border-gentle-divider);
1028
+ transition: background-color var(--motion-duration-fast) var(--motion-ease-default);
1029
+ }
1030
+
1031
+ .home-project-inventory-row:has(.home-project-inventory-media) {
1032
+ grid-template-columns: 5.5rem minmax(0, 1fr);
1033
+ }
1034
+
1035
+ .home-project-inventory-row:hover,
1036
+ .home-project-inventory-row:focus-within {
1037
+ background: var(--color-surface-high);
1038
+ }
1039
+
1040
+ .home-band--contrast .home-project-inventory-row:hover,
1041
+ .home-band--contrast .home-project-inventory-row:focus-within {
1042
+ background: var(--color-surface-high-contrast);
1043
+ }
1044
+
1045
+ .home-project-inventory-media {
1046
+ min-width: 0;
1047
+ }
1048
+
1049
+ .home-project-inventory-media .ledger-poster,
1050
+ .home-project-inventory-mark {
1051
+ aspect-ratio: 16 / 9;
1052
+ width: 100%;
994
1053
  overflow: hidden;
1054
+ border: 1px solid var(--border-gentle-subtle);
1055
+ background: var(--color-panel-contrast);
1056
+ }
1057
+
1058
+ .home-project-inventory-media .ledger-poster img {
1059
+ width: 100%;
1060
+ height: 100%;
1061
+ object-fit: cover;
1062
+ display: block;
1063
+ }
1064
+
1065
+ .home-project-inventory-mark {
1066
+ display: flex;
1067
+ align-items: center;
1068
+ justify-content: center;
1069
+ color: var(--color-primary);
1070
+ }
1071
+
1072
+ .home-project-inventory-mark .material-symbols-outlined {
1073
+ font-size: 1.25rem;
1074
+ }
1075
+
1076
+ .home-project-inventory-body {
1077
+ display: flex;
1078
+ flex-direction: column;
1079
+ gap: var(--space-2xs);
1080
+ min-width: 0;
1081
+ }
1082
+
1083
+ .home-project-inventory-title {
1084
+ margin: 0;
1085
+ font-family: var(--font-content-title);
1086
+ font-size: var(--type-card);
1087
+ font-weight: var(--weight-title);
1088
+ font-synthesis: none;
1089
+ line-height: 1.25;
1090
+ }
1091
+
1092
+ .home-project-inventory-title a {
1093
+ color: var(--color-on-surface);
1094
+ text-decoration: none;
1095
+ }
1096
+
1097
+ .home-project-inventory-row:hover .home-project-inventory-title a,
1098
+ .home-project-inventory-row:focus-within .home-project-inventory-title a {
1099
+ color: var(--color-primary);
1100
+ }
1101
+
1102
+ .home-project-inventory-row .ledger-meta {
1103
+ margin: 0;
995
1104
  }
996
1105
 
997
1106
 
@@ -206,6 +206,17 @@
206
206
  padding: var(--space-lg);
207
207
  }
208
208
 
209
+ .projects-page .projects-lead-rail {
210
+ display: flex;
211
+ flex-wrap: wrap;
212
+ align-items: center;
213
+ gap: var(--space-sm) var(--space-md);
214
+ }
215
+
216
+ .projects-page .projects-lead-rail .ledger-meta {
217
+ margin: 0;
218
+ }
219
+
209
220
  .projects-page .projects-lead-title {
210
221
  font-family: var(--font-content-title);
211
222
  font-size: var(--type-card-lg);
@@ -24,7 +24,7 @@ module Pandorga
24
24
 
25
25
  gem "pandorga", "~> 1.3"
26
26
  # Local checkout: gem "pandorga", path: "../pandorga"
27
- # GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.3.0"
27
+ # GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.3.1"
28
28
  gem "csv"
29
29
  gem "base64"
30
30
  RUBY
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pandorga
4
- VERSION = "1.3.0"
4
+ VERSION = "1.3.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pandorga
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Pandorga contributors