@hegemonart/get-design-done 1.16.0 → 1.19.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 (58) hide show
  1. package/.claude-plugin/marketplace.json +12 -4
  2. package/.claude-plugin/plugin.json +22 -4
  3. package/CHANGELOG.md +111 -0
  4. package/README.md +27 -2
  5. package/agents/design-auditor.md +65 -1
  6. package/agents/design-context-builder.md +6 -1
  7. package/agents/design-doc-writer.md +21 -0
  8. package/agents/design-executor.md +22 -4
  9. package/agents/design-pattern-mapper.md +62 -0
  10. package/agents/design-phase-researcher.md +1 -1
  11. package/agents/motion-mapper.md +74 -9
  12. package/agents/token-mapper.md +8 -0
  13. package/package.json +16 -2
  14. package/reference/components/README.md +27 -23
  15. package/reference/components/alert.md +198 -0
  16. package/reference/components/badge.md +202 -0
  17. package/reference/components/breadcrumbs.md +198 -0
  18. package/reference/components/chip.md +209 -0
  19. package/reference/components/command-palette.md +228 -0
  20. package/reference/components/date-picker.md +227 -0
  21. package/reference/components/file-upload.md +219 -0
  22. package/reference/components/list.md +217 -0
  23. package/reference/components/menu.md +212 -0
  24. package/reference/components/navbar.md +211 -0
  25. package/reference/components/pagination.md +205 -0
  26. package/reference/components/progress.md +210 -0
  27. package/reference/components/rich-text-editor.md +226 -0
  28. package/reference/components/sidebar.md +211 -0
  29. package/reference/components/skeleton.md +197 -0
  30. package/reference/components/slider.md +208 -0
  31. package/reference/components/stepper.md +220 -0
  32. package/reference/components/table.md +229 -0
  33. package/reference/components/toast.md +200 -0
  34. package/reference/components/tree.md +225 -0
  35. package/reference/css-grid-layout.md +835 -0
  36. package/reference/data-visualization.md +333 -0
  37. package/reference/external/NOTICE.hyperframes +28 -0
  38. package/reference/form-patterns.md +245 -0
  39. package/reference/image-optimization.md +582 -0
  40. package/reference/information-architecture.md +255 -0
  41. package/reference/motion-advanced.md +754 -0
  42. package/reference/motion-easings.md +381 -0
  43. package/reference/motion-interpolate.md +282 -0
  44. package/reference/motion-spring.md +234 -0
  45. package/reference/motion-transition-taxonomy.md +155 -0
  46. package/reference/motion.md +20 -0
  47. package/reference/onboarding-progressive-disclosure.md +250 -0
  48. package/reference/output-contracts/motion-map.schema.json +135 -0
  49. package/reference/platforms.md +346 -0
  50. package/reference/registry.json +445 -220
  51. package/reference/registry.schema.json +4 -0
  52. package/reference/rtl-cjk-cultural.md +353 -0
  53. package/reference/user-research.md +360 -0
  54. package/reference/variable-fonts-loading.md +532 -0
  55. package/scripts/lib/easings.cjs +280 -0
  56. package/scripts/lib/parse-contract.cjs +220 -0
  57. package/scripts/lib/spring.cjs +160 -0
  58. package/scripts/tests/test-motion-provenance.sh +64 -0
@@ -0,0 +1,835 @@
1
+ <!-- Source: Phase 18 — get-design-done -->
2
+
3
+ # CSS Grid Layout — Advanced Craft Reference
4
+
5
+ ## 1. CSS Grid Template Patterns
6
+
7
+ ### Holy Grail Layout
8
+
9
+ Classic five-area layout: header, nav, main, aside, footer.
10
+
11
+ ```css
12
+ .holy-grail {
13
+ display: grid;
14
+ grid-template-areas:
15
+ "header header header"
16
+ "nav main aside"
17
+ "footer footer footer";
18
+ grid-template-columns: 200px 1fr 200px;
19
+ grid-template-rows: auto 1fr auto;
20
+ min-height: 100dvh;
21
+ }
22
+
23
+ .header { grid-area: header; }
24
+ .nav { grid-area: nav; }
25
+ .main { grid-area: main; }
26
+ .aside { grid-area: aside; }
27
+ .footer { grid-area: footer; }
28
+ ```
29
+
30
+ Responsive collapse — stack columns below 768px:
31
+
32
+ ```css
33
+ @media (max-width: 768px) {
34
+ .holy-grail {
35
+ grid-template-areas:
36
+ "header"
37
+ "nav"
38
+ "main"
39
+ "aside"
40
+ "footer";
41
+ grid-template-columns: 1fr;
42
+ grid-template-rows: auto;
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Bento Grid Layout
48
+
49
+ Dashboard card mosaic where cards span varied tracks.
50
+
51
+ ```css
52
+ .bento {
53
+ display: grid;
54
+ grid-template-columns: repeat(4, 1fr);
55
+ grid-template-rows: repeat(3, 200px);
56
+ gap: 16px;
57
+ }
58
+
59
+ /* Feature card — spans 2 cols × 2 rows */
60
+ .bento__card--featured {
61
+ grid-column: span 2;
62
+ grid-row: span 2;
63
+ }
64
+
65
+ /* Wide card — full width */
66
+ .bento__card--wide {
67
+ grid-column: 1 / -1;
68
+ }
69
+
70
+ /* Tall card */
71
+ .bento__card--tall {
72
+ grid-row: span 2;
73
+ }
74
+ ```
75
+
76
+ Auto-fit bento with minimum card size:
77
+
78
+ ```css
79
+ .bento-auto {
80
+ display: grid;
81
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
82
+ grid-auto-rows: minmax(180px, auto);
83
+ gap: 16px;
84
+ }
85
+ ```
86
+
87
+ ### Masonry via `grid-template-rows: masonry`
88
+
89
+ Native CSS masonry — items pack into shortest column, no JavaScript.
90
+
91
+ ```css
92
+ .masonry {
93
+ display: grid;
94
+ grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
95
+ grid-template-rows: masonry; /* native masonry axis */
96
+ gap: 16px;
97
+ }
98
+ ```
99
+
100
+ **Browser support (2025):** Firefox (behind flag), Safari 18+ (partial). Use `@supports` for progressive enhancement:
101
+
102
+ ```css
103
+ @supports (grid-template-rows: masonry) {
104
+ .masonry {
105
+ grid-template-rows: masonry;
106
+ }
107
+ }
108
+
109
+ /* Fallback: multi-column layout */
110
+ @supports not (grid-template-rows: masonry) {
111
+ .masonry {
112
+ column-count: 3;
113
+ column-gap: 16px;
114
+ }
115
+ .masonry > * {
116
+ break-inside: avoid;
117
+ margin-bottom: 16px;
118
+ }
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 2. Subgrid
125
+
126
+ ### What It Is
127
+
128
+ `subgrid` lets a nested grid inherit track definitions from its parent grid. Without subgrid, inner grids define their own tracks independently — card headers and footers cannot align across sibling cards.
129
+
130
+ ```css
131
+ /* Parent defines the tracks */
132
+ .card-grid {
133
+ display: grid;
134
+ grid-template-columns: repeat(3, 1fr);
135
+ grid-template-rows: auto 1fr auto; /* header, body, footer */
136
+ gap: 24px;
137
+ }
138
+
139
+ /* Each card participates in parent row tracks */
140
+ .card {
141
+ display: grid;
142
+ grid-row: span 3;
143
+ grid-template-rows: subgrid; /* inherit parent's 3 row tracks */
144
+ }
145
+
146
+ .card__header { grid-row: 1; }
147
+ .card__body { grid-row: 2; }
148
+ .card__footer { grid-row: 3; }
149
+ ```
150
+
151
+ ### When to Use Subgrid
152
+
153
+ - Card grids where headers, body areas, and CTAs must align across columns
154
+ - Form layouts with labels and inputs spanning parent tracks
155
+ - Table-like layouts built from components
156
+
157
+ ### Browser Support
158
+
159
+ Chrome 117+, Firefox 71+, Safari 16+. Baseline widely available as of 2024.
160
+
161
+ ```css
162
+ /* Safe to use without @supports for modern browsers */
163
+ /* Fallback pattern for older targets */
164
+ @supports not (grid-template-rows: subgrid) {
165
+ .card {
166
+ display: flex;
167
+ flex-direction: column;
168
+ }
169
+ .card__body {
170
+ flex: 1; /* push footer down */
171
+ }
172
+ }
173
+ ```
174
+
175
+ ---
176
+
177
+ ## 3. Container Queries
178
+
179
+ ### Core Syntax
180
+
181
+ Query an element's own container rather than the viewport.
182
+
183
+ ```css
184
+ /* 1. Define the container */
185
+ .card-wrapper {
186
+ container-type: inline-size;
187
+ container-name: card;
188
+ }
189
+
190
+ /* 2. Query inside */
191
+ @container card (min-width: 400px) {
192
+ .card {
193
+ display: grid;
194
+ grid-template-columns: 120px 1fr;
195
+ }
196
+ }
197
+
198
+ @container card (min-width: 600px) {
199
+ .card__title {
200
+ font-size: 1.5rem;
201
+ }
202
+ }
203
+ ```
204
+
205
+ ### `container-type` Values
206
+
207
+ | Value | Queries |
208
+ |---|---|
209
+ | `inline-size` | Width queries only (most common) |
210
+ | `size` | Width and height queries |
211
+ | `normal` | No containment (default) |
212
+
213
+ ### `container-name`
214
+
215
+ Named containers allow nested or specific targeting:
216
+
217
+ ```css
218
+ .sidebar {
219
+ container-type: inline-size;
220
+ container-name: sidebar;
221
+ }
222
+
223
+ .main-content {
224
+ container-type: inline-size;
225
+ container-name: main;
226
+ }
227
+
228
+ @container sidebar (max-width: 300px) {
229
+ .widget { font-size: 0.875rem; }
230
+ }
231
+
232
+ @container main (min-width: 700px) {
233
+ .widget { font-size: 1rem; }
234
+ }
235
+ ```
236
+
237
+ ### Practical Reusable Component Pattern
238
+
239
+ ```css
240
+ /* Component owns its responsiveness */
241
+ .media-card {
242
+ container-type: inline-size;
243
+ }
244
+
245
+ /* Stacked by default */
246
+ .media-card__inner {
247
+ display: flex;
248
+ flex-direction: column;
249
+ }
250
+
251
+ /* Side-by-side when container is wide enough */
252
+ @container (min-width: 480px) {
253
+ .media-card__inner {
254
+ flex-direction: row;
255
+ }
256
+
257
+ .media-card__image {
258
+ width: 40%;
259
+ flex-shrink: 0;
260
+ }
261
+ }
262
+ ```
263
+
264
+ **Browser support:** Chrome 105+, Firefox 110+, Safari 16+. Baseline widely available.
265
+
266
+ ---
267
+
268
+ ## 4. Fluid Typography with `clamp()`
269
+
270
+ ### The Utopia.fyi Formula
271
+
272
+ ```
273
+ font-size: clamp(min, preferred, max)
274
+ ```
275
+
276
+ Where preferred is a linear interpolation between viewport sizes:
277
+
278
+ ```
279
+ preferred = V × 1vw + R × 1rem
280
+ ```
281
+
282
+ - `V` = viewport coefficient (controls how fast size scales)
283
+ - `R` = root-relative offset (base size contribution)
284
+
285
+ ### Deriving V and R
286
+
287
+ Given: min font size `f_min` at viewport `v_min`, max font size `f_max` at viewport `v_max` (all in px):
288
+
289
+ ```
290
+ V = (f_max - f_min) / (v_max - v_min) × 100
291
+ R = f_min - V × (v_min / 100) (convert back to rem ÷ 16)
292
+ ```
293
+
294
+ ### Real Examples
295
+
296
+ **Body text — 16px at 320px viewport → 20px at 1440px:**
297
+
298
+ ```
299
+ V = (20 - 16) / (1440 - 320) × 100 = 0.357
300
+ R = 16 - 0.357 × (320/100) = 16 - 1.143 = 14.857 → ÷16 = 0.929rem
301
+ ```
302
+
303
+ ```css
304
+ body {
305
+ font-size: clamp(1rem, 0.929rem + 0.357vw, 1.25rem);
306
+ }
307
+ ```
308
+
309
+ **Display heading — 32px at 320px → 72px at 1440px:**
310
+
311
+ ```css
312
+ h1 {
313
+ font-size: clamp(2rem, 0.286rem + 5.357vw, 4.5rem);
314
+ }
315
+ ```
316
+
317
+ **Practical scale using clamp:**
318
+
319
+ ```css
320
+ :root {
321
+ --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
322
+ --text-sm: clamp(0.875rem, 0.825rem + 0.25vw, 1rem);
323
+ --text-base: clamp(1rem, 0.929rem + 0.357vw, 1.25rem);
324
+ --text-lg: clamp(1.125rem, 1rem + 0.625vw, 1.5rem);
325
+ --text-xl: clamp(1.25rem, 1rem + 1.25vw, 2rem);
326
+ --text-2xl: clamp(1.5rem, 1rem + 2.5vw, 2.5rem);
327
+ --text-3xl: clamp(1.875rem, 1rem + 4.375vw, 3.5rem);
328
+ --text-4xl: clamp(2.25rem, 0.75rem + 7.5vw, 5rem);
329
+ }
330
+ ```
331
+
332
+ **Fluid spacing with clamp:**
333
+
334
+ ```css
335
+ :root {
336
+ --space-s: clamp(0.75rem, 0.25vw + 0.68rem, 1rem);
337
+ --space-m: clamp(1rem, 0.5vw + 0.87rem, 1.5rem);
338
+ --space-l: clamp(1.5rem, 1vw + 1.25rem, 2.5rem);
339
+ --space-xl: clamp(2rem, 2vw + 1.5rem, 4rem);
340
+ }
341
+ ```
342
+
343
+ ---
344
+
345
+ ## 5. Intrinsic Sizing in Grid Track Definitions
346
+
347
+ ### Keywords
348
+
349
+ | Keyword | Behavior |
350
+ |---|---|
351
+ | `min-content` | Shrinks to smallest content size (longest unbreakable word) |
352
+ | `max-content` | Grows to fit all content on one line |
353
+ | `fit-content(N)` | Like `max-content` but clamps at `N` |
354
+ | `auto` | Distributes remaining space, respects min/max |
355
+ | `fr` | Fractional remaining space after fixed tracks |
356
+
357
+ ### Usage in Grid
358
+
359
+ ```css
360
+ .layout {
361
+ display: grid;
362
+
363
+ /* Label column: as wide as needed, content column: takes rest */
364
+ grid-template-columns: max-content 1fr;
365
+
366
+ /* Sidebar: shrinks to content, main: fills */
367
+ grid-template-columns: min-content 1fr;
368
+
369
+ /* Tag list: constrained but wraps if narrow */
370
+ grid-template-columns: fit-content(200px) 1fr;
371
+ }
372
+ ```
373
+
374
+ ### Auto-sizing Rows
375
+
376
+ ```css
377
+ .card-grid {
378
+ grid-auto-rows: minmax(min-content, auto);
379
+ /* Each row is at least as tall as its shortest content,
380
+ and grows to fit the tallest cell */
381
+ }
382
+ ```
383
+
384
+ ### `minmax()` Patterns
385
+
386
+ ```css
387
+ /* Never narrower than 250px, fills available space */
388
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
389
+
390
+ /* Text column: at least 45 characters wide */
391
+ grid-template-columns: minmax(45ch, 1fr) 300px;
392
+ ```
393
+
394
+ ---
395
+
396
+ ## 6. Logical Properties
397
+
398
+ ### Why They Matter
399
+
400
+ Physical properties (`margin-left`, `padding-top`) break when:
401
+ - Language direction is RTL (Arabic, Hebrew, Farsi)
402
+ - Writing mode is vertical (Japanese, Chinese traditional)
403
+
404
+ Logical properties map to flow-relative directions.
405
+
406
+ ### Property Mapping
407
+
408
+ | Physical | Logical |
409
+ |---|---|
410
+ | `margin-left` | `margin-inline-start` |
411
+ | `margin-right` | `margin-inline-end` |
412
+ | `margin-top` | `margin-block-start` |
413
+ | `margin-bottom` | `margin-block-end` |
414
+ | `padding-left/right` | `padding-inline` |
415
+ | `padding-top/bottom` | `padding-block` |
416
+ | `width` | `inline-size` |
417
+ | `height` | `block-size` |
418
+ | `top` | `inset-block-start` |
419
+ | `left` | `inset-inline-start` |
420
+ | `border-left` | `border-inline-start` |
421
+ | `text-align: left` | `text-align: start` |
422
+
423
+ ### Real Usage
424
+
425
+ ```css
426
+ /* Navigation link — respects RTL padding */
427
+ .nav__link {
428
+ padding-inline: 1rem;
429
+ padding-block: 0.5rem;
430
+ border-inline-start: 3px solid transparent;
431
+ }
432
+
433
+ .nav__link:hover {
434
+ border-inline-start-color: var(--color-accent);
435
+ }
436
+
437
+ /* Card — flow-safe spacing */
438
+ .card {
439
+ margin-block-end: 1.5rem;
440
+ padding-inline: 1.5rem;
441
+ padding-block: 1rem;
442
+ }
443
+
444
+ /* Positioned element — flow-relative */
445
+ .tooltip {
446
+ position: absolute;
447
+ inset-block-start: 100%;
448
+ inset-inline-start: 0;
449
+ }
450
+
451
+ /* Shorthand: all four insets */
452
+ .overlay {
453
+ inset: 0; /* shorthand for top/right/bottom/left: 0 */
454
+ }
455
+ ```
456
+
457
+ **Browser support:** All modern browsers. IE11 does not support logical properties.
458
+
459
+ ---
460
+
461
+ ## 7. Safe Area Insets
462
+
463
+ ### Purpose
464
+
465
+ On devices with notches, home bars, rounded corners, or camera cutouts, content can be hidden behind the system UI. CSS environment variables expose the safe zone.
466
+
467
+ ### Variables
468
+
469
+ | Variable | Maps to |
470
+ |---|---|
471
+ | `env(safe-area-inset-top)` | Top notch / status bar |
472
+ | `env(safe-area-inset-right)` | Right edge |
473
+ | `env(safe-area-inset-bottom)` | Home indicator / bottom bar |
474
+ | `env(safe-area-inset-left)` | Left edge |
475
+
476
+ ### Requirements
477
+
478
+ The viewport meta tag must include `viewport-fit=cover`:
479
+
480
+ ```html
481
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
482
+ ```
483
+
484
+ ### Usage Patterns
485
+
486
+ ```css
487
+ /* Fixed header — clear the notch */
488
+ .app-header {
489
+ position: fixed;
490
+ top: 0;
491
+ inset-inline: 0;
492
+ padding-block-start: env(safe-area-inset-top);
493
+ height: calc(60px + env(safe-area-inset-top));
494
+ }
495
+
496
+ /* Fixed bottom nav — clear home indicator */
497
+ .bottom-nav {
498
+ position: fixed;
499
+ bottom: 0;
500
+ inset-inline: 0;
501
+ padding-block-end: env(safe-area-inset-bottom);
502
+ }
503
+
504
+ /* Scrollable content — offset for fixed header/footer */
505
+ .scroll-content {
506
+ padding-block-start: calc(60px + env(safe-area-inset-top));
507
+ padding-block-end: calc(56px + env(safe-area-inset-bottom));
508
+ }
509
+
510
+ /* Fallback with max() for older browsers */
511
+ .app-header {
512
+ padding-top: max(env(safe-area-inset-top), 16px);
513
+ }
514
+ ```
515
+
516
+ **Browser support:** Safari 11.1+, Chrome 69+, Firefox 110+.
517
+
518
+ ---
519
+
520
+ ## 8. `aspect-ratio` with `object-fit` and `object-position`
521
+
522
+ ### `aspect-ratio`
523
+
524
+ Forces an element to maintain a width-to-height ratio:
525
+
526
+ ```css
527
+ .card__image {
528
+ aspect-ratio: 16 / 9;
529
+ width: 100%;
530
+ }
531
+
532
+ .avatar {
533
+ aspect-ratio: 1; /* square */
534
+ width: 48px;
535
+ }
536
+
537
+ .portrait {
538
+ aspect-ratio: 3 / 4;
539
+ }
540
+ ```
541
+
542
+ ### `object-fit`
543
+
544
+ Controls how replaced content (img, video) fills its box:
545
+
546
+ | Value | Behavior |
547
+ |---|---|
548
+ | `cover` | Scales to fill, may crop. Maintains aspect ratio. |
549
+ | `contain` | Scales to fit inside. Letterboxed if needed. |
550
+ | `fill` | Stretches to fill exactly. Distorts if different ratio. |
551
+ | `none` | No resizing. May overflow or underflow. |
552
+ | `scale-down` | Picks smaller of `none` or `contain`. |
553
+
554
+ ```css
555
+ /* Hero image — always fills, crops if needed */
556
+ .hero__img {
557
+ width: 100%;
558
+ aspect-ratio: 21 / 9;
559
+ object-fit: cover;
560
+ object-position: center 30%; /* focus on upper portion */
561
+ }
562
+
563
+ /* Thumbnail — fits inside, no crop */
564
+ .thumb {
565
+ width: 80px;
566
+ height: 80px;
567
+ object-fit: contain;
568
+ background: var(--color-surface-muted); /* fills letterbox area */
569
+ }
570
+
571
+ /* Product shot — keep top of image in frame */
572
+ .product__img {
573
+ aspect-ratio: 1;
574
+ object-fit: cover;
575
+ object-position: top center;
576
+ }
577
+ ```
578
+
579
+ ### `object-position`
580
+
581
+ Same syntax as `background-position`. Positions the content within the box:
582
+
583
+ ```css
584
+ /* Keywords */
585
+ object-position: center center; /* default */
586
+ object-position: top right;
587
+ object-position: bottom left;
588
+
589
+ /* Length / percentage */
590
+ object-position: 50% 20%; /* horizontal vertical */
591
+ object-position: 0 0; /* top-left corner */
592
+ ```
593
+
594
+ ---
595
+
596
+ ## 9. Alignment Shorthands: `place-items`, `place-content`, `place-self`
597
+
598
+ These are shorthands combining `align-*` and `justify-*`.
599
+
600
+ ### `place-items` (on container)
601
+
602
+ Sets both `align-items` and `justify-items`:
603
+
604
+ ```css
605
+ /* Center all items in their grid cell */
606
+ .grid {
607
+ display: grid;
608
+ place-items: center; /* align-items: center; justify-items: center */
609
+ }
610
+
611
+ /* Different values: align-items / justify-items */
612
+ .grid {
613
+ place-items: start end;
614
+ }
615
+ ```
616
+
617
+ ### `place-content` (on container)
618
+
619
+ Sets both `align-content` and `justify-content`:
620
+
621
+ ```css
622
+ /* Full centering of the grid tracks within the container */
623
+ .grid {
624
+ display: grid;
625
+ place-content: center;
626
+
627
+ /* Or with different values */
628
+ place-content: space-between center;
629
+ }
630
+ ```
631
+
632
+ ### `place-self` (on grid/flex child)
633
+
634
+ Sets both `align-self` and `justify-self` for one item:
635
+
636
+ ```css
637
+ .modal {
638
+ display: grid;
639
+ place-items: center; /* centers all children */
640
+ }
641
+
642
+ .modal__close-btn {
643
+ place-self: start end; /* override: top-right corner */
644
+ }
645
+ ```
646
+
647
+ ### Centering Cheat Sheet
648
+
649
+ ```css
650
+ /* Center a single element, any size */
651
+ .parent {
652
+ display: grid;
653
+ place-items: center;
654
+ }
655
+
656
+ /* Center flex children */
657
+ .flex-parent {
658
+ display: flex;
659
+ place-content: center;
660
+ gap: 1rem;
661
+ }
662
+ ```
663
+
664
+ ---
665
+
666
+ ## 10. `grid-auto-flow: dense`
667
+
668
+ ### What It Does
669
+
670
+ When grid items have different sizes (some spanning multiple columns), gaps appear when larger items cannot fit in the current row. `dense` backfills those gaps with smaller items, ignoring source order.
671
+
672
+ ```css
673
+ .gallery {
674
+ display: grid;
675
+ grid-template-columns: repeat(4, 1fr);
676
+ grid-auto-rows: 200px;
677
+ gap: 16px;
678
+ grid-auto-flow: dense; /* fills gaps with smaller items */
679
+ }
680
+
681
+ .gallery__item--wide { grid-column: span 2; }
682
+ .gallery__item--tall { grid-row: span 2; }
683
+ .gallery__item--large { grid-column: span 2; grid-row: span 2; }
684
+ ```
685
+
686
+ ### Trade-off
687
+
688
+ `dense` reorders items visually away from DOM order. This breaks keyboard navigation and screen reader traversal for interactive content. Use only for purely visual galleries where tab order is not meaningful.
689
+
690
+ ```css
691
+ /* Safe: purely decorative image mosaic */
692
+ .photo-mosaic {
693
+ grid-auto-flow: dense;
694
+ }
695
+
696
+ /* Unsafe: card grid with links or buttons */
697
+ /* Do NOT use dense here — tab order will seem random */
698
+ .card-grid {
699
+ grid-auto-flow: row; /* default — preserve order */
700
+ }
701
+ ```
702
+
703
+ ---
704
+
705
+ ## 11. Anchor Positioning
706
+
707
+ ### What It Is
708
+
709
+ CSS Anchor Positioning (`anchor()`, `position-anchor`) allows an absolutely positioned element to tether its position to a named anchor element — without JavaScript. Replaces Popper.js / Floating UI for tooltips, dropdowns, popovers.
710
+
711
+ ### Core Syntax
712
+
713
+ ```css
714
+ /* 1. Define the anchor */
715
+ .trigger {
716
+ anchor-name: --my-tooltip;
717
+ }
718
+
719
+ /* 2. Tether positioned element to anchor */
720
+ .tooltip {
721
+ position: absolute;
722
+ position-anchor: --my-tooltip;
723
+
724
+ /* Position relative to anchor edges */
725
+ top: anchor(bottom); /* align tooltip top to anchor bottom */
726
+ left: anchor(left); /* align tooltip left to anchor left */
727
+ }
728
+ ```
729
+
730
+ ### `anchor()` Values
731
+
732
+ ```css
733
+ .popover {
734
+ position: absolute;
735
+ position-anchor: --trigger;
736
+
737
+ /* Anchor edge references */
738
+ top: anchor(bottom); /* below anchor */
739
+ bottom: anchor(top); /* above anchor */
740
+ left: anchor(right); /* right of anchor */
741
+ right: anchor(left); /* left of anchor */
742
+ top: anchor(center); /* anchor vertical center */
743
+ left: anchor(center); /* anchor horizontal center */
744
+ }
745
+ ```
746
+
747
+ ### `@position-try` — Automatic Flip
748
+
749
+ Define fallback positions if primary placement goes off-screen:
750
+
751
+ ```css
752
+ @position-try --flip-above {
753
+ top: auto;
754
+ bottom: anchor(top);
755
+ }
756
+
757
+ .tooltip {
758
+ position: absolute;
759
+ position-anchor: --trigger;
760
+ top: anchor(bottom);
761
+ position-try-fallbacks: --flip-above;
762
+ }
763
+ ```
764
+
765
+ ### Progressive Enhancement Pattern
766
+
767
+ ```css
768
+ /* Base: JavaScript-positioned fallback */
769
+ .tooltip {
770
+ position: fixed; /* JS will set top/left */
771
+ }
772
+
773
+ /* Enhancement: native anchor positioning */
774
+ @supports (anchor-name: --x) {
775
+ .tooltip {
776
+ position: absolute;
777
+ position-anchor: --trigger;
778
+ top: anchor(bottom);
779
+ left: anchor(left);
780
+ /* Remove JS positioning when supported */
781
+ }
782
+
783
+ .trigger {
784
+ anchor-name: --trigger;
785
+ }
786
+ }
787
+ ```
788
+
789
+ **Browser support (2025):** Chrome 125+, Edge 125+. Firefox and Safari: not yet shipped. Use `@supports (anchor-name: --x)` gate for all production use.
790
+
791
+ ---
792
+
793
+ ## Quick Reference: Grid Track Sizing
794
+
795
+ ```css
796
+ /* Fixed */
797
+ grid-template-columns: 200px 1fr;
798
+
799
+ /* Repeat patterns */
800
+ grid-template-columns: repeat(3, 1fr);
801
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
802
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
803
+
804
+ /* Mixed */
805
+ grid-template-columns: 250px repeat(3, 1fr) min-content;
806
+
807
+ /* Named lines */
808
+ grid-template-columns: [sidebar-start] 250px [sidebar-end main-start] 1fr [main-end];
809
+
810
+ /* Content item span */
811
+ .item {
812
+ grid-column: main-start / main-end;
813
+ grid-column: 1 / -1; /* full width */
814
+ grid-column: span 2;
815
+ }
816
+ ```
817
+
818
+ ## Quick Reference: Alignment
819
+
820
+ ```css
821
+ /* Container — distribute tracks */
822
+ justify-content: start | end | center | stretch | space-between | space-around | space-evenly;
823
+ align-content: start | end | center | stretch | space-between | space-around | space-evenly;
824
+ place-content: <align-content> <justify-content>;
825
+
826
+ /* Container — align items within cells */
827
+ justify-items: start | end | center | stretch;
828
+ align-items: start | end | center | stretch | baseline;
829
+ place-items: <align-items> <justify-items>;
830
+
831
+ /* Item — override for one child */
832
+ justify-self: start | end | center | stretch;
833
+ align-self: start | end | center | stretch | baseline;
834
+ place-self: <align-self> <justify-self>;
835
+ ```