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,631 @@
1
+ # MyFitnessPal (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports MyFitnessPal's visual language to **Android with Jetpack Compose (Material 3)**: a color token object, a `Typography` set, paste-ready `@Composable`s, the calorie ring, macro donut, diary FAB, 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 (MyFitnessPal's white clinical-but-friendly canvas, MFP Blue heritage + Lake Blue action, the color-flipping calorie ring, the locked macro trio) while making everything idiomatic Android — `NavigationBar` instead of a UITabBar, a translucent `Surface` instead of iOS blur, `sp`/`dp` instead of `pt`, tabular figures via `fontFeatureSettings = "tnum"`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3, and [Coil](https://coil-kt.github.io/coil/) `2.6+` if you load remote food thumbnails. MyFitnessPal does no runtime color extraction, so no Palette dependency is needed.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ ```kotlin
12
+ // ui/theme/MfpColors.kt
13
+ import androidx.compose.ui.graphics.Color
14
+
15
+ object MfpColors {
16
+ // Canvas & Surfaces
17
+ val Canvas = Color(0xFFFFFFFF)
18
+ val SurfaceGray = Color(0xFFF5F7FA)
19
+ val SurfaceGray2 = Color(0xFFE5E9F0)
20
+ val Divider = Color(0xFFE5E7EB)
21
+ val Hairline = Color(0xFFEEF1F5)
22
+
23
+ // Text
24
+ val Ink = Color(0xFF1F2937) // primary
25
+ val Slate = Color(0xFF4B5563) // secondary
26
+ val Mute = Color(0xFF9CA3AF) // tertiary
27
+ val HeroNumber = Color(0xFF111827) // the big calorie number — even darker than Ink
28
+
29
+ // Brand
30
+ val Blue = Color(0xFF005DAA) // heritage — logomark, Premium gradient
31
+ val LakeBlue = Color(0xFF0072CE) // current action color, ring fill at on-track
32
+ val LakePressed = Color(0xFF005FA8)
33
+ val SkyBlue = Color(0xFFE7F0FF) // tinted backgrounds
34
+
35
+ // Macro trio — do NOT reorder, do NOT recolor
36
+ val Carbs = Color(0xFFFF9F1C) // always first slice
37
+ val Fat = Color(0xFFA463F2) // always second slice
38
+ val Protein = Color(0xFF19C37D) // always third slice
39
+
40
+ // Semantic
41
+ val UnderGoal = Color(0xFF19C37D)
42
+ val Approaching = Color(0xFFF59E0B)
43
+ val OverLimit = Color(0xFFEF4444)
44
+ val Streak = Color(0xFFFB923C)
45
+ val PremiumGold = Color(0xFFD4A437)
46
+
47
+ // Dark mode (deep, slightly-blue dark — not pure black)
48
+ val DarkCanvas = Color(0xFF0F1419)
49
+ val DarkSurface1 = Color(0xFF1A1F26)
50
+ val DarkSurface2 = Color(0xFF252B33)
51
+ val DarkDivider = Color(0xFF2A2F37)
52
+ val DarkTextPri = Color(0xFFF3F4F6)
53
+ val DarkTextSec = Color(0xFF9CA3AF)
54
+ val LakeDark = Color(0xFF3B8FDF)
55
+ }
56
+ ```
57
+
58
+ MyFitnessPal defaults to the clinical white surface; dark mode is a deep blue-black. Wire both Material 3 schemes so ripples and default component colors inherit the brand. **Never** map the macro trio into the scheme — those colors belong only to the macro context.
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.foundation.isSystemInDarkTheme
66
+
67
+ private val MfpLight = lightColorScheme(
68
+ primary = MfpColors.LakeBlue,
69
+ onPrimary = Color.White,
70
+ background = MfpColors.Canvas,
71
+ onBackground = MfpColors.Ink,
72
+ surface = MfpColors.Canvas,
73
+ onSurface = MfpColors.Ink,
74
+ surfaceVariant = MfpColors.SurfaceGray,
75
+ outline = MfpColors.Divider,
76
+ error = MfpColors.OverLimit,
77
+ )
78
+
79
+ private val MfpDark = darkColorScheme(
80
+ primary = MfpColors.LakeDark,
81
+ onPrimary = Color.White,
82
+ background = MfpColors.DarkCanvas,
83
+ onBackground = MfpColors.DarkTextPri,
84
+ surface = MfpColors.DarkSurface1,
85
+ onSurface = MfpColors.DarkTextPri,
86
+ surfaceVariant = MfpColors.DarkSurface2,
87
+ outline = MfpColors.DarkDivider,
88
+ )
89
+
90
+ @Composable
91
+ fun MfpTheme(content: @Composable () -> Unit) =
92
+ MaterialTheme(
93
+ colorScheme = if (isSystemInDarkTheme()) MfpDark else MfpLight,
94
+ typography = MfpTypography,
95
+ content = content,
96
+ )
97
+ ```
98
+
99
+ ## 2. Typography
100
+
101
+ MyFitnessPal uses the system font (SF Pro on iOS → Roboto on Android; Proxima Nova only on marketing/web). The whole point is the numerals — **tabular figures on every number that summarizes nutrition**. Compose has no `monospacedDigit()`; the equivalent is `fontFeatureSettings = "tnum"`, baked into every numeric style below.
102
+
103
+ ```kotlin
104
+ // ui/theme/MfpType.kt
105
+ import androidx.compose.material3.Typography
106
+ import androidx.compose.ui.text.TextStyle
107
+ import androidx.compose.ui.text.font.FontFamily
108
+ import androidx.compose.ui.text.font.FontWeight
109
+ import androidx.compose.ui.unit.sp
110
+
111
+ private val Sys = FontFamily.Default // Roboto on Android; Display behavior is automatic
112
+
113
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1).
114
+ // `fontFeatureSettings = "tnum"` == iOS .monospacedDigit() — non-negotiable on numbers.
115
+ object MfpText {
116
+ val CalorieHero = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 56.sp, lineHeight = 56.sp, letterSpacing = (-1.0).sp, fontFeatureSettings = "tnum")
117
+ val CalorieLabel = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 13.sp, lineHeight = 13.sp, letterSpacing = 0.6.sp)
118
+ val LargeNav = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 28.sp, lineHeight = 32.sp, letterSpacing = (-0.4).sp)
119
+ val Section = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 22.sp, lineHeight = 26.sp, letterSpacing = (-0.3).sp)
120
+ val Meal = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 18.sp, lineHeight = 22.sp, letterSpacing = (-0.2).sp)
121
+ val FoodName = TextStyle(Sys, fontWeight = FontWeight.Medium, fontSize = 16.sp, lineHeight = 21.sp, letterSpacing = (-0.1).sp)
122
+ val FoodSub = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 17.sp)
123
+ val Calorie = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 16.sp, fontFeatureSettings = "tnum")
124
+ val Body = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 21.sp)
125
+ val BodySmall = TextStyle(Sys, fontWeight = FontWeight.Normal, fontSize = 13.sp, lineHeight = 18.sp)
126
+ val MacroNumber = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 22.sp, lineHeight = 22.sp, letterSpacing = (-0.3).sp, fontFeatureSettings = "tnum")
127
+ val MacroLabel = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 11.sp, lineHeight = 11.sp, letterSpacing = 0.8.sp)
128
+ val Button = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 16.sp)
129
+ val Tab = TextStyle(Sys, fontWeight = FontWeight.SemiBold, fontSize = 10.sp, lineHeight = 10.sp, letterSpacing = 0.2.sp)
130
+ val StreakBadge = TextStyle(Sys, fontWeight = FontWeight.Bold, fontSize = 12.sp, lineHeight = 12.sp, fontFeatureSettings = "tnum")
131
+ }
132
+
133
+ // Map onto Material 3 slots so stock components inherit the brand
134
+ val MfpTypography = Typography(
135
+ headlineLarge = MfpText.LargeNav,
136
+ headlineSmall = MfpText.Section,
137
+ titleMedium = MfpText.Meal,
138
+ bodyMedium = MfpText.Body,
139
+ labelLarge = MfpText.Button,
140
+ labelSmall = MfpText.Tab,
141
+ )
142
+ ```
143
+
144
+ ## 3. Signature Components
145
+
146
+ ### Calorie Ring (the hero of Dashboard) — semantic color flip
147
+
148
+ ```kotlin
149
+ import androidx.compose.animation.core.Animatable
150
+ import androidx.compose.animation.core.tween
151
+ import androidx.compose.foundation.Canvas
152
+ import androidx.compose.foundation.layout.*
153
+ import androidx.compose.material3.Text
154
+ import androidx.compose.runtime.*
155
+ import androidx.compose.ui.Modifier
156
+ import androidx.compose.ui.graphics.Color
157
+ import androidx.compose.ui.graphics.StrokeCap
158
+ import androidx.compose.ui.graphics.drawscope.Stroke
159
+ import androidx.compose.ui.unit.Dp
160
+ import androidx.compose.ui.unit.dp
161
+
162
+ @Composable
163
+ fun CalorieRing(
164
+ goal: Int,
165
+ consumed: Int,
166
+ exercise: Int,
167
+ diameter: Dp = 220.dp,
168
+ strokeWidth: Dp = 18.dp,
169
+ ) {
170
+ val remaining = goal - consumed + exercise
171
+ val target = (consumed.toFloat() / goal.coerceAtLeast(1)).coerceIn(0f, 1f)
172
+
173
+ // Color flips semantically with how much of the goal is used
174
+ val ringColor: Color = when (consumed.toFloat() / goal.coerceAtLeast(1)) {
175
+ in 0f..0.6f -> MfpColors.UnderGoal
176
+ in 0.6f..0.95f -> MfpColors.LakeBlue // the most common state
177
+ in 0.95f..1.0f -> MfpColors.Approaching
178
+ else -> MfpColors.OverLimit
179
+ }
180
+
181
+ val progress = remember { Animatable(0f) }
182
+ LaunchedEffect(target) { progress.animateTo(target, tween(600)) } // 600ms ease-out fill
183
+
184
+ Box(Modifier.size(diameter), contentAlignment = Alignment.Center) {
185
+ Canvas(Modifier.fillMaxSize()) {
186
+ val sw = strokeWidth.toPx()
187
+ drawCircle(MfpColors.SurfaceGray2, style = Stroke(sw))
188
+ drawArc(
189
+ color = ringColor,
190
+ startAngle = -90f,
191
+ sweepAngle = 360f * progress.value,
192
+ useCenter = false,
193
+ style = Stroke(sw, cap = StrokeCap.Round),
194
+ )
195
+ }
196
+ Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(4.dp)) {
197
+ Text("REMAINING", style = MfpText.CalorieLabel, color = MfpColors.Slate)
198
+ // contentTransition gives the iOS number-flip when a food is added
199
+ androidx.compose.animation.AnimatedContent(
200
+ targetState = remaining,
201
+ transitionSpec = {
202
+ (androidx.compose.animation.slideInVertically { it / 2 } + androidx.compose.animation.fadeIn())
203
+ .togetherWith(androidx.compose.animation.slideOutVertically { -it / 2 } + androidx.compose.animation.fadeOut())
204
+ },
205
+ label = "calorieFlip",
206
+ ) { value ->
207
+ Text("%,d".format(value), style = MfpText.CalorieHero, color = MfpColors.HeroNumber)
208
+ }
209
+ Text("calories", style = MfpText.BodySmall, color = MfpColors.Slate)
210
+ }
211
+ }
212
+ }
213
+ ```
214
+
215
+ ### Macro Donut (Carbs / Fat / Protein) — locked order, locked colors
216
+
217
+ ```kotlin
218
+ @Composable
219
+ fun MacroDonut(
220
+ carbs: Int, fat: Int, protein: Int,
221
+ carbsGoal: Int, fatGoal: Int, proteinGoal: Int,
222
+ diameter: Dp = 96.dp,
223
+ strokeWidth: Dp = 10.dp,
224
+ ) {
225
+ val total = (carbs + fat + protein).coerceAtLeast(1)
226
+ val carbsFrac = carbs.toFloat() / total
227
+ val fatFrac = fat.toFloat() / total
228
+ val proteinFrac = protein.toFloat() / total
229
+ val goalTotal = (carbsGoal + fatGoal + proteinGoal).coerceAtLeast(1)
230
+
231
+ Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(16.dp)) {
232
+ Box(Modifier.size(diameter), contentAlignment = Alignment.Center) {
233
+ Canvas(Modifier.fillMaxSize()) {
234
+ val sw = strokeWidth.toPx()
235
+ fun seg(start: Float, sweep: Float, color: Color) =
236
+ drawArc(color, -90f + start * 360f, sweep * 360f, false, style = Stroke(sw, cap = StrokeCap.Butt))
237
+ seg(0f, carbsFrac, MfpColors.Carbs) // 1st — orange
238
+ seg(carbsFrac, fatFrac, MfpColors.Fat) // 2nd — purple
239
+ seg(carbsFrac + fatFrac, proteinFrac, MfpColors.Protein) // 3rd — green
240
+ }
241
+ Text("${(total.toFloat() / goalTotal * 100).toInt()}%", style = MfpText.MacroNumber, color = MfpColors.Ink)
242
+ }
243
+ Row(horizontalArrangement = Arrangement.spacedBy(24.dp)) {
244
+ MacroLegend(MfpColors.Carbs, "CARBS", carbs, carbsGoal)
245
+ MacroLegend(MfpColors.Fat, "FAT", fat, fatGoal)
246
+ MacroLegend(MfpColors.Protein, "PROTEIN", protein, proteinGoal)
247
+ }
248
+ }
249
+ }
250
+
251
+ @Composable
252
+ private fun MacroLegend(color: Color, label: String, grams: Int, goal: Int) {
253
+ Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
254
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp)) {
255
+ Box(
256
+ Modifier
257
+ .size(8.dp)
258
+ .clip(androidx.compose.foundation.shape.RoundedCornerShape(2.dp))
259
+ .background(color)
260
+ )
261
+ Text(label, style = MfpText.MacroLabel, color = MfpColors.Slate)
262
+ }
263
+ Text(
264
+ "${grams}g · ${(grams.toFloat() / goal.coerceAtLeast(1) * 100).toInt()}%",
265
+ style = MfpText.BodySmall.copy(fontFeatureSettings = "tnum"),
266
+ color = MfpColors.Ink,
267
+ )
268
+ }
269
+ }
270
+ ```
271
+
272
+ ### Diary Food Row
273
+
274
+ ```kotlin
275
+ import androidx.compose.foundation.clickable
276
+ import androidx.compose.foundation.interaction.MutableInteractionSource
277
+ import androidx.compose.foundation.interaction.collectIsPressedAsState
278
+ import androidx.compose.material.icons.Icons
279
+ import androidx.compose.material.icons.filled.ChevronRight
280
+ import androidx.compose.material3.Icon
281
+ import androidx.compose.ui.draw.clip
282
+ import androidx.compose.ui.text.style.TextOverflow
283
+
284
+ @Composable
285
+ fun FoodRow(name: String, subtitle: String, calories: Int, onClick: () -> Unit) {
286
+ val interaction = remember { MutableInteractionSource() }
287
+ val pressed by interaction.collectIsPressedAsState()
288
+
289
+ Row(
290
+ Modifier
291
+ .fillMaxWidth()
292
+ .heightIn(min = 64.dp)
293
+ .background(if (pressed) MfpColors.SurfaceGray else MfpColors.Canvas) // 100ms fade, no scale
294
+ .clickable(interaction, indication = null, onClick = onClick)
295
+ .padding(horizontal = 16.dp),
296
+ verticalAlignment = Alignment.CenterVertically,
297
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
298
+ ) {
299
+ Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
300
+ Text(name, style = MfpText.FoodName, color = MfpColors.Ink, maxLines = 1, overflow = TextOverflow.Ellipsis)
301
+ Text(subtitle, style = MfpText.FoodSub, color = MfpColors.Slate, maxLines = 1, overflow = TextOverflow.Ellipsis)
302
+ }
303
+ Text("%,d".format(calories), style = MfpText.Calorie, color = MfpColors.Ink)
304
+ Icon(Icons.Filled.ChevronRight, contentDescription = null, tint = MfpColors.Mute, modifier = Modifier.size(12.dp))
305
+ }
306
+ }
307
+ ```
308
+
309
+ ### Meal Section ("Breakfast" / "Lunch" / "Dinner" / "Snacks")
310
+
311
+ Keep this exact order — it is the cultural pattern users expect.
312
+
313
+ ```kotlin
314
+ import androidx.compose.animation.AnimatedVisibility
315
+ import androidx.compose.animation.expandVertically
316
+ import androidx.compose.animation.shrinkVertically
317
+ import androidx.compose.animation.core.tween
318
+ import androidx.compose.material.icons.filled.AddCircle
319
+
320
+ @Composable
321
+ fun MealSection(
322
+ title: String,
323
+ totalCalories: Int,
324
+ onAddFood: () -> Unit,
325
+ content: @Composable () -> Unit,
326
+ ) {
327
+ var expanded by remember { mutableStateOf(true) }
328
+
329
+ Column(Modifier.fillMaxWidth().background(MfpColors.Canvas)) {
330
+ Row(
331
+ Modifier
332
+ .fillMaxWidth()
333
+ .height(48.dp)
334
+ .clickable { expanded = !expanded }
335
+ .padding(horizontal = 16.dp),
336
+ verticalAlignment = Alignment.CenterVertically,
337
+ ) {
338
+ Text(title, style = MfpText.Meal, color = MfpColors.Ink)
339
+ Spacer(Modifier.weight(1f))
340
+ Text("%,d".format(totalCalories), style = MfpText.Calorie, color = MfpColors.Ink)
341
+ }
342
+ Box(Modifier.fillMaxWidth().height(0.5.dp).background(MfpColors.Divider))
343
+
344
+ AnimatedVisibility(
345
+ visible = expanded,
346
+ enter = expandVertically(tween(250)),
347
+ exit = shrinkVertically(tween(250)),
348
+ ) {
349
+ Column {
350
+ content()
351
+ // "+ Add Food" row — the fastest entry path, never omit it
352
+ Row(
353
+ Modifier
354
+ .fillMaxWidth()
355
+ .height(56.dp)
356
+ .clickable(onClick = onAddFood)
357
+ .padding(horizontal = 16.dp),
358
+ verticalAlignment = Alignment.CenterVertically,
359
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
360
+ ) {
361
+ Icon(Icons.Filled.AddCircle, contentDescription = null, tint = MfpColors.LakeBlue, modifier = Modifier.size(22.dp))
362
+ Text("Add Food", style = MfpText.Button.copy(fontSize = 15.sp), color = MfpColors.LakeBlue)
363
+ }
364
+ }
365
+ }
366
+ }
367
+ }
368
+ ```
369
+
370
+ ### Diary FAB (centered Scan/Add button, blue-tinted shadow)
371
+
372
+ ```kotlin
373
+ import androidx.compose.foundation.shape.CircleShape
374
+ import androidx.compose.material.icons.filled.Add
375
+ import androidx.compose.ui.draw.shadow
376
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
377
+ import androidx.compose.ui.platform.LocalHapticFeedback
378
+
379
+ @Composable
380
+ fun DiaryFAB(onClick: () -> Unit, modifier: Modifier = Modifier) {
381
+ val haptics = LocalHapticFeedback.current
382
+ Box(
383
+ modifier
384
+ .size(56.dp)
385
+ .shadow(16.dp, CircleShape, spotColor = MfpColors.Blue.copy(alpha = 0.35f)) // blue-tinted, not neutral
386
+ .clip(CircleShape)
387
+ .background(MfpColors.LakeBlue)
388
+ .clickable(interactionSource = remember { MutableInteractionSource() }, indication = null) {
389
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ≈ iOS medium impact
390
+ onClick()
391
+ },
392
+ contentAlignment = Alignment.Center,
393
+ ) {
394
+ Icon(Icons.Filled.Add, contentDescription = "Add food", tint = Color.White, modifier = Modifier.size(22.dp))
395
+ }
396
+ }
397
+ ```
398
+
399
+ ### Primary CTA
400
+
401
+ ```kotlin
402
+ import androidx.compose.animation.core.animateFloatAsState
403
+ import androidx.compose.foundation.shape.RoundedCornerShape
404
+ import androidx.compose.ui.draw.scale
405
+
406
+ @Composable
407
+ fun MfpPrimaryButton(label: String, onClick: () -> Unit, modifier: Modifier = Modifier) {
408
+ val interaction = remember { MutableInteractionSource() }
409
+ val pressed by interaction.collectIsPressedAsState()
410
+ val scale by animateFloatAsState(if (pressed) 0.98f else 1f, label = "ctaScale")
411
+ val haptics = LocalHapticFeedback.current
412
+
413
+ Box(
414
+ modifier
415
+ .fillMaxWidth()
416
+ .scale(scale)
417
+ .heightIn(min = 48.dp)
418
+ .clip(RoundedCornerShape(12.dp)) // never a full pill on the primary CTA
419
+ .background(if (pressed) MfpColors.LakePressed else MfpColors.LakeBlue)
420
+ .clickable(interaction, indication = null) {
421
+ haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove) // ≈ iOS light impact
422
+ onClick()
423
+ }
424
+ .padding(horizontal = 28.dp, vertical = 14.dp),
425
+ contentAlignment = Alignment.Center,
426
+ ) {
427
+ Text(label, style = MfpText.Button, color = Color.White)
428
+ }
429
+ }
430
+ ```
431
+
432
+ ### Streak Flame Badge
433
+
434
+ ```kotlin
435
+ import androidx.compose.material.icons.filled.LocalFireDepartment
436
+
437
+ @Composable
438
+ fun StreakBadge(days: Int) {
439
+ Row(
440
+ Modifier
441
+ .clip(CircleShape)
442
+ .background(MfpColors.SurfaceGray)
443
+ .padding(horizontal = 10.dp, vertical = 6.dp),
444
+ verticalAlignment = Alignment.CenterVertically,
445
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
446
+ ) {
447
+ Icon(Icons.Filled.LocalFireDepartment, contentDescription = null, tint = MfpColors.Streak, modifier = Modifier.size(14.dp))
448
+ Text("$days", style = MfpText.StreakBadge, color = MfpColors.Ink)
449
+ }
450
+ }
451
+ ```
452
+
453
+ ### Dashboard Card
454
+
455
+ ```kotlin
456
+ import androidx.compose.foundation.border
457
+ import androidx.compose.ui.graphics.vector.ImageVector
458
+
459
+ @Composable
460
+ fun DashboardCard(label: String, icon: ImageVector, content: @Composable () -> Unit) {
461
+ Column(
462
+ Modifier
463
+ .clip(RoundedCornerShape(16.dp))
464
+ .background(MfpColors.Canvas)
465
+ .border(1.dp, MfpColors.Divider, RoundedCornerShape(16.dp)) // no shadow — clinical & flat
466
+ .padding(16.dp),
467
+ verticalArrangement = Arrangement.spacedBy(8.dp),
468
+ ) {
469
+ Row(verticalAlignment = Alignment.CenterVertically) {
470
+ Text(label, style = MfpText.MacroLabel, color = MfpColors.Slate)
471
+ Spacer(Modifier.weight(1f))
472
+ Icon(icon, contentDescription = null, tint = MfpColors.Slate, modifier = Modifier.size(14.dp))
473
+ }
474
+ content()
475
+ }
476
+ }
477
+ ```
478
+
479
+ ## 4. The Calorie Ring color-flip — the distinctive system
480
+
481
+ MyFitnessPal does no color extraction; its distinctive system is the **220pt calorie ring whose fill flips color semantically** as the day's eating accumulates (the implementation lives in §3). The thresholds:
482
+
483
+ | Consumed vs goal | Ring color | Token |
484
+ |------------------|-----------|-------|
485
+ | Under 60% | green | `MfpColors.UnderGoal` `#19C37D` |
486
+ | 60–95% (on track) | blue | `MfpColors.LakeBlue` `#0072CE` (most common) |
487
+ | 95–100% (approaching) | amber | `MfpColors.Approaching` `#F59E0B` |
488
+ | Over 100% | red | `MfpColors.OverLimit` `#EF4444` |
489
+
490
+ When a food is added, the ring's swept arc animates over 600ms (`Animatable.animateTo(target, tween(600))`) and the center number does a quick vertical flip (`AnimatedContent` with slide+fade — Compose's equivalent of iOS `contentTransition(.numericText)`). Never render the ring without tabular figures: `MfpText.CalorieHero` carries `fontFeatureSettings = "tnum"` so the giant number's digits align as it ticks. Never compress the ring below 180.dp (the number stops being legible) and never repurpose the macro trio colors here — the ring uses only the semantic blue/green/amber/red.
491
+
492
+ ## 5. Navigation (Bottom Tab Bar + FAB)
493
+
494
+ Use Material 3 `NavigationBar`. MyFitnessPal's iOS tab bar gains `.regularMaterial` blur on scroll; Android has no first-class live blur, so use a 92%-opaque white surface with a 0.5dp top divider. Five tabs, **active tint Lake Blue**. The Diary tab is special — a 56.dp Lake Blue FAB floats *centered above* the tab bar.
495
+
496
+ ```kotlin
497
+ import androidx.compose.material.icons.filled.GridView
498
+ import androidx.compose.material.icons.filled.MenuBook
499
+ import androidx.compose.material.icons.filled.Assignment
500
+ import androidx.compose.material.icons.filled.Groups
501
+ import androidx.compose.material.icons.filled.MoreHoriz
502
+ import androidx.compose.material3.*
503
+
504
+ @Composable
505
+ fun MfpScaffold(
506
+ selected: Int,
507
+ onSelect: (Int) -> Unit,
508
+ onFab: () -> Unit,
509
+ content: @Composable (PaddingValues) -> Unit,
510
+ ) {
511
+ val items = listOf(
512
+ "Dashboard" to Icons.Filled.GridView,
513
+ "Diary" to Icons.Filled.MenuBook,
514
+ "Plans" to Icons.Filled.Assignment,
515
+ "Community" to Icons.Filled.Groups,
516
+ "More" to Icons.Filled.MoreHoriz,
517
+ )
518
+ val haptics = LocalHapticFeedback.current
519
+
520
+ Scaffold(
521
+ bottomBar = {
522
+ NavigationBar(
523
+ containerColor = MfpColors.Canvas.copy(alpha = 0.92f),
524
+ tonalElevation = 0.dp,
525
+ ) {
526
+ items.forEachIndexed { i, (label, icon) ->
527
+ NavigationBarItem(
528
+ selected = selected == i,
529
+ onClick = {
530
+ haptics.performHapticFeedback(HapticFeedbackType.TextHandleMove)
531
+ onSelect(i)
532
+ },
533
+ icon = { Icon(icon, contentDescription = label, modifier = Modifier.size(22.dp)) },
534
+ label = { Text(label, style = MfpText.Tab) },
535
+ colors = NavigationBarItemDefaults.colors(
536
+ selectedIconColor = MfpColors.LakeBlue,
537
+ selectedTextColor = MfpColors.LakeBlue,
538
+ unselectedIconColor = MfpColors.Mute,
539
+ unselectedTextColor = MfpColors.Mute,
540
+ indicatorColor = Color.Transparent, // MFP has no Material pill
541
+ ),
542
+ )
543
+ }
544
+ }
545
+ },
546
+ floatingActionButton = {
547
+ // Only show the FAB on the Diary tab; it sits centered above the bar
548
+ if (selected == 1) DiaryFAB(onClick = onFab)
549
+ },
550
+ floatingActionButtonPosition = FabPosition.Center,
551
+ content = content,
552
+ )
553
+ }
554
+ ```
555
+
556
+ The FAB tap opens an Add-Food bottom sheet (`ModalBottomSheet`) with Scan Barcode / Search Food / Quick Add / Recent / My Foods. The barcode scanner is a full-screen `Surface(color = Color.Black)` with four white 3.dp L-bracket corners (drawn via `Canvas`) framing a 280×180.dp window and a 1.dp red scan line pulsing via `rememberInfiniteTransition`.
557
+
558
+ ## 6. Motion
559
+
560
+ | Moment | Compose recipe |
561
+ |--------|----------------|
562
+ | Calorie ring fill | `Animatable.animateTo(target, tween(600))` on the swept arc + `AnimatedContent` slide/fade number flip |
563
+ | Food row press | background `Canvas` → `SurfaceGray` over ~100ms (no scale) |
564
+ | FAB tap | `animateFloatAsState` 1 → 0.92 → 1 spring ~250ms + `LongPress` (medium) haptic |
565
+ | Add-Food sheet | `ModalBottomSheet` slide-up ~350ms; scrim `rgba(0,0,0,0.4)` |
566
+ | Barcode laser | `rememberInfiniteTransition` alpha 0.4 → 1.0 → 0.4 every 1200ms; green tick replaces it 800ms on capture |
567
+ | Streak confetti | only at 7/30/100/365 milestones — particle burst ~1.4s + success haptic |
568
+ | Tab switch | `TextHandleMove` haptic; no animation |
569
+
570
+ ```kotlin
571
+ import androidx.compose.animation.core.rememberInfiniteTransition
572
+ import androidx.compose.animation.core.infiniteRepeatable
573
+ import androidx.compose.animation.core.RepeatMode
574
+ import androidx.compose.animation.core.animateFloat
575
+
576
+ // Barcode scan-line pulse
577
+ @Composable
578
+ fun BarcodeLaser(modifier: Modifier = Modifier) {
579
+ val t = rememberInfiniteTransition(label = "laser")
580
+ val alpha by t.animateFloat(
581
+ 0.4f, 1f,
582
+ infiniteRepeatable(tween(1200), RepeatMode.Reverse),
583
+ label = "laserAlpha",
584
+ )
585
+ Box(
586
+ modifier
587
+ .fillMaxWidth()
588
+ .height(1.dp)
589
+ .background(MfpColors.OverLimit.copy(alpha = alpha)),
590
+ )
591
+ }
592
+ ```
593
+
594
+ Haptics: `LocalHapticFeedback` — `TextHandleMove` ≈ iOS `.light`/`.selection` (primary CTA, tab switch), `LongPress` ≈ `.medium`/`.success` (FAB, Complete Diary, barcode capture, streak milestone). For a closer match to iOS impact use `LocalView.current.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)` (API 30+) or a `Vibrator` `VibrationEffect.createOneShot(12, 100)`.
595
+
596
+ ## 7. Icons
597
+
598
+ The SF Symbols map to Material Icons (`androidx.compose.material:material-icons-extended`). The M-square logomark is a custom asset — ship as a vector drawable.
599
+
600
+ | Component | SF Symbol (iOS) | Material Icon (Compose) |
601
+ |-----------|-----------------|--------------------------|
602
+ | FAB add | `plus` | `Icons.Filled.Add` |
603
+ | Add-food row | `plus.circle.fill` | `Icons.Filled.AddCircle` |
604
+ | Barcode scan | `barcode.viewfinder` | `Icons.Filled.QrCodeScanner` |
605
+ | Search | `magnifyingglass` | `Icons.Filled.Search` |
606
+ | Streak | `flame.fill` | `Icons.Filled.LocalFireDepartment` (Streak Orange) |
607
+ | Steps | `figure.walk` | `Icons.Filled.DirectionsWalk` |
608
+ | Weight | `scalemass` | `Icons.Filled.MonitorWeight` |
609
+ | Water | `drop.fill` | `Icons.Filled.WaterDrop` |
610
+ | Dashboard tab | `square.grid.2x2` / `.fill` | `Icons.Filled.GridView` |
611
+ | Diary tab | `book.closed` / `.fill` | `Icons.Filled.MenuBook` |
612
+ | Plans tab | `list.clipboard` | `Icons.Filled.Assignment` |
613
+ | Community tab | `person.3` / `.fill` | `Icons.Filled.Groups` |
614
+ | More tab | `ellipsis` | `Icons.Filled.MoreHoriz` |
615
+ | Premium gate | `lock.fill` | `Icons.Filled.Lock` (Premium Gold) |
616
+ | Chevron (row) | `chevron.right` | `Icons.Filled.ChevronRight` |
617
+ | Date picker (Diary) | `chevron.down` | `Icons.Filled.ExpandMore` |
618
+
619
+ The MFP heritage mark (rounded `#005DAA` square with a white serif "M") has no Material equivalent — bundle it as a vector drawable and render with `Image(painterResource(...))`. Never recolor it to Lake Blue; it stays heritage MFP Blue `#005DAA`.
620
+
621
+ ## 8. Minimum SDK & Accessibility Notes
622
+
623
+ - **minSdk 24** (Compose floor is 21; `AnimatedContent` number flip, `rememberInfiniteTransition`, modern motion are comfortable at 24). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`.
624
+ - **Edge-to-edge**: call `enableEdgeToEdge()` in the `Activity`. The white canvas wants dark-content system bars (`isAppearanceLightStatusBars = true`); the blue-black dark mode flips to light-content. The large nav title starts at safe-area top + 16.dp; `Scaffold` insets keep the tab bar + FAB clear of the gesture nav (FAB ~88.dp above the bottom safe area on Diary).
625
+ - **Font scaling**: `sp` honors the user's font scale automatically — keep it on food names, meal titles, body. **Pin** layout-sensitive numbers (the 56.sp calorie hero, macro numbers, 10.sp tab labels, streak badge) by wrapping in `CompositionLocalProvider(LocalDensity provides Density(LocalDensity.current.density, fontScale = 1f))` — the ring layout breaks if the giant number scales.
626
+ - **Tabular figures**: `fontFeatureSettings = "tnum"` is baked into every numeric `TextStyle` (`CalorieHero`, `Calorie`, `MacroNumber`, `StreakBadge`) — this is the Compose equivalent of iOS `.monospacedDigit()` and is **non-negotiable**: non-aligned digits make the giant number look broken.
627
+ - **TalkBack**: read the calorie ring as one element — `Modifier.semantics { contentDescription = "1,247 calories remaining out of a 2,000 calorie goal; 753 consumed, 0 from exercise" }`. Read the macro donut as "187 grams of carbs (65 percent), 64 grams of fat (88 percent), 92 grams of protein (74 percent)". Group food rows with `Modifier.semantics(mergeDescendants = true)`.
628
+ - **Touch targets**: Material guidance is 48.dp minimum. The FAB (56.dp) clears it; the 64.dp food row and 56.dp Add-Food row are generous; the 12.dp row chevron gets a 48.dp hit area via the full-row clickable. Tab items fill the 56.dp bar row.
629
+ - **Contrast**: Ink `#1F2937` on white meets WCAG AAA at all sizes; Slate `#4B5563` meets AA at 14sp+; Mute `#9CA3AF` is placeholder/disabled only. Lake Blue `#0072CE` on white passes AA for 16sp SemiBold — do not use a brighter blue on light mode (it loses contrast).
630
+ - **Reduce Motion**: when `Settings.Global.ANIMATOR_DURATION_SCALE == 0f`, snap the ring fill instantly (skip the `Animatable` tween), drop the number-flip to an instant swap, and disable streak confetti.
631
+ - **Material You**: do **not** enable `dynamicColorScheme()` — the macro trio (orange/purple/green) and the semantic ring colors are fixed brand language and must never bend to wallpaper. Dark mode is the deliberate blue-black `#0F1419`; Lake Blue lifts to `#3B8FDF` for OLED legibility.