domma-cms 0.10.0 → 0.13.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.
Files changed (121) hide show
  1. package/CLAUDE.md +248 -159
  2. package/admin/css/admin.css +1 -1
  3. package/admin/js/api.js +1 -1
  4. package/admin/js/app.js +7 -3
  5. package/admin/js/config/sidebar-config.js +1 -1
  6. package/admin/js/http-interceptor.js +1 -0
  7. package/admin/js/lib/safe-html.js +1 -0
  8. package/admin/js/templates/documentation.html +611 -2
  9. package/admin/js/templates/layouts.html +5 -4
  10. package/admin/js/templates/notifications.html +14 -0
  11. package/admin/js/templates/plugin-marketplace.html +16 -0
  12. package/admin/js/templates/plugins.html +17 -5
  13. package/admin/js/views/index.js +1 -1
  14. package/admin/js/views/layouts.js +1 -16
  15. package/admin/js/views/notifications.js +1 -0
  16. package/admin/js/views/plugin-marketplace.js +1 -0
  17. package/admin/js/views/plugins.js +16 -16
  18. package/config/navigation.json +5 -72
  19. package/config/plugins.json +10 -14
  20. package/config/presets.json +50 -13
  21. package/config/site.json +11 -63
  22. package/package.json +2 -1
  23. package/plugins/_template/admin/templates/index.html +17 -0
  24. package/plugins/_template/admin/views/index.js +19 -0
  25. package/plugins/_template/config.js +8 -0
  26. package/plugins/_template/plugin.js +23 -0
  27. package/plugins/_template/plugin.json +34 -0
  28. package/plugins/analytics/plugin.json +41 -31
  29. package/plugins/blog/admin/templates/blog.html +22 -0
  30. package/plugins/blog/admin/templates/categories.html +7 -0
  31. package/plugins/blog/admin/templates/comments.html +11 -0
  32. package/plugins/blog/admin/templates/post-editor.html +97 -0
  33. package/plugins/blog/admin/templates/settings.html +11 -0
  34. package/plugins/blog/admin/views/blog.js +183 -0
  35. package/plugins/blog/admin/views/categories.js +235 -0
  36. package/plugins/blog/admin/views/comments.js +187 -0
  37. package/plugins/blog/admin/views/post-editor.js +291 -0
  38. package/plugins/blog/admin/views/settings.js +100 -0
  39. package/plugins/blog/collections/categories/schema.json +12 -0
  40. package/plugins/blog/collections/comments/schema.json +16 -0
  41. package/plugins/blog/collections/posts/schema.json +19 -0
  42. package/plugins/blog/config.js +8 -0
  43. package/plugins/blog/plugin.js +352 -0
  44. package/plugins/blog/plugin.json +96 -0
  45. package/plugins/blog/roles/blog-author.json +10 -0
  46. package/plugins/blog/roles/blog-editor.json +12 -0
  47. package/plugins/blog/templates/author.html +9 -0
  48. package/plugins/blog/templates/category.html +9 -0
  49. package/plugins/blog/templates/index.html +9 -0
  50. package/plugins/blog/templates/post.html +17 -0
  51. package/plugins/blog/templates/tag.html +9 -0
  52. package/plugins/contacts/collections/user-contact-groups/schema.json +1 -1
  53. package/plugins/contacts/collections/user-contacts/schema.json +1 -1
  54. package/plugins/contacts/plugin.js +4 -10
  55. package/plugins/contacts/plugin.json +13 -3
  56. package/plugins/notes/collections/user-notes/schema.json +1 -1
  57. package/plugins/notes/plugin.js +3 -9
  58. package/plugins/notes/plugin.json +13 -3
  59. package/plugins/site-search/plugin.json +5 -2
  60. package/plugins/theme-switcher/plugin.json +1 -1
  61. package/plugins/todo/collections/todos/schema.json +1 -1
  62. package/plugins/todo/plugin.js +3 -9
  63. package/plugins/todo/plugin.json +13 -3
  64. package/public/css/site.css +1 -1
  65. package/scripts/build.js +48 -0
  66. package/scripts/create-plugin.js +113 -0
  67. package/scripts/fresh.js +6 -7
  68. package/scripts/gen-instance-secret.js +46 -0
  69. package/scripts/reset.js +3 -3
  70. package/scripts/setup.js +31 -13
  71. package/server/middleware/auth.js +48 -0
  72. package/server/middleware/managerAuth.js +36 -0
  73. package/server/routes/api/actions.js +1 -1
  74. package/server/routes/api/auth.js +4 -3
  75. package/server/routes/api/layouts.js +173 -49
  76. package/server/routes/api/notifications.js +155 -0
  77. package/server/routes/api/plugin-marketplace.js +75 -0
  78. package/server/routes/api/users.js +1 -1
  79. package/server/routes/api/views.js +1 -1
  80. package/server/routes/public.js +4 -9
  81. package/server/server.js +32 -3
  82. package/server/services/actions.js +1 -1
  83. package/server/services/managerClient.js +182 -0
  84. package/server/services/markdown.js +52 -14
  85. package/server/services/permissionRegistry.js +245 -173
  86. package/server/services/pluginInstaller.js +301 -0
  87. package/server/services/plugins.js +117 -10
  88. package/server/services/presetCollections.js +66 -251
  89. package/server/services/renderer.js +99 -0
  90. package/server/services/roles.js +191 -39
  91. package/server/services/users.js +1 -1
  92. package/server/services/views.js +1 -1
  93. package/server/templates/page.html +2 -2
  94. package/plugins/docs/admin/templates/docs.html +0 -69
  95. package/plugins/docs/admin/views/docs.js +0 -276
  96. package/plugins/docs/config.js +0 -8
  97. package/plugins/docs/data/documents/57e003f0-68f2-47dc-9c36-ed4b10ed3deb.json +0 -11
  98. package/plugins/docs/data/folders.json +0 -9
  99. package/plugins/docs/data/templates.json +0 -1
  100. package/plugins/docs/data/versions/57e003f0-68f2-47dc-9c36-ed4b10ed3deb/1.json +0 -5
  101. package/plugins/docs/plugin.js +0 -375
  102. package/plugins/docs/plugin.json +0 -23
  103. package/plugins/form-builder/data/forms/contacts.json +0 -66
  104. package/plugins/form-builder/data/forms/enquiries.json +0 -103
  105. package/plugins/form-builder/data/forms/feedback.json +0 -131
  106. package/plugins/form-builder/data/forms/notes.json +0 -79
  107. package/plugins/form-builder/data/forms/to-do.json +0 -100
  108. package/plugins/form-builder/data/submissions/contacts.json +0 -1
  109. package/plugins/form-builder/data/submissions/enquiries.json +0 -1
  110. package/plugins/form-builder/data/submissions/feedback.json +0 -1
  111. package/plugins/form-builder/data/submissions/notes.json +0 -1
  112. package/plugins/form-builder/data/submissions/to-do.json +0 -1
  113. package/plugins/garage/admin/templates/garage.html +0 -111
  114. package/plugins/garage/admin/views/garage.js +0 -622
  115. package/plugins/garage/collections/garage-vehicles/schema.json +0 -101
  116. package/plugins/garage/config.js +0 -18
  117. package/plugins/garage/data/vehicles.json +0 -70
  118. package/plugins/garage/plugin.js +0 -398
  119. package/plugins/garage/plugin.json +0 -33
  120. package/scripts/seed.js +0 -1996
  121. package/server/services/userTypes.js +0 -227
@@ -299,7 +299,9 @@ Content goes here.
299
299
  <tbody>
300
300
  <tr>
301
301
  <td><code>[card title="..."]...[/card]</code></td>
302
- <td>Styled card; <code>collapsible="true"</code> makes the body toggleable</td>
302
+ <td>Styled card. Supports 6 variants, ~44 gradients and 33 layouts — see the
303
+ <strong>Cards</strong> subsection below.
304
+ </td>
303
305
  </tr>
304
306
  <tr>
305
307
  <td><code>[tabs]...[/tabs]</code></td>
@@ -338,6 +340,530 @@ Content goes here.
338
340
  </tbody>
339
341
  </table>
340
342
 
343
+ <h3>Cards &mdash; variants, gradients &amp; layouts</h3>
344
+ <p>The <code>[card]</code> shortcode is the most configurable component in the system. It has three
345
+ layers you can mix freely: <strong>variant</strong> (the overall visual style), <strong>gradient</strong>
346
+ (colour palette, used with <code>variant="gradient"</code> or any layout that accepts a gradient),
347
+ and <strong>layout</strong> (the internal structure — header/body/footer, image position, sub-tags,
348
+ etc.). Every layout accepts every variant, gradient and universal attribute listed below.</p>
349
+ <pre><code>[card variant="gradient" gradient="ocean" layout="icon-top" icon="star" title="Fast"]
350
+ Body content in **Markdown** is supported.
351
+ [/card]</code></pre>
352
+
353
+ <h4>Variants</h4>
354
+ <table class="table table-sm">
355
+ <thead>
356
+ <tr>
357
+ <th>Variant</th>
358
+ <th>Description</th>
359
+ </tr>
360
+ </thead>
361
+ <tbody>
362
+ <tr>
363
+ <td><code>clean</code></td>
364
+ <td>Flat, minimal chrome &mdash; no border, subtle background</td>
365
+ </tr>
366
+ <tr>
367
+ <td><code>gradient</code></td>
368
+ <td>Coloured gradient background (see Gradients below). Pair with <code>gradient="name"</code>
369
+ </td>
370
+ </tr>
371
+ <tr>
372
+ <td><code>glass</code></td>
373
+ <td>Frosted glass / backdrop-blur effect, translucent background</td>
374
+ </tr>
375
+ <tr>
376
+ <td><code>accent</code></td>
377
+ <td>Primary-colour accent border on the left edge</td>
378
+ </tr>
379
+ <tr>
380
+ <td><code>dark</code></td>
381
+ <td>Dark background with inverted text &mdash; good on light pages</td>
382
+ </tr>
383
+ <tr>
384
+ <td><code>glow</code></td>
385
+ <td>Subtle halo / outer glow effect</td>
386
+ </tr>
387
+ <tr>
388
+ <td><code>primary</code></td>
389
+ <td>Legacy alias &mdash; adds <code>card-primary</code> class for backwards compatibility</td>
390
+ </tr>
391
+ </tbody>
392
+ </table>
393
+
394
+ <h4>Built-in gradients</h4>
395
+ <p>Shipped in <code>public/css/</code> &mdash; available on every install. Default when
396
+ <code>gradient</code> is omitted: <code>indigo</code>.</p>
397
+ <p><code>arctic</code>, <code>aurora</code>, <code>dusk</code>, <code>fire</code>, <code>forest</code>,
398
+ <code>gold</code>, <code>indigo</code>, <code>lagoon</code>, <code>lime</code>,
399
+ <code>midnight</code>, <code>ocean</code>, <code>rose</code>, <code>slate</code>,
400
+ <code>sunset</code></p>
401
+
402
+ <h4>Project-specific gradients</h4>
403
+ <p>Defined in <code>content/custom.css</code> on this site only &mdash; fresh installs will not have
404
+ these unless the CSS is copied over.</p>
405
+ <p><strong>Single-tone:</strong> <code>purple</code>, <code>blue</code>, <code>green</code>,
406
+ <code>night</code></p>
407
+ <p><strong>Theme &middot; light pairs:</strong> <code>ocean-light</code>, <code>forest-light</code>,
408
+ <code>sunset-light</code>, <code>royal-light</code>, <code>lemon-light</code>,
409
+ <code>silver-light</code>, <code>charcoal-light</code>, <code>christmas-light</code>,
410
+ <code>unicorn-light</code>, <code>dreamy-light</code>, <code>grayve-light</code>,
411
+ <code>mint-light</code>, <code>wedding-light</code></p>
412
+ <p><strong>Theme &middot; dark pairs:</strong> <code>ocean-dark</code>, <code>forest-dark</code>,
413
+ <code>sunset-dark</code>, <code>royal-dark</code>, <code>lemon-dark</code>,
414
+ <code>silver-dark</code>, <code>charcoal-dark</code>, <code>christmas-dark</code>,
415
+ <code>unicorn-dark</code>, <code>dreamy-dark</code>, <code>grayve-dark</code>,
416
+ <code>mint-dark</code>, <code>wedding-dark</code></p>
417
+ <p class="text-muted"><small>Gradient names are not validated &mdash; a typo falls through to the
418
+ default background with no warning. Use <code>/test-card-gradients</code> to preview every
419
+ palette.</small></p>
420
+
421
+ <h4>Universal attributes</h4>
422
+ <p>These work on any layout and any variant.</p>
423
+ <table class="table table-sm">
424
+ <thead>
425
+ <tr>
426
+ <th>Attribute</th>
427
+ <th>Values</th>
428
+ <th>Purpose</th>
429
+ </tr>
430
+ </thead>
431
+ <tbody>
432
+ <tr>
433
+ <td><code>title</code></td>
434
+ <td>string</td>
435
+ <td>Card heading (most layouts)</td>
436
+ </tr>
437
+ <tr>
438
+ <td><code>subtitle</code></td>
439
+ <td>string</td>
440
+ <td>Secondary heading (many layouts re-use it as date / role / plan)</td>
441
+ </tr>
442
+ <tr>
443
+ <td><code>icon</code></td>
444
+ <td>icon name</td>
445
+ <td>Domma icon (see Icons view)</td>
446
+ </tr>
447
+ <tr>
448
+ <td><code>footer</code></td>
449
+ <td>string</td>
450
+ <td>Footer text (also used by <code>pricing</code> as the CTA label)</td>
451
+ </tr>
452
+ <tr>
453
+ <td><code>image</code></td>
454
+ <td>URL</td>
455
+ <td>Background image for image / media layouts</td>
456
+ </tr>
457
+ <tr>
458
+ <td><code>collapsible</code></td>
459
+ <td><code>true</code></td>
460
+ <td>Body toggles open/closed via click on the header</td>
461
+ </tr>
462
+ <tr>
463
+ <td><code>hover</code></td>
464
+ <td>boolean flag</td>
465
+ <td>Raises the card on mouse-over</td>
466
+ </tr>
467
+ <tr>
468
+ <td><code>borderless</code></td>
469
+ <td>boolean flag</td>
470
+ <td>Removes the card border</td>
471
+ </tr>
472
+ <tr>
473
+ <td><code>shadow</code></td>
474
+ <td><code>none</code> &middot; <code>md</code> &middot; <code>lg</code></td>
475
+ <td>Drop-shadow depth</td>
476
+ </tr>
477
+ <tr>
478
+ <td><code>rounded</code></td>
479
+ <td><code>none</code> &middot; <code>sm</code> &middot; <code>lg</code> &middot;
480
+ <code>full</code></td>
481
+ <td>Corner radius</td>
482
+ </tr>
483
+ <tr>
484
+ <td><code>padding</code></td>
485
+ <td><code>compact</code> &middot; <code>spacious</code></td>
486
+ <td>Internal spacing</td>
487
+ </tr>
488
+ <tr>
489
+ <td><code>text-align</code></td>
490
+ <td><code>center</code> &middot; <code>right</code></td>
491
+ <td>Body text alignment (default left)</td>
492
+ </tr>
493
+ <tr>
494
+ <td><code>font</code></td>
495
+ <td><code>serif</code> &middot; <code>mono</code></td>
496
+ <td>Override card typeface</td>
497
+ </tr>
498
+ <tr>
499
+ <td><code>font-size</code></td>
500
+ <td><code>sm</code> &middot; <code>lg</code> &middot; <code>xl</code></td>
501
+ <td>Override card body text size</td>
502
+ </tr>
503
+ <tr>
504
+ <td><code>class</code></td>
505
+ <td>string</td>
506
+ <td>Extra CSS classes appended to the root element</td>
507
+ </tr>
508
+ <tr>
509
+ <td><code>id</code></td>
510
+ <td>string</td>
511
+ <td>DOM id (useful for anchor links / dconfig targets)</td>
512
+ </tr>
513
+ </tbody>
514
+ </table>
515
+
516
+ <h4>Layouts</h4>
517
+ <p>Select a layout with <code>layout="name"</code>. If omitted, the card uses a simple body-only
518
+ layout. Layouts marked <em>(needs sub-tags)</em> will render empty without their child tags.</p>
519
+
520
+ <h5>Structural</h5>
521
+ <table class="table table-sm">
522
+ <thead>
523
+ <tr>
524
+ <th>Layout</th>
525
+ <th>Attributes</th>
526
+ <th>Purpose</th>
527
+ </tr>
528
+ </thead>
529
+ <tbody>
530
+ <tr>
531
+ <td><code>basic</code></td>
532
+ <td><code>footer</code></td>
533
+ <td>Body-only card, optional footer</td>
534
+ </tr>
535
+ <tr>
536
+ <td><code>header-body</code></td>
537
+ <td><code>title</code></td>
538
+ <td>Header with title + body</td>
539
+ </tr>
540
+ <tr>
541
+ <td><code>header-body-footer</code></td>
542
+ <td><code>title</code>, <code>footer</code></td>
543
+ <td>Classic three-zone card</td>
544
+ </tr>
545
+ <tr>
546
+ <td><code>no-header-footer</code></td>
547
+ <td><code>footer</code></td>
548
+ <td>Body + footer only</td>
549
+ </tr>
550
+ </tbody>
551
+ </table>
552
+
553
+ <h5>Icon headers</h5>
554
+ <table class="table table-sm">
555
+ <thead>
556
+ <tr>
557
+ <th>Layout</th>
558
+ <th>Attributes</th>
559
+ <th>Purpose</th>
560
+ </tr>
561
+ </thead>
562
+ <tbody>
563
+ <tr>
564
+ <td><code>icon-top</code></td>
565
+ <td><code>icon</code>, <code>title</code>, <code>subtitle</code></td>
566
+ <td>Large centred icon above title &mdash; good for feature grids</td>
567
+ </tr>
568
+ <tr>
569
+ <td><code>icon-inline</code></td>
570
+ <td><code>icon</code>, <code>title</code>, <code>subtitle</code></td>
571
+ <td>Icon sits to the left of the title in the header row</td>
572
+ </tr>
573
+ </tbody>
574
+ </table>
575
+
576
+ <h5>Image</h5>
577
+ <table class="table table-sm">
578
+ <thead>
579
+ <tr>
580
+ <th>Layout</th>
581
+ <th>Attributes</th>
582
+ <th>Purpose</th>
583
+ </tr>
584
+ </thead>
585
+ <tbody>
586
+ <tr>
587
+ <td><code>image-top</code></td>
588
+ <td><code>image</code>, <code>title</code></td>
589
+ <td>Image banner above header + body</td>
590
+ </tr>
591
+ <tr>
592
+ <td><code>image-overlay</code></td>
593
+ <td><code>image</code>, <code>title</code></td>
594
+ <td>Title overlaid on the image with a tint</td>
595
+ </tr>
596
+ <tr>
597
+ <td><code>thumb-left</code></td>
598
+ <td><code>image</code>, <code>title</code></td>
599
+ <td>Square thumbnail on the left, body on the right</td>
600
+ </tr>
601
+ <tr>
602
+ <td><code>thumb-right</code></td>
603
+ <td><code>image</code>, <code>title</code></td>
604
+ <td>Mirror of <code>thumb-left</code></td>
605
+ </tr>
606
+ <tr>
607
+ <td><code>wide-left-image</code></td>
608
+ <td><code>image</code>, <code>title</code>, <code>footer</code></td>
609
+ <td>Horizontal card, wider image strip on the left</td>
610
+ </tr>
611
+ <tr>
612
+ <td><code>full-bg</code></td>
613
+ <td><code>image</code>, <code>title</code></td>
614
+ <td>Full-bleed image backdrop with body text over it</td>
615
+ </tr>
616
+ <tr>
617
+ <td><code>split-half</code></td>
618
+ <td><code>image</code>, <code>gradient</code>, <code>title</code></td>
619
+ <td>Half gradient (or image) on the left, content on the right</td>
620
+ </tr>
621
+ </tbody>
622
+ </table>
623
+
624
+ <h5>Media</h5>
625
+ <table class="table table-sm">
626
+ <thead>
627
+ <tr>
628
+ <th>Layout</th>
629
+ <th>Attributes</th>
630
+ <th>Purpose</th>
631
+ </tr>
632
+ </thead>
633
+ <tbody>
634
+ <tr>
635
+ <td><code>video-media</code></td>
636
+ <td><code>image</code> (poster), <code>duration</code>, <code>title</code></td>
637
+ <td>Video thumbnail with a play button and duration badge</td>
638
+ </tr>
639
+ <tr>
640
+ <td><code>location-map</code></td>
641
+ <td><code>address</code>, <code>title</code></td>
642
+ <td>Placeholder map panel + address block (static &mdash; no live map)</td>
643
+ </tr>
644
+ </tbody>
645
+ </table>
646
+
647
+ <h5>People &amp; social proof</h5>
648
+ <table class="table table-sm">
649
+ <thead>
650
+ <tr>
651
+ <th>Layout</th>
652
+ <th>Attributes</th>
653
+ <th>Purpose</th>
654
+ </tr>
655
+ </thead>
656
+ <tbody>
657
+ <tr>
658
+ <td><code>avatar-profile</code></td>
659
+ <td><code>icon</code>, <code>title</code>, <code>subtitle</code>,
660
+ <code>tags</code> (comma-separated)
661
+ </td>
662
+ <td>Circular avatar + name + role + pill tags &mdash; team / author cards</td>
663
+ </tr>
664
+ <tr>
665
+ <td><code>quote-testimonial</code></td>
666
+ <td><code>title</code> (author), <code>subtitle</code> (role)</td>
667
+ <td>Quotation mark + body quote + author attribution row</td>
668
+ </tr>
669
+ <tr>
670
+ <td><code>rating-review</code></td>
671
+ <td><code>rating</code> (0&ndash;5), <code>title</code>, <code>subtitle</code>,
672
+ <code>verified</code> (flag)
673
+ </td>
674
+ <td>Star rating + review body + reviewer attribution</td>
675
+ </tr>
676
+ </tbody>
677
+ </table>
678
+
679
+ <h5>Metrics &amp; data</h5>
680
+ <table class="table table-sm">
681
+ <thead>
682
+ <tr>
683
+ <th>Layout</th>
684
+ <th>Attributes</th>
685
+ <th>Purpose</th>
686
+ </tr>
687
+ </thead>
688
+ <tbody>
689
+ <tr>
690
+ <td><code>stat-metric</code></td>
691
+ <td><code>title</code> (label), <code>value</code>, <code>delta</code>,
692
+ <code>progress</code> (0&ndash;100)
693
+ </td>
694
+ <td>Big-number KPI tile with delta arrow and optional progress bar</td>
695
+ </tr>
696
+ <tr>
697
+ <td><code>progress-goal</code> <em>(needs sub-tags)</em></td>
698
+ <td><code>title</code>, <code>subtitle</code>, <code>progress</code>; child
699
+ <code>[milestone done]...[/milestone]</code>
700
+ </td>
701
+ <td>Progress bar + milestone checklist</td>
702
+ </tr>
703
+ <tr>
704
+ <td><code>activity-feed</code> <em>(needs sub-tags)</em></td>
705
+ <td><code>title</code>; child
706
+ <code>[activity user="..." action="..." time="..." /]</code>
707
+ </td>
708
+ <td>User activity list with initials avatars and timestamps</td>
709
+ </tr>
710
+ </tbody>
711
+ </table>
712
+
713
+ <h5>Markers &amp; callouts</h5>
714
+ <table class="table table-sm">
715
+ <thead>
716
+ <tr>
717
+ <th>Layout</th>
718
+ <th>Attributes</th>
719
+ <th>Purpose</th>
720
+ </tr>
721
+ </thead>
722
+ <tbody>
723
+ <tr>
724
+ <td><code>callout</code></td>
725
+ <td><code>callout-type</code> (<code>info</code>/<code>warn</code>/<code>success</code>/<code>error</code>),
726
+ <code>icon</code>, <code>title</code>
727
+ </td>
728
+ <td>Coloured inline notice / tip box</td>
729
+ </tr>
730
+ <tr>
731
+ <td><code>step-numbered</code></td>
732
+ <td><code>step</code> (number), <code>title</code>, <code>gradient</code></td>
733
+ <td>Numbered step for tutorials / walkthroughs</td>
734
+ </tr>
735
+ <tr>
736
+ <td><code>corner-badge</code></td>
737
+ <td><code>badge</code> (label), <code>icon</code>, <code>title</code></td>
738
+ <td>Card with a ribbon-style badge in the top-right corner</td>
739
+ </tr>
740
+ <tr>
741
+ <td><code>badge-band</code></td>
742
+ <td><code>badge</code>, <code>icon</code>, <code>gradient</code>, <code>title</code></td>
743
+ <td>Full-width coloured band across the top with a label and icon</td>
744
+ </tr>
745
+ <tr>
746
+ <td><code>tag-cloud</code></td>
747
+ <td><code>title</code>, <code>tags</code> (comma-separated)</td>
748
+ <td>Coloured pill list &mdash; topic tags, skills, categories</td>
749
+ </tr>
750
+ <tr>
751
+ <td><code>timeline-entry</code></td>
752
+ <td><code>title</code>, <code>subtitle</code> (date), <code>badge</code> (tag)</td>
753
+ <td>Single dot-on-line timeline entry &mdash; stack several for a history list</td>
754
+ </tr>
755
+ </tbody>
756
+ </table>
757
+
758
+ <h5>Commerce &amp; comparison</h5>
759
+ <table class="table table-sm">
760
+ <thead>
761
+ <tr>
762
+ <th>Layout</th>
763
+ <th>Attributes &amp; sub-tags</th>
764
+ <th>Purpose</th>
765
+ </tr>
766
+ </thead>
767
+ <tbody>
768
+ <tr>
769
+ <td><code>pricing</code> <em>(needs sub-tags)</em></td>
770
+ <td><code>title</code>, <code>price</code>, <code>period</code>, <code>gradient</code>,
771
+ <code>footer</code> (CTA label); child <code>[feature]...[/feature]</code>
772
+ </td>
773
+ <td>Pricing tier card with gradient header, feature list and CTA link</td>
774
+ </tr>
775
+ <tr>
776
+ <td><code>feature-comparison</code> <em>(needs sub-tags)</em></td>
777
+ <td><code>title</code>, <code>subtitle</code> (plan), <code>gradient</code>; child
778
+ <code>[feature]text[/feature]</code> or <code>[feature excluded]text[/feature]</code>
779
+ </td>
780
+ <td>Plan comparison rows with tick / cross marks</td>
781
+ </tr>
782
+ <tr>
783
+ <td><code>before-after</code> <em>(needs sub-tags)</em></td>
784
+ <td><code>title</code>; children
785
+ <code>[before]item &middot; item[/before]</code> and
786
+ <code>[after]item &middot; item[/after]</code> (items split on <code>&middot;</code> or
787
+ newline)
788
+ </td>
789
+ <td>Two-column before/after comparison list</td>
790
+ </tr>
791
+ </tbody>
792
+ </table>
793
+
794
+ <h5>Special &amp; utility</h5>
795
+ <table class="table table-sm">
796
+ <thead>
797
+ <tr>
798
+ <th>Layout</th>
799
+ <th>Attributes</th>
800
+ <th>Purpose</th>
801
+ </tr>
802
+ </thead>
803
+ <tbody>
804
+ <tr>
805
+ <td><code>glass-gradient-border</code></td>
806
+ <td><code>title</code></td>
807
+ <td>Frosted glass card with a gradient border ring. <strong>Note:</strong> this layout
808
+ bypasses <code>cardVariantClasses</code>, so universal variant / gradient / shadow
809
+ attributes do not apply.
810
+ </td>
811
+ </tr>
812
+ <tr>
813
+ <td><code>code-snippet</code></td>
814
+ <td><code>lang</code> (label); body is rendered as escaped code</td>
815
+ <td>Code block with language label header</td>
816
+ </tr>
817
+ <tr>
818
+ <td><code>file-document</code></td>
819
+ <td><code>filename</code>, <code>filesize</code>, <code>filetype</code>, <code>title</code>
820
+ </td>
821
+ <td>File attachment row with type icon and download link (link href is placeholder)</td>
822
+ </tr>
823
+ </tbody>
824
+ </table>
825
+
826
+ <h4>Sub-tag reference</h4>
827
+ <p>These are child tags accepted by specific layouts &mdash; they are not shortcodes in their own right
828
+ and only render inside a matching parent card.</p>
829
+ <table class="table table-sm">
830
+ <thead>
831
+ <tr>
832
+ <th>Sub-tag</th>
833
+ <th>Parent layout</th>
834
+ <th>Attributes</th>
835
+ </tr>
836
+ </thead>
837
+ <tbody>
838
+ <tr>
839
+ <td><code>[feature]text[/feature]</code></td>
840
+ <td><code>pricing</code>, <code>feature-comparison</code></td>
841
+ <td><code>excluded</code> (flag, comparison only) &mdash; renders as a cross instead of a tick
842
+ </td>
843
+ </tr>
844
+ <tr>
845
+ <td><code>[before]a &middot; b &middot; c[/before]</code></td>
846
+ <td><code>before-after</code></td>
847
+ <td>Items split on <code>&middot;</code> or newline</td>
848
+ </tr>
849
+ <tr>
850
+ <td><code>[after]a &middot; b &middot; c[/after]</code></td>
851
+ <td><code>before-after</code></td>
852
+ <td>Items split on <code>&middot;</code> or newline</td>
853
+ </tr>
854
+ <tr>
855
+ <td><code>[activity user="..." action="..." time="..." /]</code></td>
856
+ <td><code>activity-feed</code></td>
857
+ <td>Self-closing; one row per tag</td>
858
+ </tr>
859
+ <tr>
860
+ <td><code>[milestone done]text[/milestone]</code></td>
861
+ <td><code>progress-goal</code></td>
862
+ <td><code>done</code> (flag) &mdash; filled dot if present, hollow otherwise</td>
863
+ </tr>
864
+ </tbody>
865
+ </table>
866
+
341
867
  <h3>Content</h3>
342
868
  <table class="table table-sm">
343
869
  <thead>
@@ -362,7 +888,90 @@ Content goes here.
362
888
  </tr>
363
889
  <tr>
364
890
  <td><code>[collection slug="..." display="table" /]</code></td>
365
- <td>Renders collection entries inline (table, cards, or list)</td>
891
+ <td>Renders collection entries inline (table, cards, list, accordion, or block)</td>
892
+ </tr>
893
+ </tbody>
894
+ </table>
895
+
896
+ <h4>Collection attributes</h4>
897
+ <table class="table table-sm">
898
+ <thead>
899
+ <tr>
900
+ <th>Attribute</th>
901
+ <th>Values</th>
902
+ <th>Purpose</th>
903
+ </tr>
904
+ </thead>
905
+ <tbody>
906
+ <tr>
907
+ <td><code>slug</code></td>
908
+ <td>collection slug</td>
909
+ <td>Required. Which collection to render.</td>
910
+ </tr>
911
+ <tr>
912
+ <td><code>display</code></td>
913
+ <td><code>table</code> &middot; <code>cards</code> &middot; <code>list</code> &middot;
914
+ <code>accordion</code> &middot; <code>block</code></td>
915
+ <td>How to render each entry. Default <code>table</code>.</td>
916
+ </tr>
917
+ <tr>
918
+ <td><code>block</code></td>
919
+ <td>block template name</td>
920
+ <td>Required when <code>display="block"</code>. Names a template in
921
+ <code>content/blocks/&lt;name&gt;.html</code> whose
922
+ <code>{{field}}</code> placeholders get substituted per entry.
923
+ </td>
924
+ </tr>
925
+ <tr>
926
+ <td><code>cols</code></td>
927
+ <td><code>2</code> &middot; <code>3</code> &middot; <code>4</code> &middot; <code>5</code>
928
+ &middot; <code>6</code></td>
929
+ <td>Grid column count when <code>display="block"</code>.</td>
930
+ </tr>
931
+ <tr>
932
+ <td><code>where</code></td>
933
+ <td><code>field=value</code> or<br><code>f1=v1,f2=v2</code></td>
934
+ <td>Row filter (simple equality only, AND'd across comma-separated predicates). Example:
935
+ <code>where="tab=developers"</code> or
936
+ <code>where="tier=free,featured=true"</code>. No OR, no comparison operators &mdash;
937
+ use a saved View for anything more complex.
938
+ </td>
939
+ </tr>
940
+ <tr>
941
+ <td><code>sort</code></td>
942
+ <td>field name or <code>createdAt</code></td>
943
+ <td>Sort field. Default <code>createdAt</code>.</td>
944
+ </tr>
945
+ <tr>
946
+ <td><code>order</code></td>
947
+ <td><code>asc</code> &middot; <code>desc</code></td>
948
+ <td>Sort direction. Default <code>desc</code>.</td>
949
+ </tr>
950
+ <tr>
951
+ <td><code>limit</code></td>
952
+ <td>integer</td>
953
+ <td>Maximum number of entries to render. 0 or omitted = all.</td>
954
+ </tr>
955
+ <tr>
956
+ <td><code>fields</code></td>
957
+ <td>comma-separated field names</td>
958
+ <td>Column filter &mdash; only these fields are shown (table/cards/list displays only).
959
+ </td>
960
+ </tr>
961
+ <tr>
962
+ <td><code>title-field</code></td>
963
+ <td>field name</td>
964
+ <td>Which field to use as the entry title (cards/accordion displays).</td>
965
+ </tr>
966
+ <tr>
967
+ <td><code>empty</code></td>
968
+ <td>string</td>
969
+ <td>Message shown when the filter matches no entries.</td>
970
+ </tr>
971
+ <tr>
972
+ <td><code>cta</code></td>
973
+ <td>action slug</td>
974
+ <td>Attach a CMS Action button to each rendered entry. See CTA attributes below.</td>
366
975
  </tr>
367
976
  </tbody>
368
977
  </table>
@@ -10,10 +10,11 @@
10
10
  <div class="tab-content">
11
11
 
12
12
  <div class="tab-panel active" id="panel-presets">
13
- <div class="view-actions mb-4">
14
- <p class="text-muted">Layout presets define which structural elements appear on pages using that layout. Assign
15
- a layout to each page via the page editor.</p>
16
- <button id="save-layouts-btn" class="btn btn-primary"><span data-icon="save"></span> Save Presets</button>
13
+ <div class="view-actions mb-4"
14
+ style="display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;">
15
+ <p class="text-muted" style="margin:0;">Layout presets define the structure, width, and background of pages.
16
+ Assign a layout to each page via the page editor.</p>
17
+ <button id="create-layout-btn" class="btn btn-primary"><span data-icon="plus"></span> New Layout</button>
17
18
  </div>
18
19
  <div id="presets-grid" class="presets-grid"></div>
19
20
  </div>