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,656 @@
1
+ # Strava (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Strava's visual language to **Android with Jetpack Compose (Material 3)**: a color token object, a `Typography` set, paste-ready `@Composable`s, `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 single Strava-Orange accent, the haloed route polyline, the universal 3-up stat grid, coal-black dark mode) while making everything idiomatic Android — `NavigationBar` with a protruding center FAB instead of a UITabBar, Google Maps Compose `Polyline` instead of `MapPolyline`, `sp`/`dp` instead of `pt`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3, `com.google.maps.android:maps-compose` `4.3+` for the route snapshot, and [Coil](https://coil-kt.github.io/coil/) `2.6+` for athlete avatars. No color extraction — Strava is monochromatically Orange, so `androidx.palette` is not required.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ ```kotlin
12
+ // ui/theme/StravaColors.kt
13
+ import androidx.compose.ui.graphics.Color
14
+
15
+ object StravaColors {
16
+ // Strava Orange — the only accent
17
+ val Orange = Color(0xFFFC4C02)
18
+ val OrangePressed = Color(0xFFD44002)
19
+ val OrangeHalo = Color(0xFFFC4C02).copy(alpha = 0.3f) // luminance ring under the polyline
20
+
21
+ // Canvas, Surface, Divider (Light)
22
+ val Canvas = Color(0xFFFFFFFF)
23
+ val SurfaceWarm = Color(0xFFF5F4F2)
24
+ val SurfaceCool = Color(0xFFF0F0F0)
25
+ val Divider = Color(0xFFE5E5E5)
26
+ val MapTile = Color(0xFFE8E5DD) // warm parchment base — never gray
27
+
28
+ // Text (Light)
29
+ val InkPrimary = Color(0xFF0E0E0E)
30
+ val InkSecondary = Color(0xFF666666)
31
+ val InkTertiary = Color(0xFF9A9A9A)
32
+
33
+ // Dark mode — coal, not pure black
34
+ val DarkCanvas = Color(0xFF0F0F0F)
35
+ val DarkSurface = Color(0xFF1A1A1A)
36
+ val DarkSurface2 = Color(0xFF262626)
37
+ val DarkDivider = Color(0xFF2A2A2A)
38
+ val DarkText = Color(0xFFF2F2F2)
39
+ val DarkTextSec = Color(0xFFA0A0A0)
40
+ val DarkMapTile = Color(0xFF1B1B1B)
41
+
42
+ // Achievement & rank
43
+ val PRGold = Color(0xFFF5C24A)
44
+ val Silver = Color(0xFFC6C6C6)
45
+ val Bronze = Color(0xFFCD7F32)
46
+ val KOMCrown = Color(0xFFFFD700)
47
+
48
+ // Chart & semantic
49
+ val Success = Color(0xFF22C55E)
50
+ val HeartRed = Color(0xFFE74C3C)
51
+ val PaceBlue = Color(0xFF3B82F6)
52
+ val ElevBrown = Color(0xFF8B6F47)
53
+ val WarningAmber = Color(0xFFF59E0B)
54
+ val ErrorRed = Color(0xFFEF4444)
55
+ }
56
+ ```
57
+
58
+ Strava is white-first; supply a Material 3 `lightColorScheme` and a coal `darkColorScheme`. Orange is identical in both — it glows on coal.
59
+
60
+ ```kotlin
61
+ // ui/theme/Theme.kt
62
+ import androidx.compose.material3.lightColorScheme
63
+ import androidx.compose.material3.darkColorScheme
64
+ import androidx.compose.material3.MaterialTheme
65
+ import androidx.compose.runtime.Composable
66
+ import androidx.compose.foundation.isSystemInDarkTheme
67
+
68
+ private val StravaLight = lightColorScheme(
69
+ primary = StravaColors.Orange,
70
+ onPrimary = StravaColors.Canvas,
71
+ background = StravaColors.Canvas,
72
+ onBackground = StravaColors.InkPrimary,
73
+ surface = StravaColors.Canvas,
74
+ onSurface = StravaColors.InkPrimary,
75
+ surfaceVariant = StravaColors.SurfaceCool,
76
+ outline = StravaColors.Divider,
77
+ error = StravaColors.ErrorRed,
78
+ )
79
+
80
+ private val StravaDark = darkColorScheme(
81
+ primary = StravaColors.Orange,
82
+ onPrimary = StravaColors.Canvas,
83
+ background = StravaColors.DarkCanvas, // coal #0F0F0F, not pure black
84
+ onBackground = StravaColors.DarkText,
85
+ surface = StravaColors.DarkSurface,
86
+ onSurface = StravaColors.DarkText,
87
+ surfaceVariant = StravaColors.DarkSurface2,
88
+ outline = StravaColors.DarkDivider,
89
+ error = StravaColors.ErrorRed,
90
+ )
91
+
92
+ @Composable
93
+ fun StravaTheme(
94
+ darkTheme: Boolean = isSystemInDarkTheme(),
95
+ content: @Composable () -> Unit,
96
+ ) = MaterialTheme(
97
+ colorScheme = if (darkTheme) StravaDark else StravaLight,
98
+ typography = StravaTypography,
99
+ content = content,
100
+ )
101
+ ```
102
+
103
+ ## 2. Typography
104
+
105
+ Inside the iOS app Strava leans on SF Pro for its numeric weight stack. On Android the system equivalent is Roboto — but the Strava data voice depends on **tabular figures**, so the closest free substitute is `Roboto` with `FontFeatureSetting("tnum")`. Bundle the marketing face (Maison Neue) only if you have a license; otherwise Roboto holds.
106
+
107
+ ```kotlin
108
+ // ui/theme/StravaType.kt
109
+ import androidx.compose.material3.Typography
110
+ import androidx.compose.ui.text.TextStyle
111
+ import androidx.compose.ui.text.font.FontFamily
112
+ import androidx.compose.ui.text.font.FontWeight
113
+ import androidx.compose.ui.unit.sp
114
+
115
+ private val Sans = FontFamily.Default // Roboto on Android — closest to SF Pro
116
+ private const val TNUM = "tnum" // tabular figures — Strava's column alignment depends on it
117
+
118
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1, weights preserved)
119
+ object StravaText {
120
+ val HeroStat = TextStyle(Sans, fontWeight = FontWeight.Black, fontSize = 44.sp, lineHeight = 44.sp, letterSpacing = (-0.6).sp, fontFeatureSettings = TNUM)
121
+ val HeroUnit = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 13.sp, lineHeight = 13.sp, letterSpacing = 0.5.sp)
122
+ val LargeNav = TextStyle(Sans, fontWeight = FontWeight.Bold, fontSize = 28.sp, lineHeight = 31.sp, letterSpacing = (-0.4).sp)
123
+ val ActivityTitle = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 20.sp, letterSpacing = (-0.2).sp)
124
+ val Athlete = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 15.sp, lineHeight = 18.sp, letterSpacing = (-0.1).sp)
125
+ val SectionHdr = TextStyle(Sans, fontWeight = FontWeight.Bold, fontSize = 13.sp, lineHeight = 16.sp, letterSpacing = 0.5.sp)
126
+ val Body = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 21.sp, letterSpacing = (-0.2).sp)
127
+ val BodySmall = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 18.sp, letterSpacing = (-0.1).sp)
128
+ val StatLabel = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 11.sp, lineHeight = 13.sp, letterSpacing = 0.6.sp)
129
+ val StatValue = TextStyle(Sans, fontWeight = FontWeight.Bold, fontSize = 17.sp, lineHeight = 19.sp, fontFeatureSettings = TNUM)
130
+ val KudosCount = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 13.sp, lineHeight = 13.sp, fontFeatureSettings = TNUM)
131
+ val Meta = TextStyle(Sans, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 17.sp, letterSpacing = (-0.1).sp)
132
+ val Button = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 17.sp, letterSpacing = (-0.2).sp)
133
+ val ButtonSm = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 15.sp, lineHeight = 15.sp, letterSpacing = (-0.1).sp)
134
+ val Tab = TextStyle(Sans, fontWeight = FontWeight.SemiBold, fontSize = 10.sp, lineHeight = 10.sp, letterSpacing = 0.2.sp)
135
+ val Rank = TextStyle(Sans, fontWeight = FontWeight.Black, fontSize = 13.sp, lineHeight = 13.sp, fontFeatureSettings = TNUM)
136
+ }
137
+
138
+ // Map onto Material 3 slots so stock components inherit the brand
139
+ val StravaTypography = Typography(
140
+ headlineMedium = StravaText.LargeNav,
141
+ titleMedium = StravaText.ActivityTitle,
142
+ bodyMedium = StravaText.Body,
143
+ labelLarge = StravaText.Button,
144
+ labelSmall = StravaText.Tab,
145
+ )
146
+ ```
147
+
148
+ > Every numeric style sets `fontFeatureSettings = "tnum"`. This is the Compose analog of SwiftUI's `.monospacedDigit()` — without it, pace columns and split tables misalign and Strava users notice.
149
+
150
+ ## 3. Signature Components
151
+
152
+ ### Stat Cell + 3-Up Grid (the universal activity-card primitive)
153
+
154
+ ```kotlin
155
+ import androidx.compose.foundation.background
156
+ import androidx.compose.foundation.layout.*
157
+ import androidx.compose.material3.Text
158
+ import androidx.compose.runtime.Composable
159
+ import androidx.compose.ui.Alignment
160
+ import androidx.compose.ui.Modifier
161
+ import androidx.compose.ui.text.style.TextAlign
162
+ import androidx.compose.ui.unit.dp
163
+
164
+ @Composable
165
+ fun StatCell(label: String, value: String, modifier: Modifier = Modifier) {
166
+ Column(
167
+ modifier = modifier.padding(vertical = 16.dp),
168
+ horizontalAlignment = Alignment.CenterHorizontally,
169
+ verticalArrangement = Arrangement.spacedBy(4.dp),
170
+ ) {
171
+ Text(label.uppercase(), style = StravaText.StatLabel, color = StravaColors.InkSecondary)
172
+ Text(value, style = StravaText.StatValue, color = StravaColors.InkPrimary)
173
+ }
174
+ }
175
+
176
+ @Composable
177
+ fun StatGrid(stats: List<Pair<String, String>>, modifier: Modifier = Modifier) {
178
+ Row(modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
179
+ stats.forEachIndexed { idx, (label, value) ->
180
+ StatCell(label, value, Modifier.weight(1f))
181
+ if (idx < stats.lastIndex) {
182
+ // 1pt vertical divider only in light mode (DESIGN.md §4)
183
+ Box(
184
+ Modifier
185
+ .width(1.dp)
186
+ .height(40.dp)
187
+ .background(StravaColors.SurfaceCool)
188
+ )
189
+ }
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ ### Route Map Snapshot with Polyline Halo
196
+
197
+ iOS draws two `MapPolyline`s on a `Map`. On Android use Google Maps Compose: draw the **halo polyline first** (width ~12px, `OrangeHalo`), then the **main stroke on top** (width ~8px, `Orange`). Round caps + round joins so switchbacks don't miter.
198
+
199
+ ```kotlin
200
+ import com.google.android.gms.maps.model.LatLng
201
+ import com.google.maps.android.compose.*
202
+ import com.google.android.gms.maps.model.JointType
203
+ import com.google.android.gms.maps.model.RoundCap
204
+ import androidx.compose.foundation.shape.RoundedCornerShape
205
+ import androidx.compose.ui.draw.clip
206
+
207
+ @Composable
208
+ fun RouteMapSnapshot(
209
+ route: List<LatLng>,
210
+ modifier: Modifier = Modifier,
211
+ ) {
212
+ Box(
213
+ modifier
214
+ .fillMaxWidth()
215
+ .aspectRatio(16f / 9f)
216
+ .clip(RoundedCornerShape(6.dp)),
217
+ ) {
218
+ GoogleMap(
219
+ modifier = Modifier.fillMaxSize(),
220
+ uiSettings = MapUiSettings(
221
+ zoomControlsEnabled = false,
222
+ scrollGesturesEnabled = false,
223
+ tiltGesturesEnabled = false,
224
+ ),
225
+ properties = MapProperties(mapStyleOptions = stravaMapStyle()), // warm parchment / coal dark JSON
226
+ ) {
227
+ // halo first
228
+ Polyline(
229
+ points = route,
230
+ color = StravaColors.OrangeHalo,
231
+ width = 12f,
232
+ startCap = RoundCap(), endCap = RoundCap(),
233
+ jointType = JointType.ROUND,
234
+ )
235
+ // main stroke on top — 4dp scaled (≈8px); thins to ≈6px for long activities
236
+ Polyline(
237
+ points = route,
238
+ color = StravaColors.Orange,
239
+ width = 8f,
240
+ startCap = RoundCap(), endCap = RoundCap(),
241
+ jointType = JointType.ROUND,
242
+ )
243
+ route.firstOrNull()?.let {
244
+ MarkerComposable(state = MarkerState(it)) { RouteDot(filled = false) }
245
+ }
246
+ route.lastOrNull()?.let {
247
+ MarkerComposable(state = MarkerState(it)) { RouteDot(filled = true) }
248
+ }
249
+ }
250
+ }
251
+ }
252
+
253
+ @Composable
254
+ private fun RouteDot(filled: Boolean) {
255
+ Box(
256
+ Modifier
257
+ .size(12.dp)
258
+ .clip(androidx.compose.foundation.shape.CircleShape)
259
+ .background(if (filled) StravaColors.Orange else StravaColors.Canvas)
260
+ .then(
261
+ if (filled) Modifier.border(2.dp, StravaColors.Canvas, androidx.compose.foundation.shape.CircleShape)
262
+ else Modifier.border(2.dp, StravaColors.Orange, androidx.compose.foundation.shape.CircleShape)
263
+ )
264
+ )
265
+ }
266
+
267
+ // Supply a styled-map JSON in res/raw (warm parchment light, charcoal dark)
268
+ private fun stravaMapStyle(): com.google.android.gms.maps.model.MapStyleOptions? = null
269
+ ```
270
+
271
+ ### Kudos Button (spring bounce + confetti)
272
+
273
+ ```kotlin
274
+ import androidx.compose.animation.core.Animatable
275
+ import androidx.compose.animation.core.spring
276
+ import androidx.compose.foundation.clickable
277
+ import androidx.compose.foundation.interaction.MutableInteractionSource
278
+ import androidx.compose.material.icons.Icons
279
+ import androidx.compose.material.icons.filled.ThumbUp
280
+ import androidx.compose.material.icons.outlined.ThumbUp
281
+ import androidx.compose.material3.Icon
282
+ import androidx.compose.runtime.*
283
+ import androidx.compose.ui.draw.scale
284
+ import androidx.compose.ui.graphics.Color
285
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
286
+ import androidx.compose.ui.platform.LocalHapticFeedback
287
+ import kotlin.math.cos
288
+ import kotlin.math.sin
289
+
290
+ @Composable
291
+ fun KudosButton(
292
+ initialCount: Int,
293
+ modifier: Modifier = Modifier,
294
+ ) {
295
+ var given by remember { mutableStateOf(false) }
296
+ var count by remember { mutableIntStateOf(initialCount) }
297
+ val scale = remember { Animatable(1f) }
298
+ var burst by remember { mutableStateOf(false) }
299
+ val haptics = LocalHapticFeedback.current
300
+ val interaction = remember { MutableInteractionSource() }
301
+
302
+ LaunchedEffect(given) {
303
+ if (given) {
304
+ // 1.0 → 1.3 → 1.0 spring (damping 0.6)
305
+ scale.animateTo(1.3f, spring(dampingRatio = 0.6f, stiffness = 500f))
306
+ scale.animateTo(1.0f, spring(dampingRatio = 0.6f))
307
+ }
308
+ }
309
+
310
+ Box(modifier) {
311
+ Row(
312
+ verticalAlignment = Alignment.CenterVertically,
313
+ horizontalArrangement = Arrangement.spacedBy(6.dp),
314
+ modifier = Modifier
315
+ .clip(androidx.compose.foundation.shape.CircleShape)
316
+ .clickable(interaction, indication = null) {
317
+ given = !given
318
+ count += if (given) 1 else -1
319
+ burst = given
320
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ~iOS medium impact
321
+ }
322
+ .padding(horizontal = 4.dp, vertical = 8.dp),
323
+ ) {
324
+ Icon(
325
+ imageVector = if (given) Icons.Filled.ThumbUp else Icons.Outlined.ThumbUp,
326
+ contentDescription = if (given) "Kudos given, $count" else "Give kudos, $count",
327
+ tint = if (given) StravaColors.Orange else StravaColors.InkSecondary,
328
+ modifier = Modifier.size(18.dp).scale(scale.value),
329
+ )
330
+ Text("$count", style = StravaText.KudosCount, color = StravaColors.InkPrimary)
331
+ }
332
+ if (burst) ConfettiBurst(onDone = { burst = false })
333
+ }
334
+ }
335
+
336
+ @Composable
337
+ private fun ConfettiBurst(onDone: () -> Unit) {
338
+ val rise = remember { Animatable(0f) }
339
+ LaunchedEffect(Unit) {
340
+ rise.animateTo(1f, androidx.compose.animation.core.tween(600))
341
+ onDone()
342
+ }
343
+ Box(Modifier.size(40.dp), contentAlignment = Alignment.Center) {
344
+ repeat(8) { i ->
345
+ val angle = i * Math.PI / 4
346
+ Box(
347
+ Modifier
348
+ .size(4.dp)
349
+ .offset(
350
+ x = (cos(angle) * 30 * rise.value).dp,
351
+ y = (-sin(angle) * 30 * rise.value).dp,
352
+ )
353
+ .clip(androidx.compose.foundation.shape.CircleShape)
354
+ .background(StravaColors.Orange.copy(alpha = 1f - rise.value))
355
+ )
356
+ }
357
+ }
358
+ }
359
+ ```
360
+
361
+ ### Activity Feed Card (the hero component)
362
+
363
+ ```kotlin
364
+ import androidx.compose.material.icons.filled.DirectionsRun
365
+ import androidx.compose.material.icons.outlined.ChatBubbleOutline
366
+ import androidx.compose.material3.HorizontalDivider
367
+ import coil.compose.AsyncImage
368
+ import androidx.compose.ui.layout.ContentScale
369
+
370
+ @Composable
371
+ fun ActivityCard(
372
+ athleteAvatarUrl: String,
373
+ athleteName: String,
374
+ timestamp: String,
375
+ activityTitle: String,
376
+ route: List<LatLng>,
377
+ distance: String,
378
+ elapsed: String,
379
+ pace: String,
380
+ kudosCount: Int,
381
+ commentCount: Int,
382
+ modifier: Modifier = Modifier,
383
+ ) {
384
+ Column(
385
+ modifier = modifier
386
+ .fillMaxWidth()
387
+ .background(StravaColors.Canvas) // flat — no shadow, no border
388
+ .padding(horizontal = 16.dp, vertical = 16.dp),
389
+ verticalArrangement = Arrangement.spacedBy(12.dp),
390
+ ) {
391
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) {
392
+ AsyncImage(
393
+ model = athleteAvatarUrl,
394
+ contentDescription = null,
395
+ modifier = Modifier.size(40.dp).clip(androidx.compose.foundation.shape.CircleShape),
396
+ contentScale = ContentScale.Crop,
397
+ )
398
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
399
+ Text(athleteName, style = StravaText.Athlete, color = StravaColors.InkPrimary)
400
+ Text(timestamp, style = StravaText.Meta, color = StravaColors.InkSecondary)
401
+ }
402
+ Icon(Icons.Filled.DirectionsRun, null, tint = StravaColors.Orange, modifier = Modifier.size(18.dp))
403
+ }
404
+
405
+ Text(activityTitle, style = StravaText.ActivityTitle, color = StravaColors.InkPrimary, maxLines = 2)
406
+
407
+ RouteMapSnapshot(route)
408
+
409
+ StatGrid(listOf("Distance" to distance, "Time" to elapsed, "Pace" to pace))
410
+
411
+ HorizontalDivider(color = StravaColors.Divider)
412
+
413
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(16.dp)) {
414
+ KudosButton(initialCount = kudosCount)
415
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) {
416
+ Icon(Icons.Outlined.ChatBubbleOutline, null, tint = StravaColors.InkSecondary, modifier = Modifier.size(16.dp))
417
+ Text("$commentCount", style = StravaText.KudosCount, color = StravaColors.InkSecondary)
418
+ }
419
+ Spacer(Modifier.weight(1f))
420
+ Text("View Activity", style = StravaText.ButtonSm, color = StravaColors.Orange)
421
+ }
422
+ }
423
+ }
424
+ ```
425
+
426
+ ### Segment Leaderboard Row
427
+
428
+ ```kotlin
429
+ @Composable
430
+ fun LeaderboardRow(
431
+ rank: Int,
432
+ avatarUrl: String,
433
+ name: String,
434
+ date: String,
435
+ time: String,
436
+ gap: String,
437
+ modifier: Modifier = Modifier,
438
+ ) {
439
+ val rankBg = when (rank) {
440
+ 1 -> StravaColors.PRGold
441
+ 2 -> StravaColors.Silver
442
+ 3 -> StravaColors.Bronze
443
+ else -> StravaColors.SurfaceCool
444
+ }
445
+ val rankFg = if (rank <= 3) StravaColors.Canvas else StravaColors.InkPrimary
446
+
447
+ Column(modifier.fillMaxWidth()) {
448
+ Row(
449
+ Modifier.height(56.dp).padding(horizontal = 16.dp),
450
+ verticalAlignment = Alignment.CenterVertically,
451
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
452
+ ) {
453
+ Box(
454
+ Modifier.size(32.dp).clip(androidx.compose.foundation.shape.CircleShape).background(rankBg),
455
+ contentAlignment = Alignment.Center,
456
+ ) { Text("$rank", style = StravaText.Rank, color = rankFg) }
457
+ AsyncImage(
458
+ model = avatarUrl, contentDescription = null,
459
+ modifier = Modifier.size(36.dp).clip(androidx.compose.foundation.shape.CircleShape),
460
+ contentScale = ContentScale.Crop,
461
+ )
462
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
463
+ Text(name, style = StravaText.Athlete, color = StravaColors.InkPrimary)
464
+ Text(date, style = StravaText.Meta, color = StravaColors.InkSecondary)
465
+ }
466
+ Column(horizontalAlignment = Alignment.End, verticalArrangement = Arrangement.spacedBy(2.dp)) {
467
+ Text(time, style = StravaText.StatValue, color = StravaColors.InkPrimary)
468
+ Text(gap, style = StravaText.Meta, color = StravaColors.InkSecondary)
469
+ }
470
+ }
471
+ HorizontalDivider(color = StravaColors.Divider, thickness = 0.5.dp)
472
+ }
473
+ }
474
+ ```
475
+
476
+ ### Achievement Badge
477
+
478
+ ```kotlin
479
+ import androidx.compose.material.icons.filled.EmojiEvents
480
+
481
+ @Composable
482
+ fun AchievementBadge(text: String, modifier: Modifier = Modifier) {
483
+ Row(
484
+ modifier
485
+ .clip(RoundedCornerShape(50))
486
+ .background(StravaColors.Orange.copy(alpha = 0.08f))
487
+ .padding(horizontal = 10.dp, vertical = 4.dp),
488
+ verticalAlignment = Alignment.CenterVertically,
489
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
490
+ ) {
491
+ Icon(Icons.Filled.EmojiEvents, null, tint = StravaColors.Orange, modifier = Modifier.size(14.dp))
492
+ Text(text, style = StravaText.KudosCount, color = StravaColors.InkPrimary)
493
+ }
494
+ }
495
+ ```
496
+
497
+ ## 4. The Center Record Button (the signature elevated control)
498
+
499
+ Strava's only elevated element is the **center Record button** — it protrudes 8dp above a 5-item bottom bar with a glowing orange shadow and fires the *heaviest* haptic in the app. Compose has no center-FAB `NavigationBar` slot, so compose a `Box` overlay above a `NavigationBar` (the iOS pattern is a placeholder center tab + a floating button).
500
+
501
+ ```kotlin
502
+ import androidx.compose.foundation.shape.CircleShape
503
+ import androidx.compose.material.icons.filled.*
504
+ import androidx.compose.material3.*
505
+ import androidx.compose.ui.draw.shadow
506
+ import androidx.compose.ui.draw.scale
507
+ import androidx.compose.animation.core.animateFloatAsState
508
+
509
+ @Composable
510
+ fun StravaRecordButton(
511
+ onRecord: () -> Unit,
512
+ modifier: Modifier = Modifier,
513
+ ) {
514
+ val interaction = remember { MutableInteractionSource() }
515
+ val pressed by interaction.collectIsPressedAsState()
516
+ val scale by animateFloatAsState(if (pressed) 0.95f else 1f, label = "recordScale")
517
+ val haptics = LocalHapticFeedback.current
518
+
519
+ Box(
520
+ modifier = modifier
521
+ .offset(y = (-8).dp) // protrudes 8dp above the bar
522
+ .size(56.dp)
523
+ .scale(scale)
524
+ // glowing orange aura — rgba(252,76,2,0.4) 0 8px 16px
525
+ .shadow(16.dp, CircleShape, spotColor = StravaColors.Orange.copy(alpha = 0.4f))
526
+ .clip(CircleShape)
527
+ .background(StravaColors.Orange)
528
+ .clickable(interaction, indication = null) {
529
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // heaviest tap in the app
530
+ onRecord()
531
+ },
532
+ contentAlignment = Alignment.Center,
533
+ ) {
534
+ Icon(Icons.Filled.RadioButtonChecked, "Record", tint = StravaColors.Canvas, modifier = Modifier.size(22.dp))
535
+ }
536
+ }
537
+
538
+ @Composable
539
+ fun StravaScaffold(content: @Composable (PaddingValues) -> Unit) {
540
+ var tab by remember { mutableIntStateOf(0) }
541
+ Scaffold(
542
+ bottomBar = {
543
+ Box(contentAlignment = Alignment.TopCenter) {
544
+ NavigationBar(containerColor = StravaColors.Canvas, tonalElevation = 0.dp) {
545
+ val items = listOf(
546
+ "Home" to Icons.Filled.Home,
547
+ "Maps" to Icons.Filled.Map,
548
+ null to null, // placeholder slot for Record
549
+ "Groups" to Icons.Filled.Groups,
550
+ "You" to Icons.Filled.Person,
551
+ )
552
+ items.forEachIndexed { i, (label, icon) ->
553
+ if (icon == null) {
554
+ NavigationBarItem(false, onClick = {}, enabled = false, icon = { Spacer(Modifier.size(24.dp)) })
555
+ } else {
556
+ NavigationBarItem(
557
+ selected = tab == i,
558
+ onClick = { tab = i },
559
+ icon = { Icon(icon, label, modifier = Modifier.size(24.dp)) },
560
+ label = { Text(label!!, style = StravaText.Tab) },
561
+ colors = NavigationBarItemDefaults.colors(
562
+ selectedIconColor = StravaColors.Orange,
563
+ selectedTextColor = StravaColors.Orange,
564
+ unselectedIconColor = StravaColors.InkSecondary,
565
+ unselectedTextColor = StravaColors.InkSecondary,
566
+ indicatorColor = Color.Transparent,
567
+ ),
568
+ )
569
+ }
570
+ }
571
+ }
572
+ StravaRecordButton(onRecord = { /* present record sheet */ })
573
+ }
574
+ },
575
+ content = content,
576
+ )
577
+ }
578
+ ```
579
+
580
+ Note: Android has no first-class live blur. Strava's iOS bottom bar is already a solid `#FFFFFF`/`#0F0F0F` with a 0.5pt top divider (no blur), so an opaque `containerColor` is exact — add a `HorizontalDivider(thickness = 0.5.dp)` above the bar.
581
+
582
+ ## 5. Navigation
583
+
584
+ Strava's nav model is a 5-tab bottom bar with the protruding center Record button (see §4) plus per-screen top app bars (large `SF Pro Display 28pt Bold` titles → `StravaText.LargeNav`, trailing 22dp action icons). No rail, no drawer. The active tab tint is Strava Orange; inactive is `#666666`. Because there is no Material pill indicator in Strava's design, set `indicatorColor = Color.Transparent`.
585
+
586
+ ## 6. Motion
587
+
588
+ | Moment | Compose recipe |
589
+ |--------|----------------|
590
+ | Kudos tap | `Animatable` 1 → 1.3 → 1.0 `spring(dampingRatio=0.6f)` + 8-particle `ConfettiBurst` over `tween(600)`; `HapticFeedbackType.LongPress` (medium) |
591
+ | Record button tap | `animateFloatAsState` 1 → 0.95 + heaviest haptic, then record sheet rises `tween(350)` |
592
+ | Activity card tap | very subtle scale 1 → 0.99, then nav push (`tween(280)`) |
593
+ | Tab switch | recolor outlined → Orange over ~200ms; selection haptic |
594
+ | Pace chart scrub | real-time, no haptic — value badge follows finger |
595
+ | PR celebration | trophy `Animatable` 1 → 1.1 → 1.0 `spring` (600ms feel); `HapticFeedbackType.LongPress` (success) |
596
+ | Pull-to-refresh | Material `PullToRefreshBox` tinted `StravaColors.Orange` |
597
+
598
+ ```kotlin
599
+ // PR celebration pulse on first view of an activity with a PR
600
+ @Composable
601
+ fun PRTrophy(seen: Boolean) {
602
+ val scale = remember { Animatable(1f) }
603
+ val haptics = LocalHapticFeedback.current
604
+ LaunchedEffect(seen) {
605
+ if (seen) {
606
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress)
607
+ scale.animateTo(1.1f, spring(dampingRatio = 0.7f, stiffness = 400f))
608
+ scale.animateTo(1.0f, spring(dampingRatio = 0.7f))
609
+ }
610
+ }
611
+ Icon(
612
+ Icons.Filled.EmojiEvents, "Personal Record",
613
+ tint = StravaColors.PRGold,
614
+ modifier = Modifier.size(28.dp).scale(scale.value),
615
+ )
616
+ }
617
+ ```
618
+
619
+ Haptics: `LocalHapticFeedback` covers light/medium/heavy needs via `TextHandleMove` / `LongPress`. For a true graded heavy cue on Record, use `LocalView.current.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)` or a `Vibrator` `VibrationEffect.createOneShot(20, 255)` — Record is the most serious tap in the app.
620
+
621
+ ## 7. Icons
622
+
623
+ Strava ships custom activity-type glyphs; the closest first-party set is `androidx.compose.material:material-icons-extended`. For exact parity (the Strava trophy, the activity-type strip) export them as vector drawables and load via `ImageVector.vectorResource(R.drawable.…)`.
624
+
625
+ | Component | SF Symbol (iOS) | Material Icon (Compose) |
626
+ |-----------|-----------------|--------------------------|
627
+ | Kudos (un-given / given) | `hand.thumbsup` / `hand.thumbsup.fill` | `Icons.Outlined.ThumbUp` / `Icons.Filled.ThumbUp` |
628
+ | Comment | `bubble.left` | `Icons.Outlined.ChatBubbleOutline` |
629
+ | Activity — Run | `figure.run` | `Icons.Filled.DirectionsRun` |
630
+ | Activity — Ride | `figure.outdoor.cycle` | `Icons.Filled.DirectionsBike` |
631
+ | Activity — Swim | `figure.pool.swim` | `Icons.Filled.Pool` |
632
+ | Activity — Hike | `figure.hiking` | `Icons.Filled.Hiking` |
633
+ | Activity — Walk | `figure.walk` | `Icons.Filled.DirectionsWalk` |
634
+ | Record (center) | `record.circle` | `Icons.Filled.RadioButtonChecked` |
635
+ | Trophy / PR | `trophy.fill` | `Icons.Filled.EmojiEvents` |
636
+ | Crown / KOM | `crown.fill` | `Icons.Filled.WorkspacePremium` |
637
+ | Maps tab | `map` | `Icons.Filled.Map` |
638
+ | Groups tab | `person.3` | `Icons.Filled.Groups` |
639
+ | Profile tab | `person.crop.circle` | `Icons.Filled.Person` |
640
+ | Search | `magnifyingglass` | `Icons.Filled.Search` |
641
+ | Filter | `slider.horizontal.3` | `Icons.Filled.Tune` |
642
+ | Share | `square.and.arrow.up` | `Icons.Filled.Share` |
643
+ | Heart rate | `heart.fill` | `Icons.Filled.Favorite` |
644
+ | Elevation | `mountain.2.fill` | `Icons.Filled.Terrain` |
645
+
646
+ ## 8. Minimum SDK & Accessibility Notes
647
+
648
+ - **minSdk 24** (Compose floor is 21; Maps Compose + motion are comfortable at 24). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`.
649
+ - **Edge-to-edge**: call `enableEdgeToEdge()` in the `Activity`. Light mode wants dark status-bar icons over the white canvas; coal dark wants light icons. The Record button's glow extends below the gesture-nav inset — let it draw into the bottom inset, but keep the tappable bar inside `Scaffold` insets.
650
+ - **Font scaling**: `sp` honors the user's font scale automatically — scale activity titles, body, metadata. **Pin** the layout-sensitive trio: the **44sp Black hero stats**, the **11sp/17sp 3-up stat grid** (clamp via `CompositionLocalProvider(LocalDensity provides Density(density, fontScale = 1f))` around the grid), tab labels, and rank chips — the column alignment breaks if they scale.
651
+ - **TalkBack**: group the activity card as one element — `Modifier.semantics(mergeDescendants = true) { contentDescription = "Casey Reardon's run, Tuesday Morning Run, 8.2 miles in 1:14:23, 9:03 per mile, 27 kudos, 12 comments, 2 hours ago" }`. The Kudos button is a separate node ("Give kudos, 27" / "Kudos given, 28").
652
+ - **Touch targets**: Material guidance is 48.dp. The 56.dp Record button is clear; the kudos thumb is a 36.dp glyph on a 44–48.dp target via padding — verify with `Modifier.minimumInteractiveComponentSize()`.
653
+ - **Contrast**: Strava Orange `#FC4C02` on white passes WCAG AA at 17sp+ SemiBold — do not use it for small body text; keep it on the 17sp `Button` / `View Activity` link and the 15sp `ButtonSm`.
654
+ - **Tabular figures**: `fontFeatureSettings = "tnum"` everywhere there's a stat (pace columns, splits, times) — the Compose equivalent of `.monospacedDigit()`.
655
+ - **Reduce motion**: detect `Settings.Global.ANIMATOR_DURATION_SCALE == 0f` (or a stored pref) — skip the kudos scale bounce + confetti and fall back to an instant color change.
656
+ - **Dynamic color**: do **not** enable Material You `dynamicLightColorScheme()` / `dynamicDarkColorScheme()` — Strava's discipline is a single fixed Orange accent and the coal `#0F0F0F` dark canvas regardless of wallpaper.