designmd-forge 1.2.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 (907) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/__tests__/designStore.test.js +41 -0
  4. package/dist/__tests__/linter.test.js +23 -0
  5. package/dist/__tests__/sectionParser.test.js +60 -0
  6. package/dist/__tests__/server.test.js +129 -0
  7. package/dist/constants.js +12 -0
  8. package/dist/data/authoring-guide.md +113 -0
  9. package/dist/data/designs/airbnb.md +545 -0
  10. package/dist/data/designs/airtable.md +554 -0
  11. package/dist/data/designs/apple.md +562 -0
  12. package/dist/data/designs/binance.md +634 -0
  13. package/dist/data/designs/bmw-m.md +503 -0
  14. package/dist/data/designs/bmw.md +544 -0
  15. package/dist/data/designs/bugatti.md +454 -0
  16. package/dist/data/designs/cal.md +542 -0
  17. package/dist/data/designs/card-heavy.md +250 -0
  18. package/dist/data/designs/claude.md +589 -0
  19. package/dist/data/designs/clay.md +541 -0
  20. package/dist/data/designs/clickhouse.md +544 -0
  21. package/dist/data/designs/cohere.md +451 -0
  22. package/dist/data/designs/coinbase.md +570 -0
  23. package/dist/data/designs/composio.md +506 -0
  24. package/dist/data/designs/content-first.md +236 -0
  25. package/dist/data/designs/cursor.md +537 -0
  26. package/dist/data/designs/data-dashboard.md +300 -0
  27. package/dist/data/designs/dell-1996.md +632 -0
  28. package/dist/data/designs/elevenlabs.md +504 -0
  29. package/dist/data/designs/enterprise-neutral.md +252 -0
  30. package/dist/data/designs/expo.md +526 -0
  31. package/dist/data/designs/ferrari.md +531 -0
  32. package/dist/data/designs/figma.md +578 -0
  33. package/dist/data/designs/framer.md +544 -0
  34. package/dist/data/designs/hashicorp.md +575 -0
  35. package/dist/data/designs/hp.md +670 -0
  36. package/dist/data/designs/ibm.md +550 -0
  37. package/dist/data/designs/intercom.md +546 -0
  38. package/dist/data/designs/ios-acorns-android.md +430 -0
  39. package/dist/data/designs/ios-acorns-expo.md +381 -0
  40. package/dist/data/designs/ios-acorns-swiftui.md +378 -0
  41. package/dist/data/designs/ios-acorns.md +384 -0
  42. package/dist/data/designs/ios-airbnb-android.md +658 -0
  43. package/dist/data/designs/ios-airbnb-expo.md +457 -0
  44. package/dist/data/designs/ios-airbnb-swiftui.md +464 -0
  45. package/dist/data/designs/ios-airbnb.md +410 -0
  46. package/dist/data/designs/ios-alltrails-android.md +451 -0
  47. package/dist/data/designs/ios-alltrails-expo.md +400 -0
  48. package/dist/data/designs/ios-alltrails-swiftui.md +343 -0
  49. package/dist/data/designs/ios-alltrails.md +344 -0
  50. package/dist/data/designs/ios-amazon-android.md +686 -0
  51. package/dist/data/designs/ios-amazon-expo.md +433 -0
  52. package/dist/data/designs/ios-amazon-music-android.md +416 -0
  53. package/dist/data/designs/ios-amazon-music-expo.md +368 -0
  54. package/dist/data/designs/ios-amazon-music-swiftui.md +436 -0
  55. package/dist/data/designs/ios-amazon-music.md +389 -0
  56. package/dist/data/designs/ios-amazon-swiftui.md +460 -0
  57. package/dist/data/designs/ios-amazon.md +440 -0
  58. package/dist/data/designs/ios-apple-fitness-android.md +462 -0
  59. package/dist/data/designs/ios-apple-fitness-expo.md +373 -0
  60. package/dist/data/designs/ios-apple-fitness-swiftui.md +373 -0
  61. package/dist/data/designs/ios-apple-fitness.md +399 -0
  62. package/dist/data/designs/ios-apple-maps-android.md +646 -0
  63. package/dist/data/designs/ios-apple-maps-expo.md +557 -0
  64. package/dist/data/designs/ios-apple-maps-swiftui.md +588 -0
  65. package/dist/data/designs/ios-apple-maps.md +447 -0
  66. package/dist/data/designs/ios-apple-music-android.md +737 -0
  67. package/dist/data/designs/ios-apple-music-expo.md +596 -0
  68. package/dist/data/designs/ios-apple-music-swiftui.md +578 -0
  69. package/dist/data/designs/ios-apple-music.md +494 -0
  70. package/dist/data/designs/ios-apple-notes-android.md +675 -0
  71. package/dist/data/designs/ios-apple-notes-expo.md +468 -0
  72. package/dist/data/designs/ios-apple-notes-swiftui.md +489 -0
  73. package/dist/data/designs/ios-apple-notes.md +413 -0
  74. package/dist/data/designs/ios-apple-tv-android.md +405 -0
  75. package/dist/data/designs/ios-apple-tv-expo.md +341 -0
  76. package/dist/data/designs/ios-apple-tv-swiftui.md +348 -0
  77. package/dist/data/designs/ios-apple-tv.md +390 -0
  78. package/dist/data/designs/ios-apple-wallet-android.md +617 -0
  79. package/dist/data/designs/ios-apple-wallet-expo.md +487 -0
  80. package/dist/data/designs/ios-apple-wallet-swiftui.md +425 -0
  81. package/dist/data/designs/ios-apple-wallet.md +360 -0
  82. package/dist/data/designs/ios-asana-android.md +435 -0
  83. package/dist/data/designs/ios-asana-expo.md +411 -0
  84. package/dist/data/designs/ios-asana-swiftui.md +416 -0
  85. package/dist/data/designs/ios-asana.md +433 -0
  86. package/dist/data/designs/ios-audible-android.md +450 -0
  87. package/dist/data/designs/ios-audible-expo.md +328 -0
  88. package/dist/data/designs/ios-audible-swiftui.md +418 -0
  89. package/dist/data/designs/ios-audible.md +364 -0
  90. package/dist/data/designs/ios-bandcamp-android.md +471 -0
  91. package/dist/data/designs/ios-bandcamp-expo.md +378 -0
  92. package/dist/data/designs/ios-bandcamp-swiftui.md +374 -0
  93. package/dist/data/designs/ios-bandcamp.md +372 -0
  94. package/dist/data/designs/ios-bear-android.md +496 -0
  95. package/dist/data/designs/ios-bear-expo.md +449 -0
  96. package/dist/data/designs/ios-bear-swiftui.md +479 -0
  97. package/dist/data/designs/ios-bear.md +412 -0
  98. package/dist/data/designs/ios-bereal-android.md +392 -0
  99. package/dist/data/designs/ios-bereal-expo.md +299 -0
  100. package/dist/data/designs/ios-bereal-swiftui.md +319 -0
  101. package/dist/data/designs/ios-bereal.md +336 -0
  102. package/dist/data/designs/ios-binance-android.md +481 -0
  103. package/dist/data/designs/ios-binance-expo.md +404 -0
  104. package/dist/data/designs/ios-binance-swiftui.md +418 -0
  105. package/dist/data/designs/ios-binance.md +410 -0
  106. package/dist/data/designs/ios-bluesky-android.md +442 -0
  107. package/dist/data/designs/ios-bluesky-expo.md +362 -0
  108. package/dist/data/designs/ios-bluesky-swiftui.md +328 -0
  109. package/dist/data/designs/ios-bluesky.md +338 -0
  110. package/dist/data/designs/ios-booking-android.md +471 -0
  111. package/dist/data/designs/ios-booking-expo.md +364 -0
  112. package/dist/data/designs/ios-booking-swiftui.md +377 -0
  113. package/dist/data/designs/ios-booking.md +346 -0
  114. package/dist/data/designs/ios-bumble-android.md +756 -0
  115. package/dist/data/designs/ios-bumble-expo.md +629 -0
  116. package/dist/data/designs/ios-bumble-swiftui.md +546 -0
  117. package/dist/data/designs/ios-bumble.md +424 -0
  118. package/dist/data/designs/ios-cal-ai-android.md +664 -0
  119. package/dist/data/designs/ios-cal-ai-expo.md +415 -0
  120. package/dist/data/designs/ios-cal-ai-swiftui.md +486 -0
  121. package/dist/data/designs/ios-cal-ai.md +387 -0
  122. package/dist/data/designs/ios-calm-android.md +431 -0
  123. package/dist/data/designs/ios-calm-expo.md +384 -0
  124. package/dist/data/designs/ios-calm-swiftui.md +327 -0
  125. package/dist/data/designs/ios-calm.md +356 -0
  126. package/dist/data/designs/ios-canva-android.md +469 -0
  127. package/dist/data/designs/ios-canva-expo.md +374 -0
  128. package/dist/data/designs/ios-canva-swiftui.md +422 -0
  129. package/dist/data/designs/ios-canva.md +395 -0
  130. package/dist/data/designs/ios-cash-app-android.md +601 -0
  131. package/dist/data/designs/ios-cash-app-expo.md +453 -0
  132. package/dist/data/designs/ios-cash-app-swiftui.md +463 -0
  133. package/dist/data/designs/ios-cash-app.md +365 -0
  134. package/dist/data/designs/ios-character-ai-android.md +489 -0
  135. package/dist/data/designs/ios-character-ai-expo.md +420 -0
  136. package/dist/data/designs/ios-character-ai-swiftui.md +417 -0
  137. package/dist/data/designs/ios-character-ai.md +392 -0
  138. package/dist/data/designs/ios-charles-schwab-android.md +454 -0
  139. package/dist/data/designs/ios-charles-schwab-expo.md +388 -0
  140. package/dist/data/designs/ios-charles-schwab-swiftui.md +394 -0
  141. package/dist/data/designs/ios-charles-schwab.md +380 -0
  142. package/dist/data/designs/ios-chatgpt-android.md +753 -0
  143. package/dist/data/designs/ios-chatgpt-expo.md +644 -0
  144. package/dist/data/designs/ios-chatgpt-swiftui.md +653 -0
  145. package/dist/data/designs/ios-chatgpt.md +466 -0
  146. package/dist/data/designs/ios-chime-android.md +438 -0
  147. package/dist/data/designs/ios-chime-expo.md +419 -0
  148. package/dist/data/designs/ios-chime-swiftui.md +383 -0
  149. package/dist/data/designs/ios-chime.md +389 -0
  150. package/dist/data/designs/ios-chipotle-android.md +397 -0
  151. package/dist/data/designs/ios-chipotle-expo.md +301 -0
  152. package/dist/data/designs/ios-chipotle-swiftui.md +345 -0
  153. package/dist/data/designs/ios-chipotle.md +340 -0
  154. package/dist/data/designs/ios-citymapper-android.md +466 -0
  155. package/dist/data/designs/ios-citymapper-expo.md +420 -0
  156. package/dist/data/designs/ios-citymapper-swiftui.md +424 -0
  157. package/dist/data/designs/ios-citymapper.md +394 -0
  158. package/dist/data/designs/ios-claude-android.md +625 -0
  159. package/dist/data/designs/ios-claude-expo.md +671 -0
  160. package/dist/data/designs/ios-claude-swiftui.md +649 -0
  161. package/dist/data/designs/ios-claude.md +447 -0
  162. package/dist/data/designs/ios-clickup-android.md +484 -0
  163. package/dist/data/designs/ios-clickup-expo.md +423 -0
  164. package/dist/data/designs/ios-clickup-swiftui.md +416 -0
  165. package/dist/data/designs/ios-clickup.md +431 -0
  166. package/dist/data/designs/ios-clubhouse-android.md +524 -0
  167. package/dist/data/designs/ios-clubhouse-expo.md +425 -0
  168. package/dist/data/designs/ios-clubhouse-swiftui.md +447 -0
  169. package/dist/data/designs/ios-clubhouse.md +406 -0
  170. package/dist/data/designs/ios-coffee-meets-bagel-android.md +461 -0
  171. package/dist/data/designs/ios-coffee-meets-bagel-expo.md +372 -0
  172. package/dist/data/designs/ios-coffee-meets-bagel-swiftui.md +368 -0
  173. package/dist/data/designs/ios-coffee-meets-bagel.md +376 -0
  174. package/dist/data/designs/ios-coinbase-android.md +611 -0
  175. package/dist/data/designs/ios-coinbase-expo.md +500 -0
  176. package/dist/data/designs/ios-coinbase-swiftui.md +490 -0
  177. package/dist/data/designs/ios-coinbase.md +409 -0
  178. package/dist/data/designs/ios-copilot-android.md +625 -0
  179. package/dist/data/designs/ios-copilot-expo.md +423 -0
  180. package/dist/data/designs/ios-copilot-swiftui.md +471 -0
  181. package/dist/data/designs/ios-copilot.md +367 -0
  182. package/dist/data/designs/ios-craft-android.md +459 -0
  183. package/dist/data/designs/ios-craft-expo.md +417 -0
  184. package/dist/data/designs/ios-craft-swiftui.md +449 -0
  185. package/dist/data/designs/ios-craft.md +449 -0
  186. package/dist/data/designs/ios-crunchyroll-android.md +432 -0
  187. package/dist/data/designs/ios-crunchyroll-expo.md +388 -0
  188. package/dist/data/designs/ios-crunchyroll-swiftui.md +417 -0
  189. package/dist/data/designs/ios-crunchyroll.md +388 -0
  190. package/dist/data/designs/ios-crypto-com-android.md +461 -0
  191. package/dist/data/designs/ios-crypto-com-expo.md +404 -0
  192. package/dist/data/designs/ios-crypto-com-swiftui.md +419 -0
  193. package/dist/data/designs/ios-crypto-com.md +410 -0
  194. package/dist/data/designs/ios-deepseek-android.md +471 -0
  195. package/dist/data/designs/ios-deepseek-expo.md +391 -0
  196. package/dist/data/designs/ios-deepseek-swiftui.md +354 -0
  197. package/dist/data/designs/ios-deepseek.md +393 -0
  198. package/dist/data/designs/ios-deezer-android.md +475 -0
  199. package/dist/data/designs/ios-deezer-expo.md +400 -0
  200. package/dist/data/designs/ios-deezer-swiftui.md +430 -0
  201. package/dist/data/designs/ios-deezer.md +388 -0
  202. package/dist/data/designs/ios-deliveroo-android.md +493 -0
  203. package/dist/data/designs/ios-deliveroo-expo.md +424 -0
  204. package/dist/data/designs/ios-deliveroo-swiftui.md +398 -0
  205. package/dist/data/designs/ios-deliveroo.md +420 -0
  206. package/dist/data/designs/ios-delta-android.md +439 -0
  207. package/dist/data/designs/ios-delta-expo.md +381 -0
  208. package/dist/data/designs/ios-delta-swiftui.md +400 -0
  209. package/dist/data/designs/ios-delta.md +397 -0
  210. package/dist/data/designs/ios-discord-android.md +611 -0
  211. package/dist/data/designs/ios-discord-expo.md +618 -0
  212. package/dist/data/designs/ios-discord-swiftui.md +630 -0
  213. package/dist/data/designs/ios-discord.md +451 -0
  214. package/dist/data/designs/ios-disney-plus-android.md +464 -0
  215. package/dist/data/designs/ios-disney-plus-expo.md +358 -0
  216. package/dist/data/designs/ios-disney-plus-swiftui.md +412 -0
  217. package/dist/data/designs/ios-disney-plus.md +355 -0
  218. package/dist/data/designs/ios-dominos-android.md +417 -0
  219. package/dist/data/designs/ios-dominos-expo.md +316 -0
  220. package/dist/data/designs/ios-dominos-swiftui.md +340 -0
  221. package/dist/data/designs/ios-dominos.md +347 -0
  222. package/dist/data/designs/ios-doordash-android.md +527 -0
  223. package/dist/data/designs/ios-doordash-expo.md +323 -0
  224. package/dist/data/designs/ios-doordash-swiftui.md +301 -0
  225. package/dist/data/designs/ios-doordash.md +393 -0
  226. package/dist/data/designs/ios-dropbox-android.md +522 -0
  227. package/dist/data/designs/ios-dropbox-expo.md +393 -0
  228. package/dist/data/designs/ios-dropbox-swiftui.md +400 -0
  229. package/dist/data/designs/ios-dropbox.md +374 -0
  230. package/dist/data/designs/ios-duolingo-android.md +641 -0
  231. package/dist/data/designs/ios-duolingo-expo.md +597 -0
  232. package/dist/data/designs/ios-duolingo-swiftui.md +539 -0
  233. package/dist/data/designs/ios-duolingo.md +409 -0
  234. package/dist/data/designs/ios-ebay-android.md +436 -0
  235. package/dist/data/designs/ios-ebay-expo.md +344 -0
  236. package/dist/data/designs/ios-ebay-swiftui.md +308 -0
  237. package/dist/data/designs/ios-ebay.md +355 -0
  238. package/dist/data/designs/ios-espn-android.md +468 -0
  239. package/dist/data/designs/ios-espn-expo.md +387 -0
  240. package/dist/data/designs/ios-espn-swiftui.md +410 -0
  241. package/dist/data/designs/ios-espn.md +384 -0
  242. package/dist/data/designs/ios-etsy-android.md +439 -0
  243. package/dist/data/designs/ios-etsy-expo.md +351 -0
  244. package/dist/data/designs/ios-etsy-swiftui.md +296 -0
  245. package/dist/data/designs/ios-etsy.md +355 -0
  246. package/dist/data/designs/ios-evernote-android.md +419 -0
  247. package/dist/data/designs/ios-evernote-expo.md +379 -0
  248. package/dist/data/designs/ios-evernote-swiftui.md +380 -0
  249. package/dist/data/designs/ios-evernote.md +416 -0
  250. package/dist/data/designs/ios-expedia-android.md +451 -0
  251. package/dist/data/designs/ios-expedia-expo.md +433 -0
  252. package/dist/data/designs/ios-expedia-swiftui.md +399 -0
  253. package/dist/data/designs/ios-expedia.md +431 -0
  254. package/dist/data/designs/ios-facebook-android.md +628 -0
  255. package/dist/data/designs/ios-facebook-expo.md +471 -0
  256. package/dist/data/designs/ios-facebook-swiftui.md +459 -0
  257. package/dist/data/designs/ios-facebook.md +452 -0
  258. package/dist/data/designs/ios-feeld-android.md +431 -0
  259. package/dist/data/designs/ios-feeld-expo.md +379 -0
  260. package/dist/data/designs/ios-feeld-swiftui.md +401 -0
  261. package/dist/data/designs/ios-feeld.md +378 -0
  262. package/dist/data/designs/ios-fidelity-android.md +426 -0
  263. package/dist/data/designs/ios-fidelity-expo.md +396 -0
  264. package/dist/data/designs/ios-fidelity-swiftui.md +398 -0
  265. package/dist/data/designs/ios-fidelity.md +387 -0
  266. package/dist/data/designs/ios-figma-android.md +578 -0
  267. package/dist/data/designs/ios-figma-expo.md +504 -0
  268. package/dist/data/designs/ios-figma-swiftui.md +542 -0
  269. package/dist/data/designs/ios-figma.md +404 -0
  270. package/dist/data/designs/ios-fitbit-android.md +439 -0
  271. package/dist/data/designs/ios-fitbit-expo.md +389 -0
  272. package/dist/data/designs/ios-fitbit-swiftui.md +380 -0
  273. package/dist/data/designs/ios-fitbit.md +396 -0
  274. package/dist/data/designs/ios-flickr-android.md +506 -0
  275. package/dist/data/designs/ios-flickr-expo.md +434 -0
  276. package/dist/data/designs/ios-flickr-swiftui.md +421 -0
  277. package/dist/data/designs/ios-flickr.md +394 -0
  278. package/dist/data/designs/ios-flighty-android.md +418 -0
  279. package/dist/data/designs/ios-flighty-expo.md +353 -0
  280. package/dist/data/designs/ios-flighty-swiftui.md +337 -0
  281. package/dist/data/designs/ios-flighty.md +357 -0
  282. package/dist/data/designs/ios-flo-android.md +447 -0
  283. package/dist/data/designs/ios-flo-expo.md +363 -0
  284. package/dist/data/designs/ios-flo-swiftui.md +355 -0
  285. package/dist/data/designs/ios-flo.md +351 -0
  286. package/dist/data/designs/ios-garmin-connect-android.md +531 -0
  287. package/dist/data/designs/ios-garmin-connect-expo.md +429 -0
  288. package/dist/data/designs/ios-garmin-connect-swiftui.md +459 -0
  289. package/dist/data/designs/ios-garmin-connect.md +419 -0
  290. package/dist/data/designs/ios-gas-android.md +438 -0
  291. package/dist/data/designs/ios-gas-expo.md +350 -0
  292. package/dist/data/designs/ios-gas-swiftui.md +329 -0
  293. package/dist/data/designs/ios-gas.md +387 -0
  294. package/dist/data/designs/ios-gemini-android.md +568 -0
  295. package/dist/data/designs/ios-gemini-expo.md +416 -0
  296. package/dist/data/designs/ios-gemini-swiftui.md +424 -0
  297. package/dist/data/designs/ios-gemini.md +351 -0
  298. package/dist/data/designs/ios-github-android.md +507 -0
  299. package/dist/data/designs/ios-github-expo.md +486 -0
  300. package/dist/data/designs/ios-github-swiftui.md +459 -0
  301. package/dist/data/designs/ios-github.md +394 -0
  302. package/dist/data/designs/ios-gmail-android.md +548 -0
  303. package/dist/data/designs/ios-gmail-expo.md +457 -0
  304. package/dist/data/designs/ios-gmail-swiftui.md +470 -0
  305. package/dist/data/designs/ios-gmail.md +441 -0
  306. package/dist/data/designs/ios-goodreads-android.md +436 -0
  307. package/dist/data/designs/ios-goodreads-expo.md +407 -0
  308. package/dist/data/designs/ios-goodreads-swiftui.md +378 -0
  309. package/dist/data/designs/ios-goodreads.md +385 -0
  310. package/dist/data/designs/ios-google-calendar-android.md +565 -0
  311. package/dist/data/designs/ios-google-calendar-expo.md +616 -0
  312. package/dist/data/designs/ios-google-calendar-swiftui.md +585 -0
  313. package/dist/data/designs/ios-google-calendar.md +431 -0
  314. package/dist/data/designs/ios-google-maps-android.md +614 -0
  315. package/dist/data/designs/ios-google-maps-expo.md +515 -0
  316. package/dist/data/designs/ios-google-maps-swiftui.md +484 -0
  317. package/dist/data/designs/ios-google-maps.md +451 -0
  318. package/dist/data/designs/ios-grammarly-android.md +449 -0
  319. package/dist/data/designs/ios-grammarly-expo.md +383 -0
  320. package/dist/data/designs/ios-grammarly-swiftui.md +381 -0
  321. package/dist/data/designs/ios-grammarly.md +392 -0
  322. package/dist/data/designs/ios-grindr-android.md +494 -0
  323. package/dist/data/designs/ios-grindr-expo.md +358 -0
  324. package/dist/data/designs/ios-grindr-swiftui.md +357 -0
  325. package/dist/data/designs/ios-grindr.md +356 -0
  326. package/dist/data/designs/ios-grok-android.md +471 -0
  327. package/dist/data/designs/ios-grok-expo.md +388 -0
  328. package/dist/data/designs/ios-grok-swiftui.md +397 -0
  329. package/dist/data/designs/ios-grok.md +357 -0
  330. package/dist/data/designs/ios-groupme-android.md +551 -0
  331. package/dist/data/designs/ios-groupme-expo.md +442 -0
  332. package/dist/data/designs/ios-groupme-swiftui.md +439 -0
  333. package/dist/data/designs/ios-groupme.md +424 -0
  334. package/dist/data/designs/ios-grubhub-android.md +506 -0
  335. package/dist/data/designs/ios-grubhub-expo.md +428 -0
  336. package/dist/data/designs/ios-grubhub-swiftui.md +408 -0
  337. package/dist/data/designs/ios-grubhub.md +427 -0
  338. package/dist/data/designs/ios-happn-android.md +464 -0
  339. package/dist/data/designs/ios-happn-expo.md +411 -0
  340. package/dist/data/designs/ios-happn-swiftui.md +401 -0
  341. package/dist/data/designs/ios-happn.md +400 -0
  342. package/dist/data/designs/ios-headspace-android.md +688 -0
  343. package/dist/data/designs/ios-headspace-expo.md +574 -0
  344. package/dist/data/designs/ios-headspace-swiftui.md +498 -0
  345. package/dist/data/designs/ios-headspace.md +430 -0
  346. package/dist/data/designs/ios-hevy-android.md +473 -0
  347. package/dist/data/designs/ios-hevy-expo.md +405 -0
  348. package/dist/data/designs/ios-hevy-swiftui.md +367 -0
  349. package/dist/data/designs/ios-hevy.md +410 -0
  350. package/dist/data/designs/ios-hinge-android.md +743 -0
  351. package/dist/data/designs/ios-hinge-expo.md +580 -0
  352. package/dist/data/designs/ios-hinge-swiftui.md +512 -0
  353. package/dist/data/designs/ios-hinge.md +405 -0
  354. package/dist/data/designs/ios-hopper-android.md +440 -0
  355. package/dist/data/designs/ios-hopper-expo.md +353 -0
  356. package/dist/data/designs/ios-hopper-swiftui.md +340 -0
  357. package/dist/data/designs/ios-hopper.md +354 -0
  358. package/dist/data/designs/ios-hulu-android.md +435 -0
  359. package/dist/data/designs/ios-hulu-expo.md +331 -0
  360. package/dist/data/designs/ios-hulu-swiftui.md +374 -0
  361. package/dist/data/designs/ios-hulu.md +353 -0
  362. package/dist/data/designs/ios-iheartradio-android.md +481 -0
  363. package/dist/data/designs/ios-iheartradio-expo.md +417 -0
  364. package/dist/data/designs/ios-iheartradio-swiftui.md +423 -0
  365. package/dist/data/designs/ios-iheartradio.md +381 -0
  366. package/dist/data/designs/ios-imessage-android.md +426 -0
  367. package/dist/data/designs/ios-imessage-expo.md +384 -0
  368. package/dist/data/designs/ios-imessage-swiftui.md +378 -0
  369. package/dist/data/designs/ios-imessage.md +394 -0
  370. package/dist/data/designs/ios-instacart-android.md +471 -0
  371. package/dist/data/designs/ios-instacart-expo.md +349 -0
  372. package/dist/data/designs/ios-instacart-swiftui.md +378 -0
  373. package/dist/data/designs/ios-instacart.md +360 -0
  374. package/dist/data/designs/ios-instagram-android.md +646 -0
  375. package/dist/data/designs/ios-instagram-expo.md +310 -0
  376. package/dist/data/designs/ios-instagram-swiftui.md +333 -0
  377. package/dist/data/designs/ios-instagram.md +376 -0
  378. package/dist/data/designs/ios-jira-android.md +432 -0
  379. package/dist/data/designs/ios-jira-expo.md +375 -0
  380. package/dist/data/designs/ios-jira-swiftui.md +433 -0
  381. package/dist/data/designs/ios-jira.md +424 -0
  382. package/dist/data/designs/ios-kakaotalk-android.md +491 -0
  383. package/dist/data/designs/ios-kakaotalk-expo.md +418 -0
  384. package/dist/data/designs/ios-kakaotalk-swiftui.md +406 -0
  385. package/dist/data/designs/ios-kakaotalk.md +414 -0
  386. package/dist/data/designs/ios-kayak-android.md +466 -0
  387. package/dist/data/designs/ios-kayak-expo.md +407 -0
  388. package/dist/data/designs/ios-kayak-swiftui.md +426 -0
  389. package/dist/data/designs/ios-kayak.md +392 -0
  390. package/dist/data/designs/ios-kick-android.md +487 -0
  391. package/dist/data/designs/ios-kick-expo.md +434 -0
  392. package/dist/data/designs/ios-kick-swiftui.md +429 -0
  393. package/dist/data/designs/ios-kick.md +389 -0
  394. package/dist/data/designs/ios-kik-android.md +433 -0
  395. package/dist/data/designs/ios-kik-expo.md +363 -0
  396. package/dist/data/designs/ios-kik-swiftui.md +363 -0
  397. package/dist/data/designs/ios-kik.md +392 -0
  398. package/dist/data/designs/ios-kindle-android.md +439 -0
  399. package/dist/data/designs/ios-kindle-expo.md +356 -0
  400. package/dist/data/designs/ios-kindle-swiftui.md +372 -0
  401. package/dist/data/designs/ios-kindle.md +369 -0
  402. package/dist/data/designs/ios-klarna-android.md +420 -0
  403. package/dist/data/designs/ios-klarna-expo.md +349 -0
  404. package/dist/data/designs/ios-klarna-swiftui.md +360 -0
  405. package/dist/data/designs/ios-klarna.md +356 -0
  406. package/dist/data/designs/ios-lemon8-android.md +492 -0
  407. package/dist/data/designs/ios-lemon8-expo.md +413 -0
  408. package/dist/data/designs/ios-lemon8-swiftui.md +428 -0
  409. package/dist/data/designs/ios-lemon8.md +378 -0
  410. package/dist/data/designs/ios-life360-android.md +474 -0
  411. package/dist/data/designs/ios-life360-expo.md +375 -0
  412. package/dist/data/designs/ios-life360-swiftui.md +390 -0
  413. package/dist/data/designs/ios-life360.md +402 -0
  414. package/dist/data/designs/ios-line-android.md +517 -0
  415. package/dist/data/designs/ios-line-expo.md +402 -0
  416. package/dist/data/designs/ios-line-swiftui.md +361 -0
  417. package/dist/data/designs/ios-line.md +362 -0
  418. package/dist/data/designs/ios-linear-android.md +457 -0
  419. package/dist/data/designs/ios-linear-expo.md +367 -0
  420. package/dist/data/designs/ios-linear-swiftui.md +401 -0
  421. package/dist/data/designs/ios-linear.md +368 -0
  422. package/dist/data/designs/ios-linkedin-android.md +620 -0
  423. package/dist/data/designs/ios-linkedin-expo.md +469 -0
  424. package/dist/data/designs/ios-linkedin-swiftui.md +472 -0
  425. package/dist/data/designs/ios-linkedin.md +444 -0
  426. package/dist/data/designs/ios-locket-android.md +500 -0
  427. package/dist/data/designs/ios-locket-expo.md +375 -0
  428. package/dist/data/designs/ios-locket-swiftui.md +375 -0
  429. package/dist/data/designs/ios-locket.md +381 -0
  430. package/dist/data/designs/ios-lyft-android.md +406 -0
  431. package/dist/data/designs/ios-lyft-expo.md +333 -0
  432. package/dist/data/designs/ios-lyft-swiftui.md +315 -0
  433. package/dist/data/designs/ios-lyft.md +337 -0
  434. package/dist/data/designs/ios-marriott-bonvoy-android.md +488 -0
  435. package/dist/data/designs/ios-marriott-bonvoy-expo.md +412 -0
  436. package/dist/data/designs/ios-marriott-bonvoy-swiftui.md +461 -0
  437. package/dist/data/designs/ios-marriott-bonvoy.md +379 -0
  438. package/dist/data/designs/ios-mastodon-android.md +476 -0
  439. package/dist/data/designs/ios-mastodon-expo.md +379 -0
  440. package/dist/data/designs/ios-mastodon-swiftui.md +349 -0
  441. package/dist/data/designs/ios-mastodon.md +337 -0
  442. package/dist/data/designs/ios-match-android.md +496 -0
  443. package/dist/data/designs/ios-match-expo.md +393 -0
  444. package/dist/data/designs/ios-match-swiftui.md +450 -0
  445. package/dist/data/designs/ios-match.md +382 -0
  446. package/dist/data/designs/ios-max-android.md +454 -0
  447. package/dist/data/designs/ios-max-expo.md +342 -0
  448. package/dist/data/designs/ios-max-swiftui.md +332 -0
  449. package/dist/data/designs/ios-max.md +352 -0
  450. package/dist/data/designs/ios-mcdonalds-android.md +497 -0
  451. package/dist/data/designs/ios-mcdonalds-expo.md +382 -0
  452. package/dist/data/designs/ios-mcdonalds-swiftui.md +394 -0
  453. package/dist/data/designs/ios-mcdonalds.md +410 -0
  454. package/dist/data/designs/ios-messenger-android.md +523 -0
  455. package/dist/data/designs/ios-messenger-expo.md +379 -0
  456. package/dist/data/designs/ios-messenger-swiftui.md +369 -0
  457. package/dist/data/designs/ios-messenger.md +361 -0
  458. package/dist/data/designs/ios-microsoft-teams-android.md +446 -0
  459. package/dist/data/designs/ios-microsoft-teams-expo.md +362 -0
  460. package/dist/data/designs/ios-microsoft-teams-swiftui.md +384 -0
  461. package/dist/data/designs/ios-microsoft-teams.md +359 -0
  462. package/dist/data/designs/ios-midjourney-android.md +503 -0
  463. package/dist/data/designs/ios-midjourney-expo.md +406 -0
  464. package/dist/data/designs/ios-midjourney-swiftui.md +376 -0
  465. package/dist/data/designs/ios-midjourney.md +407 -0
  466. package/dist/data/designs/ios-miro-android.md +475 -0
  467. package/dist/data/designs/ios-miro-expo.md +421 -0
  468. package/dist/data/designs/ios-miro-swiftui.md +407 -0
  469. package/dist/data/designs/ios-miro.md +424 -0
  470. package/dist/data/designs/ios-monday-android.md +426 -0
  471. package/dist/data/designs/ios-monday-expo.md +382 -0
  472. package/dist/data/designs/ios-monday-swiftui.md +386 -0
  473. package/dist/data/designs/ios-monday.md +415 -0
  474. package/dist/data/designs/ios-monzo-android.md +423 -0
  475. package/dist/data/designs/ios-monzo-expo.md +391 -0
  476. package/dist/data/designs/ios-monzo-swiftui.md +371 -0
  477. package/dist/data/designs/ios-monzo.md +382 -0
  478. package/dist/data/designs/ios-myfitnesspal-android.md +631 -0
  479. package/dist/data/designs/ios-myfitnesspal-expo.md +489 -0
  480. package/dist/data/designs/ios-myfitnesspal-swiftui.md +500 -0
  481. package/dist/data/designs/ios-myfitnesspal.md +408 -0
  482. package/dist/data/designs/ios-netflix-android.md +570 -0
  483. package/dist/data/designs/ios-netflix-expo.md +528 -0
  484. package/dist/data/designs/ios-netflix-swiftui.md +543 -0
  485. package/dist/data/designs/ios-netflix.md +476 -0
  486. package/dist/data/designs/ios-nextdoor-android.md +399 -0
  487. package/dist/data/designs/ios-nextdoor-expo.md +317 -0
  488. package/dist/data/designs/ios-nextdoor-swiftui.md +343 -0
  489. package/dist/data/designs/ios-nextdoor.md +332 -0
  490. package/dist/data/designs/ios-nike-run-club-android.md +598 -0
  491. package/dist/data/designs/ios-nike-run-club-expo.md +459 -0
  492. package/dist/data/designs/ios-nike-run-club-swiftui.md +474 -0
  493. package/dist/data/designs/ios-nike-run-club.md +400 -0
  494. package/dist/data/designs/ios-noom-android.md +455 -0
  495. package/dist/data/designs/ios-noom-expo.md +362 -0
  496. package/dist/data/designs/ios-noom-swiftui.md +369 -0
  497. package/dist/data/designs/ios-noom.md +404 -0
  498. package/dist/data/designs/ios-notion-android.md +575 -0
  499. package/dist/data/designs/ios-notion-expo.md +543 -0
  500. package/dist/data/designs/ios-notion-swiftui.md +562 -0
  501. package/dist/data/designs/ios-notion.md +506 -0
  502. package/dist/data/designs/ios-nubank-android.md +447 -0
  503. package/dist/data/designs/ios-nubank-expo.md +391 -0
  504. package/dist/data/designs/ios-nubank-swiftui.md +391 -0
  505. package/dist/data/designs/ios-nubank.md +388 -0
  506. package/dist/data/designs/ios-obsidian-android.md +456 -0
  507. package/dist/data/designs/ios-obsidian-expo.md +401 -0
  508. package/dist/data/designs/ios-obsidian-swiftui.md +412 -0
  509. package/dist/data/designs/ios-obsidian.md +363 -0
  510. package/dist/data/designs/ios-okcupid-android.md +496 -0
  511. package/dist/data/designs/ios-okcupid-expo.md +378 -0
  512. package/dist/data/designs/ios-okcupid-swiftui.md +343 -0
  513. package/dist/data/designs/ios-okcupid.md +364 -0
  514. package/dist/data/designs/ios-opentable-android.md +426 -0
  515. package/dist/data/designs/ios-opentable-expo.md +350 -0
  516. package/dist/data/designs/ios-opentable-swiftui.md +328 -0
  517. package/dist/data/designs/ios-opentable.md +411 -0
  518. package/dist/data/designs/ios-oura-android.md +426 -0
  519. package/dist/data/designs/ios-oura-expo.md +353 -0
  520. package/dist/data/designs/ios-oura-swiftui.md +327 -0
  521. package/dist/data/designs/ios-oura.md +356 -0
  522. package/dist/data/designs/ios-overcast-android.md +508 -0
  523. package/dist/data/designs/ios-overcast-expo.md +420 -0
  524. package/dist/data/designs/ios-overcast-swiftui.md +427 -0
  525. package/dist/data/designs/ios-overcast.md +414 -0
  526. package/dist/data/designs/ios-pandora-android.md +477 -0
  527. package/dist/data/designs/ios-pandora-expo.md +406 -0
  528. package/dist/data/designs/ios-pandora-swiftui.md +413 -0
  529. package/dist/data/designs/ios-pandora.md +366 -0
  530. package/dist/data/designs/ios-panera-android.md +414 -0
  531. package/dist/data/designs/ios-panera-expo.md +352 -0
  532. package/dist/data/designs/ios-panera-swiftui.md +369 -0
  533. package/dist/data/designs/ios-panera.md +412 -0
  534. package/dist/data/designs/ios-paramount-plus-android.md +415 -0
  535. package/dist/data/designs/ios-paramount-plus-expo.md +363 -0
  536. package/dist/data/designs/ios-paramount-plus-swiftui.md +372 -0
  537. package/dist/data/designs/ios-paramount-plus.md +400 -0
  538. package/dist/data/designs/ios-paypal-android.md +535 -0
  539. package/dist/data/designs/ios-paypal-expo.md +429 -0
  540. package/dist/data/designs/ios-paypal-swiftui.md +466 -0
  541. package/dist/data/designs/ios-paypal.md +393 -0
  542. package/dist/data/designs/ios-peacock-android.md +453 -0
  543. package/dist/data/designs/ios-peacock-expo.md +393 -0
  544. package/dist/data/designs/ios-peacock-swiftui.md +420 -0
  545. package/dist/data/designs/ios-peacock.md +411 -0
  546. package/dist/data/designs/ios-peloton-android.md +470 -0
  547. package/dist/data/designs/ios-peloton-expo.md +401 -0
  548. package/dist/data/designs/ios-peloton-swiftui.md +409 -0
  549. package/dist/data/designs/ios-peloton.md +415 -0
  550. package/dist/data/designs/ios-perplexity-android.md +553 -0
  551. package/dist/data/designs/ios-perplexity-expo.md +703 -0
  552. package/dist/data/designs/ios-perplexity-swiftui.md +602 -0
  553. package/dist/data/designs/ios-perplexity.md +453 -0
  554. package/dist/data/designs/ios-pinterest-android.md +551 -0
  555. package/dist/data/designs/ios-pinterest-expo.md +466 -0
  556. package/dist/data/designs/ios-pinterest-swiftui.md +464 -0
  557. package/dist/data/designs/ios-pinterest.md +427 -0
  558. package/dist/data/designs/ios-plenty-of-fish-android.md +462 -0
  559. package/dist/data/designs/ios-plenty-of-fish-expo.md +380 -0
  560. package/dist/data/designs/ios-plenty-of-fish-swiftui.md +429 -0
  561. package/dist/data/designs/ios-plenty-of-fish.md +387 -0
  562. package/dist/data/designs/ios-plex-android.md +403 -0
  563. package/dist/data/designs/ios-plex-expo.md +333 -0
  564. package/dist/data/designs/ios-plex-swiftui.md +349 -0
  565. package/dist/data/designs/ios-plex.md +379 -0
  566. package/dist/data/designs/ios-pluto-tv-android.md +413 -0
  567. package/dist/data/designs/ios-pluto-tv-expo.md +379 -0
  568. package/dist/data/designs/ios-pluto-tv-swiftui.md +411 -0
  569. package/dist/data/designs/ios-pluto-tv.md +362 -0
  570. package/dist/data/designs/ios-pocket-casts-android.md +492 -0
  571. package/dist/data/designs/ios-pocket-casts-expo.md +430 -0
  572. package/dist/data/designs/ios-pocket-casts-swiftui.md +479 -0
  573. package/dist/data/designs/ios-pocket-casts.md +427 -0
  574. package/dist/data/designs/ios-postman-android.md +472 -0
  575. package/dist/data/designs/ios-postman-expo.md +372 -0
  576. package/dist/data/designs/ios-postman-swiftui.md +377 -0
  577. package/dist/data/designs/ios-postman.md +405 -0
  578. package/dist/data/designs/ios-prime-video-android.md +447 -0
  579. package/dist/data/designs/ios-prime-video-expo.md +365 -0
  580. package/dist/data/designs/ios-prime-video-swiftui.md +333 -0
  581. package/dist/data/designs/ios-prime-video.md +351 -0
  582. package/dist/data/designs/ios-quora-android.md +513 -0
  583. package/dist/data/designs/ios-quora-expo.md +362 -0
  584. package/dist/data/designs/ios-quora-swiftui.md +375 -0
  585. package/dist/data/designs/ios-quora.md +359 -0
  586. package/dist/data/designs/ios-raya-android.md +401 -0
  587. package/dist/data/designs/ios-raya-expo.md +366 -0
  588. package/dist/data/designs/ios-raya-swiftui.md +393 -0
  589. package/dist/data/designs/ios-raya.md +366 -0
  590. package/dist/data/designs/ios-reddit-android.md +605 -0
  591. package/dist/data/designs/ios-reddit-expo.md +553 -0
  592. package/dist/data/designs/ios-reddit-swiftui.md +514 -0
  593. package/dist/data/designs/ios-reddit.md +460 -0
  594. package/dist/data/designs/ios-resy-android.md +430 -0
  595. package/dist/data/designs/ios-resy-expo.md +344 -0
  596. package/dist/data/designs/ios-resy-swiftui.md +330 -0
  597. package/dist/data/designs/ios-resy.md +412 -0
  598. package/dist/data/designs/ios-revolut-android.md +433 -0
  599. package/dist/data/designs/ios-revolut-expo.md +379 -0
  600. package/dist/data/designs/ios-revolut-swiftui.md +372 -0
  601. package/dist/data/designs/ios-revolut.md +353 -0
  602. package/dist/data/designs/ios-robinhood-android.md +587 -0
  603. package/dist/data/designs/ios-robinhood-expo.md +416 -0
  604. package/dist/data/designs/ios-robinhood-swiftui.md +431 -0
  605. package/dist/data/designs/ios-robinhood.md +380 -0
  606. package/dist/data/designs/ios-runna-android.md +485 -0
  607. package/dist/data/designs/ios-runna-expo.md +388 -0
  608. package/dist/data/designs/ios-runna-swiftui.md +413 -0
  609. package/dist/data/designs/ios-runna.md +390 -0
  610. package/dist/data/designs/ios-shazam-android.md +436 -0
  611. package/dist/data/designs/ios-shazam-expo.md +348 -0
  612. package/dist/data/designs/ios-shazam-swiftui.md +394 -0
  613. package/dist/data/designs/ios-shazam.md +338 -0
  614. package/dist/data/designs/ios-signal-android.md +462 -0
  615. package/dist/data/designs/ios-signal-expo.md +361 -0
  616. package/dist/data/designs/ios-signal-swiftui.md +350 -0
  617. package/dist/data/designs/ios-signal.md +357 -0
  618. package/dist/data/designs/ios-skype-android.md +398 -0
  619. package/dist/data/designs/ios-skype-expo.md +368 -0
  620. package/dist/data/designs/ios-skype-swiftui.md +369 -0
  621. package/dist/data/designs/ios-skype.md +406 -0
  622. package/dist/data/designs/ios-skyscanner-android.md +451 -0
  623. package/dist/data/designs/ios-skyscanner-expo.md +423 -0
  624. package/dist/data/designs/ios-skyscanner-swiftui.md +419 -0
  625. package/dist/data/designs/ios-skyscanner.md +421 -0
  626. package/dist/data/designs/ios-slack-android.md +695 -0
  627. package/dist/data/designs/ios-slack-expo.md +601 -0
  628. package/dist/data/designs/ios-slack-swiftui.md +594 -0
  629. package/dist/data/designs/ios-slack.md +474 -0
  630. package/dist/data/designs/ios-sleep-cycle-android.md +436 -0
  631. package/dist/data/designs/ios-sleep-cycle-expo.md +380 -0
  632. package/dist/data/designs/ios-sleep-cycle-swiftui.md +409 -0
  633. package/dist/data/designs/ios-sleep-cycle.md +386 -0
  634. package/dist/data/designs/ios-snapchat-android.md +671 -0
  635. package/dist/data/designs/ios-snapchat-expo.md +528 -0
  636. package/dist/data/designs/ios-snapchat-swiftui.md +557 -0
  637. package/dist/data/designs/ios-snapchat.md +478 -0
  638. package/dist/data/designs/ios-sofi-android.md +446 -0
  639. package/dist/data/designs/ios-sofi-expo.md +387 -0
  640. package/dist/data/designs/ios-sofi-swiftui.md +379 -0
  641. package/dist/data/designs/ios-sofi.md +385 -0
  642. package/dist/data/designs/ios-soundcloud-android.md +488 -0
  643. package/dist/data/designs/ios-soundcloud-expo.md +364 -0
  644. package/dist/data/designs/ios-soundcloud-swiftui.md +399 -0
  645. package/dist/data/designs/ios-soundcloud.md +359 -0
  646. package/dist/data/designs/ios-southwest-android.md +446 -0
  647. package/dist/data/designs/ios-southwest-expo.md +389 -0
  648. package/dist/data/designs/ios-southwest-swiftui.md +405 -0
  649. package/dist/data/designs/ios-southwest.md +405 -0
  650. package/dist/data/designs/ios-spotify-android.md +427 -0
  651. package/dist/data/designs/ios-spotify-expo.md +321 -0
  652. package/dist/data/designs/ios-spotify-swiftui.md +312 -0
  653. package/dist/data/designs/ios-spotify.md +366 -0
  654. package/dist/data/designs/ios-starbucks-android.md +622 -0
  655. package/dist/data/designs/ios-starbucks-expo.md +497 -0
  656. package/dist/data/designs/ios-starbucks-swiftui.md +500 -0
  657. package/dist/data/designs/ios-starbucks.md +440 -0
  658. package/dist/data/designs/ios-strava-android.md +656 -0
  659. package/dist/data/designs/ios-strava-expo.md +501 -0
  660. package/dist/data/designs/ios-strava-swiftui.md +465 -0
  661. package/dist/data/designs/ios-strava.md +433 -0
  662. package/dist/data/designs/ios-strong-android.md +479 -0
  663. package/dist/data/designs/ios-strong-expo.md +396 -0
  664. package/dist/data/designs/ios-strong-swiftui.md +363 -0
  665. package/dist/data/designs/ios-strong.md +415 -0
  666. package/dist/data/designs/ios-substack-android.md +440 -0
  667. package/dist/data/designs/ios-substack-expo.md +395 -0
  668. package/dist/data/designs/ios-substack-swiftui.md +371 -0
  669. package/dist/data/designs/ios-substack.md +372 -0
  670. package/dist/data/designs/ios-swiggy-android.md +549 -0
  671. package/dist/data/designs/ios-swiggy-expo.md +443 -0
  672. package/dist/data/designs/ios-swiggy-swiftui.md +471 -0
  673. package/dist/data/designs/ios-swiggy.md +432 -0
  674. package/dist/data/designs/ios-taco-bell-android.md +529 -0
  675. package/dist/data/designs/ios-taco-bell-expo.md +407 -0
  676. package/dist/data/designs/ios-taco-bell-swiftui.md +419 -0
  677. package/dist/data/designs/ios-taco-bell.md +430 -0
  678. package/dist/data/designs/ios-telegram-android.md +676 -0
  679. package/dist/data/designs/ios-telegram-expo.md +594 -0
  680. package/dist/data/designs/ios-telegram-swiftui.md +518 -0
  681. package/dist/data/designs/ios-telegram.md +458 -0
  682. package/dist/data/designs/ios-the-league-android.md +454 -0
  683. package/dist/data/designs/ios-the-league-expo.md +391 -0
  684. package/dist/data/designs/ios-the-league-swiftui.md +409 -0
  685. package/dist/data/designs/ios-the-league.md +368 -0
  686. package/dist/data/designs/ios-things-3-android.md +421 -0
  687. package/dist/data/designs/ios-things-3-expo.md +351 -0
  688. package/dist/data/designs/ios-things-3-swiftui.md +359 -0
  689. package/dist/data/designs/ios-things-3.md +339 -0
  690. package/dist/data/designs/ios-threads-android.md +588 -0
  691. package/dist/data/designs/ios-threads-expo.md +468 -0
  692. package/dist/data/designs/ios-threads-swiftui.md +452 -0
  693. package/dist/data/designs/ios-threads.md +424 -0
  694. package/dist/data/designs/ios-threema-android.md +496 -0
  695. package/dist/data/designs/ios-threema-expo.md +415 -0
  696. package/dist/data/designs/ios-threema-swiftui.md +446 -0
  697. package/dist/data/designs/ios-threema.md +397 -0
  698. package/dist/data/designs/ios-tidal-android.md +398 -0
  699. package/dist/data/designs/ios-tidal-expo.md +323 -0
  700. package/dist/data/designs/ios-tidal-swiftui.md +340 -0
  701. package/dist/data/designs/ios-tidal.md +351 -0
  702. package/dist/data/designs/ios-tiktok-android.md +654 -0
  703. package/dist/data/designs/ios-tiktok-expo.md +578 -0
  704. package/dist/data/designs/ios-tiktok-swiftui.md +595 -0
  705. package/dist/data/designs/ios-tiktok.md +387 -0
  706. package/dist/data/designs/ios-tinder-android.md +681 -0
  707. package/dist/data/designs/ios-tinder-expo.md +512 -0
  708. package/dist/data/designs/ios-tinder-swiftui.md +497 -0
  709. package/dist/data/designs/ios-tinder.md +415 -0
  710. package/dist/data/designs/ios-todoist-android.md +711 -0
  711. package/dist/data/designs/ios-todoist-expo.md +607 -0
  712. package/dist/data/designs/ios-todoist-swiftui.md +573 -0
  713. package/dist/data/designs/ios-todoist.md +418 -0
  714. package/dist/data/designs/ios-trello-android.md +412 -0
  715. package/dist/data/designs/ios-trello-expo.md +332 -0
  716. package/dist/data/designs/ios-trello-swiftui.md +359 -0
  717. package/dist/data/designs/ios-trello.md +344 -0
  718. package/dist/data/designs/ios-tripadvisor-android.md +450 -0
  719. package/dist/data/designs/ios-tripadvisor-expo.md +322 -0
  720. package/dist/data/designs/ios-tripadvisor-swiftui.md +326 -0
  721. package/dist/data/designs/ios-tripadvisor.md +356 -0
  722. package/dist/data/designs/ios-tubi-android.md +453 -0
  723. package/dist/data/designs/ios-tubi-expo.md +419 -0
  724. package/dist/data/designs/ios-tubi-swiftui.md +463 -0
  725. package/dist/data/designs/ios-tubi.md +383 -0
  726. package/dist/data/designs/ios-tumblr-android.md +462 -0
  727. package/dist/data/designs/ios-tumblr-expo.md +374 -0
  728. package/dist/data/designs/ios-tumblr-swiftui.md +380 -0
  729. package/dist/data/designs/ios-tumblr.md +337 -0
  730. package/dist/data/designs/ios-turo-android.md +500 -0
  731. package/dist/data/designs/ios-turo-expo.md +454 -0
  732. package/dist/data/designs/ios-turo-swiftui.md +447 -0
  733. package/dist/data/designs/ios-turo.md +392 -0
  734. package/dist/data/designs/ios-twitch-android.md +412 -0
  735. package/dist/data/designs/ios-twitch-expo.md +342 -0
  736. package/dist/data/designs/ios-twitch-swiftui.md +328 -0
  737. package/dist/data/designs/ios-twitch.md +354 -0
  738. package/dist/data/designs/ios-uber-android.md +637 -0
  739. package/dist/data/designs/ios-uber-eats-android.md +502 -0
  740. package/dist/data/designs/ios-uber-eats-expo.md +407 -0
  741. package/dist/data/designs/ios-uber-eats-swiftui.md +393 -0
  742. package/dist/data/designs/ios-uber-eats.md +353 -0
  743. package/dist/data/designs/ios-uber-expo.md +512 -0
  744. package/dist/data/designs/ios-uber-swiftui.md +483 -0
  745. package/dist/data/designs/ios-uber.md +395 -0
  746. package/dist/data/designs/ios-united-airlines-android.md +494 -0
  747. package/dist/data/designs/ios-united-airlines-expo.md +408 -0
  748. package/dist/data/designs/ios-united-airlines-swiftui.md +453 -0
  749. package/dist/data/designs/ios-united-airlines.md +388 -0
  750. package/dist/data/designs/ios-venmo-android.md +654 -0
  751. package/dist/data/designs/ios-venmo-expo.md +458 -0
  752. package/dist/data/designs/ios-venmo-swiftui.md +469 -0
  753. package/dist/data/designs/ios-venmo.md +436 -0
  754. package/dist/data/designs/ios-vercel-android.md +454 -0
  755. package/dist/data/designs/ios-vercel-expo.md +387 -0
  756. package/dist/data/designs/ios-vercel-swiftui.md +374 -0
  757. package/dist/data/designs/ios-vercel.md +399 -0
  758. package/dist/data/designs/ios-vero-android.md +498 -0
  759. package/dist/data/designs/ios-vero-expo.md +376 -0
  760. package/dist/data/designs/ios-vero-swiftui.md +374 -0
  761. package/dist/data/designs/ios-vero.md +394 -0
  762. package/dist/data/designs/ios-viber-android.md +377 -0
  763. package/dist/data/designs/ios-viber-expo.md +375 -0
  764. package/dist/data/designs/ios-viber-swiftui.md +378 -0
  765. package/dist/data/designs/ios-viber.md +403 -0
  766. package/dist/data/designs/ios-vimeo-android.md +465 -0
  767. package/dist/data/designs/ios-vimeo-expo.md +347 -0
  768. package/dist/data/designs/ios-vimeo-swiftui.md +383 -0
  769. package/dist/data/designs/ios-vimeo.md +403 -0
  770. package/dist/data/designs/ios-vrbo-android.md +488 -0
  771. package/dist/data/designs/ios-vrbo-expo.md +395 -0
  772. package/dist/data/designs/ios-vrbo-swiftui.md +421 -0
  773. package/dist/data/designs/ios-vrbo.md +383 -0
  774. package/dist/data/designs/ios-vsco-android.md +490 -0
  775. package/dist/data/designs/ios-vsco-expo.md +413 -0
  776. package/dist/data/designs/ios-vsco-swiftui.md +449 -0
  777. package/dist/data/designs/ios-vsco.md +412 -0
  778. package/dist/data/designs/ios-walmart-android.md +479 -0
  779. package/dist/data/designs/ios-walmart-expo.md +370 -0
  780. package/dist/data/designs/ios-walmart-swiftui.md +387 -0
  781. package/dist/data/designs/ios-walmart.md +366 -0
  782. package/dist/data/designs/ios-waze-android.md +695 -0
  783. package/dist/data/designs/ios-waze-expo.md +587 -0
  784. package/dist/data/designs/ios-waze-swiftui.md +601 -0
  785. package/dist/data/designs/ios-waze.md +453 -0
  786. package/dist/data/designs/ios-webull-android.md +429 -0
  787. package/dist/data/designs/ios-webull-expo.md +384 -0
  788. package/dist/data/designs/ios-webull-swiftui.md +406 -0
  789. package/dist/data/designs/ios-webull.md +375 -0
  790. package/dist/data/designs/ios-wechat-android.md +545 -0
  791. package/dist/data/designs/ios-wechat-expo.md +398 -0
  792. package/dist/data/designs/ios-wechat-swiftui.md +394 -0
  793. package/dist/data/designs/ios-wechat.md +363 -0
  794. package/dist/data/designs/ios-whatsapp-android.md +568 -0
  795. package/dist/data/designs/ios-whatsapp-expo.md +502 -0
  796. package/dist/data/designs/ios-whatsapp-swiftui.md +483 -0
  797. package/dist/data/designs/ios-whatsapp.md +425 -0
  798. package/dist/data/designs/ios-whoop-android.md +635 -0
  799. package/dist/data/designs/ios-whoop-expo.md +562 -0
  800. package/dist/data/designs/ios-whoop-swiftui.md +553 -0
  801. package/dist/data/designs/ios-whoop.md +419 -0
  802. package/dist/data/designs/ios-wise-android.md +428 -0
  803. package/dist/data/designs/ios-wise-expo.md +357 -0
  804. package/dist/data/designs/ios-wise-swiftui.md +356 -0
  805. package/dist/data/designs/ios-wise.md +361 -0
  806. package/dist/data/designs/ios-x-twitter-android.md +618 -0
  807. package/dist/data/designs/ios-x-twitter-expo.md +442 -0
  808. package/dist/data/designs/ios-x-twitter-swiftui.md +429 -0
  809. package/dist/data/designs/ios-x-twitter.md +432 -0
  810. package/dist/data/designs/ios-yelp-android.md +455 -0
  811. package/dist/data/designs/ios-yelp-expo.md +397 -0
  812. package/dist/data/designs/ios-yelp-swiftui.md +369 -0
  813. package/dist/data/designs/ios-yelp.md +398 -0
  814. package/dist/data/designs/ios-youtube-android.md +668 -0
  815. package/dist/data/designs/ios-youtube-expo.md +435 -0
  816. package/dist/data/designs/ios-youtube-music-android.md +450 -0
  817. package/dist/data/designs/ios-youtube-music-expo.md +404 -0
  818. package/dist/data/designs/ios-youtube-music-swiftui.md +434 -0
  819. package/dist/data/designs/ios-youtube-music.md +381 -0
  820. package/dist/data/designs/ios-youtube-swiftui.md +496 -0
  821. package/dist/data/designs/ios-youtube.md +466 -0
  822. package/dist/data/designs/ios-zalo-android.md +510 -0
  823. package/dist/data/designs/ios-zalo-expo.md +389 -0
  824. package/dist/data/designs/ios-zalo-swiftui.md +431 -0
  825. package/dist/data/designs/ios-zalo.md +388 -0
  826. package/dist/data/designs/ios-zomato-android.md +527 -0
  827. package/dist/data/designs/ios-zomato-expo.md +437 -0
  828. package/dist/data/designs/ios-zomato-swiftui.md +433 -0
  829. package/dist/data/designs/ios-zomato.md +439 -0
  830. package/dist/data/designs/ios-zoom-android.md +423 -0
  831. package/dist/data/designs/ios-zoom-expo.md +355 -0
  832. package/dist/data/designs/ios-zoom-swiftui.md +379 -0
  833. package/dist/data/designs/ios-zoom.md +357 -0
  834. package/dist/data/designs/ios-zwift-android.md +402 -0
  835. package/dist/data/designs/ios-zwift-expo.md +402 -0
  836. package/dist/data/designs/ios-zwift-swiftui.md +378 -0
  837. package/dist/data/designs/ios-zwift.md +411 -0
  838. package/dist/data/designs/kraken.md +125 -0
  839. package/dist/data/designs/lamborghini.md +288 -0
  840. package/dist/data/designs/linear.app.md +548 -0
  841. package/dist/data/designs/lovable.md +298 -0
  842. package/dist/data/designs/mastercard.md +365 -0
  843. package/dist/data/designs/material-clean.md +289 -0
  844. package/dist/data/designs/meta.md +683 -0
  845. package/dist/data/designs/midnight-pro.md +256 -0
  846. package/dist/data/designs/minimal-brutalist.md +245 -0
  847. package/dist/data/designs/minimax.md +746 -0
  848. package/dist/data/designs/mintlify.md +852 -0
  849. package/dist/data/designs/miro.md +825 -0
  850. package/dist/data/designs/mistral.ai.md +773 -0
  851. package/dist/data/designs/mongodb.md +767 -0
  852. package/dist/data/designs/nike.md +575 -0
  853. package/dist/data/designs/nintendo-2001.md +649 -0
  854. package/dist/data/designs/notion.md +821 -0
  855. package/dist/data/designs/nova-mobile-design-md.md +235 -0
  856. package/dist/data/designs/nvidia.md +640 -0
  857. package/dist/data/designs/ollama.md +539 -0
  858. package/dist/data/designs/opencode.ai.md +521 -0
  859. package/dist/data/designs/pinterest.md +597 -0
  860. package/dist/data/designs/playful-color.md +253 -0
  861. package/dist/data/designs/playstation.md +661 -0
  862. package/dist/data/designs/posthog.md +690 -0
  863. package/dist/data/designs/raycast.md +669 -0
  864. package/dist/data/designs/renault.md +589 -0
  865. package/dist/data/designs/replicate.md +616 -0
  866. package/dist/data/designs/resend.md +585 -0
  867. package/dist/data/designs/revolut.md +636 -0
  868. package/dist/data/designs/runwayml.md +244 -0
  869. package/dist/data/designs/sanity.md +357 -0
  870. package/dist/data/designs/sentry.md +551 -0
  871. package/dist/data/designs/shopify.md +516 -0
  872. package/dist/data/designs/slack.md +482 -0
  873. package/dist/data/designs/soft-glass.md +258 -0
  874. package/dist/data/designs/spacex.md +363 -0
  875. package/dist/data/designs/spotify.md +246 -0
  876. package/dist/data/designs/starbucks.md +580 -0
  877. package/dist/data/designs/stripe.md +487 -0
  878. package/dist/data/designs/supabase.md +462 -0
  879. package/dist/data/designs/superhuman.md +448 -0
  880. package/dist/data/designs/tesla.md +286 -0
  881. package/dist/data/designs/theverge.md +339 -0
  882. package/dist/data/designs/together.ai.md +633 -0
  883. package/dist/data/designs/uber.md +636 -0
  884. package/dist/data/designs/vercel.md +736 -0
  885. package/dist/data/designs/vodafone.md +538 -0
  886. package/dist/data/designs/voltagent.md +521 -0
  887. package/dist/data/designs/warp.md +526 -0
  888. package/dist/data/designs/webflow.md +588 -0
  889. package/dist/data/designs/wired.md +497 -0
  890. package/dist/data/designs/wise.md +544 -0
  891. package/dist/data/designs/x.ai.md +465 -0
  892. package/dist/data/designs/zapier.md +537 -0
  893. package/dist/data/index.json +2600 -0
  894. package/dist/httpServer.js +83 -0
  895. package/dist/index.js +13 -0
  896. package/dist/server.js +32 -0
  897. package/dist/services/designStore.js +59 -0
  898. package/dist/services/linter.js +87 -0
  899. package/dist/services/sectionParser.js +154 -0
  900. package/dist/tools/authoring.js +131 -0
  901. package/dist/tools/browse.js +232 -0
  902. package/dist/tools/diff.js +88 -0
  903. package/dist/tools/getDesign.js +216 -0
  904. package/dist/tools/guardrails.js +87 -0
  905. package/dist/tools/lint.js +104 -0
  906. package/dist/types.js +1 -0
  907. package/package.json +65 -0
@@ -0,0 +1,695 @@
1
+ # Waze (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Waze's playful, cartoon-forward visual language to **Android with Jetpack Compose (Material 3)**: a color token object, a `Typography` set, paste-ready `@Composable`s (the cartoon hazard speech bubble, the cyan arrow puck, the next-turn card, the report FAB, the speed-limit tile, the "Go" button), `Modifier`s, motion, and haptics.
4
+
5
+ > Why a Compose guide for an iOS-referenced app? The DESIGN.md tokens are platform-neutral. This file keeps the *visual* identity (the Waze Purple + Cyan electric duo, the **chunky cartoon speech-bubble hazard reports with triangular tails**, the cyan arrow puck, the loud saturated cartography, the tinted purple FAB shadow, Boing's roundness) while making everything idiomatic Android — Google Maps Compose instead of MapKit, SF Pro Rounded's analog (`FontFamily` fallback) for Boing, custom `Shape`s for the tail and arrow, `LocalHapticFeedback` instead of `.sensoryFeedback`, `sp`/`dp` instead of `pt`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3, and `com.google.maps.android:maps-compose` for the loud cartography. No color extraction, so `androidx.palette` is not required.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ ```kotlin
12
+ // ui/theme/WazeColors.kt
13
+ import androidx.compose.ui.graphics.Color
14
+
15
+ object WazeColors {
16
+ // Brand
17
+ val Purple = Color(0xFF7E55BE) // logo, polyline, FAB, "Go", primary CTAs
18
+ val PurpleDeep = Color(0xFF5B3C9A)
19
+ val PurpleTint = Color(0xFFE8DEF5)
20
+ val Cyan = Color(0xFF33CCFF) // location puck, info glyphs, 2nd logo color
21
+ val CyanDeep = Color(0xFF0099E5)
22
+
23
+ // Hazard colors (the cartoon system)
24
+ val PoliceRed = Color(0xFFEF6A65)
25
+ val TrafficOrng = Color(0xFFF69833)
26
+ val ClosureYel = Color(0xFFF9C42E)
27
+ val ClearedGrn = Color(0xFF75C73E)
28
+ val HazardBrown = Color(0xFF8B6F47)
29
+ val CameraGray = Color(0xFF6B6B6B)
30
+
31
+ // Map cartography (light) — LOUD by design
32
+ val MapCream = Color(0xFFFFFCF2)
33
+ val MapWater = Color(0xFF9BDEEF)
34
+ val MapPark = Color(0xFFC5E89B)
35
+ val MapRoadMajor = Color(0xFFFFFFFF)
36
+ val MapRoadMinor = Color(0xFFF5F0E5)
37
+ val MapHighway = Color(0xFFFFD970)
38
+ val MapBuilding = Color(0xFFE8E2D1)
39
+ val MapLabel = Color(0xFF3D3D3D)
40
+
41
+ // UI chrome
42
+ val CardCanvas = Color(0xFFFFFFFF)
43
+ val SurfaceGray = Color(0xFFF5F5F7)
44
+ val SurfaceGray2 = Color(0xFFEAEAEC)
45
+ val Divider = Color(0xFFD6D6D9)
46
+
47
+ // Text
48
+ val Ink = Color(0xFF1A1A1A) // warm near-black
49
+ val Secondary = Color(0xFF6B6B6B)
50
+ val Tertiary = Color(0xFFA0A0A0)
51
+
52
+ // Semantic
53
+ val Success = Color(0xFF34C759)
54
+ val Warning = Color(0xFFF9C42E)
55
+ val Error = Color(0xFFEF6A65)
56
+
57
+ // Dark (night driving)
58
+ val DarkMapLand = Color(0xFF1E2026)
59
+ val DarkMapWater = Color(0xFF0F3D5E)
60
+ val DarkMapPark = Color(0xFF1F3A1F)
61
+ val DarkCardSurf = Color(0xFF262932)
62
+ val DarkSurface2 = Color(0xFF3A3D47)
63
+ val DarkDivider = Color(0xFF4A4D58)
64
+ val PurpleDark = Color(0xFF9F76DA) // brightened for dark legibility
65
+ val CyanDark = Color(0xFF5DD9FF)
66
+ }
67
+ ```
68
+
69
+ Waze is a map-first app: a loud light cartography by day, near-black "night driving" by night — but the **Waze Purple + Cyan stay at brand saturation in both**. Wire both Material 3 schemes accordingly.
70
+
71
+ ```kotlin
72
+ // ui/theme/Theme.kt
73
+ import androidx.compose.material3.lightColorScheme
74
+ import androidx.compose.material3.darkColorScheme
75
+ import androidx.compose.material3.MaterialTheme
76
+
77
+ private val WazeLight = lightColorScheme(
78
+ primary = WazeColors.Purple,
79
+ onPrimary = Color.White,
80
+ secondary = WazeColors.Cyan,
81
+ background = WazeColors.CardCanvas,
82
+ onBackground = WazeColors.Ink,
83
+ surface = WazeColors.CardCanvas,
84
+ onSurface = WazeColors.Ink,
85
+ surfaceVariant = WazeColors.SurfaceGray,
86
+ outline = WazeColors.Divider,
87
+ error = WazeColors.Error,
88
+ )
89
+
90
+ private val WazeDark = darkColorScheme(
91
+ primary = WazeColors.PurpleDark, // brightened, still brand
92
+ onPrimary = Color.White,
93
+ secondary = WazeColors.CyanDark,
94
+ background = WazeColors.DarkMapLand,
95
+ onBackground = Color.White,
96
+ surface = WazeColors.DarkCardSurf,
97
+ onSurface = Color.White,
98
+ surfaceVariant = WazeColors.DarkSurface2,
99
+ outline = WazeColors.DarkDivider,
100
+ error = WazeColors.Error,
101
+ )
102
+
103
+ @Composable
104
+ fun WazeTheme(darkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) =
105
+ MaterialTheme(
106
+ colorScheme = if (darkTheme) WazeDark else WazeLight,
107
+ typography = WazeTypography,
108
+ content = content,
109
+ )
110
+ ```
111
+
112
+ ## 2. Typography
113
+
114
+ Waze ships **Boing**, a proprietary rounded sans — roundness IS the brand. The correct Android fallback is the rounded system family. Compose has no built-in `.rounded` design like iOS, so bundle Boing TTFs in `res/font/`; if unavailable, ship a rounded open-source face (Quicksand / Nunito) as the fallback `FontFamily`. **Boing Mono on every numeric** (distance, time, speed, ETA) — variable widths break the at-a-glance driving read.
115
+
116
+ ```kotlin
117
+ // ui/theme/WazeType.kt
118
+ import androidx.compose.material3.Typography
119
+ import androidx.compose.ui.text.TextStyle
120
+ import androidx.compose.ui.text.font.Font
121
+ import androidx.compose.ui.text.font.FontFamily
122
+ import androidx.compose.ui.text.font.FontWeight
123
+ import androidx.compose.ui.unit.sp
124
+
125
+ // Boing, with a rounded open-source fallback (Quicksand/Nunito) bundled in res/font/
126
+ val Boing = FontFamily(
127
+ Font(R.font.boing_regular, FontWeight.Normal), // 400
128
+ Font(R.font.boing_bold, FontWeight.Bold), // 700
129
+ Font(R.font.boing_black, FontWeight.Black), // 900 — hero moments only
130
+ )
131
+ val BoingMono = FontFamily(
132
+ Font(R.font.boing_mono_medium, FontWeight.Medium),
133
+ Font(R.font.boing_mono_bold, FontWeight.Bold),
134
+ Font(R.font.boing_mono_black, FontWeight.Black),
135
+ )
136
+
137
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1). Numerics use BoingMono + tabular figures.
138
+ object WazeText {
139
+ val HeroStreet = TextStyle(Boing, fontWeight = FontWeight.Black, fontSize = 32.sp, lineHeight = 35.sp, letterSpacing = (-0.4).sp)
140
+ val NextTurnDist = TextStyle(BoingMono, fontWeight = FontWeight.Bold, fontSize = 28.sp, lineHeight = 31.sp, fontFeatureSettings = "tnum")
141
+ val StepTitle = TextStyle(Boing, fontWeight = FontWeight.Bold, fontSize = 22.sp, lineHeight = 26.sp, letterSpacing = (-0.2).sp)
142
+ val StepSubtitle = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 17.sp, lineHeight = 22.sp)
143
+ val ETATime = TextStyle(BoingMono, fontWeight = FontWeight.Bold, fontSize = 24.sp, lineHeight = 26.sp, fontFeatureSettings = "tnum")
144
+ val ETADistance = TextStyle(BoingMono, fontWeight = FontWeight.Medium, fontSize = 17.sp, lineHeight = 20.sp, fontFeatureSettings = "tnum")
145
+ val PlaceTitle = TextStyle(Boing, fontWeight = FontWeight.Bold, fontSize = 26.sp, lineHeight = 30.sp, letterSpacing = (-0.3).sp)
146
+ val PlaceSubtitle = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 20.sp)
147
+ val SearchHint = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 17.sp, lineHeight = 22.sp)
148
+ val Section = TextStyle(Boing, fontWeight = FontWeight.Bold, fontSize = 13.sp, lineHeight = 16.sp, letterSpacing = 0.6.sp) // UPPERCASE at call site
149
+ val ListTitle = TextStyle(Boing, fontWeight = FontWeight.Medium, fontSize = 17.sp, lineHeight = 22.sp)
150
+ val ListSubtitle = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 16.sp)
151
+ val SpeedLimitNum = TextStyle(BoingMono, fontWeight = FontWeight.Black, fontSize = 22.sp, lineHeight = 22.sp, fontFeatureSettings = "tnum")
152
+ val CurrentSpeed = TextStyle(BoingMono, fontWeight = FontWeight.Bold, fontSize = 32.sp, lineHeight = 32.sp, fontFeatureSettings = "tnum")
153
+ val SpeedLimitLbl = TextStyle(Boing, fontWeight = FontWeight.Bold, fontSize = 9.sp, lineHeight = 11.sp)
154
+ val MphLabel = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 11.sp, lineHeight = 13.sp)
155
+ val HazardTitle = TextStyle(Boing, fontWeight = FontWeight.Bold, fontSize = 14.sp, lineHeight = 15.sp)
156
+ val HazardTime = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 11.sp, lineHeight = 12.sp)
157
+ val Button = TextStyle(Boing, fontWeight = FontWeight.Bold, fontSize = 17.sp, lineHeight = 17.sp)
158
+ val Caption = TextStyle(Boing, fontWeight = FontWeight.Normal, fontSize = 12.sp, lineHeight = 16.sp)
159
+ val Tab = TextStyle(Boing, fontWeight = FontWeight.Medium, fontSize = 10.sp, lineHeight = 10.sp, letterSpacing = 0.1.sp)
160
+ }
161
+
162
+ // Map onto Material 3 slots so stock components inherit the brand
163
+ val WazeTypography = Typography(
164
+ headlineLarge = WazeText.HeroStreet,
165
+ headlineSmall = WazeText.PlaceTitle,
166
+ titleMedium = WazeText.StepTitle,
167
+ bodyMedium = WazeText.PlaceSubtitle,
168
+ labelLarge = WazeText.Button,
169
+ labelSmall = WazeText.Tab,
170
+ )
171
+ ```
172
+
173
+ ## 3. Signature Components
174
+
175
+ ### Hazard Speech Bubble (The Signature)
176
+
177
+ The single most recognizable component: a chunky 14.dp-corner rounded rectangle in a full-saturation hazard color with a **triangular tail** pointing down to the location. Implemented with a custom `Shape` for the tail (no SF Symbol / Compose primitive matches it).
178
+
179
+ ```kotlin
180
+ import androidx.compose.animation.core.Animatable
181
+ import androidx.compose.animation.core.spring
182
+ import androidx.compose.foundation.background
183
+ import androidx.compose.foundation.layout.*
184
+ import androidx.compose.foundation.shape.RoundedCornerShape
185
+ import androidx.compose.material.icons.Icons
186
+ import androidx.compose.material.icons.filled.*
187
+ import androidx.compose.material3.Icon
188
+ import androidx.compose.material3.Text
189
+ import androidx.compose.runtime.*
190
+ import androidx.compose.ui.Alignment
191
+ import androidx.compose.ui.Modifier
192
+ import androidx.compose.ui.draw.clip
193
+ import androidx.compose.ui.draw.drawBehind
194
+ import androidx.compose.ui.draw.shadow
195
+ import androidx.compose.ui.geometry.Offset
196
+ import androidx.compose.ui.graphics.Color
197
+ import androidx.compose.ui.graphics.Path
198
+ import androidx.compose.ui.graphics.drawscope.Stroke
199
+ import androidx.compose.ui.graphics.vector.ImageVector
200
+ import androidx.compose.ui.unit.dp
201
+
202
+ enum class HazardType { POLICE, TRAFFIC, CLOSURE, CLEARED, POTHOLE, CAMERA }
203
+
204
+ val HazardType.color: Color
205
+ get() = when (this) {
206
+ HazardType.POLICE -> WazeColors.PoliceRed
207
+ HazardType.TRAFFIC -> WazeColors.TrafficOrng
208
+ HazardType.CLOSURE -> WazeColors.ClosureYel
209
+ HazardType.CLEARED -> WazeColors.ClearedGrn
210
+ HazardType.POTHOLE -> WazeColors.HazardBrown
211
+ HazardType.CAMERA -> WazeColors.CameraGray
212
+ }
213
+
214
+ val HazardType.icon: ImageVector
215
+ get() = when (this) {
216
+ HazardType.POLICE -> Icons.Filled.Shield
217
+ HazardType.TRAFFIC -> Icons.Filled.Warning
218
+ HazardType.CLOSURE -> Icons.Filled.Block
219
+ HazardType.CLEARED -> Icons.Filled.CheckCircle
220
+ HazardType.POTHOLE -> Icons.Filled.ReportProblem
221
+ HazardType.CAMERA -> Icons.Filled.CameraAlt
222
+ }
223
+
224
+ val HazardType.title: String
225
+ get() = name.lowercase().replaceFirstChar { it.uppercase() }
226
+
227
+ @Composable
228
+ fun HazardSpeechBubble(
229
+ type: HazardType,
230
+ timeAgo: String?,
231
+ modifier: Modifier = Modifier,
232
+ ) {
233
+ val appear = remember { Animatable(0f) }
234
+ LaunchedEffect(Unit) {
235
+ appear.animateTo(1f, spring(dampingRatio = 0.55f, stiffness = 400f)) // pop: 0 → 1.15 → 1.0
236
+ }
237
+
238
+ Column(
239
+ modifier = modifier
240
+ .graphicsLayer { scaleX = appear.value; scaleY = appear.value }
241
+ .shadow(12.dp, RoundedCornerShape(14.dp), spotColor = Color.Black.copy(alpha = 0.2f)),
242
+ horizontalAlignment = Alignment.CenterHorizontally,
243
+ ) {
244
+ Row(
245
+ Modifier
246
+ .clip(RoundedCornerShape(14.dp))
247
+ .background(type.color)
248
+ .widthIn(min = 88.dp)
249
+ .padding(horizontal = 12.dp, vertical = 8.dp),
250
+ verticalAlignment = Alignment.CenterVertically,
251
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
252
+ ) {
253
+ Icon(type.icon, contentDescription = null, tint = Color.White, modifier = Modifier.size(24.dp))
254
+ Column {
255
+ Text(type.title, style = WazeText.HazardTitle, color = Color.White)
256
+ if (timeAgo != null) Text(timeAgo, style = WazeText.HazardTime, color = Color.White.copy(alpha = 0.8f))
257
+ }
258
+ }
259
+ // Downward triangular tail — custom drawn, same color as the bubble
260
+ Box(
261
+ Modifier
262
+ .size(12.dp, 8.dp)
263
+ .drawBehind {
264
+ val p = Path().apply {
265
+ moveTo(0f, 0f)
266
+ lineTo(size.width, 0f)
267
+ lineTo(size.width / 2f, size.height)
268
+ close()
269
+ }
270
+ drawPath(p, type.color)
271
+ }
272
+ )
273
+ }
274
+ }
275
+ ```
276
+
277
+ ### Report FAB (Tinted Purple Shadow — Signature)
278
+
279
+ Bottom-right Waze Purple circle with a **tinted purple shadow** (`spotColor` purple, not black). Opens the report wheel.
280
+
281
+ ```kotlin
282
+ import androidx.compose.animation.core.animateFloatAsState
283
+ import androidx.compose.foundation.clickable
284
+ import androidx.compose.foundation.interaction.MutableInteractionSource
285
+ import androidx.compose.foundation.interaction.collectIsPressedAsState
286
+ import androidx.compose.foundation.shape.CircleShape
287
+ import androidx.compose.ui.draw.scale
288
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
289
+ import androidx.compose.ui.platform.LocalHapticFeedback
290
+
291
+ @Composable
292
+ fun WazeFAB(onClick: () -> Unit, modifier: Modifier = Modifier) {
293
+ val interaction = remember { MutableInteractionSource() }
294
+ val pressed by interaction.collectIsPressedAsState()
295
+ val scale by animateFloatAsState(if (pressed) 0.94f else 1f, label = "fabScale")
296
+ val haptics = LocalHapticFeedback.current
297
+
298
+ Box(
299
+ modifier = modifier
300
+ .size(56.dp)
301
+ .scale(scale)
302
+ .shadow(16.dp, CircleShape, spotColor = WazeColors.Purple, ambientColor = WazeColors.Purple) // SIGNATURE tinted purple
303
+ .clip(CircleShape)
304
+ .background(if (pressed) WazeColors.PurpleDeep else WazeColors.Purple)
305
+ .clickable(interaction, indication = null) {
306
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ~iOS medium impact
307
+ onClick()
308
+ }
309
+ .semantics { contentDescription = "Report a hazard" },
310
+ contentAlignment = Alignment.Center,
311
+ ) {
312
+ Icon(Icons.Filled.Campaign, contentDescription = null, tint = Color.White, modifier = Modifier.size(24.dp))
313
+ }
314
+ }
315
+ ```
316
+
317
+ > `spotColor` is honored on API 28+; on older devices draw a soft purple radial glow behind the circle so the signature reads on every device.
318
+
319
+ ### Current-Location Puck (Cyan Arrow with Pulse)
320
+
321
+ Waze's puck is a **chunky cyan arrow** (NOT a dot), white-outlined, rotating with heading, with a faint 60.dp pulse ring. Both the arrow and the pulse are custom-drawn.
322
+
323
+ ```kotlin
324
+ import androidx.compose.animation.core.*
325
+ import androidx.compose.foundation.Canvas
326
+ import androidx.compose.ui.geometry.Size
327
+ import androidx.compose.ui.graphics.StrokeCap
328
+ import androidx.compose.ui.graphics.drawscope.Stroke as DrawStroke
329
+
330
+ @Composable
331
+ fun WazeLocationPuck(headingDegrees: Float, modifier: Modifier = Modifier) {
332
+ val t = rememberInfiniteTransition(label = "puck")
333
+ val pulse by t.animateFloat(
334
+ 0f, 1f, infiniteRepeatable(tween(2000, easing = LinearEasing), RepeatMode.Restart), label = "pulse",
335
+ )
336
+
337
+ Box(modifier, contentAlignment = Alignment.Center) {
338
+ // Outer cyan pulse ring — 0.15 alpha, scale 1.0 → 1.5
339
+ Box(
340
+ Modifier
341
+ .size(60.dp)
342
+ .graphicsLayer { scaleX = 1f + pulse * 0.5f; scaleY = 1f + pulse * 0.5f }
343
+ .background(WazeColors.Cyan.copy(alpha = 0.15f * (1f - pulse)), CircleShape)
344
+ )
345
+ // Chunky cyan arrow, rotates with heading, 3.dp white outline
346
+ Canvas(
347
+ Modifier.size(32.dp, 36.dp).graphicsLayer { rotationZ = headingDegrees }
348
+ ) {
349
+ val w = size.width
350
+ val h = size.height
351
+ val arrow = Path().apply {
352
+ moveTo(w * 0.5f, 0f) // tip
353
+ lineTo(w, h * 0.85f) // bottom-right
354
+ lineTo(w * 0.5f, h * 0.70f) // V indent
355
+ lineTo(0f, h * 0.85f) // bottom-left
356
+ close()
357
+ }
358
+ drawPath(arrow, WazeColors.Cyan)
359
+ drawPath(arrow, Color.White, style = DrawStroke(width = 3.dp.toPx()))
360
+ }
361
+ }
362
+ }
363
+ ```
364
+
365
+ ### Next-Turn Card (Top of Screen During Navigation)
366
+
367
+ Full-width 100.dp solid Waze Purple card, 16.dp **bottom** corners only (extends into the safe area on top), big direction arrow + Mono distance + street name.
368
+
369
+ ```kotlin
370
+ @Composable
371
+ fun NextTurnCard(
372
+ arrowIcon: ImageVector, // e.g. Icons.AutoMirrored.Filled.TurnRight
373
+ arrowRotation: Float,
374
+ distance: String, // "0.4 mi"
375
+ streetName: String, // "Market Street"
376
+ subInstruction: String?, // "then turn left in 0.6 mi"
377
+ modifier: Modifier = Modifier,
378
+ ) {
379
+ Row(
380
+ modifier = modifier
381
+ .fillMaxWidth()
382
+ .clip(RoundedCornerShape(bottomStart = 16.dp, bottomEnd = 16.dp)) // top extends into safe area
383
+ .background(WazeColors.Purple)
384
+ .padding(horizontal = 20.dp, vertical = 16.dp),
385
+ verticalAlignment = Alignment.CenterVertically,
386
+ horizontalArrangement = Arrangement.spacedBy(16.dp),
387
+ ) {
388
+ Icon(
389
+ arrowIcon, contentDescription = null, tint = Color.White,
390
+ modifier = Modifier.size(64.dp).graphicsLayer { rotationZ = arrowRotation },
391
+ )
392
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) {
393
+ Text(distance, style = WazeText.NextTurnDist, color = Color.White)
394
+ Text(streetName, style = WazeText.StepTitle, color = Color.White, maxLines = 2)
395
+ if (subInstruction != null) {
396
+ Text(subInstruction, style = WazeText.Caption.copy(fontSize = 14.sp), color = Color.White.copy(alpha = 0.8f))
397
+ }
398
+ }
399
+ }
400
+ }
401
+ ```
402
+
403
+ ### Speed Limit + Current Speed Tile
404
+
405
+ US-style speed-limit signage as an 80×80.dp bottom-left tile; the current-speed number flips red when speeding.
406
+
407
+ ```kotlin
408
+ import androidx.compose.foundation.border
409
+ import androidx.compose.material3.HorizontalDivider
410
+
411
+ @Composable
412
+ fun SpeedTile(limit: Int, current: Int, modifier: Modifier = Modifier) {
413
+ val speeding = current > limit
414
+ Column(
415
+ modifier = modifier
416
+ .width(80.dp)
417
+ .shadow(8.dp, RoundedCornerShape(12.dp), spotColor = Color.Black.copy(alpha = 0.10f))
418
+ .clip(RoundedCornerShape(12.dp))
419
+ .background(WazeColors.CardCanvas)
420
+ .padding(8.dp),
421
+ horizontalAlignment = Alignment.CenterHorizontally,
422
+ verticalArrangement = Arrangement.spacedBy(6.dp),
423
+ ) {
424
+ Text("SPEED LIMIT", style = WazeText.SpeedLimitLbl, color = WazeColors.Ink)
425
+ Box(
426
+ Modifier.size(40.dp).clip(CircleShape).background(Color.White).border(2.dp, WazeColors.Ink, CircleShape),
427
+ contentAlignment = Alignment.Center,
428
+ ) { Text("$limit", style = WazeText.SpeedLimitNum, color = WazeColors.Ink) }
429
+ HorizontalDivider(color = WazeColors.Divider, modifier = Modifier.padding(horizontal = 8.dp))
430
+ Row(verticalAlignment = Alignment.Bottom, horizontalArrangement = Arrangement.spacedBy(4.dp)) {
431
+ Text("$current", style = WazeText.CurrentSpeed, color = if (speeding) WazeColors.Error else WazeColors.Ink)
432
+ Text("mph", style = WazeText.MphLabel, color = WazeColors.Secondary)
433
+ }
434
+ }
435
+ }
436
+ ```
437
+
438
+ ### ETA Bottom Bar & "Go" Button
439
+
440
+ ```kotlin
441
+ @Composable
442
+ fun WazeETABar(
443
+ duration: String, // "12 min"
444
+ distance: String, // "5.2 mi"
445
+ arrival: String, // "6:14 PM"
446
+ alternativeRouteSaves: String?, // "Save 3 min"
447
+ onEnd: () -> Unit,
448
+ modifier: Modifier = Modifier,
449
+ ) {
450
+ Row(
451
+ modifier = modifier.fillMaxWidth().height(80.dp).background(WazeColors.CardCanvas).padding(horizontal = 20.dp),
452
+ verticalAlignment = Alignment.CenterVertically,
453
+ horizontalArrangement = Arrangement.spacedBy(16.dp),
454
+ ) {
455
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) {
456
+ Text(duration, style = WazeText.ETATime, color = WazeColors.Ink)
457
+ Text("$distance · $arrival", style = WazeText.ETADistance, color = WazeColors.Secondary)
458
+ }
459
+ if (alternativeRouteSaves != null) {
460
+ Box(
461
+ Modifier.clip(CircleShape).background(WazeColors.ClearedGrn).padding(horizontal = 14.dp, vertical = 8.dp)
462
+ ) { Text(alternativeRouteSaves, style = WazeText.Button.copy(fontSize = 14.sp), color = Color.White) }
463
+ }
464
+ Box(
465
+ Modifier.clip(CircleShape).background(WazeColors.CardCanvas).border(1.5.dp, WazeColors.Error, CircleShape)
466
+ .clickable(onClick = onEnd).padding(horizontal = 20.dp, vertical = 12.dp)
467
+ ) { Text("End", style = WazeText.Button, color = WazeColors.Error) }
468
+ }
469
+ }
470
+
471
+ @Composable
472
+ fun WazeGoButton(onClick: () -> Unit, modifier: Modifier = Modifier) {
473
+ val interaction = remember { MutableInteractionSource() }
474
+ val pressed by interaction.collectIsPressedAsState()
475
+ val scale by animateFloatAsState(if (pressed) 0.97f else 1f, label = "goScale")
476
+ val haptics = LocalHapticFeedback.current
477
+
478
+ Box(
479
+ modifier = modifier
480
+ .fillMaxWidth()
481
+ .height(56.dp)
482
+ .scale(scale)
483
+ .shadow(12.dp, CircleShape, spotColor = WazeColors.Purple, ambientColor = WazeColors.Purple) // tinted purple
484
+ .clip(CircleShape)
485
+ .background(if (pressed) WazeColors.PurpleDeep else WazeColors.Purple)
486
+ .clickable(interaction, indication = null) {
487
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ~iOS heavy impact (see §6 for stronger)
488
+ onClick()
489
+ },
490
+ contentAlignment = Alignment.Center,
491
+ ) {
492
+ Text("Go", style = WazeText.Button, color = Color.White)
493
+ }
494
+ }
495
+ ```
496
+
497
+ ## 4. Loud Cartography + Report Wheel (the distinctive interaction)
498
+
499
+ Waze has no color extraction. Its defining systems are the **loud saturated cartography** and the **cartoon report wheel**. Use Google Maps Compose with a JSON style built from the bright Waze tokens; the polyline is a 6.dp purple "ant trail".
500
+
501
+ ```kotlin
502
+ import com.google.maps.android.compose.GoogleMap
503
+ import com.google.maps.android.compose.MapProperties
504
+ import com.google.maps.android.compose.Polyline
505
+ import com.google.maps.android.compose.rememberCameraPositionState
506
+ import com.google.android.gms.maps.model.MapStyleOptions
507
+ import com.google.android.gms.maps.model.LatLng
508
+ import com.google.android.gms.maps.model.RoundCap
509
+
510
+ @Composable
511
+ fun WazeMap(route: List<LatLng>, modifier: Modifier = Modifier, darkTheme: Boolean = isSystemInDarkTheme()) {
512
+ val cameraPositionState = rememberCameraPositionState()
513
+ GoogleMap(
514
+ modifier = modifier.fillMaxSize(),
515
+ cameraPositionState = cameraPositionState,
516
+ properties = MapProperties(
517
+ // JSON style from Waze tokens: water #9BDEEF, parks #C5E89B, land #FFFCF2,
518
+ // highways #FFD970, roads #FFFFFF — LOUD by design (dark: #0F3D5E / #1F3A1F / #1E2026)
519
+ mapStyleOptions = MapStyleOptions(if (darkTheme) WAZE_MAP_STYLE_DARK else WAZE_MAP_STYLE_LIGHT),
520
+ ),
521
+ ) {
522
+ Polyline(
523
+ points = route,
524
+ color = WazeColors.Purple, // 6.dp purple — thicker than typical
525
+ width = with(androidx.compose.ui.platform.LocalDensity.current) { 6.dp.toPx() },
526
+ startCap = RoundCap(), endCap = RoundCap(),
527
+ )
528
+ // Ant-trail chevron overlay: a second dashed polyline whose pattern offset animates (see §6)
529
+ }
530
+ }
531
+
532
+ const val WAZE_MAP_STYLE_LIGHT = """[ /* water #9BDEEF, parks #C5E89B, land #FFFCF2, highway #FFD970, roads #FFFFFF */ ]"""
533
+ const val WAZE_MAP_STYLE_DARK = """[ /* water #0F3D5E, parks #1F3A1F, land #1E2026, roads #2F2F2F */ ]"""
534
+ ```
535
+
536
+ ### Report Wheel (Cartoon Dial)
537
+
538
+ A literal cartoon dial — embrace it, never tone it down. 8 wedges of hazard icons over a purple scrim.
539
+
540
+ ```kotlin
541
+ import androidx.compose.foundation.layout.Box
542
+ import kotlin.math.cos
543
+ import kotlin.math.sin
544
+
545
+ @Composable
546
+ fun ReportWheel(
547
+ onPick: (HazardType) -> Unit,
548
+ onClose: () -> Unit,
549
+ modifier: Modifier = Modifier,
550
+ ) {
551
+ val types = listOf(
552
+ HazardType.POLICE, HazardType.TRAFFIC, HazardType.CLOSURE, HazardType.POTHOLE,
553
+ HazardType.CAMERA, HazardType.CLEARED,
554
+ )
555
+ val wheelScale = remember { Animatable(0f) }
556
+ LaunchedEffect(Unit) { wheelScale.animateTo(1f, spring(dampingRatio = 0.7f, stiffness = 300f)) } // spins in
557
+
558
+ Box(
559
+ modifier
560
+ .fillMaxSize()
561
+ .background(WazeColors.Purple.copy(alpha = 0.85f)) // semi-transparent purple scrim
562
+ .clickable(interactionSource = remember { MutableInteractionSource() }, indication = null, onClick = onClose),
563
+ contentAlignment = Alignment.BottomCenter,
564
+ ) {
565
+ Box(
566
+ Modifier
567
+ .padding(bottom = 80.dp)
568
+ .size(280.dp)
569
+ .graphicsLayer { scaleX = wheelScale.value; scaleY = wheelScale.value }
570
+ .clip(CircleShape)
571
+ .background(WazeColors.CardCanvas),
572
+ contentAlignment = Alignment.Center,
573
+ ) {
574
+ types.forEachIndexed { i, type ->
575
+ val angle = Math.toRadians((i * (360.0 / types.size)) - 90.0)
576
+ val r = 90.dp
577
+ Box(
578
+ Modifier
579
+ .offset(x = (cos(angle) * r.value).dp, y = (sin(angle) * r.value).dp)
580
+ .size(44.dp).clip(CircleShape).background(type.color.copy(alpha = 0.20f))
581
+ .clickable { onPick(type) },
582
+ contentAlignment = Alignment.Center,
583
+ ) { Icon(type.icon, contentDescription = type.title, tint = type.color, modifier = Modifier.size(28.dp)) }
584
+ }
585
+ Box(
586
+ Modifier.size(56.dp).clip(CircleShape).background(WazeColors.SurfaceGray).clickable(onClick = onClose),
587
+ contentAlignment = Alignment.Center,
588
+ ) { Icon(Icons.Filled.Close, contentDescription = "Close", tint = WazeColors.Ink, modifier = Modifier.size(24.dp)) }
589
+ }
590
+ }
591
+ }
592
+ ```
593
+
594
+ ## 5. Navigation (search bottom sheet, no tab bar)
595
+
596
+ Waze has no bottom tab bar during driving — the map is full-screen with the next-turn card on top, the ETA bar on the bottom, and a **search bottom sheet** (3 detents: small ≈88.dp, medium ≈50%, full). Android has no live blur; Waze uses a **solid white card** anyway (explicitly unlike Apple's translucent sheet), so a plain opaque `Surface` is the correct choice — no translucency needed.
597
+
598
+ ```kotlin
599
+ import androidx.compose.material3.ExperimentalMaterial3Api
600
+ import androidx.compose.material3.ModalBottomSheet
601
+ import androidx.compose.material3.rememberModalBottomSheetState
602
+ import androidx.compose.foundation.text.BasicTextField
603
+ import androidx.compose.ui.graphics.SolidColor
604
+
605
+ @OptIn(ExperimentalMaterial3Api::class)
606
+ @Composable
607
+ fun WazeSearchSheet(onDismiss: () -> Unit, content: @Composable ColumnScope.() -> Unit) {
608
+ ModalBottomSheet(
609
+ onDismissRequest = onDismiss,
610
+ sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = false),
611
+ containerColor = WazeColors.CardCanvas, // solid white — Waze never uses a translucent sheet
612
+ shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
613
+ dragHandle = {
614
+ Box(Modifier.fillMaxWidth().padding(top = 8.dp, bottom = 8.dp), contentAlignment = Alignment.Center) {
615
+ Box(Modifier.size(36.dp, 5.dp).clip(RoundedCornerShape(2.5.dp)).background(WazeColors.Divider))
616
+ }
617
+ },
618
+ ) {
619
+ Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp)) {
620
+ Row(
621
+ Modifier.fillMaxWidth().height(48.dp).clip(RoundedCornerShape(16.dp)).background(WazeColors.SurfaceGray)
622
+ .padding(horizontal = 16.dp),
623
+ verticalAlignment = Alignment.CenterVertically,
624
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
625
+ ) {
626
+ Icon(Icons.Filled.Search, null, tint = WazeColors.Secondary, modifier = Modifier.size(17.dp))
627
+ Text("Where to?", style = WazeText.SearchHint, color = WazeColors.Tertiary)
628
+ }
629
+ content()
630
+ }
631
+ }
632
+ }
633
+ ```
634
+
635
+ ## 6. Motion
636
+
637
+ | Moment | Compose recipe |
638
+ |--------|----------------|
639
+ | FAB tap | `animateFloatAsState(0.94f)` + shadow tighten; `HapticFeedbackType.LongPress` |
640
+ | Report wheel open | `Animatable.animateTo(1f, spring(dampingRatio = 0.7f, stiffness = 300f))` — wheel spins in (~350ms) |
641
+ | Hazard bubble appear | `Animatable.animateTo(1f, spring(dampingRatio = 0.55f))` — pop 0 → 1.15 → 1.0 over ~400ms |
642
+ | Hazard dismiss (timer) | `animateFloatAsState` alpha 1 → 0 over 1000ms + slight `rotationZ` |
643
+ | Location puck pulse | `rememberInfiniteTransition` scale 1.0 → 1.5, alpha 0.15 → 0, 2000ms `RepeatMode.Restart` |
644
+ | Polyline ant trail | animate a dash-phase `Float` linearly, 2s loop, `RepeatMode.Restart` |
645
+ | Next-turn update | `Crossfade` 250ms + arrow `rotationZ` to the new turn |
646
+ | "Go" tap | `animateFloatAsState(0.97f)` + heavy haptic; 400ms `Crossfade` into navigation mode |
647
+ | Reach destination | confetti/sparkle `Canvas` over the destination pin + success haptic |
648
+
649
+ ```kotlin
650
+ // Polyline "ant trail" — animate the dash phase (DESIGN.md §6: 1 chevron / 2 s)
651
+ @Composable
652
+ fun rememberAntTrailPhase(): Float {
653
+ val t = rememberInfiniteTransition(label = "antTrail")
654
+ val phase by t.animateFloat(
655
+ 0f, -24f, infiniteRepeatable(tween(2000, easing = LinearEasing), RepeatMode.Restart), label = "phase",
656
+ )
657
+ return phase // feed into a PathEffect dashPathEffect on a Canvas-drawn route overlay
658
+ }
659
+ ```
660
+
661
+ Haptics: prefer `LocalHapticFeedback`. For the heavier "Go" / arrival moments use a `Vibrator` `VibrationEffect.createOneShot(25, VibrationEffect.DEFAULT_AMPLITUDE)` to approximate iOS `.impact(.heavy)` / `.success`; the speeding warning maps to a single `VibrationEffect.createOneShot(15, ...)` triggered once when current speed crosses the limit.
662
+
663
+ ## 7. Icons
664
+
665
+ Waze ships custom cartoon glyphs (the police hat, the chunky direction arrows); the closest first-party set is `androidx.compose.material:material-icons-extended`. For the playful cartoon feel that makes contributing fun, export Waze's hazard glyphs and the direction arrows as vector drawables and load via `ImageVector.vectorResource(R.drawable.…)`. The triangular speech-bubble tail and the cyan arrow puck are custom `Path`s (above) — no SF Symbol or Compose primitive matches them.
666
+
667
+ | Purpose | SF Symbol (iOS) | Material Icon (Compose) |
668
+ |---------|-----------------|--------------------------|
669
+ | FAB report icon | `exclamationmark.bubble.fill` | `Icons.Filled.Campaign` (or custom speech-bubble drawable) |
670
+ | Police hazard | `shield.fill` (or custom hat) | `Icons.Filled.Shield` |
671
+ | Traffic hazard | `cone.fill` | `Icons.Filled.Warning` |
672
+ | Closure | `xmark.octagon.fill` | `Icons.Filled.Block` |
673
+ | Cleared | `checkmark.circle.fill` | `Icons.Filled.CheckCircle` |
674
+ | Pothole | `exclamationmark.triangle.fill` | `Icons.Filled.ReportProblem` |
675
+ | Camera | `camera.fill` | `Icons.Filled.CameraAlt` |
676
+ | Direction right / left | `arrow.turn.up.right` / `.left` | `Icons.AutoMirrored.Filled.TurnRight` / `TurnLeft` |
677
+ | Search | `magnifyingglass` | `Icons.Filled.Search` |
678
+ | Speed warning | `exclamationmark.octagon.fill` | `Icons.Filled.Report` |
679
+ | Beacon share | `bell.badge.fill` | `Icons.Filled.NotificationsActive` |
680
+ | Gas | `fuelpump.fill` | `Icons.Filled.LocalGasStation` |
681
+ | Home | `house.fill` | `Icons.Filled.Home` |
682
+ | Work | `briefcase.fill` | `Icons.Filled.Work` |
683
+ | Favorite | `star.fill` | `Icons.Filled.Star` |
684
+ | Recent | `clock` | `Icons.Filled.History` |
685
+
686
+ ## 8. Minimum SDK & Accessibility Notes
687
+
688
+ - **minSdk 24** (Compose floor is 21; Maps Compose + the tinted shadows are comfortable at 24 — `spotColor` needs API 28+, fall back to a soft purple radial glow behind the FAB/"Go" on older devices). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`. Add a Maps API key in the manifest.
689
+ - **Edge-to-edge**: call `enableEdgeToEdge()`. The next-turn card intentionally extends into the status-bar area (top corners are square) with 16.dp of content padding from the safe-area top; the ETA bar and FAB respect `WindowInsets.navigationBars` (the FAB sits 16.dp above the ETA bar's inset).
690
+ - **Font scaling**: `sp` honors the user's font scale automatically — keep it on the place card title, body, list rows, and search. **FIX** the glance-critical text — next-turn card, ETA numbers, speed-limit number, hazard speech-bubble text are read at driving speed and must not reflow: derive from `dp` or wrap those subtrees in `CompositionLocalProvider(LocalDensity provides Density(density, fontScale = 1f))`.
691
+ - **TalkBack**: the hazard bubble reads as `"$type, reported $timeAgo, ahead"` via `Modifier.semantics(mergeDescendants = true)`; the location puck announces `"Your current position, heading <direction>"`; the speed tile reads limit + current speed and announces a warning state.
692
+ - **Touch targets**: Material guidance is 48.dp minimum. The 56.dp FAB and 56.dp "Go" button clear it; the full hazard bubble is tappable; report-wheel wedges are 44.dp (pad to a 48.dp hit slop); the Wazer avatar carries a 48.dp hit area on a 24.dp glyph.
693
+ - **Contrast**: Ink `#1A1A1A` on white passes WCAG AAA. White on Waze Purple `#7E55BE` passes AAA at all sizes (next-turn card, "Go"). The hazard speech bubbles use white text on full-saturation hazard colors — Closure Yellow `#F9C42E` with white is a known low-contrast pair; keep the 14sp Bold title weight (it passes AA at that weight) and never go below 14sp for hazard text. The 0.8-alpha white timestamp on hazard colors stays ≥11sp Bold-adjacent.
694
+ - **Reduce motion**: when a reduced-motion preference is set, skip the hazard "pop", freeze the location-puck pulse and the polyline ant trail (static), and replace the "Go" → navigation crossfade with an instant cut.
695
+ - **Dynamic color**: do **not** enable Material You `dynamicColorScheme` — Waze's identity is the fixed electric duo (Waze Purple `#7E55BE` + Cyan `#33CCFF`) and the full-saturation hazard palette. These must stay at brand saturation across light/dark/night modes; wallpaper-derived tints would mute the cartoon system and break the at-a-glance hazard color code.