@humanforest/slidev-theme 0.1.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 (124) hide show
  1. package/LICENSE +67 -0
  2. package/README.md +577 -0
  3. package/assetUrl.js +38 -0
  4. package/components/Alert.vue +209 -0
  5. package/components/AreaBox.vue +152 -0
  6. package/components/AreaChart.vue +145 -0
  7. package/components/Avatar.vue +267 -0
  8. package/components/AvatarGroup.vue +94 -0
  9. package/components/BadgeStrip.vue +203 -0
  10. package/components/Bars.vue +207 -0
  11. package/components/BoroughShape.vue +127 -0
  12. package/components/BrowserFrame.vue +484 -0
  13. package/components/CalendarGrid.vue +480 -0
  14. package/components/Card.vue +70 -0
  15. package/components/Carousel.vue +266 -0
  16. package/components/ChartFrame.vue +426 -0
  17. package/components/ChordChart.vue +264 -0
  18. package/components/ComposedChart.vue +187 -0
  19. package/components/Contents.vue +86 -0
  20. package/components/DataTable.vue +244 -0
  21. package/components/DeckMap.vue +409 -0
  22. package/components/DeviceFrame.vue +331 -0
  23. package/components/DonutChart.vue +103 -0
  24. package/components/DottedMap.vue +126 -0
  25. package/components/Endorsement.vue +76 -0
  26. package/components/Grid.vue +169 -0
  27. package/components/GroupedBarChart.vue +141 -0
  28. package/components/IconTile.vue +116 -0
  29. package/components/Kpi.vue +188 -0
  30. package/components/LineChart.vue +133 -0
  31. package/components/Logo.vue +203 -0
  32. package/components/LondonMap.vue +348 -0
  33. package/components/MarkPair.vue +109 -0
  34. package/components/Marquee.vue +263 -0
  35. package/components/NestedDonutChart.vue +295 -0
  36. package/components/Placeholder.vue +88 -0
  37. package/components/SankeyChart.vue +223 -0
  38. package/components/ScatterChart.vue +142 -0
  39. package/components/StackedBarChart.vue +143 -0
  40. package/components/StatCard.vue +134 -0
  41. package/components/StatusTrack.vue +334 -0
  42. package/components/Timeline.vue +249 -0
  43. package/components/TimelineChart.vue +329 -0
  44. package/components/TreemapChart.vue +267 -0
  45. package/components/backgrounds.js +135 -0
  46. package/components/boroughGeometry.ts +59 -0
  47. package/components/chartData.ts +277 -0
  48. package/components/chartTip.ts +201 -0
  49. package/components/codeTheme.ts +239 -0
  50. package/components/deckPalette.ts +157 -0
  51. package/components/dottedMapGeometry.js +60 -0
  52. package/components/iconSlugs.js +55 -0
  53. package/components/iconUrl.js +51 -0
  54. package/components/mermaidTheme.ts +972 -0
  55. package/components/motionDuration.ts +41 -0
  56. package/components/tableRules.ts +257 -0
  57. package/confidential-mark.vue +151 -0
  58. package/custom-nav-controls.vue +79 -0
  59. package/endorsements/b-corp-black.svg +30 -0
  60. package/endorsements/b-corp-white.svg +30 -0
  61. package/global-top.vue +1662 -0
  62. package/icons/forest/bike-asterisk.svg +21 -0
  63. package/icons/forest/bike-down.svg +19 -0
  64. package/icons/forest/bike-off.svg +20 -0
  65. package/icons/forest/bike-up.svg +19 -0
  66. package/icons/forest/bike-x.svg +19 -0
  67. package/icons/forest/bike.svg +18 -0
  68. package/icons/forest/mark-fill.svg +6 -0
  69. package/icons/forest/mark.svg +6 -0
  70. package/icons/forest/parking.svg +3 -0
  71. package/icons/forest/star-fill.svg +4 -0
  72. package/icons/forest/star.svg +4 -0
  73. package/icons/forest/traffic-light-caution.svg +8 -0
  74. package/icons/forest/traffic-light-go.svg +8 -0
  75. package/icons/forest/traffic-light-lit.svg +8 -0
  76. package/icons/forest/traffic-light-stop.svg +8 -0
  77. package/icons/forest/traffic-light.svg +8 -0
  78. package/icons/lucide/battery.svg +1 -0
  79. package/icons/lucide/bike.svg +1 -0
  80. package/icons/lucide/chart-line.svg +1 -0
  81. package/icons/lucide/check.svg +1 -0
  82. package/icons/lucide/circle-check.svg +1 -0
  83. package/icons/lucide/clock.svg +1 -0
  84. package/icons/lucide/code.svg +1 -0
  85. package/icons/lucide/component.svg +1 -0
  86. package/icons/lucide/frame.svg +1 -0
  87. package/icons/lucide/layout-grid.svg +1 -0
  88. package/icons/lucide/map-pin.svg +1 -0
  89. package/icons/lucide/map.svg +1 -0
  90. package/icons/lucide/palette.svg +1 -0
  91. package/icons/lucide/table.svg +1 -0
  92. package/icons/lucide/triangle-alert.svg +1 -0
  93. package/icons/lucide/type.svg +1 -0
  94. package/icons/lucide/wrench.svg +1 -0
  95. package/layouts/bleed.vue +317 -0
  96. package/layouts/cover.vue +1514 -0
  97. package/layouts/default.vue +187 -0
  98. package/layouts/divider.vue +286 -0
  99. package/layouts/end.vue +384 -0
  100. package/layouts/quote.vue +218 -0
  101. package/layouts/split.vue +1875 -0
  102. package/layouts/stack.vue +944 -0
  103. package/layouts/statement.vue +67 -0
  104. package/manifest/chrome.ts +36 -0
  105. package/manifest/components.ts +49 -0
  106. package/manifest/index.ts +57 -0
  107. package/manifest/layouts.ts +37 -0
  108. package/manifest/manifest.json +6514 -0
  109. package/manifest/presets.ts +635 -0
  110. package/notch.js +458 -0
  111. package/notchPath.js +188 -0
  112. package/package.json +77 -0
  113. package/section.js +110 -0
  114. package/setup/mermaid-renderer.ts +2120 -0
  115. package/setup/mermaid.ts +30 -0
  116. package/setup/shiki.ts +44 -0
  117. package/setup/shortcuts.ts +28 -0
  118. package/slide-bottom.vue +305 -0
  119. package/slide-top.vue +268 -0
  120. package/styles/base.css +2611 -0
  121. package/styles/index.ts +71 -0
  122. package/styles/tokens.css +144 -0
  123. package/uno.config.ts +231 -0
  124. package/useNotchCuts.js +200 -0
@@ -0,0 +1,21 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M5 3V7.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
19
+ <path d="M7 4L3 6.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
20
+ <path d="M3 4L7 6.5" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
21
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M4 8L4 2.5M4 8L2 5.5M4 8L6 5.5" stroke-width="2" stroke-linecap="round" />
19
+ </svg>
@@ -0,0 +1,20 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 18C20.433 18 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 18 18.5 18Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 18C7.433 18 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 18 5.5 18Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M8 18H3" stroke-width="2" stroke-linecap="round" />
19
+ <path d="M21 18H16" stroke-width="2" stroke-linecap="round" />
20
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M4 2.5V8M4 2.5L6 5M4 2.5L2 5" stroke-width="2" stroke-linecap="round" />
19
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ <path d="M3 7L7 3M7 7L3 3" stroke-width="2" stroke-linecap="round" />
19
+ </svg>
@@ -0,0 +1,18 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ d="M18.5 19C20.433 19 22 17.433 22 15.5C22 13.567 20.433 12 18.5 12C16.567 12 15 13.567 15 15.5C15 17.433 16.567 19 18.5 19Z"
4
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path
6
+ d="M5.5 19C7.433 19 9 17.433 9 15.5C9 13.567 7.433 12 5.5 12C3.567 12 2 13.567 2 15.5C2 17.433 3.567 19 5.5 19Z"
7
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
8
+ <path d="M6 15.5H11.3602C11.7502 15.5 12.1047 15.2732 12.2681 14.9191L15 9" stroke-width="2"
9
+ stroke-linecap="round" />
10
+ <path d="M8 9H10" stroke-width="2" stroke-linecap="round" />
11
+ <path d="M9 9L12 15" stroke-width="2" stroke-linecap="round" />
12
+ <path d="M12 5H12.8686C13.2543 5 13.6056 5.22183 13.7715 5.57007L18.5 15.5" stroke-width="2"
13
+ stroke-linecap="round" />
14
+ <path
15
+ d="M15 6H18.6126C19.2951 6 19.7771 6.6687 19.5613 7.31623L19.2279 8.31623C19.0918 8.72457 18.7097 9 18.2792 9H16"
16
+ stroke-width="2" stroke-linecap="round" />
17
+ <path d="M5.5 12H3" stroke-width="2" stroke-linecap="round" />
18
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12 2L17.2 12.4H15.4L17.2 16H6.8L8.6 12.4H6.8L12 2Z" stroke-width="2"
3
+ stroke-linecap="round" stroke-linejoin="round" />
4
+ <path d="M10.2 16V22H8.6" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path d="M13.8 16V22H15.4" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M12 2L17.2 12.4H15.4L17.2 16H6.8L8.6 12.4H6.8L12 2Z" stroke-width="2"
3
+ stroke-linecap="round" stroke-linejoin="round" />
4
+ <path d="M10.2 16V22H8.6" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <path d="M13.8 16V22H15.4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
6
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M4.68 20.5 6.48 3.5H12.99Q16.15 3.5 17.78 5.02Q19.41 6.53 19.32 9.35Q19.24 12.66 17.19 14.43Q15.14 16.2 11.62 16.2H10.22L9.78 20.5ZM10.7 11.79H11.95Q13 11.79 13.57 11.26Q14.14 10.73 14.2 9.74Q14.23 8.88 13.77 8.4Q13.3 7.91 12.38 7.91H11.1Z" />
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M 11.5251 2.2969 a 0.5299 0.5299 0 0 1 0.9498 0 l 2.3095 4.6781 a 2.1196 2.1196 0 0 0 1.5947 1.1598 l 5.165 0.7558 a 0.5299 0.5299 0 0 1 0.2939 0.9038 l -3.7353 3.6373 a 2.1196 2.1196 0 0 0 -0.6109 1.8776 l 0.8818 5.139 a 0.5299 0.5299 0 0 1 -0.7708 0.5599 l -4.6171 -2.4275 a 2.1196 2.1196 0 0 0 -1.9726 0 L 6.3971 21.0082 a 0.5299 0.5299 0 0 1 -0.7698 -0.5599 l 0.8808 -5.138 a 2.1196 2.1196 0 0 0 -0.6109 -1.8786 L 2.162 9.7954 a 0.5299 0.5299 0 0 1 0.2939 -0.9058 l 5.164 -0.7548 a 2.1196 2.1196 0 0 0 1.5967 -1.1598 z"
3
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
4
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M 11.5251 2.2969 a 0.5299 0.5299 0 0 1 0.9498 0 l 2.3095 4.6781 a 2.1196 2.1196 0 0 0 1.5947 1.1598 l 5.165 0.7558 a 0.5299 0.5299 0 0 1 0.2939 0.9038 l -3.7353 3.6373 a 2.1196 2.1196 0 0 0 -0.6109 1.8776 l 0.8818 5.139 a 0.5299 0.5299 0 0 1 -0.7708 0.5599 l -4.6171 -2.4275 a 2.1196 2.1196 0 0 0 -1.9726 0 L 6.3971 21.0082 a 0.5299 0.5299 0 0 1 -0.7698 -0.5599 l 0.8808 -5.138 a 2.1196 2.1196 0 0 0 -0.6109 -1.8786 L 2.162 9.7954 a 0.5299 0.5299 0 0 1 0.2939 -0.9058 l 5.164 -0.7548 a 2.1196 2.1196 0 0 0 1.5967 -1.1598 z"
3
+ stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
4
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="currentColor" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="var(--ui-warning, currentColor)" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="currentColor" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="currentColor" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="currentColor" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="var(--ui-success, currentColor)" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="var(--ui-error, currentColor)" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="var(--ui-warning, currentColor)" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="var(--ui-success, currentColor)" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="var(--ui-error, currentColor)" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="currentColor" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="currentColor" stroke="none" />
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="7" y="2" width="10" height="18" rx="2" stroke-width="2" stroke-linecap="round"
3
+ stroke-linejoin="round" />
4
+ <path d="M12 20v2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
5
+ <circle cx="12" cy="6" r="2" fill="currentColor" stroke="none" />
6
+ <circle cx="12" cy="11" r="2" fill="currentColor" stroke="none" />
7
+ <circle cx="12" cy="16" r="2" fill="currentColor" stroke="none" />
8
+ </svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M22 14v-4"/><rect width="16" height="12" x="2" y="6" rx="2"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="18.5" cy="17.5" r="3.5"/><circle cx="5.5" cy="17.5" r="3.5"/><circle cx="15" cy="5" r="1"/><path d="M12 17.5V14l-3-3l4-3l2 3h2"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M3 3v16a2 2 0 0 0 2 2h16"/><path d="m19 9l-5 5l-4-4l-3 3"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 6L9 17l-5-5"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="m9 12l2 2l4-4"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m16 18l6-6l-6-6M8 6l-6 6l6 6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 11.293a1 1 0 0 0 0 1.414l2.376 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0zm-13.239 0a1 1 0 0 0 0 1.414l2.377 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414L6.088 8.916a1 1 0 0 0-1.414 0zm6.619 6.619a1 1 0 0 0 0 1.415l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.415l-2.377-2.376a1 1 0 0 0-1.414 0zm0-13.238a1 1 0 0 0 0 1.414l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M22 6H2m20 12H2M6 2v20M18 2v20"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0zm.894.211v15M9 3.236v15"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 22a1 1 0 0 1 0-20a10 9 0 0 1 10 9a5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z"/><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 3v18"/><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M3 9h18M3 15h18"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m21.73 18l-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4m0 4h.01"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2M9 20h6"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z"/></svg>
@@ -0,0 +1,317 @@
1
+ <script setup>
2
+ import { assetUrl } from '../assetUrl.js';
3
+ /*
4
+ Full-bleed media with content laid over it. The only layout that escapes the slide's padding,
5
+ which is why it sets its own instead of wearing `.slidev-layout`'s.
6
+
7
+ The root needs `h-full` — every other layout carries it, but this one is easy to omit because
8
+ `.bleed-media`/`.bleed-overlay` are absolutely positioned and so never contribute to the root's
9
+ own height. Without it the root shrink-wraps to `.bleed-content`'s natural height (measured
10
+ live: 336px of a 1080px canvas), so the "full-bleed" media only covers the top third of the
11
+ slide and a bottom-anchored `::overlay::` block overflows past the top edge.
12
+ */
13
+
14
+ // Same clamp discipline as split.vue: a validator is stripped in production, so an out-of-range
15
+ // `scrim`/`align` must not reach the template raw and mint an unstyled modifier class. These
16
+ // lookups fall back to the documented default independent of the validators below.
17
+ const SCRIM_CLASS = { none: 'scrim-none', full: 'scrim-full', half: 'scrim-half' };
18
+ const ALIGN_CLASS = { start: 'align-start', center: 'align-center', end: 'align-end' };
19
+ /* Physical class names, driven by the boolean: the SCRIM's direction is derived from the same fact
20
+ (see `--bleed-scrim-to` below), so one value moves the column and the wash together. */
21
+ const FLIP_CLASS = { false: 'side-left', true: 'side-right' };
22
+
23
+ defineProps({
24
+ /** The figure's image URL. This is Slidev's own frontmatter key, used as Slidev means it: `extractImagesUsage()` harvests it and emits a `<link rel=preload as=image>`, so the URL belongs here rather than in an `<img>` a slide writes by hand. Slot content still wins when a slide provides its own figure. */
25
+ image: { type: String, default: '' },
26
+ /** Alt text — for `image` when there is one, and the label the `<Placeholder>` carries when there is not. */
27
+ alt: { type: String, default: '' },
28
+ /**
29
+ * The wash between the photograph and the words: `full` (the whole canvas) or `half` (a gradient
30
+ * over the side the content sits on, faded out by the far edge).
31
+ *
32
+ * ★★ `none` IS FOR A SLIDE WITH NOTHING TO PROTECT, AND FOR NOTHING ELSE. A scrim exists to keep
33
+ * TEXT legible over a photograph; with no text there is nothing to keep legible, and a wash is
34
+ * then just a veil over somebody's picture — which is exactly what a full-bleed photograph slide
35
+ * and the layout's own areas diagram need.
36
+ *
37
+ * ⚠ IT IS NOT A RUNG OF THE LADDER. It used to be drawn as one — two specimen slides putting real
38
+ * copy on an unwashed photograph and declaring `expectContrastFail` so the audit would let them
39
+ * past, which is a layout demonstrating a pairing it also says must never ship. Dark text straight
40
+ * onto an image is the one thing this system cannot make legible, because the contrast depends on
41
+ * pixels no token can see. scripts/deckSpecimen.ts refuses the combination now: `scrim: none` with
42
+ * content in the default slot fails the generator. A slide that wants words over an unwashed
43
+ * picture wants `split` at `frame: photo`, where the words have a column of their own.
44
+ *
45
+ * ★ IT WAS `split`, AND THAT WAS ONE WORD DOING TWO JOBS. `split` is a LAYOUT in this theme — two
46
+ * columns, text beside a figure — and it was also this scrim's shape, on a layout that is the
47
+ * opposite arrangement: one photograph across the whole canvas with the text ON it. A reader
48
+ * meeting `layout: bleed` / `scrim: split` had to know the two were unrelated. `half` says what
49
+ * the wash covers and collides with nothing.
50
+ */
51
+ scrim: { type: String, default: 'half', validator: (s) => ['none', 'full', 'half'].includes(s) },
52
+ /**
53
+ * Draws this slide on the DARK register — the deck's dark ground with light ink — by putting
54
+ * `deck-dark` on the layout root.
55
+ *
56
+ * ★★ THIS IS NOT SLIDEV'S DARK MODE, and the two must not be confused. Slidev has one:
57
+ * `colorSchema` in headmatter, toggling `html.dark` for the WHOLE deck as a viewer preference.
58
+ * This theme pins `colorSchema: 'light'` (package.json) and never toggles it, because a
59
+ * presentation's register is a design decision baked into the deck rather than something the
60
+ * audience picks — dark is punctuation here, not the ground. Slidev offers no per-slide
61
+ * colorSchema; its supported per-slide hook is `class:`, which is exactly what this writes.
62
+ *
63
+ * It replaces `class: 'deck-dark'` in frontmatter — same class, same element, said as a prop the
64
+ * layout documents instead of a raw class name an author had to know.
65
+ *
66
+ * ⚠ THE TWO DARKS DO INTERACT, and base.css records where: Slidev's own code stylesheet picks
67
+ * shiki's palette off `html.dark`, which stays LIGHT through a dark slide, so a code block on
68
+ * this register needs the theme's own override or it scores 2.43:1.
69
+ */
70
+ dark: { type: Boolean, default: false },
71
+ /** Where the content block sits vertically in the field. */
72
+ align: { type: String, default: 'start', validator: (a) => ['start', 'center', 'end'].includes(a) },
73
+ /** Which physical side the CONTENT sits on; the photograph keeps the other. The `half` scrim follows it, so the cover is always on the words and the picture is always clear beside them. Same reading as `split` and `quote`. */
74
+ /**
75
+ * Mirror the layout: by default the content column takes the left and the photograph keeps the right;
76
+ * flipped, they swap. The `half` scrim follows, so the cover is always under the words.
77
+ *
78
+ * ★★ A BOOLEAN, AND SHARED WITH `stack` — which is the only shape that gives the two layouts one
79
+ * key with one DEFAULT. They invert deliberately (split leads with the title, stack subordinates
80
+ * it), so any value that names a POSITION comes out opposite between them: content-first on one
81
+ * is content-last on the other. `false` means "this layout's own arrangement" on both, and that
82
+ * is the only thing they genuinely share — there is no word for "figure right" and "band top" at
83
+ * once. It replaced `flip`, which had no third value in prospect either.
84
+ *
85
+ * ⚠ IT IS RELATIVE, WHICH IS THE TRADE. `flip: true` said where the content went; `flip` says
86
+ * "the other way from the default", so reading a slide needs the default in hand — and reversing
87
+ * a layout's default would silently change every flipped slide. The defaults are doctrine and do
88
+ * not move, which is what makes that acceptable.
89
+ */
90
+ flip: { type: Boolean, default: false },
91
+ });
92
+ </script>
93
+
94
+ <template>
95
+ <div class="slidev-layout bleed h-full" :class="[SCRIM_CLASS[scrim] ?? 'scrim-half', ALIGN_CLASS[align] ?? 'align-start', FLIP_CLASS[String(flip)] ?? 'side-left', dark ? 'deck-dark' : '']">
96
+ <div class="bleed-media">
97
+ <!--
98
+ No `kind` prop deciding this — it never did. `Placeholder` is the FALLBACK of the
99
+ `media` slot, so slot presence already decides what renders; a `kind` prop that read
100
+ alongside it only added a state (`kind: 'component'` with no `::media::` block) that
101
+ rendered nothing at all — a silent blank full-bleed slide, with no error and nothing for
102
+ the audit to catch. Deleted rather than "fixed", because the slot already IS the decision.
103
+ -->
104
+ <slot name="media">
105
+ <img v-if="image" :src="assetUrl(image)" :alt="alt">
106
+ <Placeholder v-else :label="alt || 'Full-bleed image'" ratio="16:9" />
107
+ </slot>
108
+ </div>
109
+ <div class="bleed-content"><slot /></div>
110
+ <div v-if="$slots.overlay" class="bleed-overlay"><slot name="overlay" /></div>
111
+ </div>
112
+ </template>
113
+
114
+ <style scoped>
115
+ .bleed { position: relative; padding: 0; overflow: hidden; }
116
+ .bleed-media { position: absolute; inset: 0; }
117
+ /*
118
+ Forcing width/height 100% here is the layout's actual contract, not an accident: "full bleed"
119
+ means the media region is completely filled, and nothing in a layout named for that should be
120
+ optional. `object-fit: cover` (not a raw stretch) is what makes that safe for a real <img>/
121
+ <video> whose intrinsic ratio does not match the frame — it crops instead of distorting, and is
122
+ a no-op for a non-replaced element like Placeholder's own <div> root.
123
+
124
+ border-radius/border are deliberately NOT forced here any more — they were, at this same
125
+ selector, which silently overrode a caller's own utility classes at (0,2,0) specificity (the
126
+ same shipped-once bug as `items-center` on <Grid>) and, worse, stripped Placeholder's own
127
+ intentional dashed border — the affordance that makes a placeholder look like a placeholder
128
+ rather than a shippable image. A caller who wants square corners on real media can still ask
129
+ for them; this layout no longer takes that choice away.
130
+ */
131
+ .bleed-media :deep(> *) { width: 100%; height: 100%; object-fit: cover; }
132
+ .bleed::after {
133
+ content: '';
134
+ position: absolute;
135
+ inset: 0;
136
+ pointer-events: none;
137
+ }
138
+ /*
139
+ ★★ TWO WAYS TO COVER A PHOTOGRAPH, AND THE SECOND ONE EXISTS BECAUSE THE FIRST FAILED.
140
+
141
+ `full` is an even wash over the whole frame. It has one strength and not a ladder of them,
142
+ because the ladder is what went wrong: an even wash has to be weak enough not to kill the picture
143
+ and strong enough to carry text, and it cannot be both. MEASURED on real Forest photography, the
144
+ old `soft` rung scored 2.34:1 against a 3:1 floor on the light register and 1.70:1 on the dark —
145
+ a documented default that did not clear its own gate. What survives here is the strength that did.
146
+
147
+ `split` puts the cover where the words are and takes it off the rest of the picture. Same idea as
148
+ a designer reaching for a gradient overlay by hand: opaque against the content edge, clear by the
149
+ far side, so a photograph keeps its depth everywhere the reader is not reading.
150
+
151
+ ⚠ The name is `split` because the FRAME is split — dressed on one side, bare on the other. It has
152
+ nothing to do with the `split` LAYOUT, which is a different file and a different idea.
153
+
154
+ Both take their colour from --deck-bg, so the register still decides whether the cover is cream or
155
+ forest-950, and --deck-fg flips the ink with it. That is one pair of tokens doing both jobs: a
156
+ scrim tone prop would be a second opinion about the same question, free to disagree with the ink.
157
+
158
+ The direction is `to right` and not a prop. Bleed content is a column at the LEFT of the frame
159
+ (`.bleed-content` pads --deck-inset-text and the measure holds the line short), and `align` moves
160
+ it up and down, never across — so the content side is a fact about the layout, not a choice a
161
+ slide gets to make wrong.
162
+ */
163
+ .scrim-full::after { background: color-mix(in oklab, var(--deck-bg), transparent 20%); }
164
+ /*
165
+ ⚠ BLACK ON THE DARK REGISTER, NOT --deck-bg, WHICH IS A GREEN. The rule above reads the ground
166
+ token so the register decides the wash — right on the light half, where it is the deck's own
167
+ paper. On the dark half --deck-bg is --forest-950, so a full scrim laid a GREEN veil over the
168
+ photograph underneath it and every colour in the picture came back tinted.
169
+
170
+ `scrim-half` two rules down has always known this: white on light, pure black on dark, because a
171
+ scrim is a neutral density over somebody's photograph rather than a colour applied to it. `full`
172
+ simply never got the second half of that pair. 80% here against half's 78% start — the same
173
+ strength `full` already had, only neutral.
174
+
175
+ ★ The light half is left reading --deck-bg. Cream over a photograph is a paper wash and looks
176
+ deliberate; near-black over one is a tint, and only one of those is a scrim.
177
+ */
178
+ .scrim-full.deck-dark::after { background: rgb(0 0 0 / 80%); }
179
+ /*
180
+ ★★ A BLACK GRADIENT CARRIES ITS OWN INK, because it is a dark surface whatever the slide's
181
+ register says. MEASURED with the ink left to the register: nine elements at 1.00:1, every one of
182
+ them on the LIGHT register — forest-950 text on a near-black wash. The register cannot decide this
183
+ one, so `split` decides it.
184
+
185
+ Re-pointing --deck-fg rather than setting `color` is what makes that reach everything: the ink is
186
+ read by `.slidev-layout` and by every component under it, so one declaration moves the heading,
187
+ the body, an eyebrow and a caption together instead of whichever of them a `color` rule happened
188
+ to outrank.
189
+ */
190
+ /*
191
+ ★★ THE GRADIENT IS BLACK OR WHITE, NOT THE DECK'S GROUND — and that is the difference between a
192
+ cover and a wash.
193
+
194
+ It used to be color-mix(--deck-bg, …), so it faded towards cream on the light register. Cream
195
+ LIFTS a photograph towards the deck's own ground: the frame goes milky and the picture flattens,
196
+ which is the same complaint the even wash had and the reason this mode exists. Black sinks it
197
+ instead, and white blows it out cleanly rather than muddying it — both read as a deliberate
198
+ overlay, which cream never did.
199
+
200
+ So the pair is a real choice again, and the register picks it: white over the light register,
201
+ black over the dark one. The INK is left to the register too, exactly as it was before — a black
202
+ gradient only ever appears under `deck-dark`, which already flips --deck-fg and its derived muted
203
+ and subtle tiers. That is why there is no ink override here any more: an earlier pass forced
204
+ forest-0 on every split rung, and it had to, because the gradient was black on BOTH registers and
205
+ the light one then put forest-950 text on near-black (MEASURED: nine elements at 1.00:1). Pair the
206
+ gradient with the register and the problem stops existing rather than being corrected.
207
+ */
208
+ /*
209
+ ★ THE DIRECTION IS NOT A PROP OF ITS OWN. It is `flip` — the same value that moves the content —
210
+ read through a custom property, so the cover can only ever be on the words. A `gradientFrom` beside
211
+ `flip` would be two names for one fact, free to disagree the moment someone set one and not the
212
+ other, and the failure would be silent: a slide that reads perfectly in review and puts white text
213
+ on a bare photograph the day the other one is flipped.
214
+ */
215
+ .side-left { --bleed-scrim-to: right; }
216
+ .side-right { --bleed-scrim-to: left; }
217
+ .scrim-half::after {
218
+ background: linear-gradient(
219
+ to var(--bleed-scrim-to, right),
220
+ rgb(255 255 255 / 84%) 0%,
221
+ rgb(255 255 255 / 68%) 46%,
222
+ transparent 82%
223
+ );
224
+ }
225
+ .scrim-half.deck-dark::after {
226
+ background: linear-gradient(
227
+ to var(--bleed-scrim-to, right),
228
+ rgb(0 0 0 / 78%) 0%,
229
+ rgb(0 0 0 / 62%) 46%,
230
+ transparent 82%
231
+ );
232
+ }
233
+ /*
234
+ ★★ ON A SPLIT SCRIM, PROSE STAYS ON THE SCRIM — and this is the one job the old 20em body cap was
235
+ doing that nobody had written down.
236
+
237
+ base.css used to hold every paragraph to 20em (≈39 characters) as a READING measure. On these
238
+ slides it was also, silently, a CONTAINMENT one: 20em at the deck body size ends around 55% of the
239
+ canvas, and the gradient above is 62% opaque at its 46% stop and fully transparent by 82%. So a
240
+ capped paragraph happened to stop while the wash was still carrying it.
241
+
242
+ Uncapping running prose (see base.css's Measure note) removed that by accident, and the deck audit
243
+ named the six slides it broke immediately: text running to the full inset, out past the fade and
244
+ onto bare photograph, scoring 1.05:1 to 2.07:1 against a 3:1 floor.
245
+
246
+ So the bound comes back HERE, where it belongs, and as the thing it actually is: a fraction of the
247
+ slide tied to the gradient's own stops, not a character count. It applies only to `scrim: half` —
248
+ `full` washes the whole canvas and needs no bound.
249
+
250
+ Headings are left alone: they are short, large and land well inside the strong half on their own.
251
+ */
252
+ .scrim-half .bleed-content :deep(p),
253
+ .scrim-half .bleed-content :deep(li) {
254
+ /* Ends at ~55% of the canvas — inside the gradient's 46% stop's reach, well before its 82% fade. */
255
+ max-width: 55%;
256
+ }
257
+ .bleed-content {
258
+ position: relative;
259
+ z-index: 1;
260
+ height: 100%;
261
+ display: flex;
262
+ flex-direction: column;
263
+ /* task-14-brief.md — this is TEXT, not media: bleed's own media layer (`.bleed-media`, above)
264
+ is the one thing in this theme that stays at inset 0 on purpose ("full bleed" means exactly
265
+ that, and it is unaffected by the two-track system this padding now joins), but the CONTENT
266
+ laid over it wants the same measure every other content box in the theme gets, for the same
267
+ reason — --deck-inset-text (90px, task-14b-brief.md's revision of task-14's original 100px),
268
+ all four edges, not a bleed-specific number.
269
+
270
+ ★ FOUND, not just changed: the old value here (--deck-space-6/60px vertical, grid*2.5/100px
271
+ horizontal) UNDER-cleared the chrome band even before task-14 — the top pill band sat at
272
+ y 24–73 (task-14's own predecessor's chrome inset) and this padding started content at y:60, a
273
+ 13px overlap identical in shape to the defect base.css's own `.slidev-layout` comment describes
274
+ and had already been corrected FOR THAT ELEMENT. It was never corrected here, and
275
+ scripts/deckAudit.ts could not have caught it (collision, not overflow — see base.css). It went
276
+ unnoticed in practice only because the bleed slides that were looked at ship `chrome: false`
277
+ (see slide-bottom.vue's own comment) — a real slide with `chrome: true` and `align: start`
278
+ would have shown it. ⚠ "every bleed slide ships chrome: false" was the claim here and it is
279
+ FALSE: the retired apps/deck-layouts had 6 bleed slides with the chrome left on. Reported, not silently absorbed: task-14's fix widened the gap rather than
280
+ narrowing it, and task-14b's 90px still clears the (now 36px-inset) band, by 5px — see
281
+ base.css's own `.slidev-layout` comment for that arithmetic in full.
282
+
283
+ ★ THE TOP EDGE TAKES THE HEADING SPACE THE OTHER LAYOUTS TAKE. This padded all four sides with
284
+ --deck-inset-text alone, so a bleed heading started at 90 where a `default` heading starts at
285
+ 130 and a split's ::header:: starts at 130 — a deck moving onto a photograph stepped its title
286
+ up 40px and back down again. The other three edges keep the plain inset: the extra air is about
287
+ a HEADING clearing the top of the frame, which is what --deck-heading-top-space is named for,
288
+ and nothing about the left, right or bottom of a full-bleed box wants it. */
289
+ padding: calc(var(--deck-inset-text) + var(--deck-heading-top-space)) var(--deck-inset-text) var(--deck-inset-text);
290
+ }
291
+ /*
292
+ `flip` moves the column ACROSS, `align` moves it UP AND DOWN — two axes, never one.
293
+
294
+ ★ AND THE TYPE MIRRORS WITH IT. The first pass moved only the box — align-items: flex-end, lines
295
+ left as they were — on the reasoning that a right-aligned paragraph is a typographic decision a
296
+ position prop should not make. Rendered, that reasoning is wrong: a single-line h1 in a
297
+ shrink-to-fit box lands FLUSH right while the paragraph beside it, left-set inside its own measure,
298
+ ends ragged and short of the same wall. The heading and the body then disagree about where the
299
+ edge is, and it reads as a mistake rather than as a choice.
300
+
301
+ `flip` is a MIRROR, and a mirror that moves the box but not the setting contradicts itself. So the
302
+ lines turn with the block: flush against the wall the content sits on, ragged towards the picture.
303
+
304
+ The cost is real and worth stating: a ragged LEFT edge slows the return sweep, so this is a
305
+ trade that only holds for the short blocks a slide carries. It is not a licence to set a paragraph
306
+ of body copy right-aligned — that is what `flip: false` is for, and it stays the default.
307
+ */
308
+ .side-right .bleed-content { align-items: flex-end; text-align: right; }
309
+ .align-start .bleed-content { justify-content: flex-start; }
310
+ .align-center .bleed-content { justify-content: center; }
311
+ .align-end .bleed-content { justify-content: flex-end; }
312
+ /* The wrapper stays click-through so it never intercepts clicks over the media/content beneath
313
+ it, but its own children must opt back in — otherwise anything interactive an author puts in
314
+ `::overlay::` (a link, a button) is dead in presentation mode. */
315
+ .bleed-overlay { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
316
+ .bleed-overlay > * { pointer-events: auto; }
317
+ </style>