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,664 @@
1
+ # Cal AI (iOS) — Jetpack Compose Implementation Guide
2
+
3
+ Companion to [DESIGN.md](DESIGN.md) — the framework-neutral spec. This file ports Cal AI's visual language to **Android with Jetpack Compose (Material 3)**: a color token object, a `Typography` set, paste-ready `@Composable`s, the macro ring, the white capture FAB, and the AI tri-color processing sweep.
4
+
5
+ > Why a Compose guide for an iOS-referenced app? The DESIGN.md tokens are platform-neutral. This file keeps the *visual* identity (Cal AI's near-black OLED canvas, the desaturated macro trio, oversized tabular numerals, the white-on-black CTA, the AI gradient sweep) while making everything idiomatic Android — `drawArc` for macro rings, a custom raised FAB in the `NavigationBar` slot, a `Brush.linearGradient` mask animation for the AI bar, `sp`/`dp` instead of `pt`.
6
+
7
+ Assumes Compose BOM `2024.09+`, Kotlin `2.0+`, `minSdk 24`, Material 3, and [Coil](https://coil-kt.github.io/coil/) `2.6+` for meal photos. No color extraction, so no `androidx.palette`.
8
+
9
+ ## 1. Color Tokens
10
+
11
+ ```kotlin
12
+ // ui/theme/CalColors.kt
13
+ import androidx.compose.ui.graphics.Color
14
+
15
+ object CalColors {
16
+ // Canvas & Surfaces (dark — primary)
17
+ val Canvas = Color(0xFF0A0A0A) // near-black, NOT pure #000 — softer on OLED
18
+ val Surface1 = Color(0xFF151515) // meal cards, hero, grouped rows
19
+ val Surface2 = Color(0xFF1E1E1E) // sheets, modals, input fills
20
+ val Surface3 = Color(0xFF2A2A2A) // pressed states, ring track
21
+ val Divider = Color(0xFF252525) // hairline dividers
22
+
23
+ // Text
24
+ val TextPrimary = Color(0xFFFFFFFF)
25
+ val TextSecondary = Color(0xFFA1A1A1) // "1 serving", timestamps, macro labels
26
+ val TextTertiary = Color(0xFF6E6E6E) // placeholder, disabled
27
+
28
+ // Macro accents (the ONLY color story — desaturated pastels)
29
+ val Protein = Color(0xFF4DA8FF) // soft blue
30
+ val Carbs = Color(0xFFFFB54C) // soft amber
31
+ val Fat = Color(0xFFFF6E87) // soft pink
32
+
33
+ // Action & Semantic
34
+ val ActionWhite = Color(0xFFFFFFFF) // primary CTA background
35
+ val ActionText = Color(0xFF000000) // black text on the white CTA — intentional
36
+ val Success = Color(0xFF42E17D) // logged-confirmed check
37
+ val Warning = Color(0xFFFFB54C) // over-budget — soft amber, NEVER red
38
+ val Destructive = Color(0xFFFF5A5A) // delete / clear-all only
39
+ val AIAccent = Color(0xFF8B8DF5) // AI-confidence indigo
40
+
41
+ // Light mode (secondary — rare)
42
+ val LightCanvas = Color(0xFFFFFFFF)
43
+ val LightSurface1 = Color(0xFFF5F5F5)
44
+ val LightText = Color(0xFF0A0A0A)
45
+ }
46
+ ```
47
+
48
+ Wire it into a Material 3 `darkColorScheme` — Cal AI is dark-first; light mode is a secondary experience and reuses the identical macro hexes.
49
+
50
+ ```kotlin
51
+ // ui/theme/Theme.kt
52
+ import androidx.compose.material3.darkColorScheme
53
+ import androidx.compose.material3.MaterialTheme
54
+
55
+ private val CalScheme = darkColorScheme(
56
+ primary = CalColors.ActionWhite, // CTA is white, not a brand hue
57
+ onPrimary = CalColors.ActionText, // black on white
58
+ background = CalColors.Canvas,
59
+ onBackground = CalColors.TextPrimary,
60
+ surface = CalColors.Surface1,
61
+ onSurface = CalColors.TextPrimary,
62
+ surfaceVariant = CalColors.Surface2,
63
+ outline = CalColors.Divider,
64
+ error = CalColors.Destructive,
65
+ )
66
+
67
+ @Composable
68
+ fun CalTheme(content: @Composable () -> Unit) =
69
+ MaterialTheme(colorScheme = CalScheme, typography = CalTypography, content = content)
70
+ ```
71
+
72
+ ## 2. Typography
73
+
74
+ Cal AI uses a clean modern sans (Inter, or SF Pro on iOS). Drop Inter's TTFs in `res/font/` (lowercase, snake_case). Roboto is an acceptable system fallback but Inter is the visual sibling — bundle it. **No light weights** — the floor is 400; thin weights vanish on the near-black canvas.
75
+
76
+ ```kotlin
77
+ // ui/theme/CalType.kt
78
+ import androidx.compose.material3.Typography
79
+ import androidx.compose.ui.text.TextStyle
80
+ import androidx.compose.ui.text.font.Font
81
+ import androidx.compose.ui.text.font.FontFamily
82
+ import androidx.compose.ui.text.font.FontWeight
83
+ import androidx.compose.ui.unit.sp
84
+
85
+ val Inter = FontFamily(
86
+ Font(R.font.inter_regular, FontWeight.Normal), // 400
87
+ Font(R.font.inter_medium, FontWeight.Medium), // 500
88
+ Font(R.font.inter_semibold, FontWeight.SemiBold), // 600
89
+ Font(R.font.inter_bold, FontWeight.Bold), // 700
90
+ )
91
+
92
+ // Every numeral display must be tabular — prevents "5 → 50" layout jitter.
93
+ private const val TNUM = "tnum"
94
+
95
+ // Named ramp — mirrors DESIGN.md §3 exactly (pt → sp 1:1, same weights/tracking)
96
+ object CalText {
97
+ val Hero = TextStyle(Inter, fontWeight = FontWeight.Bold, fontSize = 72.sp, lineHeight = 72.sp, letterSpacing = (-1.5).sp, fontFeatureSettings = TNUM)
98
+ val MealCals = TextStyle(Inter, fontWeight = FontWeight.Bold, fontSize = 40.sp, lineHeight = 40.sp, letterSpacing = (-0.8).sp, fontFeatureSettings = TNUM)
99
+ val Streak = TextStyle(Inter, fontWeight = FontWeight.Bold, fontSize = 48.sp, lineHeight = 48.sp, letterSpacing = (-1.0).sp, fontFeatureSettings = TNUM)
100
+ val ScreenTitle = TextStyle(Inter, fontWeight = FontWeight.Bold, fontSize = 28.sp, lineHeight = 31.sp, letterSpacing = (-0.4).sp)
101
+ val Section = TextStyle(Inter, fontWeight = FontWeight.Bold, fontSize = 22.sp, lineHeight = 26.sp, letterSpacing = (-0.3).sp)
102
+ val Nav = TextStyle(Inter, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 19.sp, letterSpacing = (-0.1).sp)
103
+ val MealName = TextStyle(Inter, fontWeight = FontWeight.SemiBold, fontSize = 17.sp, lineHeight = 22.sp, letterSpacing = (-0.15).sp)
104
+ val Body = TextStyle(Inter, fontWeight = FontWeight.Normal, fontSize = 15.sp, lineHeight = 21.sp)
105
+ val MacroChip = TextStyle(Inter, fontWeight = FontWeight.SemiBold, fontSize = 12.sp, lineHeight = 14.sp, fontFeatureSettings = TNUM)
106
+ val Meta = TextStyle(Inter, fontWeight = FontWeight.Medium, fontSize = 13.sp, lineHeight = 17.sp, fontFeatureSettings = TNUM)
107
+ val LabelUpper = TextStyle(Inter, fontWeight = FontWeight.Bold, fontSize = 11.sp, lineHeight = 13.sp, letterSpacing = 0.8.sp)
108
+ val Button = TextStyle(Inter, fontWeight = FontWeight.SemiBold, fontSize = 16.sp, lineHeight = 16.sp, letterSpacing = (-0.1).sp)
109
+ val ButtonSec = TextStyle(Inter, fontWeight = FontWeight.SemiBold, fontSize = 14.sp, lineHeight = 14.sp)
110
+ val Tab = TextStyle(Inter, fontWeight = FontWeight.SemiBold, fontSize = 10.sp, lineHeight = 10.sp, letterSpacing = 0.2.sp)
111
+ }
112
+
113
+ // Map onto Material 3 slots so stock components inherit the brand
114
+ val CalTypography = Typography(
115
+ displayLarge = CalText.Hero,
116
+ headlineLarge = CalText.ScreenTitle,
117
+ titleLarge = CalText.Section,
118
+ titleMedium = CalText.MealName,
119
+ bodyMedium = CalText.Body,
120
+ labelSmall = CalText.Tab,
121
+ )
122
+ ```
123
+
124
+ The `tnum` feature is baked into every numeral style above — this is critical for calorie/macro/weight readouts that update live.
125
+
126
+ ## 3. Signature Components
127
+
128
+ ### Primary CTA (White Pill)
129
+
130
+ ```kotlin
131
+ import androidx.compose.animation.core.animateFloatAsState
132
+ import androidx.compose.animation.core.spring
133
+ import androidx.compose.foundation.background
134
+ import androidx.compose.foundation.clickable
135
+ import androidx.compose.foundation.interaction.MutableInteractionSource
136
+ import androidx.compose.foundation.interaction.collectIsPressedAsState
137
+ import androidx.compose.foundation.layout.*
138
+ import androidx.compose.foundation.shape.CircleShape
139
+ import androidx.compose.material3.Text
140
+ import androidx.compose.runtime.*
141
+ import androidx.compose.ui.Alignment
142
+ import androidx.compose.ui.Modifier
143
+ import androidx.compose.ui.draw.clip
144
+ import androidx.compose.ui.draw.scale
145
+ import androidx.compose.ui.graphics.Color
146
+ import androidx.compose.ui.hapticfeedback.HapticFeedbackType
147
+ import androidx.compose.ui.platform.LocalHapticFeedback
148
+ import androidx.compose.ui.unit.dp
149
+
150
+ @Composable
151
+ fun CalPrimaryButton(
152
+ title: String,
153
+ onClick: () -> Unit,
154
+ modifier: Modifier = Modifier,
155
+ enabled: Boolean = true,
156
+ ) {
157
+ val interaction = remember { MutableInteractionSource() }
158
+ val pressed by interaction.collectIsPressedAsState()
159
+ val scale by animateFloatAsState(
160
+ targetValue = if (pressed) 0.97f else 1f,
161
+ animationSpec = spring(dampingRatio = 0.7f, stiffness = 700f),
162
+ label = "ctaScale",
163
+ )
164
+ Box(
165
+ modifier = modifier
166
+ .fillMaxWidth()
167
+ .scale(scale)
168
+ .clip(CircleShape) // 28dp pill
169
+ .background(
170
+ when {
171
+ !enabled -> CalColors.Surface3
172
+ pressed -> Color(0xFFE8E8E8)
173
+ else -> CalColors.ActionWhite
174
+ }
175
+ )
176
+ .clickable(interaction, indication = null, enabled = enabled, onClick = onClick)
177
+ .padding(vertical = 16.dp, horizontal = 28.dp),
178
+ contentAlignment = Alignment.Center,
179
+ ) {
180
+ Text(
181
+ title,
182
+ style = CalText.Button,
183
+ color = if (enabled) CalColors.ActionText else CalColors.TextTertiary, // black on white
184
+ )
185
+ }
186
+ }
187
+ ```
188
+
189
+ ### Capture FAB (the signature element)
190
+
191
+ A 68dp white circle with a 2dp canvas-colored inner ring and a soft white glow — the only "active light source" on the dark canvas.
192
+
193
+ ```kotlin
194
+ import androidx.compose.foundation.border
195
+ import androidx.compose.foundation.shape.CircleShape
196
+ import androidx.compose.ui.draw.shadow
197
+
198
+ @Composable
199
+ fun CaptureFAB(onClick: () -> Unit, modifier: Modifier = Modifier) {
200
+ val interaction = remember { MutableInteractionSource() }
201
+ val pressed by interaction.collectIsPressedAsState()
202
+ val scale by animateFloatAsState(
203
+ targetValue = if (pressed) 0.92f else 1f,
204
+ animationSpec = spring(dampingRatio = 0.7f, stiffness = 600f),
205
+ label = "fabScale",
206
+ )
207
+ val haptics = LocalHapticFeedback.current
208
+ Box(
209
+ modifier = modifier
210
+ .size(68.dp)
211
+ .scale(scale)
212
+ // White glow on dark canvas — Android has no colored blur; a white ambient
213
+ // + spot shadow approximates rgba(255,255,255,0.15) 0 0 40px.
214
+ .shadow(40.dp, CircleShape, ambientColor = Color.White.copy(alpha = 0.15f),
215
+ spotColor = Color.White.copy(alpha = 0.15f))
216
+ .clip(CircleShape)
217
+ .background(CalColors.ActionWhite)
218
+ .border(2.dp, CalColors.Canvas, CircleShape) // ≈ inset inner ring
219
+ .padding(4.dp)
220
+ .clickable(interaction, indication = null) {
221
+ haptics.performHapticFeedback(HapticFeedbackType.LongPress) // ≈ .impact(.medium)
222
+ onClick()
223
+ },
224
+ )
225
+ }
226
+ ```
227
+
228
+ ### Macro Ring
229
+
230
+ iOS uses `Circle().trim(...)`; Compose uses `Canvas` + `drawArc`. Track is `Surface3`, fill is the macro color with a round cap, sweeping from -90° (12 o'clock).
231
+
232
+ ```kotlin
233
+ import androidx.compose.foundation.Canvas
234
+ import androidx.compose.animation.core.tween
235
+ import androidx.compose.ui.geometry.Offset
236
+ import androidx.compose.ui.geometry.Size
237
+ import androidx.compose.ui.graphics.StrokeCap
238
+ import androidx.compose.ui.graphics.drawscope.Stroke
239
+
240
+ enum class Macro(val color: Color, val label: String) {
241
+ Protein(CalColors.Protein, "PROTEIN"),
242
+ Carbs(CalColors.Carbs, "CARBS"),
243
+ Fat(CalColors.Fat, "FAT"),
244
+ }
245
+
246
+ @Composable
247
+ fun MacroRing(
248
+ macro: Macro,
249
+ current: Float,
250
+ target: Float,
251
+ modifier: Modifier = Modifier,
252
+ size: androidx.compose.ui.unit.Dp = 80.dp,
253
+ ) {
254
+ val progress = (current / target.coerceAtLeast(0.001f)).coerceIn(0f, 1f)
255
+ val animated by androidx.compose.animation.core.animateFloatAsState(
256
+ targetValue = progress,
257
+ animationSpec = tween(600), // 0° → target % over 600ms ease-out
258
+ label = "ringFill",
259
+ )
260
+ Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(6.dp)) {
261
+ Box(Modifier.size(size), contentAlignment = Alignment.Center) {
262
+ Canvas(Modifier.fillMaxSize()) {
263
+ val stroke = 6.dp.toPx()
264
+ val inset = stroke / 2f
265
+ val arcSize = Size(size.toPx() - stroke, size.toPx() - stroke)
266
+ drawArc(
267
+ color = CalColors.Surface3,
268
+ startAngle = 0f, sweepAngle = 360f, useCenter = false,
269
+ topLeft = Offset(inset, inset), size = arcSize,
270
+ style = Stroke(width = stroke),
271
+ )
272
+ drawArc(
273
+ color = macro.color,
274
+ startAngle = -90f, sweepAngle = 360f * animated, useCenter = false,
275
+ topLeft = Offset(inset, inset), size = arcSize,
276
+ style = Stroke(width = stroke, cap = StrokeCap.Round),
277
+ )
278
+ }
279
+ Row(verticalAlignment = Alignment.Bottom) {
280
+ Text("${current.toInt()}",
281
+ style = CalText.MacroChip.copy(fontSize = 18.sp, fontWeight = FontWeight.Bold),
282
+ color = CalColors.TextPrimary)
283
+ Text("g", style = CalText.Meta.copy(fontSize = 9.sp), color = CalColors.TextSecondary)
284
+ }
285
+ }
286
+ Text(macro.label, style = CalText.LabelUpper, color = CalColors.TextSecondary)
287
+ }
288
+ }
289
+ ```
290
+
291
+ ### Today Hero Card
292
+
293
+ ```kotlin
294
+ import androidx.compose.foundation.shape.RoundedCornerShape
295
+
296
+ @Composable
297
+ fun TodayHeroCard(
298
+ remaining: Int,
299
+ goal: Int,
300
+ protein: Pair<Float, Float>,
301
+ carbs: Pair<Float, Float>,
302
+ fat: Pair<Float, Float>,
303
+ modifier: Modifier = Modifier,
304
+ ) {
305
+ val fill = ((goal - remaining).toFloat() / goal.coerceAtLeast(1)).coerceIn(0f, 1f)
306
+ Column(
307
+ modifier
308
+ .fillMaxWidth()
309
+ .clip(RoundedCornerShape(24.dp))
310
+ .background(CalColors.Surface1)
311
+ .padding(24.dp),
312
+ ) {
313
+ Text("TODAY · REMAINING", style = CalText.LabelUpper, color = CalColors.TextSecondary)
314
+ Spacer(Modifier.height(6.dp))
315
+ Text("%,d".format(remaining), style = CalText.Hero, color = CalColors.TextPrimary)
316
+ Spacer(Modifier.height(4.dp))
317
+ Text("kcal of %,d goal".format(goal), style = CalText.Meta, color = CalColors.TextSecondary)
318
+ Spacer(Modifier.height(20.dp))
319
+ // Progress bar — 6dp, rounded, white fill (no shadow; surface contrast only)
320
+ Box(
321
+ Modifier.fillMaxWidth().height(6.dp).clip(CircleShape).background(CalColors.Surface3),
322
+ ) {
323
+ Box(Modifier.fillMaxWidth(fill).fillMaxHeight().clip(CircleShape).background(Color.White))
324
+ }
325
+ Spacer(Modifier.height(20.dp))
326
+ Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
327
+ MacroRing(Macro.Protein, protein.first, protein.second, Modifier.weight(1f))
328
+ MacroRing(Macro.Carbs, carbs.first, carbs.second, Modifier.weight(1f))
329
+ MacroRing(Macro.Fat, fat.first, fat.second, Modifier.weight(1f))
330
+ }
331
+ }
332
+ }
333
+ ```
334
+
335
+ ### Meal Card (Photo + Stats)
336
+
337
+ ```kotlin
338
+ import androidx.compose.ui.graphics.Brush
339
+ import androidx.compose.ui.layout.ContentScale
340
+ import coil.compose.AsyncImage
341
+
342
+ @Composable
343
+ fun MealCard(
344
+ title: String,
345
+ time: String,
346
+ servings: String,
347
+ protein: Int,
348
+ carbs: Int,
349
+ fat: Int,
350
+ calories: Int,
351
+ photoUrl: String,
352
+ modifier: Modifier = Modifier,
353
+ ) {
354
+ Column(
355
+ modifier
356
+ .fillMaxWidth()
357
+ .clip(RoundedCornerShape(20.dp))
358
+ .background(CalColors.Surface1), // elevation = surface contrast, NO shadow
359
+ ) {
360
+ Box {
361
+ AsyncImage(
362
+ model = photoUrl,
363
+ contentDescription = title,
364
+ modifier = Modifier
365
+ .fillMaxWidth()
366
+ .aspectRatio(16f / 10f)
367
+ .clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp)),
368
+ contentScale = ContentScale.Crop,
369
+ )
370
+ Box(
371
+ Modifier
372
+ .align(Alignment.BottomCenter)
373
+ .fillMaxWidth()
374
+ .height(60.dp)
375
+ .background(Brush.verticalGradient(listOf(Color.Transparent, Color.Black.copy(alpha = 0.4f))))
376
+ )
377
+ }
378
+ Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
379
+ Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
380
+ Text(title, style = CalText.MealName, color = CalColors.TextPrimary)
381
+ Text("$time · $servings", style = CalText.Meta, color = CalColors.TextSecondary)
382
+ }
383
+ Row(verticalAlignment = Alignment.CenterVertically) {
384
+ Row(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
385
+ MacroChip("P", protein, CalColors.Protein)
386
+ MacroChip("C", carbs, CalColors.Carbs)
387
+ MacroChip("F", fat, CalColors.Fat)
388
+ }
389
+ Spacer(Modifier.weight(1f))
390
+ Text("$calories", style = CalText.MealCals, color = CalColors.TextPrimary)
391
+ }
392
+ }
393
+ }
394
+ }
395
+
396
+ @Composable
397
+ private fun MacroChip(label: String, value: Int, color: Color) {
398
+ Box(
399
+ Modifier.clip(CircleShape).background(color.copy(alpha = 0.18f))
400
+ .padding(horizontal = 8.dp, vertical = 3.dp),
401
+ ) { Text("$label $value", style = CalText.MacroChip, color = color) }
402
+ }
403
+ ```
404
+
405
+ ### AI Detection Result Card
406
+
407
+ The AI card is distinguished by a 135° `Surface2 → Surface3` gradient wash plus the tri-color accent line on its top edge.
408
+
409
+ ```kotlin
410
+ @Composable
411
+ fun AIDetectionCard(
412
+ title: String,
413
+ items: List<Pair<String, Int>>, // name to confidence%
414
+ onSave: () -> Unit,
415
+ onReject: () -> Unit,
416
+ modifier: Modifier = Modifier,
417
+ ) {
418
+ Box(
419
+ modifier
420
+ .fillMaxWidth()
421
+ .clip(RoundedCornerShape(20.dp))
422
+ .background(
423
+ Brush.linearGradient(listOf(CalColors.Surface2, CalColors.Surface3))
424
+ ),
425
+ ) {
426
+ // 2dp tri-color accent line at the top edge
427
+ Box(
428
+ Modifier
429
+ .fillMaxWidth()
430
+ .height(2.dp)
431
+ .background(Brush.horizontalGradient(listOf(CalColors.Protein, CalColors.AIAccent, CalColors.Fat)))
432
+ )
433
+ Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
434
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp)) {
435
+ Icon(Icons.Filled.AutoAwesome, null, tint = CalColors.AIAccent, modifier = Modifier.size(11.dp))
436
+ Text("AI DETECTED", style = CalText.LabelUpper, color = CalColors.AIAccent)
437
+ }
438
+ Text(title, style = CalText.MealName, color = CalColors.TextPrimary)
439
+ Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
440
+ items.forEach { (name, confidence) ->
441
+ Row(horizontalArrangement = Arrangement.spacedBy(4.dp)) {
442
+ Text(name, style = CalText.Meta, color = CalColors.TextSecondary)
443
+ Text("$confidence%", style = CalText.Meta, color = CalColors.TextTertiary)
444
+ }
445
+ }
446
+ }
447
+ Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) {
448
+ Box(
449
+ Modifier.clip(CircleShape).background(CalColors.ActionWhite)
450
+ .clickable { onSave() }.padding(horizontal = 20.dp, vertical = 12.dp),
451
+ ) { Text("Save to today", style = CalText.ButtonSec, color = CalColors.ActionText) }
452
+ Text("Reject", style = CalText.ButtonSec, color = CalColors.Destructive,
453
+ modifier = Modifier.clickable { onReject() })
454
+ }
455
+ }
456
+ }
457
+ }
458
+ ```
459
+
460
+ ## 4. AI Capture & Processing Flow (the distinctive system)
461
+
462
+ Cal AI's defining moment is the ~4-second capture → tri-color processing sweep → editable result card. The signature visual is the **2dp gradient bar** (`Protein → AIAccent → Fat`) that sweeps across while the model runs. Port the SwiftUI `AIProcessingBar` mask animation with an offset `Brush` window.
463
+
464
+ ```kotlin
465
+ import androidx.compose.animation.core.RepeatMode
466
+ import androidx.compose.animation.core.infiniteRepeatable
467
+ import androidx.compose.animation.core.rememberInfiniteTransition
468
+
469
+ @Composable
470
+ fun AIProcessingBar(modifier: Modifier = Modifier) {
471
+ val t = rememberInfiniteTransition(label = "aiSweep")
472
+ val phase by t.animateFloat(
473
+ initialValue = 0f, targetValue = 1f,
474
+ animationSpec = infiniteRepeatable(tween(1200, easing = androidx.compose.animation.core.LinearEasing)),
475
+ label = "phase",
476
+ )
477
+ Canvas(modifier.fillMaxWidth().height(2.dp)) {
478
+ val w = size.width
479
+ val windowW = w * 0.27f // ≈ 80dp window over ~300dp track
480
+ val start = -windowW + phase * (w + windowW)
481
+ drawRect(
482
+ brush = Brush.horizontalGradient(
483
+ colors = listOf(CalColors.Protein, CalColors.AIAccent, CalColors.Fat),
484
+ startX = start, endX = start + windowW,
485
+ ),
486
+ size = size,
487
+ )
488
+ }
489
+ }
490
+
491
+ @Composable
492
+ fun CaptureScreen(onDetected: () -> Unit) {
493
+ // Full-bleed CameraX preview goes here (PreviewView in an AndroidView).
494
+ var processing by remember { mutableStateOf(false) }
495
+ Box(Modifier.fillMaxSize().background(Color.Black)) {
496
+ // 4-corner reticle centered, animates 1.0 → 1.05 → 1.0 on capture prep
497
+ ReticleOverlay()
498
+ if (processing) {
499
+ // Viewfinder dims to 60% + "Detecting…" + sweeping bar
500
+ Box(Modifier.fillMaxSize().background(Color.Black.copy(alpha = 0.6f))) {
501
+ Column(
502
+ Modifier.align(Alignment.Center),
503
+ horizontalAlignment = Alignment.CenterHorizontally,
504
+ verticalArrangement = Arrangement.spacedBy(12.dp),
505
+ ) {
506
+ Text("Detecting…", style = CalText.Body, color = CalColors.TextPrimary)
507
+ AIProcessingBar(Modifier.width(200.dp))
508
+ }
509
+ }
510
+ LaunchedEffect(Unit) {
511
+ kotlinx.coroutines.delay(1000) // 800–1200ms model latency
512
+ onDetected() // then slide up the AIDetectionCard with spring(0.4, 0.7)
513
+ }
514
+ }
515
+ CaptureFAB(
516
+ onClick = { processing = true },
517
+ modifier = Modifier.align(Alignment.BottomCenter).padding(bottom = 24.dp),
518
+ )
519
+ }
520
+ }
521
+
522
+ @Composable
523
+ private fun ReticleOverlay() {
524
+ val t = rememberInfiniteTransition(label = "reticle")
525
+ val s by t.animateFloat(1f, 1.05f, infiniteRepeatable(tween(900), RepeatMode.Reverse), label = "pulse")
526
+ Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
527
+ Box(Modifier.size(220.dp).scale(s)) {
528
+ // Draw 4 corner brackets (20dp, 2dp white stroke) at the box corners
529
+ Canvas(Modifier.fillMaxSize()) {
530
+ val len = 20.dp.toPx(); val sw = 2.dp.toPx(); val w = size.width; val h = size.height
531
+ listOf(
532
+ Offset(0f, 0f) to listOf(Offset(len, 0f), Offset(0f, len)),
533
+ Offset(w, 0f) to listOf(Offset(w - len, 0f), Offset(w, len)),
534
+ Offset(0f, h) to listOf(Offset(len, h), Offset(0f, h - len)),
535
+ Offset(w, h) to listOf(Offset(w - len, h), Offset(w, h - len)),
536
+ ).forEach { (c, ends) -> ends.forEach { drawLine(Color.White, c, it, sw) } }
537
+ }
538
+ }
539
+ }
540
+ }
541
+ ```
542
+
543
+ The result card slides up with `spring(dampingRatio = 0.7f, stiffness = StiffnessMediumLow)` (≈ response 0.4) once `onDetected` fires.
544
+
545
+ ## 5. Navigation
546
+
547
+ Cal AI has 5 slots — Home / History / **[Capture FAB]** / Insights / Profile — with the FAB raised 10dp above the bar in the center slot. Material 3 `NavigationBar` has no raised-center affordance, so reserve the middle slot empty and overlay the FAB in a `Scaffold` `Box`. The iOS tab bar is `.regularMaterial`; Android has no live blur, so use a 92%-opaque canvas surface. The top nav is an opaque `#0A0A0A` large title (no blur).
548
+
549
+ ```kotlin
550
+ import androidx.compose.material.icons.Icons
551
+ import androidx.compose.material.icons.filled.Home
552
+ import androidx.compose.material.icons.filled.CalendarMonth
553
+ import androidx.compose.material.icons.filled.QueryStats
554
+ import androidx.compose.material.icons.filled.Person
555
+ import androidx.compose.material3.*
556
+
557
+ @Composable
558
+ fun CalScaffold(selected: Int, onSelect: (Int) -> Unit, onCapture: () -> Unit, content: @Composable (PaddingValues) -> Unit) {
559
+ Scaffold(
560
+ containerColor = CalColors.Canvas,
561
+ bottomBar = {
562
+ Box(contentAlignment = Alignment.TopCenter) {
563
+ NavigationBar(
564
+ containerColor = CalColors.Canvas.copy(alpha = 0.92f), // ≈ .regularMaterial
565
+ tonalElevation = 0.dp,
566
+ ) {
567
+ val items = listOf(
568
+ "Home" to Icons.Filled.Home,
569
+ "History" to Icons.Filled.CalendarMonth,
570
+ null to null, // reserved center slot for the FAB
571
+ "Insights" to Icons.Filled.QueryStats,
572
+ "Profile" to Icons.Filled.Person,
573
+ )
574
+ items.forEachIndexed { i, (label, icon) ->
575
+ if (icon == null) {
576
+ NavigationBarItem(false, {}, icon = { Spacer(Modifier.size(22.dp)) }, enabled = false)
577
+ } else {
578
+ NavigationBarItem(
579
+ selected = selected == i,
580
+ onClick = { onSelect(i) },
581
+ icon = { Icon(icon, contentDescription = label, modifier = Modifier.size(22.dp)) },
582
+ label = { Text(label!!, style = CalText.Tab) },
583
+ colors = NavigationBarItemDefaults.colors(
584
+ selectedIconColor = CalColors.TextPrimary,
585
+ selectedTextColor = CalColors.TextPrimary,
586
+ unselectedIconColor = CalColors.TextTertiary,
587
+ unselectedTextColor = CalColors.TextTertiary,
588
+ indicatorColor = Color.Transparent, // no Material pill
589
+ ),
590
+ )
591
+ }
592
+ }
593
+ }
594
+ CaptureFAB(onCapture, Modifier.offset(y = (-10).dp)) // raised above the bar
595
+ }
596
+ },
597
+ content = content,
598
+ )
599
+ }
600
+ ```
601
+
602
+ ## 6. Motion
603
+
604
+ | Moment | Compose recipe |
605
+ |--------|----------------|
606
+ | Capture tap | `animateFloatAsState` scale 1 → 0.92 `spring(dampingRatio = 0.7f)`; `HapticFeedbackType.LongPress` (.impact medium) |
607
+ | AI processing sweep | `rememberInfiniteTransition` phase 0→1 over 1200ms `LinearEasing`, offset gradient window |
608
+ | Result slide-up | `AnimatedVisibility` + `slideInVertically` with `spring(dampingRatio = 0.7f, stiffness = MediumLow)` (≈ response 0.4) |
609
+ | Ring fill | `animateFloatAsState` 0 → progress over 600ms `tween` |
610
+ | Log confirmation | 150ms white edge-flash via `Animatable` alpha; `HapticFeedbackType.Confirm` (success) |
611
+ | Streak increment | amber flame `Animatable` scale 1.0 → 1.15 → 1.0 over 600ms `spring(dampingRatio = 0.5f)`; success haptic |
612
+ | Swipe to delete | `SwipeToDismissBox` revealing a `Destructive` pill at -80dp threshold |
613
+
614
+ ```kotlin
615
+ // Streak flame increment
616
+ @Composable
617
+ fun StreakFlame(triggerCount: Int) {
618
+ val scale = remember { Animatable(1f) }
619
+ val haptics = LocalHapticFeedback.current
620
+ LaunchedEffect(triggerCount) {
621
+ if (triggerCount > 0) {
622
+ haptics.performHapticFeedback(HapticFeedbackType.Confirm) // success-equivalent
623
+ scale.animateTo(1.15f, spring(dampingRatio = 0.5f, stiffness = 400f))
624
+ scale.animateTo(1f, spring(dampingRatio = 0.5f, stiffness = 400f))
625
+ }
626
+ }
627
+ Icon(
628
+ Icons.Filled.LocalFireDepartment, contentDescription = "Streak",
629
+ tint = CalColors.Carbs, // amber flame
630
+ modifier = Modifier.size(32.dp).scale(scale.value),
631
+ )
632
+ }
633
+ ```
634
+
635
+ Motion is deliberately restrained — no confetti, no mascot bounces, no >1.0 overshoots beyond the documented streak/reticle pulses. Honor **Reduce Motion**: when `Settings.Global.ANIMATOR_DURATION_SCALE == 0f`, freeze the AI sweep and ring fill (snap to final), keep haptics. `HapticFeedbackType.Confirm` requires API 34+; gate it and fall back to `LocalView.current.performHapticFeedback(HapticFeedbackConstants.CONFIRM)` or a `Vibrator` `VibrationEffect.createOneShot(12, ...)` on older devices.
636
+
637
+ ## 7. Icons
638
+
639
+ Cal AI uses a small set of SF Symbols; the closest first-party set is `androidx.compose.material:material-icons-extended`. The capture-ring glyph is bespoke (the FAB is a pure circle, no glyph) — no Material equivalent needed there.
640
+
641
+ | Purpose | SF Symbol (iOS) | Material Icon (Compose) |
642
+ |---------|-----------------|--------------------------|
643
+ | Capture | `camera.fill` / custom ring | pure white circle (no glyph) — see `CaptureFAB` |
644
+ | AI sparkles | `sparkles` | `Icons.Filled.AutoAwesome` |
645
+ | Home (tab) | `house` / `house.fill` | `Icons.Filled.Home` |
646
+ | History (tab) | `calendar` | `Icons.Filled.CalendarMonth` |
647
+ | Insights (tab) | `chart.line.uptrend.xyaxis` | `Icons.Filled.QueryStats` |
648
+ | Profile (tab) | `person` / `person.fill` | `Icons.Filled.Person` |
649
+ | Streak | `flame.fill` | `Icons.Filled.LocalFireDepartment` |
650
+ | Add | `plus` | `Icons.Filled.Add` |
651
+ | Edit | `pencil` | `Icons.Filled.Edit` |
652
+ | Delete | `trash` | `Icons.Filled.Delete` |
653
+ | Barcode | `barcode.viewfinder` | `Icons.Filled.QrCodeScanner` |
654
+ | Library | `photo.on.rectangle` | `Icons.Filled.PhotoLibrary` |
655
+
656
+ ## 8. Minimum SDK & Accessibility Notes
657
+
658
+ - **minSdk 24** (Compose floor is 21; CameraX + modern motion comfortable at 24). `compileSdk 34+`, Compose BOM `2024.09+`, Kotlin `2.0+`. Note `HapticFeedbackType.Confirm` / `HapticFeedbackConstants.CONFIRM` are API 34+ — gate and fall back on older devices.
659
+ - **Edge-to-edge**: call `enableEdgeToEdge()` in the `Activity`; the near-black canvas wants `WindowCompat` light-content (white) system-bar icons. Use `Scaffold` insets so the capture FAB clears the gesture-nav indicator and the large title clears the status bar.
660
+ - **Font scaling**: `sp` honors the user's font scale automatically — keep it on body, titles, meal names. Display numerals must not break the hero layout: cap the 72sp `Hero` at ~140% and the 80dp ring numerals at 140% by wrapping those composables in `CompositionLocalProvider(LocalDensity provides Density(density, fontScale = fontScale.coerceAtMost(1.4f)))`.
661
+ - **TalkBack**: label each macro ring with `Modifier.semantics { contentDescription = "Protein, 112 of 140 grams, 80 percent" }`; merge the meal-card text with `Modifier.semantics(mergeDescendants = true)` and expose swipe-to-delete as a custom accessibility action. Announce AI confidence per item.
662
+ - **Touch targets**: Material guidance is 48.dp minimum. The 68dp capture FAB and 52dp CTAs clear it; ensure 32dp chip/stepper buttons are wrapped in 48dp hit areas via padding.
663
+ - **Contrast**: `#A1A1A1` on `#0A0A0A` passes WCAG AA at 13sp+. Validate `#6E6E6E` tertiary at the 11sp uppercase labels and bump toward `#808080` if targeting strict compliance. The desaturated macro accents on `#151515` pass for graphical (ring) use; do not use them for small body text.
664
+ - **Dynamic color**: do **not** enable Material You `dynamicColorScheme()` — Cal AI's identity is the fixed near-black canvas, the white CTA, and the specific desaturated macro trio regardless of wallpaper. (Material You suits Google/Material-first apps; Cal AI is a strong-brand exception.) Light mode is a secondary experience that reuses the identical macro hexes — swap only canvas/surface/text tokens.