Merge branch 'release-candidate'
diff --git a/.gitignore b/.gitignore
index 90cec54..5cd2794 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
 # MDC
 
-/docs
 build_tests/CocoapodsObjCApp/CocoapodsObjCApp.xcworkspace
 build_tests/CocoapodsSwiftApp/CocoapodsSwiftApp.xcworkspace
 scripts/external/material-design-icons/
@@ -49,6 +48,7 @@
 #
 Pods/
 demos/**/Pods/
+catalog/Podfile.lock
 
 # Carthage
 #
@@ -66,7 +66,7 @@
 fastlane/screenshots
 
 # material component site
-docsite
+docsite-generator
 
 # Compiled python
 *.pyc
diff --git a/.mdc-docsite.yml b/.mdc-docsite.yml
new file mode 100644
index 0000000..30f7279
--- /dev/null
+++ b/.mdc-docsite.yml
@@ -0,0 +1,9 @@
+# Doc site configuration.
+# TODO(shyndman): Link to documentation.
+basepath: /ios
+site_platform: ios
+site_title: Material Components for iOS
+site_short_title: iOS
+site_description: >
+  Material Components for iOS is a set of user interface components that help iOS app developers build apps with material design.
+repo_url: https://github.com/material-components/material-components-ios/
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ebe9a29..cb84f3a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,327 @@
+# 23.1.0
+
+## API diffs
+
+### Collections
+
+#### Changes
+
+Make [MDCCollectionViewController cellWidthAtSectionIndex:] public.
+
+## Component changes
+
+### ActivityIndicator
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Junius' Screenshots (#1393)](https://github.com/material-components/material-components-ios/commit/6cb4269240bac5b4ed98827070b2855ae8aed9da) (ianegordon)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [Remove remaining MP4s and markup. (#1396)](https://github.com/material-components/material-components-ios/commit/555476cf89f03a7a432489604286be1ad5ceb24b) (Adrian Secord)
+* [Update screenshot widths](https://github.com/material-components/material-components-ios/commit/e9630689f0be39fcc1df00fd78fc5ce5dc9c990c) (Junius Gunaratne)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### AnimationTiming
+
+#### Changes
+
+* [Added a link to the motion spec in the AnimationTiming README. (#1319)](https://github.com/material-components/material-components-ios/commit/92db31da5c115510c9b29be058f77434998fa9a7) (Scott Hyndman)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Junius' Screenshots (#1393)](https://github.com/material-components/material-components-ios/commit/6cb4269240bac5b4ed98827070b2855ae8aed9da) (ianegordon)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### AppBar
+
+#### Changes
+
+* [& [FeatureHighlight] - Remove references to g3 (#1349)](https://github.com/material-components/material-components-ios/commit/acd8d38dc54babbaf58969a2554164745c61cbb5) (Justin Shephard)
+* [- Removed Video from Readme (#1390)](https://github.com/material-components/material-components-ios/commit/4a879d363474b322f6ca64a965a28eb5291dfb61) (Justin Shephard)
+* [- Update docs photo (#1374)](https://github.com/material-components/material-components-ios/commit/94ed673c2ae0812c6f524162a042f1b40b430f10) (Justin Shephard)
+* [- Update readme docs (#1379)](https://github.com/material-components/material-components-ios/commit/6e54a23b74d81bb119f7edb7af6878b8d757a517) (Justin Shephard)
+* [Fix warnings uncovered by the Xcode 8.3 static analyzer (#1298)](https://github.com/material-components/material-components-ios/commit/2ce144abd0c1d074ac32677e242d4b9508d76f40) (ianegordon)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [Updated accessibility label on back button (#1334)](https://github.com/material-components/material-components-ios/commit/00009b2106a72e306773af8219e9ccd79fd61487) (Justin Shephard)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### ButtonBar
+
+#### Changes
+
+* [- Removed Video File and updated Readme (#1395)](https://github.com/material-components/material-components-ios/commit/01669183e34d6af48b3911ef40fe6c6bea5036de) (Justin Shephard)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Site] Catalog colors (#1377)](https://github.com/material-components/material-components-ios/commit/653aec06e954ab11db09ac20c0bfd21c2de769cb) (Will Larche)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Buttons
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Buttons, Page Control, Typography] Fixed screenshots (#1380)](https://github.com/material-components/material-components-ios/commit/d48a3dae3edd56b2c0f86f0d6d751cb2ae2da91c) (Randall Li)
+* [[Buttons, Page Control, Typography] Removed video demos (#1387)](https://github.com/material-components/material-components-ios/commit/d7cf7999eded279d660abaed7c37e14299d3334f) (Randall Li)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Math] New private math component (#1325)](https://github.com/material-components/material-components-ios/commit/ff5d16586947158e743eec1cc6da949662f0d7c0) (Will Larche)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### CollectionCells
+
+#### Changes
+
+* [Added new screenshot for CollectionCells. (#1381)](https://github.com/material-components/material-components-ios/commit/fd3bca404082749f354d44fb729a971d85200a98) (Adrian Secord)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Math] New private math component (#1325)](https://github.com/material-components/material-components-ios/commit/ff5d16586947158e743eec1cc6da949662f0d7c0) (Will Larche)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### CollectionLayoutAttributes
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Collections
+
+#### Changes
+
+* [Eliminate static analyzer warnings. Simplify Collection supplementary views (#1316)](https://github.com/material-components/material-components-ios/commit/f018e09afe4c0a1d73d20993d0b2283638dfbdcd) (ianegordon)
+* [Fix warnings uncovered by the Xcode 8.3 static analyzer (#1298)](https://github.com/material-components/material-components-ios/commit/2ce144abd0c1d074ac32677e242d4b9508d76f40) (ianegordon)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Temporarily expose cellWidthAtSection: in MDCCollectionViewController.h  (#1358)](https://github.com/material-components/material-components-ios/commit/3a4c859f376618e6b33533b2ebe21bcc26e81ef9) (Felix Emiliano)
+* [Updated screenshot. (#1383)](https://github.com/material-components/material-components-ios/commit/b2b433f3662220c6d06d81d8ecf8ad78b0e8d34e) (Adrian Secord)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Dialogs
+
+#### Changes
+
+* [Fix AlertController rotation layout (#1306)](https://github.com/material-components/material-components-ios/commit/74e6232777c3d10600bffaee5b1127d9de60baa3) (ianegordon)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [Screenshot (#1376)](https://github.com/material-components/material-components-ios/commit/0489e474e9f5db915e4ed9b23e3ec9be23e0467d) (ianegordon)
+* [[All] Formatting. (#1329)](https://github.com/material-components/material-components-ios/commit/d8a58feecd69219be8f1f7cc15e98ee0d19f5d49) (Will Larche)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### FeatureHighlight
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] Formatting. (#1329)](https://github.com/material-components/material-components-ios/commit/d8a58feecd69219be8f1f7cc15e98ee0d19f5d49) (Will Larche)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[AppBar] & - Remove references to g3 (#1349)](https://github.com/material-components/material-components-ios/commit/acd8d38dc54babbaf58969a2554164745c61cbb5) (Justin Shephard)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Feature Highlight] Updated screenshot (#1385)](https://github.com/material-components/material-components-ios/commit/b30161df41415824c06b5b2b97710c833f7d5e12) (Sam Morrison)
+* [[Feature highlight] Accessibility fixes (#1284)](https://github.com/material-components/material-components-ios/commit/2a47d187edc7a4aec4566641730042fd00df114b) (Sam Morrison)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### FlexibleHeader
+
+#### Changes
+
+* [- Correct use of deprecated property in docs (#1340)](https://github.com/material-components/material-components-ios/commit/9c3f162125a0c2af06877bbe3e9743d150c00c00) (Justin Shephard)
+* [- Remove video file and updated readme (#1394)](https://github.com/material-components/material-components-ios/commit/f96c040c7ee61b38e4c3d5104315f8cc2cb56c5f) (Justin Shephard)
+* [- Update readme doc (#1378)](https://github.com/material-components/material-components-ios/commit/73c83f22871f39dff753995a5697d04380c85cf0) (Justin Shephard)
+* [- Updated doc pic (#1375)](https://github.com/material-components/material-components-ios/commit/7c5586f1caa7f67fda2d190c23f71780c6b216f5) (Justin Shephard)
+* [Ensure the MDCFlexibleHeaderView adheres to UIAppearance proxy if set (#1326)](https://github.com/material-components/material-components-ios/commit/92240a337deeec844ce53061eb289c472168202e) (Justin Shephard)
+* [Fix Swift example in the FlexibleHeader docs (#1354)](https://github.com/material-components/material-components-ios/commit/d0210fa20a460fa1185f96048b9f7c4c80394b06) (Alastair Tse)
+* [Fix warnings uncovered by the Xcode 8.3 static analyzer (#1298)](https://github.com/material-components/material-components-ios/commit/2ce144abd0c1d074ac32677e242d4b9508d76f40) (ianegordon)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### HeaderStackView
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[HeaderStack] - Remove video from Readme (#1391)](https://github.com/material-components/material-components-ios/commit/ebcb49dc14d64c80ccd5cc03c95081e7c81f7a3b) (Justin Shephard)
+* [[Site] Catalog colors (#1377)](https://github.com/material-components/material-components-ios/commit/653aec06e954ab11db09ac20c0bfd21c2de769cb) (Will Larche)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Ink
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Junius' Screenshots (#1393)](https://github.com/material-components/material-components-ios/commit/6cb4269240bac5b4ed98827070b2855ae8aed9da) (ianegordon)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [Remove remaining MP4s and markup. (#1396)](https://github.com/material-components/material-components-ios/commit/555476cf89f03a7a432489604286be1ad5ceb24b) (Adrian Secord)
+* [Update screenshot widths](https://github.com/material-components/material-components-ios/commit/e9630689f0be39fcc1df00fd78fc5ce5dc9c990c) (Junius Gunaratne)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### NavigationBar
+
+#### Changes
+
+* [- Remove Video (#1392)](https://github.com/material-components/material-components-ios/commit/c4a33b3b5fdda1cba4547751310829cab008fdc0) (Justin Shephard)
+* [Fix warnings uncovered by the Xcode 8.3 static analyzer (#1298)](https://github.com/material-components/material-components-ios/commit/2ce144abd0c1d074ac32677e242d4b9508d76f40) (ianegordon)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Math] New private math component (#1325)](https://github.com/material-components/material-components-ios/commit/ff5d16586947158e743eec1cc6da949662f0d7c0) (Will Larche)
+* [[Site] Catalog colors (#1377)](https://github.com/material-components/material-components-ios/commit/653aec06e954ab11db09ac20c0bfd21c2de769cb) (Will Larche)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### OverlayWindow
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### PageControl
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Buttons, Page Control, Typography] Fixed screenshots (#1380)](https://github.com/material-components/material-components-ios/commit/d48a3dae3edd56b2c0f86f0d6d751cb2ae2da91c) (Randall Li)
+* [[Buttons, Page Control, Typography] Removed video demos (#1387)](https://github.com/material-components/material-components-ios/commit/d7cf7999eded279d660abaed7c37e14299d3334f) (Randall Li)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Palettes
+
+#### Changes
+
+* [Added Palettes screenshot. (#1373)](https://github.com/material-components/material-components-ios/commit/3dcb30a6eba5f96deec2ee2e76c0e13eec11ac86) (Adrian Secord)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### ProgressView
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Updates ProgressView to use MDCMath. (#1328)](https://github.com/material-components/material-components-ios/commit/d9b7b2f69f5d0f3bb24b2cff5b9811e09b3a9787) (Louis Romero)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Progress view] Updated screenshot (#1384)](https://github.com/material-components/material-components-ios/commit/e87a24febee47a538a6bc8bdd8857b833f9b7174) (Sam Morrison)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### ShadowElevations
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Shadows] Screenshot (#1382)](https://github.com/material-components/material-components-ios/commit/9599118c1ba4af03185e34b5ca3d5482936c7e71) (ianegordon)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### ShadowLayer
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Screenshot (#1389)](https://github.com/material-components/material-components-ios/commit/fc4f2b763a89b5b2f18c4c2ade109b3723806daa) (ianegordon)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Slider
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Updated screenshot (#1386)](https://github.com/material-components/material-components-ios/commit/8321bede0888bbf967ffbc4ffe969fd6f336ff17) (Sam Morrison)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Snackbar
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [Updated screenshot (#1388)](https://github.com/material-components/material-components-ios/commit/5e7d2ebbc76c4ba81aa6bc161fc920e6089ba030) (Sam Morrison)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Tabs
+
+#### Changes
+
+* [Corrections for readme (#1294)](https://github.com/material-components/material-components-ios/commit/7a0e7de88a82262c8f86755124f32268796aff38) (Will Larche)
+* [Fix warnings uncovered by the Xcode 8.3 static analyzer (#1298)](https://github.com/material-components/material-components-ios/commit/2ce144abd0c1d074ac32677e242d4b9508d76f40) (ianegordon)
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Minor Tweaks to address internal feedback. (#1312)](https://github.com/material-components/material-components-ios/commit/a749a98b4f27652a87527bdd7598ea30e54dd5f2) (ianegordon)
+* [Monochromatic sweep of all catalog components (#1370)](https://github.com/material-components/material-components-ios/commit/4a46c8c19e3df6f4c353057a67f34f446441b3a4) (Alastair Tse)
+* [Remove remaining MP4s and markup. (#1396)](https://github.com/material-components/material-components-ios/commit/555476cf89f03a7a432489604286be1ad5ceb24b) (Adrian Secord)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[Site] Catalog colors (#1377)](https://github.com/material-components/material-components-ios/commit/653aec06e954ab11db09ac20c0bfd21c2de769cb) (Will Larche)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
+### Typography
+
+#### Changes
+
+* [Gigantic documentation update. (#1305)](https://github.com/material-components/material-components-ios/commit/9ed1d4349d90f0bcf13b95043cf9e741846da69c) (Scott Hyndman)
+* [Workaround for medium system font on iOS 8 (#1292)](https://github.com/material-components/material-components-ios/commit/2bda2c118e66ac04b6458a6eab88a24b3c10500c) (ianegordon)
+* [[All] Formatting. (#1329)](https://github.com/material-components/material-components-ios/commit/d8a58feecd69219be8f1f7cc15e98ee0d19f5d49) (Will Larche)
+* [[All] replacing ~~~ with ```. (#1324)](https://github.com/material-components/material-components-ios/commit/3f99ed2dd9aefb903918efb9253ade09e85d9a0d) (Will Larche)
+* [[Buttons, Page Control, Typography] Fixed screenshots (#1380)](https://github.com/material-components/material-components-ios/commit/d48a3dae3edd56b2c0f86f0d6d751cb2ae2da91c) (Randall Li)
+* [[Buttons, Page Control, Typography] Removed video demos (#1387)](https://github.com/material-components/material-components-ios/commit/d7cf7999eded279d660abaed7c37e14299d3334f) (Randall Li)
+* [[Docs] Docstravaganza (#1330)](https://github.com/material-components/material-components-ios/commit/4a011e75a55fa1b0c592c44578a28162ddfa81ce) (Scott Hyndman)
+* [[Docs]: Updated link list classes. (#1320)](https://github.com/material-components/material-components-ios/commit/0913aa9aaf85cfcb041e55acd3b2aa7608bb6a1d) (Scott Hyndman)
+* [[docs] Associated icons with components (#1315)](https://github.com/material-components/material-components-ios/commit/69533578ca35c968594680a3ea50abd539fbea59) (Scott Hyndman)
+
 # 23.0.2
 
 ## API diffs
@@ -607,7 +931,7 @@
 
 ## Minimum iOS version is now 8.0
 
-Given the usage of clients on versions of iOS below 8.0 and the increased power of the APIs available to us on iOS 8, our minimum iOS version is bumped from iOS 7 to 8. 
+Given the usage of clients on versions of iOS below 8.0 and the increased power of the APIs available to us on iOS 8, our minimum iOS version is bumped from iOS 7 to 8.
 
 ## New component: Tabs
 
@@ -708,7 +1032,7 @@
 * [Fix glitchy dismissal animation (#1166)](https://github.com/material-components/material-components-ios/pull/1166) (Sam Morrison)
 * [Update file path for private file. (#1168)](https://github.com/material-components/material-components-ios/commit/1effd8ad0cb879048f00972b366bcdf481e3c2b6) (Louis Romero)
 
-# 20.1.0 
+# 20.1.0
 
 ## API diffs
 
@@ -1118,7 +1442,7 @@
 > Roboto. Once we go public, a pull request to MDFFontDiskLoader will be
 > created to add this convenience. Until that time, you can manually extend
 > your local copy of MDFRobotoFontLoader to declare that it implements
-> MDCTypographyFontLoading. 
+> MDCTypographyFontLoading.
 
 ### ShadowLayer
 #### MDCShadowLayer
@@ -1553,7 +1877,7 @@
 
 ### Switch
 
-* `MDCSwitch` is completely deprecated and will be removed in the next release. We recommend apps use UISwitch instead. 
+* `MDCSwitch` is completely deprecated and will be removed in the next release. We recommend apps use UISwitch instead.
 
 ## Component changes
 
@@ -1747,7 +2071,7 @@
 
 ### Behavior changes in MDCSnackbar
 
-The behavior of MDCSnackbar has been changed to better match [the spec](https://material.google.com/components/snackbars-toasts.html#snackbars-toasts-specs):
+The behavior of MDCSnackbar has been changed to better match [the spec](https://material.io/guidelines/components/snackbars-toasts.html#snackbars-toasts-specs):
 * Animation duration increased from 0.15s to 0.5s.
 * The snackbar no longer fades out, but translates down off screen.
 * The snackbar's text and button (but not the background) fade out during the animation.
@@ -2072,7 +2396,7 @@
 
 ## API diffs
 
-### FeatureHighlight 
+### FeatureHighlight
 
 * [FeatureHighlight](https://github.com/material-components/material-components-ios/commit/d4806473e49e65f0e9cc52139e39c3f1eba4f499) is a new component that lets you highlight a particular feature of your interface to the user.
 
@@ -2461,7 +2785,7 @@
 * [Optimize and simplify MDCSwitch](https://github.com/material-components/material-components-ios/commit/cd1ac75d8fcadd328aa93e9b661e7b063ebda6d4) (Sam Morrison)
 * [Removed all warnings from the build.](https://github.com/material-components/material-components-ios/commit/0b57f48e1dd7e5260d45a13ac5c2650860ce2913) (Adrian Secord)
 
-# 13.4.0 
+# 13.4.0
 
 ## API diffs
 
@@ -2527,7 +2851,7 @@
 * [Remove SKDisplayLinkInterface left over in MDCSwitch stress test](https://github.com/material-components/material-components-ios/commit/f19a6c92a1c59c846a191f08fd587aebf099d596) (Sam Morrison)
 * [Stress test for MDCSwitch](https://github.com/material-components/material-components-ios/commit/63d907e24ea53a4e31ac668b0ac982ab83868311) (Sam Morrison)
 
-# 13.3.0 
+# 13.3.0
 
 ## API diffs
 
diff --git a/MaterialComponents.podspec b/MaterialComponents.podspec
index 0d47f58..a0f6cf7 100644
--- a/MaterialComponents.podspec
+++ b/MaterialComponents.podspec
@@ -2,7 +2,7 @@
 
 Pod::Spec.new do |s|
   s.name         = "MaterialComponents"
-  s.version      = "23.0.2"
+  s.version      = "23.1.0"
   s.authors      = "The Material Components authors."
   s.summary      = "A collection of stand-alone production-ready UI libraries focused on design details."
   s.homepage     = "https://github.com/material-components/material-components-ios"
@@ -54,7 +54,8 @@
   s.subspec "AppBar" do |ss|
     ss.ios.deployment_target = '8.0'
     ss.public_header_files = "components/#{ss.base_name}/src/*.h"
-    ss.source_files = "components/#{ss.base_name}/src/*.{h,m}"
+    ss.source_files = "components/#{ss.base_name}/src/*.{h,m}", "components/#{ss.base_name}/src/private/*.{h,m}"
+    ss.resources = ["components/#{ss.base_name}/src/Material#{ss.base_name}.bundle"]
 
     # Navigation bar contents
     ss.dependency "MaterialComponents/HeaderStackView"
diff --git a/MaterialComponentsCatalog.podspec b/MaterialComponentsCatalog.podspec
index 04b716e..7651206 100644
--- a/MaterialComponentsCatalog.podspec
+++ b/MaterialComponentsCatalog.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name         = "MaterialComponentsCatalog"
-  s.version      = "23.0.2"
+  s.version      = "23.1.0"
   s.authors      = "The Material Components authors."
   s.summary      = "A collection of stand-alone production-ready UI libraries focused on design details."
   s.homepage     = "https://github.com/material-components/material-components-ios"
diff --git a/MaterialComponentsUnitTests.podspec b/MaterialComponentsUnitTests.podspec
index 3cc9000..e460df8 100644
--- a/MaterialComponentsUnitTests.podspec
+++ b/MaterialComponentsUnitTests.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name         = "MaterialComponentsUnitTests"
-  s.version      = "23.0.2"
+  s.version      = "23.1.0"
   s.authors      = "The Material Motion authors."
   s.summary      = "A collection of stand-alone production-ready UI libraries focused on design details."
   s.homepage     = "https://github.com/material-components/material-components-ios"
diff --git a/README.md b/README.md
index fe9242c..e68450e 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 [![Build Status](https://travis-ci.org/material-components/material-components-ios.svg?branch=develop)](https://travis-ci.org/material-components/material-components-ios)
 [![Code coverage](https://img.shields.io/codecov/c/github/material-components/material-components-ios/develop.svg)](https://codecov.io/gh/material-components/material-components-ios/branch/develop)
 
-Material Components for iOS (MDC-iOS) helps developers execute [Material Design](https://www.material.io). Developed by a core team of engineers and UX designers at Google, these components enable a reliable development workflow to build beautiful and functional iOS apps. Learn more about how Material Design supports design and usability best practices across platforms in the  [Material Design Platform Adaptation guidelines](https://material.io/guidelines/platforms/platform-adaptation.html).
+Material Components for iOS (MDC-iOS) helps developers execute [Material Design](https://www.material.io). Developed by a core team of engineers and UX designers at Google, these components enable a reliable development workflow to build beautiful and functional iOS apps. Learn more about how Material Components for iOS supports design and usability best practices across platforms in the  [Material Design Platform Adaptation guidelines](https://material.io/guidelines/platforms/platform-adaptation.html).
 
 Material Components for iOS are written in Objective-C and support Swift and Interface Builder.
 
@@ -17,7 +17,7 @@
 - [Contributing](contributing/)
 - [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
 - [Material.io](https://www.material.io) (external site)
-- [Material Design Guidelines](https://material.google.com) (external site)
+- [Material Design Guidelines](https://material.io/guidelines) (external site)
 
 ## Trying out Material Components
 
diff --git a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/Contents.json b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/Contents.json
index 449ce8a..2676f0d 100644
--- a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/Contents.json
+++ b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/Contents.json
@@ -48,13 +48,13 @@
     {
       "size" : "60x60",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_2x_ios_60dp.png",
+      "filename" : "logo_components_ios_color_2x_ios_48in60dp.png",
       "scale" : "2x"
     },
     {
       "size" : "60x60",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_3x_ios_60dp.png",
+      "filename" : "logo_components_ios_color_3x_ios_48in60dp.png",
       "scale" : "3x"
     },
     {
diff --git a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_components_ios_color_2x_ios_48in60dp.png b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_components_ios_color_2x_ios_48in60dp.png
new file mode 100644
index 0000000..e6379d7
--- /dev/null
+++ b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_components_ios_color_2x_ios_48in60dp.png
Binary files differ
diff --git a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_components_ios_color_3x_ios_48in60dp.png b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_components_ios_color_3x_ios_48in60dp.png
new file mode 100644
index 0000000..abe8899
--- /dev/null
+++ b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_components_ios_color_3x_ios_48in60dp.png
Binary files differ
diff --git a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_mdc_ios_color_2x_ios_60dp.png b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_mdc_ios_color_2x_ios_60dp.png
deleted file mode 100644
index a6f3da7..0000000
--- a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_mdc_ios_color_2x_ios_60dp.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_mdc_ios_color_3x_ios_60dp.png b/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_mdc_ios_color_3x_ios_60dp.png
deleted file mode 100644
index 9cc5320..0000000
--- a/catalog/MDCActionExtension/Assets.xcassets/ExtensionIcon.appiconset/logo_mdc_ios_color_3x_ios_60dp.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog.xcodeproj/project.pbxproj b/catalog/MDCCatalog.xcodeproj/project.pbxproj
index 7a746e5..413f7a3 100644
--- a/catalog/MDCCatalog.xcodeproj/project.pbxproj
+++ b/catalog/MDCCatalog.xcodeproj/project.pbxproj
@@ -20,6 +20,7 @@
 		64307B3F1DF74FEF004AE4AC /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 64307B3D1DF74FEF004AE4AC /* MainInterface.storyboard */; };
 		64307B431DF74FEF004AE4AC /* MDCActionExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 64307B381DF74FEF004AE4AC /* MDCActionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
 		64307B4A1DF76198004AE4AC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 64307B491DF76198004AE4AC /* Assets.xcassets */; };
+		64BD963B1EBC9EF600284D1C /* MDCCatalogStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 64BD963A1EBC9EF600284D1C /* MDCCatalogStyle.m */; };
 		664524B71C6BA62A001ADBF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664524B61C6BA62A001ADBF8 /* AppDelegate.swift */; };
 		664524B91C6BA62A001ADBF8 /* MDCNodeListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 664524B81C6BA62A001ADBF8 /* MDCNodeListViewController.swift */; };
 		664524BE1C6BA62A001ADBF8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 664524BD1C6BA62A001ADBF8 /* Assets.xcassets */; };
@@ -135,6 +136,8 @@
 		64307B3E1DF74FEF004AE4AC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
 		64307B401DF74FEF004AE4AC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
 		64307B491DF76198004AE4AC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		64BD96391EBC9EF600284D1C /* MDCCatalogStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MDCCatalogStyle.h; sourceTree = "<group>"; };
+		64BD963A1EBC9EF600284D1C /* MDCCatalogStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MDCCatalogStyle.m; sourceTree = "<group>"; };
 		664524B31C6BA62A001ADBF8 /* MDCCatalog.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MDCCatalog.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		664524B61C6BA62A001ADBF8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		664524B81C6BA62A001ADBF8 /* MDCNodeListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MDCNodeListViewController.swift; sourceTree = "<group>"; };
@@ -260,6 +263,8 @@
 				66519B061CCA980600E5423E /* MDCInkTouchController+Injection.m */,
 				664524B81C6BA62A001ADBF8 /* MDCNodeListViewController.swift */,
 				665A34DE1C6BDAE700962055 /* Resources */,
+				64BD96391EBC9EF600284D1C /* MDCCatalogStyle.h */,
+				64BD963A1EBC9EF600284D1C /* MDCCatalogStyle.m */,
 			);
 			path = MDCCatalog;
 			sourceTree = "<group>";
@@ -626,6 +631,7 @@
 				6681FDFD1CC586660013A0C7 /* MDCCatalogTileView.swift in Sources */,
 				0B4A5E6D1CC9307A00D2AC5D /* MDCCatalogWindow.swift in Sources */,
 				664524B91C6BA62A001ADBF8 /* MDCNodeListViewController.swift in Sources */,
+				64BD963B1EBC9EF600284D1C /* MDCCatalogStyle.m in Sources */,
 				0BE1D27E1DD276D000F8544B /* MDCCatalogTiles.m in Sources */,
 				66519B071CCA980600E5423E /* MDCInkTouchController+Injection.m in Sources */,
 				664524B71C6BA62A001ADBF8 /* AppDelegate.swift in Sources */,
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json
index f8a3e8d..597ff2c 100644
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -13,37 +13,55 @@
     {
       "size" : "29x29",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_29pt@2x.png",
+      "filename" : "logo_components_ios_color_1x_ios_23in29dp.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "iphone",
+      "filename" : "logo_components_ios_color_2x_ios_23in29dp.png",
       "scale" : "2x"
     },
     {
       "size" : "29x29",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_29pt@3x.png",
+      "filename" : "logo_components_ios_color_3x_ios_23in29dp.png",
       "scale" : "3x"
     },
     {
       "size" : "40x40",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_40pt@2x.png",
+      "filename" : "logo_components_ios_color_2x_ios_32in40dp.png",
       "scale" : "2x"
     },
     {
       "size" : "40x40",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_40pt@3x.png",
+      "filename" : "logo_components_ios_color_3x_ios_32in40dp.png",
       "scale" : "3x"
     },
     {
-      "size" : "60x60",
+      "size" : "57x57",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_40pt@3x.png",
+      "filename" : "logo_components_ios_color_1x_ios_46in57dp.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "logo_components_ios_color_2x_ios_46in57dp.png",
       "scale" : "2x"
     },
     {
       "size" : "60x60",
       "idiom" : "iphone",
-      "filename" : "logo_mdc_ios_color_60pt@3x.png",
+      "filename" : "logo_components_ios_color_2x_ios_48in60dp.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "logo_components_ios_color_3x_ios_48in60dp.png",
       "scale" : "3x"
     },
     {
@@ -59,43 +77,74 @@
     {
       "size" : "29x29",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_29pt.png",
+      "filename" : "logo_components_ios_color_1x_ios_23in29dp.png",
       "scale" : "1x"
     },
     {
       "size" : "29x29",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_29pt@2x.png",
+      "filename" : "logo_components_ios_color_2x_ios_23in29dp.png",
       "scale" : "2x"
     },
     {
       "size" : "40x40",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_40pt.png",
+      "filename" : "logo_components_ios_color_1x_ios_32in40dp.png",
       "scale" : "1x"
     },
     {
       "size" : "40x40",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_40pt@2x.png",
+      "filename" : "logo_components_ios_color_2x_ios_32in40dp.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "50x50",
+      "idiom" : "ipad",
+      "filename" : "logo_components_ios_color_1x_ios_41in50dp.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "50x50",
+      "idiom" : "ipad",
+      "filename" : "logo_components_ios_color_2x_ios_41in50dp.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "logo_components_ios_color_1x_ios_58in72dp.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "logo_components_ios_color_2x_ios_58in72dp.png",
       "scale" : "2x"
     },
     {
       "size" : "76x76",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_76pt.png",
+      "filename" : "logo_components_ios_color_1x_ios_61in76dp.png",
       "scale" : "1x"
     },
     {
       "size" : "76x76",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_76pt@2x.png",
+      "filename" : "logo_components_ios_color_2x_ios_61in76dp.png",
       "scale" : "2x"
     },
     {
       "size" : "83.5x83.5",
       "idiom" : "ipad",
-      "filename" : "logo_mdc_ios_color_83_5pt@2x.png",
+      "filename" : "logo_components_ios_color_1x_ios_133in167dp.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "72x72",
+      "idiom" : "ipad",
+      "filename" : "logo_components_ios_color_2x_ios_58in72dp.png",
+      "unassigned" : true,
       "scale" : "2x"
     }
   ],
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_133in167dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_133in167dp.png
new file mode 100644
index 0000000..8688bf9
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_133in167dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_23in29dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_23in29dp.png
new file mode 100644
index 0000000..ecdce81
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_23in29dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_32in40dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_32in40dp.png
new file mode 100644
index 0000000..dd90cd2
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_32in40dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_41in50dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_41in50dp.png
new file mode 100644
index 0000000..7d2b5f5
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_41in50dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_46in57dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_46in57dp.png
new file mode 100644
index 0000000..8463f7d
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_46in57dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_58in72dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_58in72dp.png
new file mode 100644
index 0000000..0d93e44
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_58in72dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_61in76dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_61in76dp.png
new file mode 100644
index 0000000..45c1c65
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_1x_ios_61in76dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_23in29dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_23in29dp.png
new file mode 100644
index 0000000..b43047a
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_23in29dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_32in40dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_32in40dp.png
new file mode 100644
index 0000000..4567b2b
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_32in40dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_41in50dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_41in50dp.png
new file mode 100644
index 0000000..b4282a5
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_41in50dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_46in57dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_46in57dp.png
new file mode 100644
index 0000000..51fe1eb
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_46in57dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_48in60dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_48in60dp.png
new file mode 100644
index 0000000..e6379d7
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_48in60dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_58in72dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_58in72dp.png
new file mode 100644
index 0000000..56d269b
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_58in72dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_61in76dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_61in76dp.png
new file mode 100644
index 0000000..b13d4a2
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_2x_ios_61in76dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_23in29dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_23in29dp.png
new file mode 100644
index 0000000..d2321cb
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_23in29dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_32in40dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_32in40dp.png
new file mode 100644
index 0000000..948be5d
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_32in40dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_48in60dp.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_48in60dp.png
new file mode 100644
index 0000000..abe8899
--- /dev/null
+++ b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_components_ios_color_3x_ios_48in60dp.png
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt.png
deleted file mode 100644
index 61e6852..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt@2x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt@2x.png
deleted file mode 100644
index 21333b5..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt@2x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt@3x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt@3x.png
deleted file mode 100644
index 174f270..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_29pt@3x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt.png
deleted file mode 100644
index fc33902..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt@2x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt@2x.png
deleted file mode 100644
index 7876f31..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt@2x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt@3x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt@3x.png
deleted file mode 100644
index 964b244..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_40pt@3x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_60pt@3x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_60pt@3x.png
deleted file mode 100644
index a6b845f..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_60pt@3x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_76pt.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_76pt.png
deleted file mode 100644
index 48fa334..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_76pt.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_76pt@2x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_76pt@2x.png
deleted file mode 100644
index e6ace06..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_76pt@2x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_83_5pt@2x.png b/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_83_5pt@2x.png
deleted file mode 100644
index eea65e2..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/AppIcon.appiconset/logo_mdc_ios_color_83_5pt@2x.png
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Assets.xcassets/DemoMain.imageset/Contents.json b/catalog/MDCCatalog/Assets.xcassets/DemoMain.imageset/Contents.json
deleted file mode 100644
index 45fbe98..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/DemoMain.imageset/Contents.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "universal",
-      "filename" : "demo_main_icon.pdf"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
\ No newline at end of file
diff --git a/catalog/MDCCatalog/Assets.xcassets/DemoMain.imageset/demo_main_icon.pdf b/catalog/MDCCatalog/Assets.xcassets/DemoMain.imageset/demo_main_icon.pdf
deleted file mode 100644
index 2a8453b..0000000
--- a/catalog/MDCCatalog/Assets.xcassets/DemoMain.imageset/demo_main_icon.pdf
+++ /dev/null
Binary files differ
diff --git a/catalog/MDCCatalog/Base.lproj/LaunchScreen.storyboard b/catalog/MDCCatalog/Base.lproj/LaunchScreen.storyboard
index ebf48f6..0e24bfc 100644
--- a/catalog/MDCCatalog/Base.lproj/LaunchScreen.storyboard
+++ b/catalog/MDCCatalog/Base.lproj/LaunchScreen.storyboard
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina4_0" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
         <!--View Controller-->
@@ -14,9 +18,9 @@
                         <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
                     </layoutGuides>
                     <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
-                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                     </view>
                 </viewController>
                 <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
diff --git a/catalog/MDCCatalog/MDCCatalogComponentsController.swift b/catalog/MDCCatalog/MDCCatalogComponentsController.swift
index 417a869..c825fb0 100644
--- a/catalog/MDCCatalog/MDCCatalogComponentsController.swift
+++ b/catalog/MDCCatalog/MDCCatalogComponentsController.swift
@@ -87,8 +87,8 @@
 
     let titleLabel = UILabel()
     titleLabel.text = self.title!.uppercased()
-    titleLabel.textColor = UIColor(white: 0.46, alpha: 1)
-    titleLabel.font = MDCTypography.titleFont()
+    titleLabel.textColor = UIColor(white: 1, alpha: 1)
+    titleLabel.font = UIFont(name: "RobotoMono-Regular", size: 14)
     titleLabel.sizeToFit()
     if inset + titleLabel.frame.size.width > containerView.frame.size.width {
       titleLabel.font = MDCTypography.body2Font()
@@ -111,10 +111,9 @@
                    height: titleSize.height)
 
     self.headerViewController.headerView.addSubview(containerView)
-
     self.headerViewController.headerView.forwardTouchEvents(for: containerView)
 
-    self.headerViewController.headerView.backgroundColor = UIColor.white
+    self.headerViewController.headerView.backgroundColor = UIColor(white: 0.1, alpha: 1.0)
     self.headerViewController.headerView.trackingScrollView = self.collectionView
 
     self.headerViewController.headerView.setShadowLayer(MDCShadowLayer()) { (layer, intensity) in
@@ -137,6 +136,12 @@
     self.collectionView?.collectionViewLayout.invalidateLayout()
   }
 
+  override var childViewControllerForStatusBarStyle: UIViewController? {
+    return self.headerViewController
+  }
+
+  // MARK: UICollectionViewDataSource
+
   override func numberOfSections(in collectionView: UICollectionView) -> Int {
     return 1
   }
@@ -149,7 +154,7 @@
   func inkViewForView(_ view: UIView) -> MDCInkView {
     let foundInkView = MDCInkTouchController.injectedInkView(for: view)
     foundInkView.inkStyle = .unbounded
-    foundInkView.inkColor = UIColor(red: 0.012, green: 0.663, blue: 0.957, alpha: 0.2)
+    foundInkView.inkColor = UIColor(white:0.957, alpha: 0.2)
     return foundInkView
   }
 
diff --git a/catalog/MDCCatalog/MDCCatalogStyle.h b/catalog/MDCCatalog/MDCCatalogStyle.h
new file mode 100644
index 0000000..5e055d2
--- /dev/null
+++ b/catalog/MDCCatalog/MDCCatalogStyle.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+ 
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCCatalogStyle : NSObject
+
++ (UIFont *)headerFont;
++ (UIColor *)mdcBlack;
++ (UIColor *)mdcGrey;
++ (UIColor *)mdcGreen;
++ (NSArray *)shadesOfGrey:(int)numberOfGreys;
+
+@end
diff --git a/catalog/MDCCatalog/MDCCatalogStyle.m b/catalog/MDCCatalog/MDCCatalogStyle.m
new file mode 100644
index 0000000..04eb455
--- /dev/null
+++ b/catalog/MDCCatalog/MDCCatalogStyle.m
@@ -0,0 +1,44 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+ 
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ 
+ http://www.apache.org/licenses/LICENSE-2.0
+ 
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCatalogStyle.h"
+
+@implementation MDCCatalogStyle
+
++ (UIFont *)headerFont {
+  return [UIFont fontWithName:@"RobotoMono-Regular" size:14];
+}
++ (UIColor *)mdcBlack {
+  return [UIColor colorWithWhite:0.1f alpha:1];
+}
++ (UIColor *)mdcGrey {
+  return [UIColor colorWithWhite:0.9f alpha:1];
+}
++ (UIColor *)mdcGreen {
+  // #B2FF59 ? TODO
+  return [UIColor colorWithRed:11/255.0f green:232/255.0f blue:94/255.0f alpha:1];
+}
+
++ (NSArray *)shadesOfGrey:(int)numberOfGreys {
+  NSMutableArray *shades = [NSMutableArray array];
+  for (int i = 0; i < numberOfGreys; i++) {
+    [shades addObject:[UIColor colorWithWhite:(CGFloat)(0.9 - i * 0.1) alpha:1]];
+  }
+  return shades;
+}
+
+
+@end
diff --git a/catalog/MDCCatalog/MDCCatalogTiles.m b/catalog/MDCCatalog/MDCCatalogTiles.m
index 194851b..7612e4b 100644
--- a/catalog/MDCCatalog/MDCCatalogTiles.m
+++ b/catalog/MDCCatalog/MDCCatalogTiles.m
@@ -27,13 +27,21 @@
   return image;
 }
 
+static UIColor *MDCPrimaryColor() {
+  return [UIColor colorWithWhite:0.2f alpha:1];
+}
+
+static UIColor *MDCSecondaryColor() {
+  return [UIColor colorWithWhite:0.7f alpha:1];
+}
+
 /* Auto-generated code using PaintCode and formatted with clang-format. */
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wassign-enum"
 #pragma clang diagnostic ignored "-Wconversion"
 void MDCCatalogDrawActivityIndicatorTile(CGRect frame) {
-  UIColor* fillColor = [UIColor colorWithRed:0.702 green:0.898 blue:0.988 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCSecondaryColor();
+  UIColor* fillColor2 = MDCPrimaryColor();
 
   CGRect activityIndicatorGroup =
       CGRectMake(CGRectGetMinX(frame) + 54, CGRectGetMinY(frame) + 24.1,
@@ -295,18 +303,18 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* strokeColor = [UIColor colorWithRed:0.649 green:0.873 blue:0.984 alpha:1];
-  UIColor* gradientColor = [UIColor colorWithRed:0.649 green:0.873 blue:0.984 alpha:1];
-  UIColor* gradientColor2 = [UIColor colorWithRed:0.149 green:0.65 blue:0.954 alpha:1];
-  UIColor* gradientColor3 = [UIColor colorWithRed:0.033 green:0.261 blue:0.537 alpha:1];
-  UIColor* fillColor1 = [UIColor colorWithRed:0.004 green:0.341 blue:0.608 alpha:0.9];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.008 green:0.467 blue:0.741 alpha:0.9];
-  UIColor* fillColor3 = [UIColor colorWithRed:0.008 green:0.533 blue:0.82 alpha:0.9];
-  UIColor* fillColor4 = [UIColor colorWithRed:0.012 green:0.608 blue:0.898 alpha:0.9];
-  UIColor* fillColor5 = [UIColor colorWithRed:0.149 green:0.651 blue:0.955 alpha:1];
-  UIColor* fillColor6 = [UIColor colorWithRed:0.31 green:0.765 blue:0.969 alpha:0.9];
-  UIColor* fillColor7 = [UIColor colorWithRed:0.506 green:0.831 blue:0.98 alpha:0.9];
-  UIColor* fillColor8 = [UIColor colorWithRed:0.702 green:0.898 blue:0.988 alpha:0.9];
+  UIColor* strokeColor = MDCSecondaryColor();
+  UIColor* gradientColor = [UIColor colorWithWhite:0.649 alpha:1];
+  UIColor* gradientColor2 = [UIColor colorWithWhite:0.149 alpha:1];
+  UIColor* gradientColor3 = [UIColor colorWithWhite:0.033 alpha:1];
+  UIColor* fillColor1 = [UIColor colorWithWhite:0.341 alpha:0.9];
+  UIColor* fillColor2 = [UIColor colorWithWhite:0.467 alpha:0.9];
+  UIColor* fillColor3 = [UIColor colorWithWhite:0.533 alpha:0.9];
+  UIColor* fillColor4 = [UIColor colorWithWhite:0.608 alpha:0.9];
+  UIColor* fillColor5 = [UIColor colorWithWhite:0.651 alpha:1];
+  UIColor* fillColor6 = [UIColor colorWithWhite:0.765 alpha:0.9];
+  UIColor* fillColor7 = [UIColor colorWithWhite:0.831 alpha:0.9];
+  UIColor* fillColor8 = [UIColor colorWithWhite:0.902 alpha:0.9];
   UIColor* fillColor9 = [fillColor8 colorWithAlphaComponent:0.5];
 
   CGFloat gradientLocations[] = {0, 0, 0.52, 1};
@@ -688,8 +696,8 @@
 void MDCCatalogDrawAppBarTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
+  UIColor* fillColor2 = MDCSecondaryColor();
 
   CGRect group2 = CGRectMake(CGRectGetMinX(frame) + 24.5, CGRectGetMinY(frame) + 24,
                              floor((CGRectGetWidth(frame) - 24.5) * 1.02783 + 24.45) - 23.95,
@@ -710,7 +718,6 @@
 
     {
       CGContextSaveGState(context);
-      CGContextSetAlpha(context, 0.2);
       CGContextBeginTransparencyLayer(context, NULL);
 
       UIBezierPath* bezierPath = [UIBezierPath bezierPath];
@@ -772,8 +779,9 @@
 }
 
 void MDCCatalogDrawButtonBarTile(CGRect frame) {
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
+
+  UIColor* fillColor = MDCPrimaryColor();
+  UIColor* fillColor2 = MDCSecondaryColor();
 
   CGRect buttonBar = CGRectMake(CGRectGetMinX(frame) - 10, CGRectGetMinY(frame) + 24,
                                 floor((CGRectGetWidth(frame) + 10) * 0.87626 - 10) + 10.5,
@@ -1702,7 +1710,7 @@
 void MDCCatalogDrawButtonsTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.077 green:0.591 blue:0.945 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
 
   CGRect group = CGRectMake(
       CGRectGetMinX(frame) + floor((CGRectGetWidth(frame) - 77.75) * 0.22200 + 0.02) + 0.48,
@@ -1740,9 +1748,10 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.1];
-  UIColor* color = [UIColor colorWithRed:0.506 green:0.831 blue:0.98 alpha:1];
+  UIColor* fillColor = [UIColor colorWithWhite:0.0 alpha:0];
+  UIColor* fillColor2 = [UIColor colorWithWhite:0.6 alpha:0.3];
+
+  UIColor* color = MDCPrimaryColor();
   UIColor* gradientColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0];
 
   // This gradient was adjusted by hand to not use macOS API
@@ -1848,9 +1857,9 @@
 void MDCCatalogDrawCollectionsTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
   UIColor* white40 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.4];
-  UIColor* blue60 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.6];
+  UIColor* blue60 = fillColor;
   UIColor* white60 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.7];
   UIColor* white80 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8];
   UIColor* white30 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.3];
@@ -1951,7 +1960,7 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* gradientColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.1];
+  UIColor* gradientColor = MDCSecondaryColor();
 
   // This gradient was adjusted by hand to not use macOS API
   CGFloat gradientLocations[] = {0.13, 1};
@@ -2009,8 +2018,8 @@
 void MDCCatalogDrawFeatureHighlightTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.71 green:0.894 blue:0.98 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
+  UIColor* fillColor2 = MDCSecondaryColor();
   UIColor* white = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
 
   CGRect featureHighlightGroup = CGRectMake(CGRectGetMinX(frame) + 24.5, CGRectGetMinY(frame) + 24,
@@ -2119,7 +2128,8 @@
 void MDCCatalogDrawFlexibleHeaderTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
+
   UIColor* blue10 = [fillColor colorWithAlphaComponent:0.1];
   UIColor* blue5 = [fillColor colorWithAlphaComponent:0.05];
 
@@ -2211,8 +2221,9 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* gradientColor = [UIColor colorWithRed:0.076 green:0.59 blue:0.945 alpha:1];
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* gradientColor = MDCPrimaryColor();
+  UIColor* fillColor = MDCSecondaryColor();
+
   CGFloat fillColorRGBA[4];
   [fillColor getRed:&fillColorRGBA[0]
               green:&fillColorRGBA[1]
@@ -2224,7 +2235,7 @@
                                     blue:(fillColorRGBA[2] * 0.6)
                                    alpha:(fillColorRGBA[3] * 0.6 + 0.4)];
   UIColor* fillColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
-  UIColor* blue80 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.56];
+  UIColor* blue80 = MDCPrimaryColor();
 
   CGFloat gradientLocations[] = {0.14, 0.51, 1};
 
@@ -2346,7 +2357,7 @@
 void MDCCatalogDrawInkTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.077 green:0.591 blue:0.945 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
   UIColor* fillColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
 
   CGRect group = CGRectMake(
@@ -2382,7 +2393,7 @@
 void MDCCatalogDrawMiscTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
   CGFloat fillColorRGBA[4];
   [fillColor getRed:&fillColorRGBA[0]
               green:&fillColorRGBA[1]
@@ -2600,10 +2611,10 @@
   CGContextRef context = UIGraphicsGetCurrentContext();
 
   UIColor* gradientColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
-  UIColor* fillColor = [UIColor colorWithRed:0.184 green:0.571 blue:0.828 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.994 green:0.994 blue:0.994 alpha:1];
-  UIColor* textForeground = [UIColor colorWithRed:0.996 green:0.996 blue:0.996 alpha:0.2];
-  UIColor* gradientColor2 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
+  UIColor* fillColor2 = MDCSecondaryColor();
+  UIColor* textForeground = [fillColor colorWithAlphaComponent:0.2];
+  UIColor* gradientColor2 = MDCPrimaryColor();
 
   CGFloat gradientLocations[] = {0.14, 0.5, 1};
   CGGradientRef gradient = CGGradientCreateWithColors(
@@ -2786,9 +2797,9 @@
 }
 
 void MDCCatalogDrawOverlayWindow(CGRect frame) {
-  UIColor* fillColor = [UIColor colorWithRed:0.649 green:0.873 blue:0.984 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.076 green:0.59 blue:0.945 alpha:1];
-  UIColor* fillColor3 = [UIColor colorWithRed:0.261 green:0.712 blue:0.959 alpha:1];
+  UIColor* fillColor = MDCSecondaryColor();
+  UIColor* fillColor2 = MDCPrimaryColor();
+  UIColor* fillColor3 = [UIColor colorWithWhite:0.5 alpha:1.0];
 
   CGRect overlayWindowGroup = CGRectMake(CGRectGetMinX(frame) + 54, CGRectGetMinY(frame) + 38,
                                          floor((CGRectGetWidth(frame) - 54) * 0.59701 + 0.5),
@@ -2907,11 +2918,11 @@
   CGContextRef context = UIGraphicsGetCurrentContext();
 
   UIColor* gradientColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
-  UIColor* fillColor10 = [UIColor colorWithRed:0.506 green:0.831 blue:0.976 alpha:1];
-  UIColor* gradientColor2 = [UIColor colorWithRed:0.075 green:0.592 blue:0.945 alpha:0.3];
-  UIColor* fillColor7 = [UIColor colorWithRed:0.902 green:0.965 blue:0.996 alpha:0.5];
-  UIColor* fillColor8 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8];
-  UIColor* color2 = [UIColor colorWithRed:0.902 green:0.965 blue:0.996 alpha:0.3];
+  UIColor* fillColor10 = MDCSecondaryColor();
+  UIColor* gradientColor2 = MDCPrimaryColor();
+  UIColor* fillColor7 = [gradientColor2 colorWithAlphaComponent:0.5];
+  UIColor* fillColor8 = [gradientColor2 colorWithAlphaComponent:0.8];
+  UIColor* color2 = [gradientColor2 colorWithAlphaComponent:0.3];
 
   CGFloat gradient2Locations[] = {0.28, 0.68, 0.98};
   CGGradientRef gradient2 = CGGradientCreateWithColors(
@@ -3043,15 +3054,15 @@
 void MDCCatalogDrawPalettesTile(CGRect frame) {
   CGFloat PalettesFontPointSize = [UIScreen mainScreen].bounds.size.width / 320 * 7;
 
-  UIColor* textDark = [UIColor colorWithRed:0.004 green:0.341 blue:0.608 alpha:1];
-  UIColor* textLight = [UIColor colorWithRed:0.702 green:0.898 blue:0.988 alpha:1];
-  UIColor* fill200 = [UIColor colorWithRed:0.506 green:0.831 blue:0.98 alpha:1];
-  UIColor* fill300 = [UIColor colorWithRed:0.31 green:0.765 blue:0.969 alpha:1];
-  UIColor* fill400 = [UIColor colorWithRed:0.161 green:0.714 blue:0.965 alpha:1];
-  UIColor* fill500 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
-  UIColor* fill600 = [UIColor colorWithRed:0.012 green:0.608 blue:0.898 alpha:1];
-  UIColor* fill700 = [UIColor colorWithRed:0.008 green:0.533 blue:0.82 alpha:1];
-  UIColor* fill800 = [UIColor colorWithRed:0.008 green:0.467 blue:0.741 alpha:1];
+  UIColor* textDark = MDCPrimaryColor();
+  UIColor* textLight = MDCSecondaryColor();
+  UIColor* fill200 = [UIColor colorWithWhite:0.831 alpha:1];
+  UIColor* fill300 = [UIColor colorWithWhite:0.765 alpha:1];
+  UIColor* fill400 = [UIColor colorWithWhite:0.714 alpha:1];
+  UIColor* fill500 = [UIColor colorWithWhite:0.663 alpha:1];
+  UIColor* fill600 = [UIColor colorWithWhite:0.608 alpha:1];
+  UIColor* fill700 = [UIColor colorWithWhite:0.533 alpha:1];
+  UIColor* fill800 = [UIColor colorWithWhite:0.467 alpha:1];
 
   CGRect palettesGroup = CGRectMake(CGRectGetMinX(frame) + 25, CGRectGetMinY(frame) + 24.1,
                                     floor((CGRectGetWidth(frame) - 25) * 0.84663 + 0.5),
@@ -3259,7 +3270,7 @@
 
     NSDictionary* label500FontAttributes = @{
       NSFontAttributeName : [UIFont fontWithName:PalettesFontName size:PalettesFontPointSize],
-      NSForegroundColorAttributeName : textLight,
+      NSForegroundColorAttributeName : textDark,
       NSParagraphStyleAttributeName : label500Style
     };
 
@@ -3277,7 +3288,7 @@
 
     NSDictionary* label600FontAttributes = @{
       NSFontAttributeName : [UIFont fontWithName:PalettesFontName size:PalettesFontPointSize],
-      NSForegroundColorAttributeName : textLight,
+      NSForegroundColorAttributeName : textDark,
       NSParagraphStyleAttributeName : label600Style
     };
 
@@ -3295,7 +3306,7 @@
 
     NSDictionary* label700FontAttributes = @{
       NSFontAttributeName : [UIFont fontWithName:PalettesFontName size:PalettesFontPointSize],
-      NSForegroundColorAttributeName : textLight,
+      NSForegroundColorAttributeName : textDark,
       NSParagraphStyleAttributeName : label700Style
     };
 
@@ -3313,7 +3324,7 @@
 
     NSDictionary* label800FontAttributes = @{
       NSFontAttributeName : [UIFont fontWithName:PalettesFontName size:PalettesFontPointSize],
-      NSForegroundColorAttributeName : textLight,
+      NSForegroundColorAttributeName : textDark,
       NSParagraphStyleAttributeName : label800Style
     };
 
@@ -3343,9 +3354,9 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.008 green:0.467 blue:0.741 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
-  UIColor* gradientColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.1];
+  UIColor* fillColor = MDCPrimaryColor();
+  UIColor* fillColor2 = [UIColor colorWithWhite:0.1 alpha:1];
+  UIColor* gradientColor = MDCSecondaryColor();
 
   CGFloat gradientLocations[] = {0.14, 1};
   CGGradientRef gradient = CGGradientCreateWithColors(
@@ -3361,7 +3372,7 @@
     CGRect gradientRectangleRect = CGRectMake(
         CGRectGetMinX(progressViewGroup) + floor(CGRectGetWidth(progressViewGroup) * 0.00000 + 0.5),
         CGRectGetMinY(progressViewGroup) +
-            floor(CGRectGetHeight(progressViewGroup) * 0.30500 + 0.5),
+            floor(CGRectGetHeight(progressViewGroup) * 0.30500),
         floor(CGRectGetWidth(progressViewGroup) * 1.00000 + 0.5) -
             floor(CGRectGetWidth(progressViewGroup) * 0.00000 + 0.5),
         floor(CGRectGetHeight(progressViewGroup) * 1.00000 - 0.1) -
@@ -3423,7 +3434,7 @@
 void MDCCatalogDrawShadowLayerTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
   UIColor* fillColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.9];
   UIColor* shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.25];
 
@@ -3565,11 +3576,11 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
-  UIColor* gradientColor = [UIColor colorWithRed:0.102 green:0.09 blue:0.094 alpha:0];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.209 green:0.73 blue:0.965 alpha:1];
-  UIColor* fillColor3 = [UIColor colorWithRed:0.407 green:0.798 blue:0.974 alpha:1];
-  UIColor* fillColor4 = [UIColor colorWithRed:0.605 green:0.865 blue:0.983 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
+  UIColor* gradientColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0];
+  UIColor* fillColor2 = [UIColor colorWithWhite:0.209 alpha:1];
+  UIColor* fillColor3 = [UIColor colorWithWhite:0.407 alpha:1];
+  UIColor* fillColor4 = MDCSecondaryColor();
   UIColor* gradientColor1 = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
 
   CGFloat gradient50Locations[] = {0, 1};
@@ -3829,8 +3840,8 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* gradientColor = [UIColor colorWithRed:0.076 green:0.59 blue:0.945 alpha:1];
-  UIColor* fillColor = [UIColor colorWithRed:0.077 green:0.591 blue:0.945 alpha:1];
+  UIColor* gradientColor = MDCSecondaryColor();
+  UIColor* fillColor = MDCPrimaryColor();
 
   CGFloat gradientLocations[] = {0, 0.14, 1};
   CGGradientRef gradient = CGGradientCreateWithColors(
@@ -3883,8 +3894,8 @@
 void MDCCatalogDrawSwitchTile(CGRect frame) {
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* fillColor = [UIColor colorWithRed:0.119 green:0.63 blue:0.95 alpha:1];
-  UIColor* fillColor2 = [UIColor colorWithRed:0.077 green:0.591 blue:0.945 alpha:1];
+  UIColor* fillColor = MDCSecondaryColor();
+  UIColor* fillColor2 = MDCPrimaryColor();
 
   CGRect group = CGRectMake(
       CGRectGetMinX(frame) + floor((CGRectGetWidth(frame) - 56.43) * 0.59180 - 0.37) + 0.87,
@@ -3934,8 +3945,8 @@
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
   CGContextRef context = UIGraphicsGetCurrentContext();
 
-  UIColor* gradientColor = [UIColor colorWithRed:0.075 green:0.592 blue:0.945 alpha:0.1];
-  UIColor* fillColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  UIColor* gradientColor = MDCSecondaryColor();
+  UIColor* fillColor = MDCPrimaryColor();
   UIColor* fillColor2 = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
 
   CGFloat gradientLocations[] = {0, 0.86, 1};
@@ -4092,7 +4103,7 @@
 }
 
 void MDCCatalogDrawTypographyTile(CGRect frame) {
-  UIColor* fillColor = [UIColor colorWithRed:0.077 green:0.591 blue:0.945 alpha:1];
+  UIColor* fillColor = MDCPrimaryColor();
 
   UIBezierPath* bezierPath = [UIBezierPath bezierPath];
   [bezierPath moveToPoint:CGPointMake(CGRectGetMinX(frame) + 0.48184 * CGRectGetWidth(frame),
diff --git a/catalog/MDCCatalog/MDCNodeListViewController.swift b/catalog/MDCCatalog/MDCNodeListViewController.swift
index 7f51cfa..5a1ddd5 100644
--- a/catalog/MDCCatalog/MDCNodeListViewController.swift
+++ b/catalog/MDCCatalog/MDCNodeListViewController.swift
@@ -80,7 +80,13 @@
     // swiftlint:enable force_cast
 
     self.addChildViewController(appBar.headerViewController)
-    appBar.headerViewController.headerView.backgroundColor = UIColor.white
+    let appBarFont = UIFont(name: "RobotoMono-Regular", size: 16)
+    
+    appBar.headerViewController.headerView.backgroundColor = UIColor(white: 0.1, alpha: 1.0)
+    appBar.navigationBar.tintColor = UIColor.white
+    appBar.navigationBar.titleTextAttributes = [
+      NSForegroundColorAttributeName: UIColor.white,
+      NSFontAttributeName: appBarFont! ]
     appBar.navigationBar.titleAlignment = .center
   }
 
@@ -108,6 +114,10 @@
 
     self.navigationController?.setNavigationBarHidden(true, animated: animated)
   }
+
+  override var childViewControllerForStatusBarStyle: UIViewController? {
+    return appBar.headerViewController
+  }
 }
 
 // MARK: UIScrollViewDelegate
@@ -263,8 +273,6 @@
     if indexPath.section == Section.description.rawValue {
       subtitleText = node.children[indexPath.row].exampleViewControllerName()
       cell!.textLabel!.text = "Demo"
-      cell!.textLabel!.textColor = UIColor(red: 0.01, green: 0.66, blue: 0.96, alpha: 1)
-      cell!.imageView?.image = UIImage(named: "DemoMain")
     } else {
       subtitleText = node.children[indexPath.row + 1].exampleViewControllerName()
       cell!.textLabel!.text = node.children[indexPath.row + 1].title
@@ -340,8 +348,12 @@
       if contentVC.responds(to: NSSelectorFromString("catalogShouldHideNavigation")) {
         vc = contentVC
       } else {
+        let appBarFont = UIFont(name: "RobotoMono-Regular", size: 16)
         let container = MDCAppBarContainerViewController(contentViewController: contentVC)
         container.appBar.navigationBar.titleAlignment = .center
+        container.appBar.navigationBar.tintColor = UIColor.white
+        container.appBar.navigationBar.titleTextAttributes =
+            [ NSForegroundColorAttributeName: UIColor.white, NSFontAttributeName: appBarFont! ]
 
         // TODO(featherless): Remove once
         // https://github.com/material-components/material-components-ios/issues/367 is resolved.
@@ -349,9 +361,9 @@
 
         let headerView = container.appBar.headerViewController.headerView
 
-        headerView.backgroundColor = UIColor.white
+        headerView.backgroundColor = UIColor(white: 0.1, alpha: 1.0)
 
-        let textColor = UIColor(white: 0, alpha: 0.8)
+        let textColor = UIColor.white
         UIBarButtonItem.appearance().setTitleTextAttributes(
           [NSForegroundColorAttributeName: textColor],
           for: UIControlState())
diff --git a/catalog/Podfile.lock b/catalog/Podfile.lock
deleted file mode 100644
index e1346c8..0000000
--- a/catalog/Podfile.lock
+++ /dev/null
@@ -1,196 +0,0 @@
-PODS:
-  - CatalogByConvention (2.1.0)
-  - EarlGrey (1.9.1)
-  - MaterialComponents (23.0.2):
-    - MaterialComponents/ActivityIndicator (= 23.0.2)
-    - MaterialComponents/AnimationTiming (= 23.0.2)
-    - MaterialComponents/AppBar (= 23.0.2)
-    - MaterialComponents/ButtonBar (= 23.0.2)
-    - MaterialComponents/Buttons (= 23.0.2)
-    - MaterialComponents/CollectionCells (= 23.0.2)
-    - MaterialComponents/CollectionLayoutAttributes (= 23.0.2)
-    - MaterialComponents/Collections (= 23.0.2)
-    - MaterialComponents/Dialogs (= 23.0.2)
-    - MaterialComponents/FeatureHighlight (= 23.0.2)
-    - MaterialComponents/FlexibleHeader (= 23.0.2)
-    - MaterialComponents/HeaderStackView (= 23.0.2)
-    - MaterialComponents/Ink (= 23.0.2)
-    - MaterialComponents/NavigationBar (= 23.0.2)
-    - MaterialComponents/OverlayWindow (= 23.0.2)
-    - MaterialComponents/PageControl (= 23.0.2)
-    - MaterialComponents/Palettes (= 23.0.2)
-    - MaterialComponents/private (= 23.0.2)
-    - MaterialComponents/ProgressView (= 23.0.2)
-    - MaterialComponents/ShadowElevations (= 23.0.2)
-    - MaterialComponents/ShadowLayer (= 23.0.2)
-    - MaterialComponents/Slider (= 23.0.2)
-    - MaterialComponents/Snackbar (= 23.0.2)
-    - MaterialComponents/Tabs (= 23.0.2)
-    - MaterialComponents/Typography (= 23.0.2)
-  - MaterialComponents/ActivityIndicator (23.0.2):
-    - MaterialComponents/private/Application
-    - MaterialComponents/private/RTL
-  - MaterialComponents/AnimationTiming (23.0.2)
-  - MaterialComponents/AppBar (23.0.2):
-    - MaterialComponents/FlexibleHeader
-    - MaterialComponents/HeaderStackView
-    - MaterialComponents/NavigationBar
-    - MaterialComponents/private/Icons/ic_arrow_back
-    - MaterialComponents/private/RTL
-    - MaterialComponents/ShadowElevations
-    - MaterialComponents/ShadowLayer
-    - MaterialComponents/Typography
-  - MaterialComponents/ButtonBar (23.0.2):
-    - MaterialComponents/Buttons
-    - MaterialComponents/private/RTL
-  - MaterialComponents/Buttons (23.0.2):
-    - MaterialComponents/Ink
-    - MaterialComponents/private/Math
-    - MaterialComponents/ShadowElevations
-    - MaterialComponents/ShadowLayer
-    - MaterialComponents/Typography
-    - MDFTextAccessibility
-  - MaterialComponents/CollectionCells (23.0.2):
-    - MaterialComponents/CollectionLayoutAttributes
-    - MaterialComponents/Ink
-    - MaterialComponents/private/Icons/ic_check
-    - MaterialComponents/private/Icons/ic_check_circle
-    - MaterialComponents/private/Icons/ic_chevron_right
-    - MaterialComponents/private/Icons/ic_info
-    - MaterialComponents/private/Icons/ic_radio_button_unchecked
-    - MaterialComponents/private/Icons/ic_reorder
-    - MaterialComponents/private/Math
-    - MaterialComponents/private/RTL
-    - MaterialComponents/Typography
-  - MaterialComponents/CollectionLayoutAttributes (23.0.2)
-  - MaterialComponents/Collections (23.0.2):
-    - MaterialComponents/CollectionCells
-    - MaterialComponents/CollectionLayoutAttributes
-    - MaterialComponents/Ink
-    - MaterialComponents/ShadowElevations
-    - MaterialComponents/ShadowLayer
-    - MaterialComponents/Typography
-  - MaterialComponents/Dialogs (23.0.2):
-    - MaterialComponents/Buttons
-    - MaterialComponents/private/KeyboardWatcher
-    - MaterialComponents/private/RTL
-    - MaterialComponents/ShadowElevations
-    - MaterialComponents/ShadowLayer
-  - MaterialComponents/FeatureHighlight (23.0.2):
-    - MaterialComponents/Typography
-    - MDFTextAccessibility
-  - MaterialComponents/FlexibleHeader (23.0.2):
-    - MaterialComponents/private/Application
-    - MDFTextAccessibility
-  - MaterialComponents/HeaderStackView (23.0.2)
-  - MaterialComponents/Ink (23.0.2)
-  - MaterialComponents/NavigationBar (23.0.2):
-    - MaterialComponents/ButtonBar
-    - MaterialComponents/private/Math
-    - MaterialComponents/private/RTL
-    - MaterialComponents/Typography
-    - MDFTextAccessibility
-  - MaterialComponents/OverlayWindow (23.0.2):
-    - MaterialComponents/private/Application
-  - MaterialComponents/PageControl (23.0.2)
-  - MaterialComponents/Palettes (23.0.2)
-  - MaterialComponents/private (23.0.2):
-    - MaterialComponents/private/Application (= 23.0.2)
-    - MaterialComponents/private/Icons (= 23.0.2)
-    - MaterialComponents/private/KeyboardWatcher (= 23.0.2)
-    - MaterialComponents/private/Math (= 23.0.2)
-    - MaterialComponents/private/Overlay (= 23.0.2)
-    - MaterialComponents/private/RTL (= 23.0.2)
-    - MaterialComponents/private/ThumbTrack (= 23.0.2)
-  - MaterialComponents/private/Application (23.0.2)
-  - MaterialComponents/private/Icons (23.0.2):
-    - MaterialComponents/private/Icons/Base (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_arrow_back (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_check (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_check_circle (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_chevron_right (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_info (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_reorder (= 23.0.2)
-  - MaterialComponents/private/Icons/Base (23.0.2)
-  - MaterialComponents/private/Icons/ic_arrow_back (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_check (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_check_circle (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_chevron_right (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_info (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_reorder (23.0.2):
-    - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/KeyboardWatcher (23.0.2):
-    - MaterialComponents/private/Application
-  - MaterialComponents/private/Math (23.0.2)
-  - MaterialComponents/private/Overlay (23.0.2)
-  - MaterialComponents/private/RTL (23.0.2)
-  - MaterialComponents/private/ThumbTrack (23.0.2):
-    - MaterialComponents/Ink
-    - MaterialComponents/private/Math
-    - MaterialComponents/private/RTL
-    - MaterialComponents/ShadowElevations
-    - MaterialComponents/ShadowLayer
-    - MaterialComponents/Typography
-  - MaterialComponents/ProgressView (23.0.2):
-    - MaterialComponents/private/Math
-    - MaterialComponents/private/RTL
-  - MaterialComponents/ShadowElevations (23.0.2)
-  - MaterialComponents/ShadowLayer (23.0.2)
-  - MaterialComponents/Slider (23.0.2):
-    - MaterialComponents/private/ThumbTrack
-  - MaterialComponents/Snackbar (23.0.2):
-    - MaterialComponents/AnimationTiming
-    - MaterialComponents/Buttons
-    - MaterialComponents/OverlayWindow
-    - MaterialComponents/private/Application
-    - MaterialComponents/private/KeyboardWatcher
-    - MaterialComponents/private/Overlay
-    - MaterialComponents/Typography
-  - MaterialComponents/Tabs (23.0.2):
-    - MaterialComponents/AnimationTiming
-    - MaterialComponents/Ink
-    - MaterialComponents/private/RTL
-    - MaterialComponents/Typography
-  - MaterialComponents/Typography (23.0.2):
-    - MaterialComponents/private/Application
-  - MaterialComponentsCatalog (23.0.2):
-    - MaterialComponents
-  - MaterialComponentsUnitTests (23.0.2):
-    - MaterialComponents
-    - MDFTextAccessibility
-  - MDFTextAccessibility (1.2.0)
-
-DEPENDENCIES:
-  - CatalogByConvention
-  - EarlGrey
-  - MaterialComponents (from `../`)
-  - MaterialComponentsCatalog (from `../`)
-  - MaterialComponentsUnitTests (from `../`)
-
-EXTERNAL SOURCES:
-  MaterialComponents:
-    :path: "../"
-  MaterialComponentsCatalog:
-    :path: "../"
-  MaterialComponentsUnitTests:
-    :path: "../"
-
-SPEC CHECKSUMS:
-  CatalogByConvention: ef0913973b86b4234bcadf22aa84037c4a47cbbd
-  EarlGrey: 853906dc3b75ebb5500bcbe519c70c5f4948c0ee
-  MaterialComponents: fc0b6f9725db1f434aa3f8d7feb7832ac99a3692
-  MaterialComponentsCatalog: 1e956249208e8ce3629e3c9e2f76f6e78631ecbc
-  MaterialComponentsUnitTests: 89f93baffdd3190a6746a403830f3982bcbb85f4
-  MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
-
-PODFILE CHECKSUM: f78876d357e88f474a199b0b4c5b36385a5ef25c
-
-COCOAPODS: 1.2.1
diff --git a/catalog/README.md b/catalog/README.md
index 751fe09..d62b46e 100644
--- a/catalog/README.md
+++ b/catalog/README.md
@@ -107,4 +107,4 @@
 - [Contributing](../contributing/)
 - [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
 - [Material.io](https://www.material.io) (external site)
-- [Material Design Guidelines](https://material.google.com) (external site)
+- [Material Design Guidelines](https://material.io/guidelines) (external site)
diff --git a/components/ActivityIndicator/README.md b/components/ActivityIndicator/README.md
index 27d8e82..f554525 100644
--- a/components/ActivityIndicator/README.md
+++ b/components/ActivityIndicator/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "Progress and activity indicators are visual indications of an app loading content."
 iconId: progress_activity
+path: /catalog/activity-indicators/
 -->
 
-# Activity Indicator
+# Activity Indicators
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/activity_indicator.png" alt="Activity Indicator" width="320">
+  <img src="docs/assets/activity_indicator.png" alt="Activity Indicator" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/activity_indicator.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 Activity indicators are visual indications of an app loading content. The Activity Indicator is a circular indicator that either rotates clockwise or fills to completion clockwise when displaying progress.
 <!--{: .article__intro }-->
@@ -24,7 +19,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://material.google.com/components/progress-activity.html">Progress & activity</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/progress-activity.html">Progress & activity</a></li>
 </ul>
 
 - - -
diff --git a/components/ActivityIndicator/docs/assets/activity_indicator.mp4 b/components/ActivityIndicator/docs/assets/activity_indicator.mp4
deleted file mode 100644
index 927367f..0000000
--- a/components/ActivityIndicator/docs/assets/activity_indicator.mp4
+++ /dev/null
Binary files differ
diff --git a/components/ActivityIndicator/docs/assets/activity_indicator.png b/components/ActivityIndicator/docs/assets/activity_indicator.png
index 3b543cd..5be947b 100644
--- a/components/ActivityIndicator/docs/assets/activity_indicator.png
+++ b/components/ActivityIndicator/docs/assets/activity_indicator.png
Binary files differ
diff --git a/components/ActivityIndicator/examples/ActivityIndicatorExample.m b/components/ActivityIndicator/examples/ActivityIndicatorExample.m
index 072885a..7e69eeb 100644
--- a/components/ActivityIndicator/examples/ActivityIndicatorExample.m
+++ b/components/ActivityIndicator/examples/ActivityIndicatorExample.m
@@ -37,6 +37,7 @@
     _activityIndicator.delegate = self;
     _activityIndicator.radius = kActivityIndicatorRadius;
     _activityIndicator.strokeWidth = 8.f;
+    _activityIndicator.cycleColors = @[[UIColor colorWithWhite:0.1 alpha:1.0]];
 
     _activityIndicator.autoresizingMask =
         (UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin |
diff --git a/components/ActivityIndicator/examples/supplemental/ActivityIndicatorExampleSupplemental.m b/components/ActivityIndicator/examples/supplemental/ActivityIndicatorExampleSupplemental.m
index 193af84..4062ac8 100644
--- a/components/ActivityIndicator/examples/supplemental/ActivityIndicatorExampleSupplemental.m
+++ b/components/ActivityIndicator/examples/supplemental/ActivityIndicatorExampleSupplemental.m
@@ -44,7 +44,10 @@
 @implementation ActivityIndicatorExample (Supplemental)
 
 - (void)setupExampleViews {
+
   self.onSwitch = [[UISwitch alloc] init];
+  self.onSwitch.onTintColor = [UIColor colorWithWhite:0.1 alpha:1.0];
+  
   [self.onSwitch setOn:YES];
   [self.onSwitch addTarget:self
                     action:@selector(didChangeOnSwitch:)
@@ -59,6 +62,7 @@
   [self.view addSubview:self.onSwitchLabel];
 
   self.determinateSwitch = [[UISwitch alloc] init];
+  self.determinateSwitch.onTintColor = [UIColor colorWithWhite:0.1 alpha:1.0];
   [self.determinateSwitch setOn:YES];
   [self.determinateSwitch addTarget:self
                              action:@selector(didChangeDeterminateSwitch:)
@@ -74,6 +78,7 @@
 
   CGRect sliderFrame = CGRectMake(0, 0, 240, 27);
   self.slider = [[UISlider alloc] initWithFrame:sliderFrame];
+  self.slider.tintColor = [UIColor colorWithWhite:0.1 alpha:1.0];
   self.slider.value = kActivityInitialProgress;
   [self.slider addTarget:self
                   action:@selector(didChangeSliderValue:)
diff --git a/components/ActivityIndicator/src/MDCActivityIndicator.h b/components/ActivityIndicator/src/MDCActivityIndicator.h
index db0b8b0..2c13f8e 100644
--- a/components/ActivityIndicator/src/MDCActivityIndicator.h
+++ b/components/ActivityIndicator/src/MDCActivityIndicator.h
@@ -41,7 +41,7 @@
  a standard UIActivityIndicator, MDCActivityIndicator supports showing determinate progress and uses
  custom Material Design animation for indeterminate progress.
 
- See https://www.google.com/design/spec/components/progress-activity.html
+ See https://material.io/guidelines/components/progress-activity.html
  */
 IB_DESIGNABLE
 @interface MDCActivityIndicator : UIView
diff --git a/components/AnimationTiming/README.md b/components/AnimationTiming/README.md
index ad8c5f8..37f85dd 100644
--- a/components/AnimationTiming/README.md
+++ b/components/AnimationTiming/README.md
@@ -3,10 +3,15 @@
 layout: detail
 section: components
 excerpt: "Material Design animation timing curves."
+iconId: animation
+path: /catalog/animation-timing/
 -->
 
 # Animation Timing
 
+<div class="article__asset article__asset--screenshot">
+  <img src="docs/assets/animation_timing.png" alt="Activity Indicator" width="375">
+</div>
 Animation timing easing curves create smooth and consistent motion. Easing curves allow elements to
 move between positions or states. These easing curves affect an object's speed, opacity, and scale.
 These animation curves allow acceleration and deceleration changes to be smooth across the duration
diff --git a/components/AnimationTiming/docs/assets/animation_timing.png b/components/AnimationTiming/docs/assets/animation_timing.png
new file mode 100644
index 0000000..e763056
--- /dev/null
+++ b/components/AnimationTiming/docs/assets/animation_timing.png
Binary files differ
diff --git a/components/AnimationTiming/examples/supplemental/AnimationTimingExampleSupplemental.m b/components/AnimationTiming/examples/supplemental/AnimationTimingExampleSupplemental.m
index 0d01d0e..d86cf08 100644
--- a/components/AnimationTiming/examples/supplemental/AnimationTimingExampleSupplemental.m
+++ b/components/AnimationTiming/examples/supplemental/AnimationTimingExampleSupplemental.m
@@ -19,6 +19,7 @@
 #import "AnimationTimingExampleSupplemental.h"
 #import "MaterialTypography.h"
 
+const CGFloat kTopMargin = 16.f;
 const CGFloat kLeftGutter = 16.f;
 const CGFloat kTextOffset = 24.f;
 
@@ -45,7 +46,7 @@
 @implementation AnimationTimingExample (Supplemental)
 
 - (void)setupExampleViews {
-  self.view.backgroundColor = [UIColor whiteColor];
+  self.view.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
   self.title = @"Animation Timing";
 
   self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
@@ -59,11 +60,11 @@
   CGFloat lineSpace = (self.view.frame.size.height - 50.f) / 4.f;
   UILabel *linearLabel = [AnimationTimingExample curveLabelWithTitle:@"Linear"];
   linearLabel.frame =
-      CGRectMake(kLeftGutter, 0, linearLabel.frame.size.width, linearLabel.frame.size.height);
+      CGRectMake(kLeftGutter, kTopMargin, linearLabel.frame.size.width, linearLabel.frame.size.height);
   [self.scrollView addSubview:linearLabel];
 
   CGRect linearViewFrame =
-      CGRectMake(kLeftGutter, kTextOffset, kAnimationCircleSize.width, kAnimationCircleSize.height);
+      CGRectMake(kLeftGutter, kTextOffset + kTopMargin, kAnimationCircleSize.width, kAnimationCircleSize.height);
   self.linearView = [[UIView alloc] initWithFrame:linearViewFrame];
   self.linearView.backgroundColor = [AnimationTimingExample defaultColors][0];
   self.linearView.layer.cornerRadius = kAnimationCircleSize.width / 2.f;
@@ -129,10 +130,10 @@
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
     defaultColors = @[
-      [[UIColor alloc] initWithRed:0.129f green:0.588f blue:0.953f alpha:1],
-      [[UIColor alloc] initWithRed:0.957f green:0.263f blue:0.212f alpha:1],
-      [[UIColor alloc] initWithRed:1.0f green:0.922f blue:0.231f alpha:1],
-      [[UIColor alloc] initWithRed:0.298f green:0.686f blue:0.314f alpha:1]
+      [UIColor colorWithWhite:0.1 alpha:1.0],
+      [UIColor colorWithWhite:0.2 alpha:1.0],
+      [UIColor colorWithWhite:0.3 alpha:1.0],
+      [UIColor colorWithWhite:0.4 alpha:1.0]
     ];
   });
   return defaultColors;
diff --git a/components/AppBar/README.md b/components/AppBar/README.md
index f595bc9..af72859 100644
--- a/components/AppBar/README.md
+++ b/components/AppBar/README.md
@@ -1,22 +1,17 @@
 <!--docs:
-title: "App Bar"
+title: "App Bars"
 layout: detail
 section: components
 excerpt: "The App Bar is a flexible navigation bar designed to provide a typical Material Design navigation experience."
 iconId: toolbar
+path: /catalog/app-bars/
 -->
 
-# App Bar
+# App Bars
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/app_bar.png" alt="App Bar" width="320">
+  <img src="docs/assets/app_bar.png" alt="App Bar" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/app_bar.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The App Bar is a flexible navigation bar designed to provide a typical Material Design
 navigation experience.
@@ -25,8 +20,8 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/layout/structure.html#structure-app-bar">App Bar Structure</a></li>
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/patterns/scrolling-techniques.html">Scrolling Techniques</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/layout/structure.html#structure-app-bar">App Bar Structure</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/patterns/scrolling-techniques.html">Scrolling Techniques</a></li>
 </ul>
 
 - - -
diff --git a/components/AppBar/docs/assets/app_bar.mp4 b/components/AppBar/docs/assets/app_bar.mp4
deleted file mode 100644
index 7e127bf..0000000
--- a/components/AppBar/docs/assets/app_bar.mp4
+++ /dev/null
Binary files differ
diff --git a/components/AppBar/docs/assets/app_bar.png b/components/AppBar/docs/assets/app_bar.png
index 1143b16..052b8b8 100644
--- a/components/AppBar/docs/assets/app_bar.png
+++ b/components/AppBar/docs/assets/app_bar.png
Binary files differ
diff --git a/components/AppBar/examples/AppBarDelegateForwardingExample.m b/components/AppBar/examples/AppBarDelegateForwardingExample.m
index 7ae3537..c1abf25 100644
--- a/components/AppBar/examples/AppBarDelegateForwardingExample.m
+++ b/components/AppBar/examples/AppBarDelegateForwardingExample.m
@@ -101,10 +101,7 @@
 
     self.title = @"Delegate Forwarding";
 
-    UIColor *color = [UIColor colorWithRed:(CGFloat)0x03 / (CGFloat)255
-                                     green:(CGFloat)0xA9 / (CGFloat)255
-                                      blue:(CGFloat)0xF4 / (CGFloat)255
-                                     alpha:1];
+    UIColor *color = [UIColor colorWithWhite:0.1 alpha:1];
     _appBar.headerViewController.headerView.backgroundColor = color;
   }
   return self;
diff --git a/components/AppBar/examples/AppBarDelegateForwardingExample.swift b/components/AppBar/examples/AppBarDelegateForwardingExample.swift
index 9ed9292..a1b33d5 100644
--- a/components/AppBar/examples/AppBarDelegateForwardingExample.swift
+++ b/components/AppBar/examples/AppBarDelegateForwardingExample.swift
@@ -38,11 +38,7 @@
 
     self.title = "Delegate Forwarding"
 
-    let color = UIColor(
-      red: CGFloat(0x03) / CGFloat(255),
-      green: CGFloat(0xA9) / CGFloat(255),
-      blue: CGFloat(0xF4) / CGFloat(255),
-      alpha: 1)
+    let color = UIColor(white: 0.1, alpha:1)
     appBar.headerViewController.headerView.backgroundColor = color
     appBar.navigationBar.tintColor = UIColor.white
   }
diff --git a/components/AppBar/examples/AppBarInterfaceBuilderExampleController.m b/components/AppBar/examples/AppBarInterfaceBuilderExampleController.m
index d489716..74cb072 100644
--- a/components/AppBar/examples/AppBarInterfaceBuilderExampleController.m
+++ b/components/AppBar/examples/AppBarInterfaceBuilderExampleController.m
@@ -51,7 +51,7 @@
       @{NSForegroundColorAttributeName : [UIColor whiteColor]};
 
   [self addChildViewController:self.appBar.headerViewController];
-  UIColor *headerColor = [UIColor colorWithRed:0.01 green:0.67 blue:0.96 alpha:1.0];
+  UIColor *headerColor = [UIColor colorWithWhite:0.1 alpha:1];
   self.appBar.headerViewController.headerView.backgroundColor = headerColor;
 }
 
diff --git a/components/AppBar/examples/AppBarInterfaceBuilderExampleController.swift b/components/AppBar/examples/AppBarInterfaceBuilderExampleController.swift
index 9063094..a500113 100644
--- a/components/AppBar/examples/AppBarInterfaceBuilderExampleController.swift
+++ b/components/AppBar/examples/AppBarInterfaceBuilderExampleController.swift
@@ -41,8 +41,8 @@
       [ NSForegroundColorAttributeName: UIColor.white ]
 
     addChildViewController(appBar.headerViewController)
-    let headerColor = UIColor(red: 0.01, green: 0.67, blue: 0.96, alpha: 1.0)
-    appBar.headerViewController.headerView.backgroundColor = headerColor
+    let color = UIColor(white: 0.1, alpha:1)
+    appBar.headerViewController.headerView.backgroundColor = color
   }
 
   override func viewDidLoad() {
diff --git a/components/AppBar/examples/AppBarModalPresentationExample.m b/components/AppBar/examples/AppBarModalPresentationExample.m
index eb904b4..eef22c5 100644
--- a/components/AppBar/examples/AppBarModalPresentationExample.m
+++ b/components/AppBar/examples/AppBarModalPresentationExample.m
@@ -32,10 +32,7 @@
     [self addChildViewController:_appBar.headerViewController];
 
     // Optional: Change the App Bar's background color and tint color.
-    UIColor *color = [UIColor colorWithRed:(CGFloat)0x03 / (CGFloat)255
-                                     green:(CGFloat)0xA9 / (CGFloat)255
-                                      blue:(CGFloat)0xF4 / (CGFloat)255
-                                     alpha:1];
+    UIColor *color = [UIColor colorWithWhite:0.1 alpha:1];
     _appBar.headerViewController.headerView.backgroundColor = color;
     _appBar.navigationBar.tintColor = [UIColor whiteColor];
     _appBar.navigationBar.titleTextAttributes =
@@ -227,10 +224,7 @@
 
     self.title = @"Modal Presentation";
 
-    UIColor *color = [UIColor colorWithRed:(CGFloat)0x03 / (CGFloat)255
-                                     green:(CGFloat)0xA9 / (CGFloat)255
-                                      blue:(CGFloat)0xF4 / (CGFloat)255
-                                     alpha:1];
+    UIColor *color = [UIColor colorWithWhite:0.1 alpha:1];
     _appBar.headerViewController.headerView.backgroundColor = color;
   }
   return self;
diff --git a/components/AppBar/examples/AppBarModalPresentationExample.swift b/components/AppBar/examples/AppBarModalPresentationExample.swift
index d21c2df..5dec7c7 100644
--- a/components/AppBar/examples/AppBarModalPresentationExample.swift
+++ b/components/AppBar/examples/AppBarModalPresentationExample.swift
@@ -28,11 +28,7 @@
 
     self.addChildViewController(appBar.headerViewController)
 
-    let color = UIColor(
-      red: CGFloat(0x03) / CGFloat(255),
-      green: CGFloat(0xA9) / CGFloat(255),
-      blue: CGFloat(0xF4) / CGFloat(255),
-      alpha: 1)
+    let color = UIColor(white: 0.1, alpha:1)
     appBar.headerViewController.headerView.backgroundColor = color
     appBar.navigationBar.tintColor = UIColor.white
     appBar.navigationBar.titleTextAttributes =
@@ -108,11 +104,7 @@
 
     self.addChildViewController(appBar.headerViewController)
 
-    let color = UIColor(
-      red: CGFloat(0x03) / CGFloat(255),
-      green: CGFloat(0xA9) / CGFloat(255),
-      blue: CGFloat(0xF4) / CGFloat(255),
-      alpha: 1)
+    let color = UIColor(white: 0.1, alpha:1)
     appBar.headerViewController.headerView.backgroundColor = color
     appBar.navigationBar.tintColor = UIColor.white
     appBar.navigationBar.titleTextAttributes =
diff --git a/components/AppBar/examples/AppBarTypicalUseExample.m b/components/AppBar/examples/AppBarTypicalUseExample.m
index 6738d76..ce34d5a 100644
--- a/components/AppBar/examples/AppBarTypicalUseExample.m
+++ b/components/AppBar/examples/AppBarTypicalUseExample.m
@@ -37,10 +37,7 @@
     [self addChildViewController:_appBar.headerViewController];
 
     // Optional: Change the App Bar's background color and tint color.
-    UIColor *color = [UIColor colorWithRed:(CGFloat)0x03 / (CGFloat)255
-                                     green:(CGFloat)0xA9 / (CGFloat)255
-                                      blue:(CGFloat)0xF4 / (CGFloat)255
-                                     alpha:1];
+    UIColor *color = [UIColor colorWithWhite:0.1 alpha:1];
     _appBar.headerViewController.headerView.backgroundColor = color;
     _appBar.navigationBar.tintColor = [UIColor whiteColor];
     _appBar.navigationBar.titleTextAttributes =
diff --git a/components/AppBar/examples/AppBarTypicalUseExample.swift b/components/AppBar/examples/AppBarTypicalUseExample.swift
index 820a89b..7f4b279 100644
--- a/components/AppBar/examples/AppBarTypicalUseExample.swift
+++ b/components/AppBar/examples/AppBarTypicalUseExample.swift
@@ -30,11 +30,7 @@
     // Step 2: Add the headerViewController as a child.
     self.addChildViewController(appBar.headerViewController)
 
-    let color = UIColor(
-      red: CGFloat(0x03) / CGFloat(255),
-      green: CGFloat(0xA9) / CGFloat(255),
-      blue: CGFloat(0xF4) / CGFloat(255),
-      alpha: 1)
+    let color = UIColor(white: 0.1, alpha:1)
     appBar.headerViewController.headerView.backgroundColor = color
     appBar.navigationBar.tintColor = UIColor.white
     appBar.navigationBar.titleTextAttributes =
diff --git a/components/AppBar/examples/resources/AppBarInterfaceBuilderExampleController.storyboard b/components/AppBar/examples/resources/AppBarInterfaceBuilderExampleController.storyboard
index cc26d55..2949447 100644
--- a/components/AppBar/examples/resources/AppBarInterfaceBuilderExampleController.storyboard
+++ b/components/AppBar/examples/resources/AppBarInterfaceBuilderExampleController.storyboard
@@ -1,8 +1,12 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+    <device id="retina4_0" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
         <!--Interface Builder-->
@@ -41,12 +45,12 @@
 
 Duis lobortis ac turpis sit amet fringilla. Maecenas mattis nibh eget nulla tempus porta. Praesent ac rutrum elit, id porttitor mi. Sed ac tincidunt lectus, vel ullamcorper risus. Fusce nec vulputate dui. Sed vitae posuere tellus. Cras quis nisl ultricies, pulvinar justo at, sodales mi. </string>
                                                 <fontDescription key="fontDescription" type="system" pointSize="17"/>
-                                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                 <nil key="highlightedColor"/>
                                                 <size key="shadowOffset" width="0.0" height="0.0"/>
                                             </label>
                                         </subviews>
-                                        <color key="backgroundColor" red="0.90196079019999997" green="0.90196079019999997" blue="0.90196079019999997" alpha="1" colorSpace="calibratedRGB"/>
+                                        <color key="backgroundColor" red="0.90196079019999997" green="0.90196079019999997" blue="0.90196079019999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                         <constraints>
                                             <constraint firstAttribute="bottom" secondItem="UXR-vF-blI" secondAttribute="bottom" constant="20" symbolic="YES" id="HnM-Ys-EZb"/>
                                             <constraint firstAttribute="trailing" secondItem="UXR-vF-blI" secondAttribute="trailing" constant="20" symbolic="YES" id="Z4o-VU-3yL"/>
@@ -63,7 +67,7 @@
                                 </constraints>
                             </scrollView>
                         </subviews>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                         <constraints>
                             <constraint firstAttribute="trailing" secondItem="cO1-IT-qp1" secondAttribute="trailing" id="0vh-lP-IQL"/>
                             <constraint firstItem="GYF-Vd-Yfr" firstAttribute="width" secondItem="8bC-Xf-vdC" secondAttribute="width" id="Ctx-p5-qml"/>
@@ -84,5 +88,5 @@
             <point key="canvasLocation" x="383" y="532"/>
         </scene>
     </scenes>
-    <color key="tintColor" red="0.011764705882352941" green="0.66274509803921566" blue="0.95686274509803915" alpha="1" colorSpace="calibratedRGB"/>
+    <color key="tintColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
 </document>
diff --git a/components/AppBar/src/MDCAppBar.h b/components/AppBar/src/MDCAppBar.h
index c4260c8..a8a9973 100644
--- a/components/AppBar/src/MDCAppBar.h
+++ b/components/AppBar/src/MDCAppBar.h
@@ -26,7 +26,7 @@
  flexible content such as a photo.
 
  Learn more at the [Material
- spec](https://www.google.com/design/spec/patterns/scrolling-techniques.html)
+ spec](https://material.io/guidelines/patterns/scrolling-techniques.html)
 
  ### Dependencies
 
diff --git a/components/AppBar/src/MDCAppBar.m b/components/AppBar/src/MDCAppBar.m
index 785a34a..b27c538 100644
--- a/components/AppBar/src/MDCAppBar.m
+++ b/components/AppBar/src/MDCAppBar.m
@@ -24,6 +24,8 @@
 #import "MaterialShadowElevations.h"
 #import "MaterialShadowLayer.h"
 #import "MaterialTypography.h"
+#import "private/MaterialAppBarStrings.h"
+#import "private/MaterialAppBarStrings_table.h"
 
 static NSString *const kBarStackKey = @"barStack";
 static NSString *const kStatusBarHeightKey = @"statusBarHeight";
@@ -32,6 +34,9 @@
 static NSString *const MDCAppBarHeaderStackViewKey = @"MDCAppBarHeaderStackViewKey";
 static const CGFloat kStatusBarHeight = 20;
 
+// The Bundle for string resources.
+static NSString *const kMaterialAppBarBundle = @"MaterialAppBar.bundle";
+
 @class MDCAppBarViewController;
 
 @interface MDCAppBar ()
@@ -220,21 +225,37 @@
                                                         action:@selector(didTapBackButton:)];
   }
   backBarButtonItem.accessibilityIdentifier = @"back_bar_button";
+  NSString *key =
+      kMaterialAppBarStringTable[kStr_MaterialAppBarBackButtonAccessibilityLabel];
+  backBarButtonItem.accessibilityLabel =
+      NSLocalizedStringFromTableInBundle(key,
+                                         kMaterialAppBarStringsTableName,
+                                         [[self class] bundle],
+                                         @"Back");
   return backBarButtonItem;
 }
 
-+ (NSBundle *)baseBundle {
+#pragma mark - Resource bundle
+
++ (NSBundle *)bundle {
   static NSBundle *bundle = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
-    // We may not be included by the main bundle, but rather by an embedded framework, so figure out
-    // to which bundle our code is compiled, and use that as the starting point for bundle loading.
-    bundle = [NSBundle bundleForClass:[self class]];
+    bundle = [NSBundle bundleWithPath:[self bundlePathWithName:kMaterialAppBarBundle]];
   });
 
   return bundle;
 }
 
++ (NSString *)bundlePathWithName:(NSString *)bundleName {
+  // In iOS 8+, we could be included by way of a dynamic framework, and our resource bundles may
+  // not be in the main .app bundle, but rather in a nested framework, so figure out where we live
+  // and use that as the search location.
+  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+  NSString *resourcePath = [(nil == bundle ? [NSBundle mainBundle] : bundle)resourcePath];
+  return [resourcePath stringByAppendingPathComponent:bundleName];
+}
+
 - (void)viewDidLoad {
   [super viewDidLoad];
 
diff --git a/components/AppBar/src/MaterialAppBar.bundle/Resources/en.lproj/MaterialAppBar.strings b/components/AppBar/src/MaterialAppBar.bundle/Resources/en.lproj/MaterialAppBar.strings
new file mode 100644
index 0000000..86d2fe3
--- /dev/null
+++ b/components/AppBar/src/MaterialAppBar.bundle/Resources/en.lproj/MaterialAppBar.strings
@@ -0,0 +1,2 @@
+/* Accessibility label for App Bar Back Button. */
+"MaterialAppBarBackButtonAccessibilityLabel" = "Back";
diff --git a/components/AppBar/src/private/MaterialAppBarStrings.h b/components/AppBar/src/private/MaterialAppBarStrings.h
new file mode 100644
index 0000000..aa38888
--- /dev/null
+++ b/components/AppBar/src/private/MaterialAppBarStrings.h
@@ -0,0 +1,8 @@
+// GENERATED CODE: DO NOT EDIT BY HAND
+// GENERATED FROM:
+// components/AppBar/src/MaterialAppBar.bundle/Resources/en.lproj/MaterialAppBar.strings
+// GENERATED BY: generate_string_tables.py
+
+typedef enum {
+  kStr_MaterialAppBarBackButtonAccessibilityLabel = 0,
+} MaterialAppBarStringId;
diff --git a/components/AppBar/src/private/MaterialAppBarStrings_table.h b/components/AppBar/src/private/MaterialAppBarStrings_table.h
new file mode 100644
index 0000000..b65c03d
--- /dev/null
+++ b/components/AppBar/src/private/MaterialAppBarStrings_table.h
@@ -0,0 +1,17 @@
+// GENERATED CODE: DO NOT EDIT BY HAND
+// GENERATED FROM:
+// components/AppBar/src/MaterialAppBar.bundle/Resources/en.lproj/MaterialAppBar.strings
+// GENERATED BY: generate_string_tables.py
+
+#import <Foundation/Foundation.h>
+
+// A table of string keys to look-up localized strings in the bundle.
+// This table is to be indexed using the generated enum.
+
+static NSString *const kMaterialAppBarStringTable[] = {
+  @"MaterialAppBarBackButtonAccessibilityLabel",   // Back
+};
+#define kNumMaterialAppBarStrings 1
+#define kMaterialAppBarStringsOffset 0
+#define kMaterialAppBarStringsEnd 10000
+static NSString *const kMaterialAppBarStringsTableName = @"MaterialAppBar";
diff --git a/components/ButtonBar/README.md b/components/ButtonBar/README.md
index cb797e5..d62cfe5 100644
--- a/components/ButtonBar/README.md
+++ b/components/ButtonBar/README.md
@@ -1,22 +1,17 @@
 <!--docs:
-title: "Button Bar"
+title: "Button Bars"
 layout: detail
 section: components
 excerpt: "The Button Bar component is a view that facilitates the creation and layout of a horizontally-aligned list of buttons."
 iconId: button
+path: /catalog/button-bars/
 -->
 
-# Button Bar
+# Button Bars
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/button_bar.png" alt="Button Bar" width="320">
+  <img src="docs/assets/button_bar.png" alt="Button Bar" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/button_bar.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Button Bar is a view that represents a list of UIBarButtonItems as horizontally aligned buttons.
 <!--{: .article__intro }-->
diff --git a/components/ButtonBar/docs/assets/button_bar.mp4 b/components/ButtonBar/docs/assets/button_bar.mp4
deleted file mode 100644
index d452958..0000000
--- a/components/ButtonBar/docs/assets/button_bar.mp4
+++ /dev/null
Binary files differ
diff --git a/components/ButtonBar/docs/assets/button_bar.png b/components/ButtonBar/docs/assets/button_bar.png
index ee3136d..d80bcd8 100644
--- a/components/ButtonBar/docs/assets/button_bar.png
+++ b/components/ButtonBar/docs/assets/button_bar.png
Binary files differ
diff --git a/components/ButtonBar/examples/ButtonBarTypicalUseExample.m b/components/ButtonBar/examples/ButtonBarTypicalUseExample.m
index b6bd037..9810b3d 100644
--- a/components/ButtonBar/examples/ButtonBarTypicalUseExample.m
+++ b/components/ButtonBar/examples/ButtonBarTypicalUseExample.m
@@ -64,7 +64,7 @@
   [self.view addSubview:buttonBar];
 
   // Ensure that the controller's view isn't transparent.
-  self.view.backgroundColor = [UIColor whiteColor];
+  self.view.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
 }
 
 #pragma mark - User actions
@@ -76,7 +76,7 @@
 #pragma mark - Visual configuration
 
 - (UIColor *)buttonBarBackgroundColor {
-  return [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.2];
+  return [UIColor colorWithWhite:0.8 alpha:1.0];
 }
 
 - (NSDictionary *)itemTitleTextAttributes {
diff --git a/components/ButtonBar/examples/ButtonBarTypicalUseExample.swift b/components/ButtonBar/examples/ButtonBarTypicalUseExample.swift
index 4fd5fc3..6e93c8f 100644
--- a/components/ButtonBar/examples/ButtonBarTypicalUseExample.swift
+++ b/components/ButtonBar/examples/ButtonBarTypicalUseExample.swift
@@ -62,7 +62,7 @@
     self.view.addSubview(buttonBar)
 
     // Ensure that the controller's view isn't transparent.
-    self.view.backgroundColor = UIColor.white
+    view.backgroundColor = UIColor(white: 0.9, alpha:1.0)
   }
 
   func didTapActionButton(_ sender: Any) {
@@ -92,11 +92,11 @@
 
 extension ButtonBarTypicalUseSwiftExample {
   func buttonBarBackgroundColor() -> UIColor {
-    return UIColor(red: 0.012, green: 0.663, blue: 0.957, alpha: 0.2)
+    return UIColor(white: 0.1, alpha: 1.0)
   }
 
   func itemTitleTextAttributes () -> [String: Any] {
-    let textColor = UIColor(white: 0, alpha: 0.8)
+    let textColor = UIColor(white: 1, alpha: 0.8)
     return [NSForegroundColorAttributeName: textColor]
   }
 }
diff --git a/components/Buttons/README.md b/components/Buttons/README.md
index bcb249d..1c05d9a 100644
--- a/components/Buttons/README.md
+++ b/components/Buttons/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "Buttons is a collection of Material Design buttons, including a flat button, a raised button and a floating action button."
 iconId: button
+path: /catalog/buttons/
 -->
 
 # Buttons
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/buttons.png" alt="Buttons" width="320">
+  <img src="docs/assets/buttons.png" alt="Buttons" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/buttons.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 Buttons is a collection of Material Design buttons, including a flat button, a raised button and a
 floating action button.
@@ -25,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="http://www.google.com/design/spec/components/buttons.html">Buttons</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/buttons.html">Buttons</a></li>
 </ul>
 
 - - -
@@ -160,7 +155,7 @@
 #### Swift
 ``` swift
 let raisedButton = MDCRaisedButton()
-// See https://www.google.com/design/spec/what-is-material/elevation-shadows.html
+// See https://material.io/guidelines/what-is-material/elevation-shadows.html
 
 raisedButton.setElevation(4, for: .normal)
 raisedButton.setTitle("Tap Me Too", for: .normal)
@@ -173,7 +168,7 @@
 
 ``` objc
 MDCRaisedButton *raisedButton = [MDCRaisedButton new];
-// See https://www.google.com/design/spec/what-is-material/elevation-shadows.html
+// See https://material.io/guidelines/what-is-material/elevation-shadows.html
 
 [raisedButton setElevation:4.0f forState:UIControlStateNormal];
 [raisedButton setTitle:@"Tap Me Too" forState:UIControlStateNormal];
diff --git a/components/Buttons/docs/assets/buttons.mp4 b/components/Buttons/docs/assets/buttons.mp4
deleted file mode 100644
index 993b637..0000000
--- a/components/Buttons/docs/assets/buttons.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Buttons/docs/assets/buttons.png b/components/Buttons/docs/assets/buttons.png
index a9101ec..1bf8850 100644
--- a/components/Buttons/docs/assets/buttons.png
+++ b/components/Buttons/docs/assets/buttons.png
Binary files differ
diff --git a/components/Buttons/examples/ButtonsDynamicTypeViewController.swift b/components/Buttons/examples/ButtonsDynamicTypeViewController.swift
index a75f1c2..b24ece0 100644
--- a/components/Buttons/examples/ButtonsDynamicTypeViewController.swift
+++ b/components/Buttons/examples/ButtonsDynamicTypeViewController.swift
@@ -26,18 +26,22 @@
   override func viewDidLoad() {
     super.viewDidLoad()
 
-    view.backgroundColor = .white
+    view.backgroundColor = UIColor(white: 0.9, alpha:1.0)
+    let titleColor = UIColor.white
+    let backgroundColor = UIColor(white: 0.1, alpha: 1.0)
 
-    let flatButtonStatic = MDCFlatButton()
-    flatButtonStatic.backgroundColor = .blue
+    let flatButtonStatic = MDCRaisedButton()
+    flatButtonStatic.setTitleColor(titleColor, for: .normal)
+    flatButtonStatic.setBackgroundColor(backgroundColor, for: .normal)
     flatButtonStatic.setTitle("Static", for: UIControlState())
     flatButtonStatic.sizeToFit()
     flatButtonStatic.translatesAutoresizingMaskIntoConstraints = false
     flatButtonStatic.addTarget(self, action: #selector(tap), for: .touchUpInside)
     view.addSubview(flatButtonStatic)
 
-    let flatButtonDynamic = MDCFlatButton()
-    flatButtonDynamic.backgroundColor = .blue
+    let flatButtonDynamic = MDCRaisedButton()
+    flatButtonDynamic.setTitleColor(titleColor, for: .normal)
+    flatButtonDynamic.setBackgroundColor(backgroundColor, for: .normal)
     flatButtonDynamic.setTitle("Dynamic", for: UIControlState())
     flatButtonDynamic.sizeToFit()
     flatButtonDynamic.translatesAutoresizingMaskIntoConstraints = false
diff --git a/components/Buttons/examples/ButtonsSimpleExampleSwiftViewController.swift b/components/Buttons/examples/ButtonsSimpleExampleSwiftViewController.swift
index 7362e97..e61fee8 100644
--- a/components/Buttons/examples/ButtonsSimpleExampleSwiftViewController.swift
+++ b/components/Buttons/examples/ButtonsSimpleExampleSwiftViewController.swift
@@ -28,10 +28,12 @@
   override func viewDidLoad() {
     super.viewDidLoad()
 
-    view.backgroundColor = .white
+    view.backgroundColor = UIColor(white: 0.9, alpha: 1.0);
+    //let titleColor = UIColor.white
+    let backgroundColor = UIColor(white: 0.1, alpha: 1.0)
 
     let raisedButton = MDCRaisedButton()
-    raisedButton.customTitleColor = .white
+    raisedButton.setBackgroundColor(backgroundColor, for: .normal)
     raisedButton.setElevation(4, for: UIControlState())
     raisedButton.setTitle("Tap Me Too", for: UIControlState())
     raisedButton.sizeToFit()
@@ -48,6 +50,7 @@
     view.addSubview(flatButton)
 
     let floatingButton = MDCFloatingButton()
+    floatingButton.backgroundColor = backgroundColor;
     floatingButton.sizeToFit()
     floatingButton.translatesAutoresizingMaskIntoConstraints = false
     floatingButton.addTarget(self, action: #selector(tap), for: .touchUpInside)
diff --git a/components/Buttons/examples/ButtonsStoryboardAndProgrammatic.swift b/components/Buttons/examples/ButtonsStoryboardAndProgrammatic.swift
index 4c4026c..277cb2f 100644
--- a/components/Buttons/examples/ButtonsStoryboardAndProgrammatic.swift
+++ b/components/Buttons/examples/ButtonsStoryboardAndProgrammatic.swift
@@ -113,20 +113,26 @@
                          constant: 0)
     ])
 
-    raisedButton.setTitle("Programmatic", for: UIControlState())
+    let titleColor = UIColor.white
+    let backgroundColor = UIColor(white: 0.1, alpha: 1.0)
+
+    raisedButton.setTitle("Programmatic", for: .normal)
+    raisedButton.setTitleColor(titleColor, for: .normal)
+    raisedButton.backgroundColor = backgroundColor
     raisedButton.sizeToFit()
     raisedButton.translatesAutoresizingMaskIntoConstraints = false
     raisedButton.addTarget(self, action: #selector(tap), for: .touchUpInside)
     innerContainerView.addSubview(raisedButton)
 
     flatButton.customTitleColor = UIColor.gray
-    flatButton.setTitle("Programmatic", for: UIControlState())
+    flatButton.setTitle("Programmatic", for: .normal)
     flatButton.sizeToFit()
     flatButton.translatesAutoresizingMaskIntoConstraints = false
     flatButton.addTarget(self, action: #selector(tap), for: .touchUpInside)
     innerContainerView.addSubview(flatButton)
 
     floatingButton.sizeToFit()
+    floatingButton.backgroundColor = backgroundColor
     floatingButton.translatesAutoresizingMaskIntoConstraints = false
     floatingButton.addTarget(self, action: #selector(tap), for: .touchUpInside)
 
diff --git a/components/Buttons/examples/ButtonsTypicalUse.m b/components/Buttons/examples/ButtonsTypicalUse.m
index 45c991f..3d7c911 100644
--- a/components/Buttons/examples/ButtonsTypicalUse.m
+++ b/components/Buttons/examples/ButtonsTypicalUse.m
@@ -27,11 +27,15 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
-  self.view.backgroundColor = [UIColor whiteColor];
+  self.view.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];
+  UIColor *buttonBackground = [UIColor colorWithWhite:0.1 alpha:1.0];
+  UIColor *titleColor = [UIColor whiteColor];
 
   // Raised button
 
   MDCRaisedButton *raisedButton = [[MDCRaisedButton alloc] init];
+  [raisedButton setTitleColor:titleColor forState:UIControlStateNormal];
+  [raisedButton setBackgroundColor:buttonBackground forState:UIControlStateNormal];
   [raisedButton setTitle:@"Button" forState:UIControlStateNormal];
   [raisedButton sizeToFit];
   [raisedButton addTarget:self
@@ -43,6 +47,8 @@
   // Disabled raised button
 
   MDCRaisedButton *disabledRaisedButton = [[MDCRaisedButton alloc] init];
+  [disabledRaisedButton setTitleColor:titleColor forState:UIControlStateNormal];
+  [disabledRaisedButton setBackgroundColor:buttonBackground forState:UIControlStateNormal];
   [disabledRaisedButton setTitle:@"Button" forState:UIControlStateNormal];
   [disabledRaisedButton sizeToFit];
   [disabledRaisedButton addTarget:self
@@ -80,6 +86,8 @@
   // Floating action button
 
   MDCFloatingButton *floatingButton = [[MDCFloatingButton alloc] init];
+  [floatingButton setTitleColor:titleColor forState:UIControlStateNormal];
+  [floatingButton setBackgroundColor:buttonBackground forState:UIControlStateNormal];
   [floatingButton sizeToFit];
   [floatingButton addTarget:self
                      action:@selector(didTap:)
diff --git a/components/Buttons/examples/resources/ButtonsStoryboardAndProgrammatic.storyboard b/components/Buttons/examples/resources/ButtonsStoryboardAndProgrammatic.storyboard
index a97f973..08b797c 100644
--- a/components/Buttons/examples/resources/ButtonsStoryboardAndProgrammatic.storyboard
+++ b/components/Buttons/examples/resources/ButtonsStoryboardAndProgrammatic.storyboard
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="rmZ-Mt-scB">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="rmZ-Mt-scB">
     <device id="retina4_7" orientation="portrait">
         <adaptation id="fullscreen"/>
     </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
         <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
         <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -31,6 +31,8 @@
                                         <subviews>
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ixI-3k-a3r" customClass="MDCRaisedButton">
                                                 <rect key="frame" x="0.0" y="0.0" width="91" height="34"/>
+                                                <color key="backgroundColor" white="0.10072546345846993" alpha="1" colorSpace="calibratedWhite"/>
+                                                <color key="tintColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
                                                 <state key="normal" title="Storyboard">
                                                     <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                 </state>
@@ -40,6 +42,8 @@
                                             </button>
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1Dc-Q4-b6Z" customClass="MDCFlatButton">
                                                 <rect key="frame" x="7" y="56" width="77" height="30"/>
+                                                <color key="backgroundColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
+                                                <color key="tintColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
                                                 <state key="normal" title="Storyboard">
                                                     <color key="titleColor" red="0.49803921579999999" green="0.49803921579999999" blue="0.49803921579999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                 </state>
@@ -49,6 +53,8 @@
                                             </button>
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BDu-tK-SwC" customClass="MDCFloatingButton">
                                                 <rect key="frame" x="30.5" y="108" width="30" height="30"/>
+                                                <color key="backgroundColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
+                                                <color key="tintColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
                                                 <state key="normal">
                                                     <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                 </state>
@@ -77,7 +83,7 @@
                                 </constraints>
                             </view>
                         </subviews>
-                        <color key="backgroundColor" red="0.81176470590000005" green="0.90980392160000001" blue="0.97254901959999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <color key="backgroundColor" white="0.89550476414816715" alpha="1" colorSpace="calibratedWhite"/>
                         <constraints>
                             <constraint firstItem="ISg-pg-Aeq" firstAttribute="width" secondItem="dz8-vM-Ak5" secondAttribute="width" multiplier="0.5" id="19q-Zc-Tgb"/>
                             <constraint firstItem="ISg-pg-Aeq" firstAttribute="trailing" secondItem="dz8-vM-Ak5" secondAttribute="trailingMargin" constant="16" id="PMn-Bh-3ZY"/>
@@ -96,4 +102,5 @@
             <point key="canvasLocation" x="442.39999999999998" y="467.3163418290855"/>
         </scene>
     </scenes>
+    <color key="tintColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
 </document>
diff --git a/components/Buttons/src/MDCButton.h b/components/Buttons/src/MDCButton.h
index c3532b9..6a38c63 100644
--- a/components/Buttons/src/MDCButton.h
+++ b/components/Buttons/src/MDCButton.h
@@ -31,7 +31,7 @@
  All buttons set the exclusiveTouch property to YES by default, which prevents users from
  simultaneously interacting with a button and other UI elements.
 
- @see http://www.google.com/design/spec/components/buttons.html
+ @see https://material.io/guidelines/components/buttons.html
  */
 @interface MDCButton : UIButton
 
diff --git a/components/Buttons/src/MDCButton.m b/components/Buttons/src/MDCButton.m
index 4f73f83..1e470fb 100644
--- a/components/Buttons/src/MDCButton.m
+++ b/components/Buttons/src/MDCButton.m
@@ -51,10 +51,10 @@
 
 static const NSTimeInterval MDCButtonAnimationDuration = 0.2;
 
-// http://www.google.com/design/spec/components/buttons.html#buttons-main-buttons
+// https://material.io/guidelines/components/buttons.html#buttons-main-buttons
 static const CGFloat MDCButtonDisabledAlpha = 0.1f;
 
-// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
 static const uint32_t MDCButtonDefaultBackgroundColor = 0x2196F3;
 
 // Creates a UIColor from a 24-bit RGB color encoded as an integer.
diff --git a/components/Buttons/src/MDCFlatButton.h b/components/Buttons/src/MDCFlatButton.h
index 886efe4..133fdb4 100644
--- a/components/Buttons/src/MDCFlatButton.h
+++ b/components/Buttons/src/MDCFlatButton.h
@@ -26,7 +26,7 @@
  Flat buttons should be used in most situations requiring a button. For layouts with many UI
  elements in which a flat button might get visually lost, consider using a MDCRaisedButton instead.
 
- @see http://www.google.com/design/spec/components/buttons.html#buttons-flat-buttons
+ @see https://material.io/guidelines/components/buttons.html#buttons-flat-buttons
  */
 @interface MDCFlatButton : MDCButton
 
diff --git a/components/Buttons/src/MDCFloatingButton.h b/components/Buttons/src/MDCFloatingButton.h
index 6552b35..7bc9bb3 100644
--- a/components/Buttons/src/MDCFloatingButton.h
+++ b/components/Buttons/src/MDCFloatingButton.h
@@ -37,7 +37,7 @@
  their own background color, and also raise briefly when touched. Floating action buttons should
  only be used rarely, for the main action of a screen.
 
- @see http://www.google.com/design/spec/components/buttons.html#buttons-main-buttons
+ @see https://material.io/guidelines/components/buttons.html#buttons-main-buttons
  */
 @interface MDCFloatingButton : MDCButton
 
diff --git a/components/Buttons/src/MDCRaisedButton.h b/components/Buttons/src/MDCRaisedButton.h
index f71e770..e682fb8 100644
--- a/components/Buttons/src/MDCRaisedButton.h
+++ b/components/Buttons/src/MDCRaisedButton.h
@@ -23,7 +23,7 @@
  briefly when touched. Raised buttons should be used when flat buttons would get lost among other
  UI elements on the screen.
 
- @see http://www.google.com/design/spec/components/buttons.html#buttons-raised-buttons
+ @see https://material.io/guidelines/components/buttons.html#buttons-raised-buttons
  */
 @interface MDCRaisedButton : MDCButton
 @end
diff --git a/components/CollectionCells/README.md b/components/CollectionCells/README.md
index 364b366..2cdf41d 100644
--- a/components/CollectionCells/README.md
+++ b/components/CollectionCells/README.md
@@ -4,12 +4,14 @@
 section: components
 excerpt: "Collection view cell classes that adhere to Material Design layout and styling."
 iconId: list
+path: /catalog/collection-cells/
 -->
 
 # Collection Cells
 
-<img src="docs/assets/collection_cells.png" alt="Collection Cells" width="320">
-<!--{: .article__asset.article__asset--screenshot }-->
+<div class="article__asset article__asset--screenshot">
+  <img src="docs/assets/collection_cells.png" alt="Collection Cells" width="375">
+</div>
 
 Collection view cell classes that adhere to Material Design layout and styling.
 <!--{: .article__intro }-->
@@ -17,7 +19,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/components/lists.html#lists-specs">Collection List Specs</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/lists.html#lists-specs">Collection List Specs</a></li>
 </ul>
 
 - - -
diff --git a/components/CollectionCells/docs/assets/collection_cells.png b/components/CollectionCells/docs/assets/collection_cells.png
index 2c0b1d8..b147172 100644
--- a/components/CollectionCells/docs/assets/collection_cells.png
+++ b/components/CollectionCells/docs/assets/collection_cells.png
Binary files differ
diff --git a/components/CollectionCells/src/MDCCollectionViewTextCell.h b/components/CollectionCells/src/MDCCollectionViewTextCell.h
index 039747a..da2d933 100644
--- a/components/CollectionCells/src/MDCCollectionViewTextCell.h
+++ b/components/CollectionCells/src/MDCCollectionViewTextCell.h
@@ -33,7 +33,7 @@
  supports Material Design layout and styling. It provides two labels for text as well as an
  image view. The default layout specifications can be found at the following link.
 
- @see http://www.google.com/design/spec/components/lists.html#lists-specs
+ @see https://material.io/guidelines/components/lists.html#lists-specs
  */
 @interface MDCCollectionViewTextCell : MDCCollectionViewCell
 
diff --git a/components/CollectionLayoutAttributes/README.md b/components/CollectionLayoutAttributes/README.md
index a160c3c..2b67f6e 100644
--- a/components/CollectionLayoutAttributes/README.md
+++ b/components/CollectionLayoutAttributes/README.md
@@ -4,6 +4,7 @@
 section: components
 excerpt: "Allows passing layout attributes to the cells and supplementary views."
 iconId: list
+path: /catalog/collection-layout-attributes/
 -->
 
 # Collection Layout Attributes
diff --git a/components/Collections/README.md b/components/Collections/README.md
index 54a588a..076e0d1 100644
--- a/components/Collections/README.md
+++ b/components/Collections/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "Collection view classes that adhere to Material Design layout and styling."
 iconId: list
+path: /catalog/collections/
 -->
 
 # Collections
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/collections.png" alt="Collections" width="320">
+  <img src="docs/assets/collections.png" alt="Collections" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/collections.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 Collection view classes that adhere to Material Design layout and styling.
 <!--{: .article__intro }-->
@@ -24,7 +19,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/components/lists.html#lists-specs">Collection List Specs</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/lists.html#lists-specs">Collection List Specs</a></li>
 </ul>
 
 - - -
diff --git a/components/Collections/docs/assets/collections.mp4 b/components/Collections/docs/assets/collections.mp4
deleted file mode 100644
index 451bbf2..0000000
--- a/components/Collections/docs/assets/collections.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Collections/docs/assets/collections.png b/components/Collections/docs/assets/collections.png
index d7b0d2b..5ebb45c 100644
--- a/components/Collections/docs/assets/collections.png
+++ b/components/Collections/docs/assets/collections.png
Binary files differ
diff --git a/components/Collections/editing/README.md b/components/Collections/editing/README.md
index e44584a..bfde786 100644
--- a/components/Collections/editing/README.md
+++ b/components/Collections/editing/README.md
@@ -1,9 +1,12 @@
----
+<!--docs:
 title: "Editing the collection view"
+navTitle: Editing
 layout: detail
 section: components
 iconId: list
----
+path: /catalog/collections/editing/
+-->
+
 # Editing the collection view
 
 The collection view controller provides an `editor` property that conforms to the
diff --git a/components/Collections/src/MDCCollectionViewController.h b/components/Collections/src/MDCCollectionViewController.h
index d61c50b..da50636 100644
--- a/components/Collections/src/MDCCollectionViewController.h
+++ b/components/Collections/src/MDCCollectionViewController.h
@@ -74,4 +74,10 @@
 
 - (void)collectionViewWillEndEditing:(nonnull UICollectionView *)collectionView NS_REQUIRES_SUPER;
 
+/**
+ * Exposes cell width calculation for subclasses to use when calculating dynamic cell height. Note
+ * that this method is only exposed temporarily until self-sizing cells are supported.
+ */
+- (CGFloat)cellWidthAtSectionIndex:(NSInteger)section;
+
 @end
diff --git a/components/Collections/src/MDCCollectionViewFlowLayout.h b/components/Collections/src/MDCCollectionViewFlowLayout.h
index fdce1ee..a500e1c 100644
--- a/components/Collections/src/MDCCollectionViewFlowLayout.h
+++ b/components/Collections/src/MDCCollectionViewFlowLayout.h
@@ -21,7 +21,7 @@
  UICollectionViewFlowLayout layout.
 
  Learn more at the
- [Material spec](https://www.google.com/design/spec/components/lists.html#lists-specs)
+ [Material spec](https://material.io/guidelines/components/lists.html#lists-specs)
  */
 @interface MDCCollectionViewFlowLayout : UICollectionViewFlowLayout
 
diff --git a/components/Collections/src/private/MDCCollectionInfoBarView.m b/components/Collections/src/private/MDCCollectionInfoBarView.m
index ad98618..a12a8e6 100644
--- a/components/Collections/src/private/MDCCollectionInfoBarView.m
+++ b/components/Collections/src/private/MDCCollectionInfoBarView.m
@@ -25,7 +25,7 @@
 
 static const CGFloat MDCCollectionInfoBarLabelHorizontalPadding = 16.0f;
 
-// Colors derived from http://www.google.com/design/spec/style/color.html#color-color-palette .
+// Colors derived from https://material.io/guidelines/style/color.html#color-color-palette .
 static const uint32_t kCollectionInfoBarBlueColor = 0x448AFF;  // Blue A200
 static const uint32_t kCollectionInfoBarRedColor = 0xF44336;   // Red 500
 
diff --git a/components/Collections/styling/README.md b/components/Collections/styling/README.md
index e971a94..723bb95 100644
--- a/components/Collections/styling/README.md
+++ b/components/Collections/styling/README.md
@@ -1,9 +1,11 @@
----
+<!--docs:
 title: "Styling the collection view"
+navTitle: Styling
 layout: detail
 section: components
 iconId: list
----
+path: /catalog/collections/styling/
+-->
 # Styling the collection view
 
 `MDCCollectionViewController` provides a `styler` property that conforms to the
diff --git a/components/Dialogs/README.md b/components/Dialogs/README.md
index d0b6c1e..2211f2b 100644
--- a/components/Dialogs/README.md
+++ b/components/Dialogs/README.md
@@ -4,10 +4,15 @@
 section: components
 excerpt: "The Dialogs component implements the Material Design specifications for modal presentations."
 iconId: dialog
+path: /catalog/dialogs/
 -->
 
 # Dialogs
 
+<div class="article__asset article__asset--screenshot">
+  <img src="docs/assets/dialogs.png" alt="Dialogs" width="375">
+</div>
+
 Dialogs provides both a presentation controller for displaying a modal dialog and an alert
 controller that will display a simple modal alert.
 <!--{: .article__intro }-->
@@ -15,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://material.google.com/components/dialogs.html">Dialogs</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/dialogs.html">Dialogs</a></li>
 </ul>
 
 ### Dialogs Classes
diff --git a/components/Dialogs/docs/assets/dialogs.png b/components/Dialogs/docs/assets/dialogs.png
new file mode 100644
index 0000000..d5963eb
--- /dev/null
+++ b/components/Dialogs/docs/assets/dialogs.png
Binary files differ
diff --git a/components/Dialogs/examples/DialogsAlertViewController.m b/components/Dialogs/examples/DialogsAlertViewController.m
index 457ff61..7d9aae1 100644
--- a/components/Dialogs/examples/DialogsAlertViewController.m
+++ b/components/Dialogs/examples/DialogsAlertViewController.m
@@ -21,9 +21,37 @@
 
 @implementation DialogsAlertViewController
 
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  [self loadCollectionView:
+    @[ @"Show Alert", @"Show Long Alert", @"Non-Dismissable Alert", @"Dynamic Alert"]];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+  switch (indexPath.row) {
+    case 0:
+      [self didTapShowAlert:nil];
+      break;
+    case 1:
+      [self didTapShowLongAlert:nil];
+      break;
+    case 2:
+      [self didTapNondismissingAlert:nil];
+      break;
+    case 3:
+    default:
+      [self didTapDynamicAlert:nil];
+      break;
+  }
+}
+
+
+
 - (IBAction)didTapShowAlert:(id)sender {
   [[MDCButton appearanceWhenContainedIn:[MDCAlertController class], nil]
-      setCustomTitleColor:[UIColor purpleColor]];
+      setCustomTitleColor:[UIColor colorWithWhite:0.1 alpha:1.0]];
 
   NSString *titleString = @"Using Material alert controller?";
   NSString *messageString = @"Be careful with modal alerts as they can be annoying if over-used.";
diff --git a/components/Dialogs/examples/DialogsKeyboardViewController.m b/components/Dialogs/examples/DialogsKeyboardViewController.m
index 7cdfb94..0ef883c 100644
--- a/components/Dialogs/examples/DialogsKeyboardViewController.m
+++ b/components/Dialogs/examples/DialogsKeyboardViewController.m
@@ -28,12 +28,15 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
+  [self loadCollectionView];
   // We must create and store a strong reference to the transitionController.
   // A presented view controller will set this object as its transitioning delegate.
   self.transitionController = [[MDCDialogTransitionController alloc] init];
 }
 
-- (IBAction)didTapPresent:(id)sender {
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+
   // If you are using this code outside of the MDCCatalog in your own app, your bundle may be nil.
   NSBundle *bundle = [NSBundle bundleForClass:[self class]];
   UIStoryboard *storyboard =
diff --git a/components/Dialogs/examples/DialogsLongAlertViewController.swift b/components/Dialogs/examples/DialogsLongAlertViewController.swift
index e6f8731..2c69fe9 100644
--- a/components/Dialogs/examples/DialogsLongAlertViewController.swift
+++ b/components/Dialogs/examples/DialogsLongAlertViewController.swift
@@ -27,7 +27,7 @@
     view.backgroundColor = UIColor.white
 
     flatButton.setTitle("PRESENT ALERT", for: UIControlState())
-    flatButton.setTitleColor(UIColor.blue, for: UIControlState())
+    flatButton.setTitleColor(UIColor(white: 0.1, alpha:1), for: UIControlState())
     flatButton.sizeToFit()
     flatButton.translatesAutoresizingMaskIntoConstraints = false
     flatButton.addTarget(self, action: #selector(tap), for: .touchUpInside)
diff --git a/components/Dialogs/examples/DialogsTypicalUseViewController.m b/components/Dialogs/examples/DialogsTypicalUseViewController.m
index d660028..8159bcd 100644
--- a/components/Dialogs/examples/DialogsTypicalUseViewController.m
+++ b/components/Dialogs/examples/DialogsTypicalUseViewController.m
@@ -29,11 +29,23 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
+  [self loadCollectionView:@[@"Programmatic", @"Storyboard", @"Modal"]];
   // We must create and store a strong reference to the transitionController.
   // A presented view controller will set this object as its transitioning delegate.
   self.transitionController = [[MDCDialogTransitionController alloc] init];
 }
 
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+  if (indexPath.row == 0) {
+    [self didTapProgrammatic:nil];
+  } else if (indexPath.row == 1) {
+    [self didTapStoryboard:nil];
+  } else if (indexPath.row == 2) {
+    [self didTapModalProgrammatic:nil];
+  }
+}
+
 - (IBAction)didTapProgrammatic:(id)sender {
   UIViewController *viewController =
       [[ProgrammaticViewController alloc] initWithNibName:nil bundle:nil];
diff --git a/components/Dialogs/examples/resources/DialogWithInputField.storyboard b/components/Dialogs/examples/resources/DialogWithInputField.storyboard
index e986809..f66b427 100644
--- a/components/Dialogs/examples/resources/DialogWithInputField.storyboard
+++ b/components/Dialogs/examples/resources/DialogWithInputField.storyboard
@@ -1,10 +1,13 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="NO">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <development version="7000" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
         <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
         <!--DialogWithInputFieldViewController-->
@@ -25,18 +28,19 @@
                                     <constraint firstAttribute="height" constant="41" id="WYg-Oo-3ho"/>
                                 </constraints>
                                 <fontDescription key="fontDescription" type="system" pointSize="24"/>
-                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eMP-C9-zSz" customClass="MDCRaisedButton">
                                 <rect key="frame" x="110" y="136" width="114" height="36"/>
-                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="backgroundColor" white="0.095072849730000006" alpha="1" colorSpace="calibratedWhite"/>
                                 <constraints>
                                     <constraint firstAttribute="width" constant="114" id="Xs0-2D-eQT"/>
                                     <constraint firstAttribute="height" constant="36" id="hWD-nJ-iWR"/>
                                 </constraints>
+                                <color key="tintColor" white="0.095072849733488896" alpha="1" colorSpace="calibratedWhite"/>
                                 <state key="normal" title="Okay">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 </state>
                                 <connections>
                                     <action selector="buttonPushed:" destination="qQc-Ib-5lF" eventType="touchUpInside" id="A7U-Zd-q5z"/>
@@ -51,7 +55,7 @@
                                 <textInputTraits key="textInputTraits"/>
                             </textField>
                         </subviews>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                         <constraints>
                             <constraint firstAttribute="trailingMargin" secondItem="90p-55-soM" secondAttribute="trailing" id="13O-ut-0ag"/>
                             <constraint firstItem="5Sj-Ry-Dh5" firstAttribute="top" secondItem="90p-55-soM" secondAttribute="bottom" constant="12" id="3IV-lG-PVY"/>
diff --git a/components/Dialogs/examples/resources/DialogWithPreferredContentSize.storyboard b/components/Dialogs/examples/resources/DialogWithPreferredContentSize.storyboard
index 95b5ade..a731f44 100644
--- a/components/Dialogs/examples/resources/DialogWithPreferredContentSize.storyboard
+++ b/components/Dialogs/examples/resources/DialogWithPreferredContentSize.storyboard
@@ -1,9 +1,13 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
         <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
         <!--DialogWithPreferredContentSize-->
@@ -24,31 +28,31 @@
                                     <constraint firstAttribute="height" constant="41" id="WYg-Oo-3ho"/>
                                 </constraints>
                                 <fontDescription key="fontDescription" type="system" pointSize="24"/>
-                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This view controller has a preferredContentSize which is observed by our presentation controller. " lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="CKe-6Q-X99">
                                 <rect key="frame" x="16" y="77" width="208" height="99"/>
                                 <fontDescription key="fontDescription" type="system" pointSize="17"/>
-                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eMP-C9-zSz" customClass="MDCRaisedButton">
                                 <rect key="frame" x="110" y="184" width="114" height="36"/>
-                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <constraints>
                                     <constraint firstAttribute="width" constant="114" id="Xs0-2D-eQT"/>
                                     <constraint firstAttribute="height" constant="36" id="hWD-nJ-iWR"/>
                                 </constraints>
                                 <state key="normal" title="Okay">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 </state>
                                 <connections>
                                     <action selector="buttonPushed:" destination="qQc-Ib-5lF" eventType="touchUpInside" id="A7U-Zd-q5z"/>
                                 </connections>
                             </button>
                         </subviews>
-                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                         <constraints>
                             <constraint firstAttribute="trailingMargin" secondItem="90p-55-soM" secondAttribute="trailing" id="13O-ut-0ag"/>
                             <constraint firstAttribute="leadingMargin" secondItem="CKe-6Q-X99" secondAttribute="leading" id="2TQ-xI-0Yw"/>
diff --git a/components/Dialogs/examples/resources/DialogsAlertViewController.storyboard b/components/Dialogs/examples/resources/DialogsAlertViewController.storyboard
deleted file mode 100644
index bfbc7de..0000000
--- a/components/Dialogs/examples/resources/DialogsAlertViewController.storyboard
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="NO" initialViewController="o5b-mD-WeU">
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <development version="7000" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
-    </dependencies>
-    <scenes>
-        <!--AlertController-->
-        <scene sceneID="aZ2-cX-Iku">
-            <objects>
-                <viewController storyboardIdentifier="DialogsAlertViewController" title="AlertController" id="o5b-mD-WeU" customClass="DialogsAlertViewController" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="Qgh-2o-Fty"/>
-                        <viewControllerLayoutGuide type="bottom" id="LFY-PB-o71"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="PBd-In-ziF">
-                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
-                        <subviews>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="752" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Svl-rE-K5t" customClass="MDCRaisedButton">
-                                <rect key="frame" x="104" y="181" width="112" height="34"/>
-                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                <inset key="contentEdgeInsets" minX="8" minY="8" maxX="8" maxY="8"/>
-                                <state key="normal" title="SHOW ALERT">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                </state>
-                                <connections>
-                                    <action selector="didTapShowAlert:" destination="o5b-mD-WeU" eventType="touchUpInside" id="TB7-z5-8hF"/>
-                                </connections>
-                            </button>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="752" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RB8-BC-9uM" customClass="MDCRaisedButton">
-                                <rect key="frame" x="82" y="223" width="157" height="34"/>
-                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                <inset key="contentEdgeInsets" minX="8" minY="8" maxX="8" maxY="8"/>
-                                <state key="normal" title="SHOW LONG ALERT">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                </state>
-                                <connections>
-                                    <action selector="didTapShowLongAlert:" destination="o5b-mD-WeU" eventType="touchUpInside" id="icX-jQ-ycZ"/>
-                                </connections>
-                            </button>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="752" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Lpe-1x-D8T" customClass="MDCRaisedButton">
-                                <rect key="frame" x="59" y="265" width="202" height="34"/>
-                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                <inset key="contentEdgeInsets" minX="8" minY="8" maxX="8" maxY="8"/>
-                                <state key="normal" title="NON-DISMISSABLE ALERT">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                </state>
-                                <connections>
-                                    <action selector="didTapNondismissingAlert:" destination="o5b-mD-WeU" eventType="touchUpInside" id="Oqc-9S-GGz"/>
-                                </connections>
-                            </button>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="752" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Vqx-6W-SeA" customClass="MDCRaisedButton">
-                                <rect key="frame" x="93" y="307" width="134" height="34"/>
-                                <color key="backgroundColor" red="0.0" green="0.50196081400000003" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                <inset key="contentEdgeInsets" minX="8" minY="8" maxX="8" maxY="8"/>
-                                <state key="normal" title="DYNAMIC ALERT">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                </state>
-                                <connections>
-                                    <action selector="didTapDynamicAlert:" destination="o5b-mD-WeU" eventType="touchUpInside" id="6oS-Px-lRF"/>
-                                </connections>
-                            </button>
-                        </subviews>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                        <constraints>
-                            <constraint firstItem="RB8-BC-9uM" firstAttribute="centerX" secondItem="PBd-In-ziF" secondAttribute="centerX" id="4b5-3V-R3n"/>
-                            <constraint firstItem="RB8-BC-9uM" firstAttribute="centerY" secondItem="PBd-In-ziF" secondAttribute="centerY" id="8fo-2n-kci"/>
-                            <constraint firstItem="Svl-rE-K5t" firstAttribute="centerX" secondItem="PBd-In-ziF" secondAttribute="centerX" id="IOo-f3-1Bq"/>
-                            <constraint firstItem="Lpe-1x-D8T" firstAttribute="centerX" secondItem="PBd-In-ziF" secondAttribute="centerX" id="IrQ-8G-4hy"/>
-                            <constraint firstItem="RB8-BC-9uM" firstAttribute="top" secondItem="Svl-rE-K5t" secondAttribute="bottom" constant="8" id="LX0-rg-GuH"/>
-                            <constraint firstItem="Lpe-1x-D8T" firstAttribute="top" secondItem="RB8-BC-9uM" secondAttribute="bottom" constant="8" id="Pf3-xA-Bp8"/>
-                            <constraint firstItem="Vqx-6W-SeA" firstAttribute="top" secondItem="Lpe-1x-D8T" secondAttribute="bottom" constant="8" id="Qow-kh-dBb"/>
-                            <constraint firstItem="Vqx-6W-SeA" firstAttribute="centerX" secondItem="PBd-In-ziF" secondAttribute="centerX" id="p8h-et-6gM"/>
-                        </constraints>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="hRQ-Ai-YYv" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="483.75" y="493.75"/>
-        </scene>
-    </scenes>
-</document>
diff --git a/components/Dialogs/examples/resources/DialogsKeyboardViewController.storyboard b/components/Dialogs/examples/resources/DialogsKeyboardViewController.storyboard
deleted file mode 100644
index 4f03067..0000000
--- a/components/Dialogs/examples/resources/DialogsKeyboardViewController.storyboard
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="NO" initialViewController="bUd-nh-klo">
-    <dependencies>
-        <deployment identifier="iOS"/>
-        <development version="7000" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
-    </dependencies>
-    <scenes>
-        <!--DialogsKeyboardViewController-->
-        <scene sceneID="WMP-nM-Jx6">
-            <objects>
-                <viewController storyboardIdentifier="DialogsKeyboardViewController" title="DialogsTypicalUse" id="bUd-nh-klo" userLabel="DialogsKeyboardViewController" customClass="DialogsKeyboardViewController" sceneMemberID="viewController">
-                    <layoutGuides>
-                        <viewControllerLayoutGuide type="top" id="yyY-OF-sQW"/>
-                        <viewControllerLayoutGuide type="bottom" id="Zhm-xj-hPs"/>
-                    </layoutGuides>
-                    <view key="view" contentMode="scaleToFill" id="D3I-hi-DX6">
-                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
-                        <autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
-                        <subviews>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Nk6-ZZ-sLb" customClass="MDCRaisedButton">
-                                <rect key="frame" x="241" y="291" width="160" height="44"/>
-                                <color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                <inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
-                                <state key="normal" title="INPUT DIALOG">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                                </state>
-                                <connections>
-                                    <action selector="didTapPresent:" destination="bUd-nh-klo" eventType="touchUpInside" id="uaA-iO-dLY"/>
-                                </connections>
-                            </button>
-                        </subviews>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
-                        <constraints>
-                            <constraint firstItem="Nk6-ZZ-sLb" firstAttribute="centerX" secondItem="D3I-hi-DX6" secondAttribute="centerX" id="UKd-PX-wT5"/>
-                            <constraint firstItem="Nk6-ZZ-sLb" firstAttribute="centerY" secondItem="D3I-hi-DX6" secondAttribute="centerY" id="wPX-Li-yIw"/>
-                        </constraints>
-                    </view>
-                </viewController>
-                <placeholder placeholderIdentifier="IBFirstResponder" id="n4R-rW-mx7" userLabel="First Responder" sceneMemberID="firstResponder"/>
-            </objects>
-            <point key="canvasLocation" x="522" y="666"/>
-        </scene>
-    </scenes>
-</document>
diff --git a/components/Dialogs/examples/resources/DialogsTypicalUseViewController.storyboard b/components/Dialogs/examples/resources/DialogsTypicalUseViewController.storyboard
index 2f9cb1b..d9e1882 100644
--- a/components/Dialogs/examples/resources/DialogsTypicalUseViewController.storyboard
+++ b/components/Dialogs/examples/resources/DialogsTypicalUseViewController.storyboard
@@ -1,9 +1,12 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="NO" initialViewController="bUd-nh-klo">
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12118" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="bUd-nh-klo">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
     <dependencies>
         <deployment identifier="iOS"/>
-        <development version="7000" identifier="xcode"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11161"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12086"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
         <!--DialogsTypicalUseViewController-->
@@ -15,43 +18,43 @@
                         <viewControllerLayoutGuide type="bottom" id="Zhm-xj-hPs"/>
                     </layoutGuides>
                     <view key="view" contentMode="scaleToFill" id="D3I-hi-DX6">
-                        <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Nk6-ZZ-sLb" customClass="MDCRaisedButton">
+                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Nk6-ZZ-sLb" customClass="MDCRaisedButton">
                                 <rect key="frame" x="91" y="28" width="193" height="18"/>
-                                <color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
                                 <state key="normal" title="PROGRAMMATIC DIALOG">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 </state>
                                 <connections>
                                     <action selector="didTapProgrammatic:" destination="bUd-nh-klo" eventType="touchUpInside" id="ZhY-yy-uaP"/>
                                 </connections>
                             </button>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9VI-Tq-cpg" customClass="MDCRaisedButton">
+                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9VI-Tq-cpg" customClass="MDCRaisedButton">
                                 <rect key="frame" x="101" y="54" width="174" height="18"/>
-                                <color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="backgroundColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
                                 <inset key="contentEdgeInsets" minX="8" minY="0.0" maxX="8" maxY="0.0"/>
                                 <state key="normal" title="STORYBOARD DIALOG">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 </state>
                                 <connections>
                                     <action selector="didTapStoryboard:" destination="bUd-nh-klo" eventType="touchUpInside" id="IWE-cI-Cnu"/>
                                 </connections>
                             </button>
-                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" misplaced="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zji-Dd-GdC" customClass="MDCRaisedButton">
+                            <button opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="751" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zji-Dd-GdC" customClass="MDCRaisedButton">
                                 <rect key="frame" x="132" y="80" width="111" height="30"/>
-                                <color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                <color key="backgroundColor" red="0.0" green="0.0" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <state key="normal" title="MODAL DIALOG">
-                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                                    <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 </state>
                                 <connections>
                                     <action selector="didTapModalProgrammatic:" destination="bUd-nh-klo" eventType="touchUpInside" id="gUx-E9-tgE"/>
                                 </connections>
                             </button>
                         </subviews>
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                         <constraints>
                             <constraint firstItem="Nk6-ZZ-sLb" firstAttribute="centerX" secondItem="D3I-hi-DX6" secondAttribute="centerX" id="UKd-PX-wT5"/>
                             <constraint firstItem="Nk6-ZZ-sLb" firstAttribute="top" secondItem="yyY-OF-sQW" secondAttribute="bottom" constant="8" id="abk-O5-qGg"/>
@@ -67,4 +70,5 @@
             <point key="canvasLocation" x="702" y="565"/>
         </scene>
     </scenes>
+    <color key="tintColor" white="0.1007254635" alpha="1" colorSpace="calibratedWhite"/>
 </document>
diff --git a/components/Dialogs/examples/supplemental/DialogWithInputFieldViewController.h b/components/Dialogs/examples/supplemental/DialogWithInputFieldViewController.h
index b1682b0..f355c31 100644
--- a/components/Dialogs/examples/supplemental/DialogWithInputFieldViewController.h
+++ b/components/Dialogs/examples/supplemental/DialogWithInputFieldViewController.h
@@ -21,6 +21,7 @@
 
 #import <UIKit/UIKit.h>
 
-@interface DialogWithInputFieldViewController : UIViewController
+@class button;
 
+@interface DialogWithInputFieldViewController : UIViewController
 @end
diff --git a/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.h b/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.h
index cc5f7e1..a1c2e4d 100644
--- a/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.h
+++ b/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.h
@@ -21,5 +21,9 @@
 
 #import <UIKit/UIKit.h>
 
-@interface DialogsAlertViewController : UIViewController
+@import MaterialComponents.MaterialCollections;
+
+@interface DialogsAlertViewController : MDCCollectionViewController
+@property(nonatomic, strong, nullable) NSArray *modes;
+- (void)loadCollectionView:(nullable NSArray *)modes;
 @end
diff --git a/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.m b/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.m
index bb8d510..ed72c0d 100644
--- a/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.m
+++ b/components/Dialogs/examples/supplemental/DialogsAlertViewControllerSupplemental.m
@@ -26,7 +26,32 @@
 #import "MaterialDialogs.h"
 #import "MaterialTypography.h"
 
-#pragma mark - DialogsAlertViewController
+
+static NSString * const kReusableIdentifierItem = @"cell";
+
+
+@implementation DialogsAlertViewController (Supplemental)
+
+- (void)loadCollectionView:(nullable NSArray *)modes {
+  [self.collectionView registerClass:[MDCCollectionViewTextCell class]
+          forCellWithReuseIdentifier:kReusableIdentifierItem];
+  self.modes = modes;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+  return self.modes.count;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  MDCCollectionViewTextCell *cell =
+  [collectionView dequeueReusableCellWithReuseIdentifier:kReusableIdentifierItem
+                                            forIndexPath:indexPath];
+  cell.textLabel.text = self.modes[indexPath.row];
+  return cell;
+}
+
+@end
 
 @implementation DialogsAlertViewController (CatalogByConvention)
 
@@ -42,8 +67,4 @@
   return NO;
 }
 
-+ (NSString *)catalogStoryboardName {
-  return @"DialogsAlertViewController";
-}
-
 @end
diff --git a/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.h b/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.h
index 2f10cda..e9a6541 100644
--- a/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.h
+++ b/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.h
@@ -21,5 +21,8 @@
 
 #import <UIKit/UIKit.h>
 
-@interface DialogsKeyboardViewController : UIViewController
+@import MaterialComponents.MaterialCollections;
+
+@interface DialogsKeyboardViewController : MDCCollectionViewController
+- (void)loadCollectionView;
 @end
diff --git a/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.m b/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.m
index 1f5c9af..a3c22c2 100644
--- a/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.m
+++ b/components/Dialogs/examples/supplemental/DialogsKeyboardViewControllerSupplemental.m
@@ -25,6 +25,32 @@
 
 #pragma mark - DialogsKeyboardViewController
 
+static NSString * const kReusableIdentifierItem = @"cell";
+
+
+@implementation DialogsKeyboardViewController (Supplemental)
+
+- (void)loadCollectionView {
+  [self.collectionView registerClass:[MDCCollectionViewTextCell class]
+          forCellWithReuseIdentifier:kReusableIdentifierItem];
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+  return 1;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  MDCCollectionViewTextCell *cell =
+      [collectionView dequeueReusableCellWithReuseIdentifier:kReusableIdentifierItem
+                                                forIndexPath:indexPath];
+  cell.textLabel.text = @"Show Dialog";
+  return cell;
+}
+
+@end
+
+
 @implementation DialogsKeyboardViewController (CatalogByConvention)
 
 + (NSArray *)catalogBreadcrumbs {
@@ -35,8 +61,4 @@
   return @"Demonstrate Material dialog controller with an input field.";
 }
 
-+ (NSString *)catalogStoryboardName {
-  return @"DialogsKeyboardViewController";
-}
-
 @end
diff --git a/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.h b/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.h
index 4255d51..56de7ba 100644
--- a/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.h
+++ b/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.h
@@ -21,9 +21,16 @@
 
 #import <UIKit/UIKit.h>
 
+@import MaterialComponents.MaterialCollections;
+
 //@class DialogsTypicalUseViewController;
 
-@interface DialogsTypicalUseViewController : UIViewController
+@interface DialogsTypicalUseViewController : MDCCollectionViewController
+@property(nonatomic, strong, nullable) NSArray *modes;
+@end
+
+@interface DialogsTypicalUseViewController (Supplemental)
+- (void)loadCollectionView:(nullable NSArray *)modes;
 @end
 
 @interface ProgrammaticViewController : UIViewController
diff --git a/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.m b/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.m
index 40ad627..3ad62a2 100644
--- a/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.m
+++ b/components/Dialogs/examples/supplemental/DialogsTypicalUseSupplemental.m
@@ -25,9 +25,36 @@
 #import "MaterialButtons.h"
 #import "MaterialDialogs.h"
 #import "MaterialTypography.h"
+#import "MaterialCollections.h"
 
 #pragma mark - DialogsTypicalUseViewController
 
+static NSString * const kReusableIdentifierItem = @"cell";
+
+
+@implementation DialogsTypicalUseViewController (Supplemental)
+
+- (void)loadCollectionView:(nullable NSArray *)modes {
+  [self.collectionView registerClass:[MDCCollectionViewTextCell class]
+          forCellWithReuseIdentifier:kReusableIdentifierItem];
+  self.modes = modes;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+  return self.modes.count;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  MDCCollectionViewTextCell *cell =
+  [collectionView dequeueReusableCellWithReuseIdentifier:kReusableIdentifierItem
+                                            forIndexPath:indexPath];
+  cell.textLabel.text = self.modes[indexPath.row];
+  return cell;
+}
+
+@end
+
 @implementation DialogsTypicalUseViewController (CatalogByConvention)
 
 + (NSArray *)catalogBreadcrumbs {
@@ -43,15 +70,11 @@
   return YES;
 }
 
-+ (NSString *)catalogStoryboardName {
-  return @"DialogsTypicalUseViewController";
-}
-
 @end
 
 @interface ProgrammaticViewController ()
 
-@property(nonatomic, strong) MDCRaisedButton *dismissButton;
+@property(nonatomic, strong) MDCFlatButton *dismissButton;
 
 @end
 
@@ -62,11 +85,12 @@
 
   self.view.backgroundColor = [UIColor whiteColor];
 
-  _dismissButton = [[MDCRaisedButton alloc] init];
-  _dismissButton.autoresizingMask =
-      UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin |
-      UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
+  _dismissButton = [[MDCFlatButton alloc] init];
   [_dismissButton setTitle:@"Dismiss" forState:UIControlStateNormal];
+  [_dismissButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
+  _dismissButton.autoresizingMask =
+      UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |
+      UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
   [_dismissButton sizeToFit];
   [_dismissButton addTarget:self
                      action:@selector(dismiss:)
diff --git a/components/Dialogs/src/MDCAlertController.h b/components/Dialogs/src/MDCAlertController.h
index ea8330a..86f9bad 100644
--- a/components/Dialogs/src/MDCAlertController.h
+++ b/components/Dialogs/src/MDCAlertController.h
@@ -25,7 +25,7 @@
 /**
  MDCAlertController displays an alert message to the user, similar to UIAlertController.
 
- https://material.google.com/components/dialogs.html
+ https://material.io/guidelines/components/dialogs.html
 
  MDCAlertController requires iOS 8 or later.
 
diff --git a/components/Dialogs/src/MDCAlertController.m b/components/Dialogs/src/MDCAlertController.m
index 4ee188c..a93df40 100644
--- a/components/Dialogs/src/MDCAlertController.m
+++ b/components/Dialogs/src/MDCAlertController.m
@@ -52,7 +52,7 @@
 
 @end
 
-// https://material.google.com/components/dialogs.html#dialogs-specs
+// https://material.io/guidelines/components/dialogs.html#dialogs-specs
 static const UIEdgeInsets MDCDialogContentInsets = {24.0, 24.0, 24.0, 24.0};
 static const CGFloat MDCDialogContentVerticalPadding = 20.0;
 
diff --git a/components/Dialogs/src/MDCDialogPresentationController.h b/components/Dialogs/src/MDCDialogPresentationController.h
index 628d0a2..04f0bc5 100644
--- a/components/Dialogs/src/MDCDialogPresentationController.h
+++ b/components/Dialogs/src/MDCDialogPresentationController.h
@@ -24,7 +24,7 @@
  MDCDialogPresentationController will present a modal ViewController as a dialog according to the
  Material spec.
 
- https://material.google.com/components/dialogs.html
+ https://material.io/guidelines/components/dialogs.html
 
  MDCDialogPresentationController should not be used to present full-screen dialogs.
 
diff --git a/components/Dialogs/src/MDCDialogTransitionController.h b/components/Dialogs/src/MDCDialogTransitionController.h
index 6353b5f..7e685c0 100644
--- a/components/Dialogs/src/MDCDialogTransitionController.h
+++ b/components/Dialogs/src/MDCDialogTransitionController.h
@@ -24,7 +24,7 @@
  MDCDialogTransitionController is be used to setup a custom transition and animationed presentation
  and dismissal for material-styled alerts, simple dialogs and confirmation dialogs.
 
- https://material.google.com/components/dialogs.html
+ https://material.io/guidelines/components/dialogs.html
 
  This class provides a basic implementation of UIViewControllerAnimatedTransitioning and
  UIViewControllerTransitioningDelegate.
diff --git a/components/FeatureHighlight/README.md b/components/FeatureHighlight/README.md
index 2650193..db46a93 100644
--- a/components/FeatureHighlight/README.md
+++ b/components/FeatureHighlight/README.md
@@ -4,26 +4,21 @@
 section: components
 excerpt: "Feature Highlight highlights a part of the screen in order to introduce users to new features and functionality."
 iconId: feature_highlight
+path: /catalog/feature-highlights/
 -->
 
 # Feature Highlight
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/feature_highlight.png" alt="Feature Highlight" width="320">
+  <img src="docs/assets/feature_highlight.png" alt="Feature Highlight" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/feature_highlight.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Feature Highlight component is a way to visually highlight a part of the screen in order to introduce users to new features and functionality.
 
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://material.google.com/growth-communications/feature-discovery.html">Feature Discovery</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/growth-communications/feature-discovery.html">Feature Discovery</a></li>
 </ul>
 
 - - -
diff --git a/components/FeatureHighlight/docs/assets/feature_highlight.mp4 b/components/FeatureHighlight/docs/assets/feature_highlight.mp4
deleted file mode 100644
index 35b71b6..0000000
--- a/components/FeatureHighlight/docs/assets/feature_highlight.mp4
+++ /dev/null
Binary files differ
diff --git a/components/FeatureHighlight/docs/assets/feature_highlight.png b/components/FeatureHighlight/docs/assets/feature_highlight.png
index 89590b9..3d2a83f 100644
--- a/components/FeatureHighlight/docs/assets/feature_highlight.png
+++ b/components/FeatureHighlight/docs/assets/feature_highlight.png
Binary files differ
diff --git a/components/FeatureHighlight/examples/FeatureHighlightTypicalUseViewController.m b/components/FeatureHighlight/examples/FeatureHighlightTypicalUseViewController.m
index 5580b4d..121354a 100644
--- a/components/FeatureHighlight/examples/FeatureHighlightTypicalUseViewController.m
+++ b/components/FeatureHighlight/examples/FeatureHighlightTypicalUseViewController.m
@@ -23,6 +23,7 @@
 - (void)didTapButton:(id)sender {
   MDCFeatureHighlightViewController *vc =
       [[MDCFeatureHighlightViewController alloc] initWithHighlightedView:_button completion:nil];
+  vc.outerHighlightColor = [UIColor colorWithRed:11/255.0 green:232/255.0 blue:94/255.0 alpha:kMDCFeatureHighlightOuterHighlightAlpha];
   vc.titleText = @"Hey a title";
   vc.bodyText = @"This is the description of the feature highlight view controller.";
   [self presentViewController:vc animated:YES completion:nil];
diff --git a/components/FeatureHighlight/examples/supplemental/FeatureHighlightExampleSupplemental.m b/components/FeatureHighlight/examples/supplemental/FeatureHighlightExampleSupplemental.m
index 2366edd..aeb1c7c 100644
--- a/components/FeatureHighlight/examples/supplemental/FeatureHighlightExampleSupplemental.m
+++ b/components/FeatureHighlight/examples/supplemental/FeatureHighlightExampleSupplemental.m
@@ -50,7 +50,9 @@
   [self.view addSubview:self.infoLabel];
 
   self.button = [[MDCRaisedButton alloc] init];
-  [self.button setTitle:@"GO!" forState:UIControlStateNormal];
+  [self.button setBackgroundColor:[UIColor colorWithWhite:0.1 alpha:1]];
+  [self.button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
+  [self.button setTitle:@"Action" forState:UIControlStateNormal];
   [self.button sizeToFit];
   [self.button addTarget:self
                   action:@selector(didTapButton:)
diff --git a/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings.h b/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings.h
index e1dfeb3..b25758b 100644
--- a/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings.h
+++ b/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings.h
@@ -1,7 +1,7 @@
 // GENERATED CODE: DO NOT EDIT BY HAND
 // GENERATED FROM:
 // components/FeatureHighlight/src/MaterialFeatureHighlight.bundle/Resources/en.lproj/MaterialFeatureHighlight.strings
-// GENERATED BY: //depot/google3/googlemac/iPhone/Shared/Tools/generate_string_tables.py
+// GENERATED BY: generate_string_tables.py
 
 typedef enum {
   kStr_MaterialFeatureHighlightDismissAccessibilityHint = 0,
diff --git a/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings_table.h b/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings_table.h
index c0ab4ca..652f40d 100644
--- a/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings_table.h
+++ b/components/FeatureHighlight/src/private/MaterialFeatureHighlightStrings_table.h
@@ -1,7 +1,7 @@
 // GENERATED CODE: DO NOT EDIT BY HAND
 // GENERATED FROM:
 // components/FeatureHighlight/src/MaterialFeatureHighlight.bundle/Resources/en.lproj/MaterialFeatureHighlight.strings
-// GENERATED BY: //depot/google3/googlemac/iPhone/Shared/Tools/generate_string_tables.py
+// GENERATED BY: generate_string_tables.py
 
 #import <Foundation/Foundation.h>
 
diff --git a/components/FlexibleHeader/README.md b/components/FlexibleHeader/README.md
index 2aa2987..cef6364 100644
--- a/components/FlexibleHeader/README.md
+++ b/components/FlexibleHeader/README.md
@@ -1,22 +1,17 @@
 <!--docs:
-title: "Flexible Header"
+title: "Flexible Headers"
 layout: detail
 section: components
 excerpt: "The Flexible Header is a container view whose height and vertical offset react to UIScrollViewDelegate events."
 iconId: header
+path: /catalog/flexible-headers/
 -->
 
 # Flexible Header
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/flexible_header.png" alt="Flexible Header" width="320">
+  <img src="docs/assets/flexible_header.png" alt="Flexible Header" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/flexible_header.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Flexible Header is a container view whose height and vertical offset react to
 UIScrollViewDelegate events.
@@ -25,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/patterns/scrolling-techniques.html">Scrolling Techniques</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/patterns/scrolling-techniques.html">Scrolling Techniques</a></li>
 </ul>
 
 - - -
@@ -317,12 +312,12 @@
 <!--<div class="material-code-render" markdown="1">-->
 #### Swift
 ``` swift
-headerViewController.headerView.behavior = .Enabled
+headerViewController.headerView.shiftBehavior = .Enabled
 ```
 
 #### Objective-C
 ``` objc
-headerViewController.headerView.behavior = MDCFlexibleHeaderShiftBehaviorEnabled;
+headerViewController.headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorEnabled;
 ```
 <!--</div>-->
 
@@ -338,7 +333,7 @@
 <!--<div class="material-code-render" markdown="1">-->
 #### Swift
 ``` swift
-headerViewController.headerView.behavior = .EnabledWithStatusBar
+headerViewController.headerView.shiftBehavior = .EnabledWithStatusBar
 
 override func childViewControllerForStatusBarHidden() -> UIViewController? {
   return headerViewController
@@ -347,7 +342,7 @@
 
 #### Objective-C
 ``` objc
-headerViewController.headerView.behavior = MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar;
+headerViewController.headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar;
 
 - (UIViewController *)childViewControllerForStatusBarHidden {
   return _headerViewController;
@@ -613,7 +608,7 @@
 <!--<div class="material-code-render" markdown="1">-->
 #### Swift
 ``` swift
-override func childViewControllerForStatusBarStyle() -> UIViewController? {
+override var childViewControllerForStatusBarStyle: UIViewController? {
   return headerViewController
 }
 ```
diff --git a/components/FlexibleHeader/docs/assets/flexible_header.mp4 b/components/FlexibleHeader/docs/assets/flexible_header.mp4
deleted file mode 100644
index 7875e45..0000000
--- a/components/FlexibleHeader/docs/assets/flexible_header.mp4
+++ /dev/null
Binary files differ
diff --git a/components/FlexibleHeader/docs/assets/flexible_header.png b/components/FlexibleHeader/docs/assets/flexible_header.png
index 9b72450..3deccff 100644
--- a/components/FlexibleHeader/docs/assets/flexible_header.png
+++ b/components/FlexibleHeader/docs/assets/flexible_header.png
Binary files differ
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderFABExample.m b/components/FlexibleHeader/examples/FlexibleHeaderFABExample.m
index 9a6c1e4..8887759 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderFABExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderFABExample.m
@@ -78,9 +78,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.333 green:0.769 blue:0.961 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
 }
 
 - (void)viewWillAppear:(BOOL)animated {
@@ -91,6 +89,8 @@
   [self.navigationController setNavigationBarHidden:YES animated:animated];
 
   self.floatingButton = [[MDCFloatingButton alloc] init];
+  [self.floatingButton setBackgroundColor:[UIColor colorWithRed:11/255.0 green:232/255.0 blue:94/255.0 alpha:1]
+                                 forState:UIControlStateNormal];
   [self.floatingButton sizeToFit];
   self.floatingButton.center = CGPointMake(
       self.view.frame.size.width - self.floatingButton.frame.size.width, kFlexibleHeaderMinHeight);
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderHorizontalPagingExample.m b/components/FlexibleHeader/examples/FlexibleHeaderHorizontalPagingExample.m
index a8fcb89..dd7a326 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderHorizontalPagingExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderHorizontalPagingExample.m
@@ -154,9 +154,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
 }
 
 - (UIStatusBarStyle)preferredStatusBarStyle {
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderPageControlExample.m b/components/FlexibleHeader/examples/FlexibleHeaderPageControlExample.m
index 3109f3a..99d68f0 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderPageControlExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderPageControlExample.m
@@ -89,14 +89,15 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.333 green:0.769 blue:0.961 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1];
 
   CGFloat boundsWidth = CGRectGetWidth(self.fhvc.headerView.bounds);
   CGFloat boundsHeight = CGRectGetHeight(self.fhvc.headerView.bounds);
 
-  NSArray *pageColors = @[ ColorFromRGB(0x55C4f5), ColorFromRGB(0x35B7F3), ColorFromRGB(0x1EAAF1) ];
+  NSArray *pageColors = @[ [UIColor colorWithWhite:0.1 alpha:1],
+                           [UIColor colorWithWhite:0.2 alpha:1],
+                           [UIColor colorWithWhite:0.3 alpha:1]];
+
 
   // Scroll view configuration
   CGRect pageScrollViewFrame = CGRectMake(0, 0, boundsWidth, boundsHeight);
@@ -117,7 +118,7 @@
     UILabel *page = [[UILabel alloc] initWithFrame:pageFrame];
     page.text = [NSString stringWithFormat:@"Page %zd", i + 1];
     page.font = [UIFont systemFontOfSize:18];
-    page.textColor = [UIColor colorWithWhite:0 alpha:0.8];
+    page.textColor = [UIColor colorWithWhite:1 alpha:0.8];
     page.textAlignment = NSTextAlignmentCenter;
     page.backgroundColor = pageColors[i];
     page.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderTopLayoutGuideExample.m b/components/FlexibleHeader/examples/FlexibleHeaderTopLayoutGuideExample.m
index 33fefa8..1cab526 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderTopLayoutGuideExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderTopLayoutGuideExample.m
@@ -76,9 +76,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.333 green:0.769 blue:0.961 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
   self.fhvc.headerView.shiftBehavior = MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar;
 
   [self setupScrollViewContent];
@@ -87,7 +85,8 @@
 
   // Create UIView Object
   UIView *constrainedView = [[UIView alloc] init];
-  constrainedView.backgroundColor = [UIColor redColor];
+  constrainedView.backgroundColor =
+      [UIColor colorWithRed:11/255.0 green:232/255.0 blue:94/255.0 alpha:1];
   constrainedView.translatesAutoresizingMaskIntoConstraints = NO;
   self.constrainedView = constrainedView;
   [self.view addSubview:self.constrainedView];
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.m b/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.m
index 389bbe0..93860b4 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.m
@@ -76,9 +76,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
 
   [self setupExampleViews];
 }
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.swift b/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.swift
index b134af4..24cfb74 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.swift
+++ b/components/FlexibleHeader/examples/FlexibleHeaderTypicalUseExample.swift
@@ -46,9 +46,7 @@
     view.addSubview(fhvc.view)
     fhvc.didMove(toParentViewController: self)
 
-    // Light blue 500
-    fhvc.headerView.backgroundColor =
-        UIColor.init(colorLiteralRed: 0.012, green: 0.663, blue: 0.957, alpha: 1)
+    fhvc.headerView.backgroundColor = UIColor(white: 0.1, alpha: 1.0);
 
     self.setupExampleViews()
   }
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderUINavigationBarExample.m b/components/FlexibleHeader/examples/FlexibleHeaderUINavigationBarExample.m
index 05fb06a..075a8b3 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderUINavigationBarExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderUINavigationBarExample.m
@@ -68,6 +68,7 @@
   navBar.shadowImage = [UIImage new];
   navBar.translucent = YES;
   navBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  navBar.tintColor = [UIColor whiteColor];
 
   [self.fhvc.headerView addSubview:navBar];
 
@@ -120,9 +121,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.333 green:0.769 blue:0.961 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
 }
 
 - (void)viewWillAppear:(BOOL)animated {
diff --git a/components/FlexibleHeader/examples/FlexibleHeaderWrappedExample.m b/components/FlexibleHeader/examples/FlexibleHeaderWrappedExample.m
index eb4b93d..bd77c54 100644
--- a/components/FlexibleHeader/examples/FlexibleHeaderWrappedExample.m
+++ b/components/FlexibleHeader/examples/FlexibleHeaderWrappedExample.m
@@ -81,9 +81,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  // Light blue 500
-  self.fhvc.headerView.backgroundColor =
-      [UIColor colorWithRed:0.333 green:0.769 blue:0.961 alpha:1];
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1];
 
   [self.scrollView setScrollEnabled:YES];
   [self.scrollView addSubview:self.wrappedViewController.view];
diff --git a/components/FlexibleHeader/examples/supplemental/FlexibleHeaderConfiguratorSupplemental.m b/components/FlexibleHeader/examples/supplemental/FlexibleHeaderConfiguratorSupplemental.m
index f11b76d..0768458 100644
--- a/components/FlexibleHeader/examples/supplemental/FlexibleHeaderConfiguratorSupplemental.m
+++ b/components/FlexibleHeader/examples/supplemental/FlexibleHeaderConfiguratorSupplemental.m
@@ -76,8 +76,7 @@
   [self.view addSubview:self.fhvc.view];
   [self.fhvc didMoveToParentViewController:self];
 
-  UIColor *lightBlue500 = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1];
-  self.fhvc.headerView.backgroundColor = lightBlue500;
+  self.fhvc.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
 
   UILabel *titleLabel = [[UILabel alloc] init];
   CGRect frame = self.fhvc.headerView.bounds;
diff --git a/components/HeaderStackView/README.md b/components/HeaderStackView/README.md
index 86df1a3..de7dfce 100644
--- a/components/HeaderStackView/README.md
+++ b/components/HeaderStackView/README.md
@@ -1,22 +1,17 @@
 <!--docs:
-title: "Header Stack View"
+title: "Header Stack Views"
 layout: detail
 section: components
 excerpt: "The Header Stack View component is a view that coordinates the layout of two vertically stacked bar views."
 iconId: header
+path: /catalog/header-stack-views/
 -->
 
-# Header Stack View
+# Header Stack Views
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
   <img src="docs/assets/header_stack_view.png" alt="Header Stack View" width="320">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/header_stack_view.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Header Stack View component is a view that coordinates the layout of two vertically stacked
 bar views.
@@ -25,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/layout/structure.html#structure-app-bar">App Bar</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/layout/structure.html#structure-app-bar">App Bar</a></li>
 </ul>
 
 - - -
diff --git a/components/HeaderStackView/docs/assets/header_stack_view.mp4 b/components/HeaderStackView/docs/assets/header_stack_view.mp4
deleted file mode 100644
index 9ee07e2..0000000
--- a/components/HeaderStackView/docs/assets/header_stack_view.mp4
+++ /dev/null
Binary files differ
diff --git a/components/HeaderStackView/docs/assets/header_stack_view.png b/components/HeaderStackView/docs/assets/header_stack_view.png
index 5f45069..34132df 100644
--- a/components/HeaderStackView/docs/assets/header_stack_view.png
+++ b/components/HeaderStackView/docs/assets/header_stack_view.png
Binary files differ
diff --git a/components/HeaderStackView/examples/resources/header_stack_view_theme.png b/components/HeaderStackView/examples/resources/header_stack_view_theme.png
index 2aa056b..682c702 100644
--- a/components/HeaderStackView/examples/resources/header_stack_view_theme.png
+++ b/components/HeaderStackView/examples/resources/header_stack_view_theme.png
Binary files differ
diff --git a/components/HeaderStackView/examples/supplemental/HeaderStackViewTypicalUseSupplemental.m b/components/HeaderStackView/examples/supplemental/HeaderStackViewTypicalUseSupplemental.m
index 1b4b426..ab5d0d2 100644
--- a/components/HeaderStackView/examples/supplemental/HeaderStackViewTypicalUseSupplemental.m
+++ b/components/HeaderStackView/examples/supplemental/HeaderStackViewTypicalUseSupplemental.m
@@ -53,14 +53,12 @@
   [self.topView addSubview:imageView];
 
   self.navBar = [[MDCNavigationBar alloc] initWithFrame:CGRectZero];
-  self.navBar.tintColor = [UIColor whiteColor];
-  self.navBar.title = @"Header Stack View";
+  self.navBar.titleTextAttributes = [self itemTitleTextAttributes];
 
-  // Light blue 500
-  [self.navBar setBackgroundColor:[UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1]];
+  [self.navBar setBackgroundColor:[UIColor colorWithWhite:0.1 alpha:1.0]];
 
   UIBarButtonItem *moreButton =
-      [[UIBarButtonItem alloc] initWithTitle:@"More"
+      [[UIBarButtonItem alloc] initWithTitle:@"Reveal"
                                        style:UIBarButtonItemStylePlain
                                       target:self
                                       action:@selector(didTapToggleButton:)];
diff --git a/components/Ink/README.md b/components/Ink/README.md
index f347b13..85ba768 100644
--- a/components/Ink/README.md
+++ b/components/Ink/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "The Ink component provides a radial action in the form of a visual ripple of ink expanding outward from the user's touch."
 iconId: ripple
+path: /catalog/ink/
 -->
 
 # Ink
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/ink.png" alt="Ink" width="320">
+  <img src="docs/assets/ink.png" alt="Ink" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/ink.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Ink component provides a radial action in the form of a visual ripple of ink expanding
 outward from the user's touch.
@@ -25,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-radial-action">Radial Action</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/animation/responsive-interaction.html#responsive-interaction-radial-action">Radial Action</a></li>
 </ul>
 
 - - -
diff --git a/components/Ink/docs/assets/ink.mp4 b/components/Ink/docs/assets/ink.mp4
deleted file mode 100644
index 568b6cb..0000000
--- a/components/Ink/docs/assets/ink.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Ink/docs/assets/ink.png b/components/Ink/docs/assets/ink.png
index 23d2da2..9cc8d75 100644
--- a/components/Ink/docs/assets/ink.png
+++ b/components/Ink/docs/assets/ink.png
Binary files differ
diff --git a/components/Ink/examples/InkTypicalUse.m b/components/Ink/examples/InkTypicalUse.m
index edf6cc9..cf72938 100644
--- a/components/Ink/examples/InkTypicalUse.m
+++ b/components/Ink/examples/InkTypicalUse.m
@@ -57,7 +57,7 @@
   inkTouchController.delegate = self;
   [inkTouchController addInkView];
 
-  UIColor *blueColor = [UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:0.2];
+  UIColor *blueColor = [UIColor colorWithRed:11/255.0 green:232/255.0 blue:94/255.0 alpha:0.2];
   inkTouchController.defaultInkView.inkColor = blueColor;
   inkTouchController.defaultInkView.inkStyle = MDCInkStyleUnbounded;
   [_inkTouchControllers addObject:inkTouchController];
diff --git a/components/NavigationBar/README.md b/components/NavigationBar/README.md
index de806cc..4be12ce 100644
--- a/components/NavigationBar/README.md
+++ b/components/NavigationBar/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "The Navigation Bar component is a view composed of a left and right Button Bar and either a title label or a custom title view."
 iconId: toolbar
+path: /catalog/navigation-bars/
 -->
 
 # Navigation Bar
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
   <img src="docs/assets/navigation_bar.png" alt="Navigation Bar" width="320">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/navigation_bar.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Navigation Bar component is a view composed of a left and right Button Bar and either a title
 label or a custom title view.
@@ -28,7 +23,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="http://www.google.com/design/spec/layout/structure.html">Layout Structure</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/layout/structure.html">Layout Structure</a></li>
 </ul>
 
 - - -
diff --git a/components/NavigationBar/docs/assets/navigation_bar.mp4 b/components/NavigationBar/docs/assets/navigation_bar.mp4
deleted file mode 100644
index a7839e0..0000000
--- a/components/NavigationBar/docs/assets/navigation_bar.mp4
+++ /dev/null
Binary files differ
diff --git a/components/NavigationBar/docs/assets/navigation_bar.png b/components/NavigationBar/docs/assets/navigation_bar.png
index 09f416c..01cfcd3 100644
--- a/components/NavigationBar/docs/assets/navigation_bar.png
+++ b/components/NavigationBar/docs/assets/navigation_bar.png
Binary files differ
diff --git a/components/NavigationBar/examples/NavigationBarTypicalUseExample.m b/components/NavigationBar/examples/NavigationBarTypicalUseExample.m
index 8cb7291..c7edca9 100644
--- a/components/NavigationBar/examples/NavigationBarTypicalUseExample.m
+++ b/components/NavigationBar/examples/NavigationBarTypicalUseExample.m
@@ -33,10 +33,9 @@
   self.title = @"Navigation Bar";
 
   self.navBar = [[MDCNavigationBar alloc] initWithFrame:CGRectZero];
+  self.navBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor whiteColor]};
   [self.navBar observeNavigationItem:self.navigationItem];
-
-  // Light blue 500
-  [self.navBar setBackgroundColor:[UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1]];
+  [self.navBar setBackgroundColor:[UIColor colorWithWhite:0.1 alpha:1.0]];
   MDCNavigationBarTextColorAccessibilityMutator *mutator =
       [[MDCNavigationBarTextColorAccessibilityMutator alloc] init];
   [mutator mutate:self.navBar];
diff --git a/components/NavigationBar/examples/NavigationBarTypicalUseExample.swift b/components/NavigationBar/examples/NavigationBarTypicalUseExample.swift
index a5897e9..84489bb 100644
--- a/components/NavigationBar/examples/NavigationBarTypicalUseExample.swift
+++ b/components/NavigationBar/examples/NavigationBarTypicalUseExample.swift
@@ -29,8 +29,7 @@
     navBar = MDCNavigationBar()
     navBar!.observe(navigationItem)
 
-    // Light blue 500
-    navBar!.backgroundColor = UIColor.init(red: 0.012, green: 0.663, blue: 0.957, alpha: 1)
+    navBar!.backgroundColor = UIColor(white: 0.1, alpha: 1.0);
     let mutator = MDCNavigationBarTextColorAccessibilityMutator()
     mutator.mutate(navBar!)
 
diff --git a/components/NavigationBar/examples/NavigationBarWithBarItemsExample.m b/components/NavigationBar/examples/NavigationBarWithBarItemsExample.m
index 4dc86a5..d7535f7 100644
--- a/components/NavigationBar/examples/NavigationBarWithBarItemsExample.m
+++ b/components/NavigationBar/examples/NavigationBarWithBarItemsExample.m
@@ -45,8 +45,7 @@
   self.navBar = [[MDCNavigationBar alloc] initWithFrame:CGRectZero];
   [self.navBar observeNavigationItem:self.navigationItem];
 
-  // Light blue 500
-  [self.navBar setBackgroundColor:[UIColor colorWithRed:0.012 green:0.663 blue:0.957 alpha:1]];
+  [self.navBar setBackgroundColor:[UIColor colorWithWhite:0.1 alpha:1.0]];
   MDCNavigationBarTextColorAccessibilityMutator *mutator =
       [[MDCNavigationBarTextColorAccessibilityMutator alloc] init];
   [mutator mutate:self.navBar];
diff --git a/components/OverlayWindow/README.md b/components/OverlayWindow/README.md
index 2ece757..b6d2ebc 100644
--- a/components/OverlayWindow/README.md
+++ b/components/OverlayWindow/README.md
@@ -4,6 +4,7 @@
 section: components
 excerpt: "A window for managing sets of overlay views."
 iconId: tooltip
+path: /catalog/overlay-windows/
 -->
 
 # Overlay Window
diff --git a/components/PageControl/README.md b/components/PageControl/README.md
index e40c4ee..acc0239 100644
--- a/components/PageControl/README.md
+++ b/components/PageControl/README.md
@@ -3,19 +3,14 @@
 layout: detail
 section: components
 excerpt: "Page Control is a drop-in Material Design replacement for UIPageControl that implements Material Design animation and layout."
+path: /catalog/page-controls/
 -->
 
 # Page Control
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/page_control.png" alt="Page Control" width="320">
+  <img src="docs/assets/page_control.png" alt="Page Control" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/page_control.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 This control is designed to be a drop-in replacement for `UIPageControl`, with a user experience
 influenced by Material Design specifications for animation and layout. The API methods are the
diff --git a/components/PageControl/docs/assets/MDCPageControl_screenshot-1.png b/components/PageControl/docs/assets/MDCPageControl_screenshot-1.png
index ce9e1ba..6a66d4e 100644
--- a/components/PageControl/docs/assets/MDCPageControl_screenshot-1.png
+++ b/components/PageControl/docs/assets/MDCPageControl_screenshot-1.png
Binary files differ
diff --git a/components/PageControl/docs/assets/MDCPageControl_screenshot-2.png b/components/PageControl/docs/assets/MDCPageControl_screenshot-2.png
index 29bbeff..98859ea 100644
--- a/components/PageControl/docs/assets/MDCPageControl_screenshot-2.png
+++ b/components/PageControl/docs/assets/MDCPageControl_screenshot-2.png
Binary files differ
diff --git a/components/PageControl/docs/assets/MDCPageControl_screenshot-3.png b/components/PageControl/docs/assets/MDCPageControl_screenshot-3.png
index 9a6fc3b..84ae4d4 100644
--- a/components/PageControl/docs/assets/MDCPageControl_screenshot-3.png
+++ b/components/PageControl/docs/assets/MDCPageControl_screenshot-3.png
Binary files differ
diff --git a/components/PageControl/docs/assets/page_control.mp4 b/components/PageControl/docs/assets/page_control.mp4
deleted file mode 100644
index 98eeaaa..0000000
--- a/components/PageControl/docs/assets/page_control.mp4
+++ /dev/null
Binary files differ
diff --git a/components/PageControl/docs/assets/page_control.png b/components/PageControl/docs/assets/page_control.png
index 804874f..7a0a870 100644
--- a/components/PageControl/docs/assets/page_control.png
+++ b/components/PageControl/docs/assets/page_control.png
Binary files differ
diff --git a/components/PageControl/examples/PageControlAnimationBlockExample.m b/components/PageControl/examples/PageControlAnimationBlockExample.m
index 705e10c..43d1674 100644
--- a/components/PageControl/examples/PageControlAnimationBlockExample.m
+++ b/components/PageControl/examples/PageControlAnimationBlockExample.m
@@ -21,10 +21,6 @@
 @interface PageControlAnimationBlockExample : UIViewController <UIScrollViewDelegate>
 @end
 
-#define RGBCOLOR(r, g, b) \
-  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
-#define HEXCOLOR(hex) RGBCOLOR((((hex) >> 16) & 0xFF), (((hex) >> 8) & 0xFF), ((hex)&0xFF))
-
 @implementation PageControlAnimationBlockExample {
   UIScrollView *_scrollView;
   MDCPageControl *_pageControl;
@@ -44,8 +40,11 @@
   CGFloat boundsHeight = CGRectGetHeight(self.view.bounds);
 
   NSArray *pageColors = @[
-    HEXCOLOR(0x55C4f5), HEXCOLOR(0x35B7F3), HEXCOLOR(0x1EAAF1), HEXCOLOR(0x35B7F3),
-    HEXCOLOR(0x1EAAF1)
+    [UIColor colorWithWhite:0.2 alpha:1.0],
+    [UIColor colorWithWhite:0.3 alpha:1.0],
+    [UIColor colorWithWhite:0.4 alpha:1.0],
+    [UIColor colorWithWhite:0.5 alpha:1.0],
+    [UIColor colorWithWhite:0.6 alpha:1.0],
   ];
 
   // Scroll view configuration
@@ -64,8 +63,8 @@
     CGRect pageFrame = CGRectOffset(self.view.bounds, i * boundsWidth, 0);
     UILabel *page = [[UILabel alloc] initWithFrame:pageFrame];
     page.text = [NSString stringWithFormat:@"Page %zd", i + 1];
-    page.font = [UIFont systemFontOfSize:50];
-    page.textColor = [UIColor colorWithWhite:0 alpha:0.8];
+    page.font = [UIFont systemFontOfSize:24];
+    page.textColor = [UIColor colorWithWhite:1 alpha:0.8];
     page.textAlignment = NSTextAlignmentCenter;
     page.backgroundColor = pageColors[i];
     page.autoresizingMask =
@@ -168,7 +167,7 @@
       MIN(MAX(0, _pageControl.currentPage + incrementAmount), _pageControl.numberOfPages - 1);
   CGPoint offset = _scrollView.contentOffset;
   offset.x = nextPage * CGRectGetWidth(_scrollView.frame);
-  [UIView animateWithDuration:2
+  [UIView animateWithDuration:0.2
                         delay:0
                       options:UIViewAnimationOptionCurveEaseOut
                    animations:^{
diff --git a/components/PageControl/examples/PageControlButtonExample.m b/components/PageControl/examples/PageControlButtonExample.m
index 22d97f0..e3b1e29 100644
--- a/components/PageControl/examples/PageControlButtonExample.m
+++ b/components/PageControl/examples/PageControlButtonExample.m
@@ -21,10 +21,6 @@
 @interface PageControlButtonExample : UIViewController <UIScrollViewDelegate>
 @end
 
-#define RGBCOLOR(r, g, b) \
-  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
-#define HEXCOLOR(hex) RGBCOLOR((((hex) >> 16) & 0xFF), (((hex) >> 8) & 0xFF), ((hex)&0xFF))
-
 @implementation PageControlButtonExample {
   UIScrollView *_scrollView;
   MDCPageControl *_pageControl;
@@ -42,9 +38,11 @@
   CGFloat boundsHeight = CGRectGetHeight(self.view.bounds);
 
   NSArray *pageColors = @[
-    HEXCOLOR(0x55C4f5), HEXCOLOR(0x35B7F3), HEXCOLOR(0x1EAAF1), HEXCOLOR(0x35B7F3),
-    HEXCOLOR(0x1EAAF1)
-  ];
+      [UIColor colorWithWhite:0.9 alpha:1.0],
+      [UIColor colorWithWhite:0.8 alpha:1.0],
+      [UIColor colorWithWhite:0.7 alpha:1.0],
+      [UIColor colorWithWhite:0.6 alpha:1.0],
+      [UIColor colorWithWhite:0.5 alpha:1.0]  ];
 
   // Scroll view configuration
   _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
diff --git a/components/PageControl/examples/PageControlTypicalUseExample.m b/components/PageControl/examples/PageControlTypicalUseExample.m
index 33e5e11..a3cc53f 100644
--- a/components/PageControl/examples/PageControlTypicalUseExample.m
+++ b/components/PageControl/examples/PageControlTypicalUseExample.m
@@ -21,10 +21,6 @@
 @interface PageControlTypicalUseViewController : UIViewController <UIScrollViewDelegate>
 @end
 
-#define RGBCOLOR(r, g, b) \
-  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
-#define HEXCOLOR(hex) RGBCOLOR((((hex) >> 16) & 0xFF), (((hex) >> 8) & 0xFF), ((hex)&0xFF))
-
 @implementation PageControlTypicalUseViewController {
   UIScrollView *_scrollView;
   MDCPageControl *_pageControl;
@@ -50,7 +46,11 @@
   CGFloat boundsWidth = CGRectGetWidth(self.view.bounds);
   CGFloat boundsHeight = CGRectGetHeight(self.view.bounds);
 
-  NSArray *pageColors = @[ HEXCOLOR(0x55C4f5), HEXCOLOR(0x35B7F3), HEXCOLOR(0x1EAAF1) ];
+  NSArray *pageColors = @[
+      [UIColor colorWithWhite:0.9 alpha:1.0],
+      [UIColor colorWithWhite:0.8 alpha:1.0],
+      [UIColor colorWithWhite:0.7 alpha:1.0],
+  ];
 
   // Scroll view configuration
   _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
diff --git a/components/Palettes/README.md b/components/Palettes/README.md
index 4b32a81..466d02b 100644
--- a/components/Palettes/README.md
+++ b/components/Palettes/README.md
@@ -4,17 +4,22 @@
 section: components
 excerpt: "The Palettes component provides Material color palettes."
 iconId: color
+path: /catalog/palette/
 -->
 
 # Palettes
 
+<div class="article__asset article__asset--screenshot">
+  <img src="docs/assets/palettes.png" alt="Palettes" width="375">
+</div>
+
 The Palettes component provides Material colors organized into similar palettes.
 <!--{: .article__intro }-->
 
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="http://www.google.com/design/spec/style/color.html#color-color-palette">Color palettes</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/style/color.html#color-color-palette">Color palettes</a></li>
 </ul>
 
 - - -
diff --git a/components/Palettes/docs/assets/palettes.png b/components/Palettes/docs/assets/palettes.png
new file mode 100644
index 0000000..927dc7c
--- /dev/null
+++ b/components/Palettes/docs/assets/palettes.png
Binary files differ
diff --git a/components/Palettes/src/MDCPalettes.h b/components/Palettes/src/MDCPalettes.h
index 78507dc..39d5350 100644
--- a/components/Palettes/src/MDCPalettes.h
+++ b/components/Palettes/src/MDCPalettes.h
@@ -65,7 +65,7 @@
  class provides access to the pre-defined set of Material palettes. MDCPalette objects are
  immutable; it is safe to use them from multiple threads in your app.
 
- @see https://www.google.com/design/spec/style/color.html#color-color-palette
+ @see https://material.io/guidelines/style/color.html#color-color-palette
  */
 @interface MDCPalette : NSObject
 
diff --git a/components/ProgressView/README.md b/components/ProgressView/README.md
index 177dcfd..8589d00 100644
--- a/components/ProgressView/README.md
+++ b/components/ProgressView/README.md
@@ -3,23 +3,18 @@
 layout: detail
 section: components
 excerpt: "Progress View is a determinate and linear progress indicator that implements Material Design animation and layout."
-iconId: progress_activity
+iconId: progress_linear
+path: /catalog/progress-views/
 -->
 
 # Progress View
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/progress_view.png" alt="Progress View" width="320">
+  <img src="docs/assets/progress_view.png" alt="Progress View" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/progress_view.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 This control is designed to be a drop-in replacement for `UIProgressView`, with a user experience
-influenced by [Material Design specifications](https://material.google.com/components/progress-activity.html#)
+influenced by [Material Design specifications](https://material.io/guidelines/components/progress-activity.html#)
 for animation and layout. The API methods are the same as a `UIProgressView`, with the addition of a
 few key methods required to achieve the desired animation of the control.
 <!--{: .article__intro }-->
@@ -27,7 +22,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://material.google.com/components/progress-activity.html">Progress & activity</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/progress-activity.html">Progress & activity</a></li>
 </ul>
 
 - - -
diff --git a/components/ProgressView/docs/assets/progress_view.mp4 b/components/ProgressView/docs/assets/progress_view.mp4
deleted file mode 100644
index 864fbb8..0000000
--- a/components/ProgressView/docs/assets/progress_view.mp4
+++ /dev/null
Binary files differ
diff --git a/components/ProgressView/docs/assets/progress_view.png b/components/ProgressView/docs/assets/progress_view.png
index a247b5b..db72ff9 100644
--- a/components/ProgressView/docs/assets/progress_view.png
+++ b/components/ProgressView/docs/assets/progress_view.png
Binary files differ
diff --git a/components/ProgressView/src/MDCProgressView.h b/components/ProgressView/src/MDCProgressView.h
index 3c01c65..9872a4a 100644
--- a/components/ProgressView/src/MDCProgressView.h
+++ b/components/ProgressView/src/MDCProgressView.h
@@ -29,7 +29,7 @@
 /**
  A Material linear determinate progress view.
 
- See https://www.google.com/design/spec/components/progress-activity.html
+ See https://material.io/guidelines/components/progress-activity.html
  */
 IB_DESIGNABLE
 @interface MDCProgressView : UIView
diff --git a/components/ProgressView/src/MDCProgressView.m b/components/ProgressView/src/MDCProgressView.m
index ade025d..127dd4f 100644
--- a/components/ProgressView/src/MDCProgressView.m
+++ b/components/ProgressView/src/MDCProgressView.m
@@ -21,7 +21,7 @@
 #import "MaterialMath.h"
 #import "MaterialRTL.h"
 
-// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
 static const uint32_t MDCProgressViewDefaultTintColor = 0x2196F3;
 
 // The ratio by which to desaturate the progress tint color to obtain the default track tint color.
diff --git a/components/README.md b/components/README.md
index 5844fe7..0d14c84 100644
--- a/components/README.md
+++ b/components/README.md
@@ -1,9 +1,3 @@
-<!--docs:
-title: "Material Components Documentation"
-layout: landing-no-drawer
-section: components
--->
-
 # Component Documentation
 
 Material Components for iOS (MDC-iOS) help developers execute [Material Design](https://www.material.io). Developed by a core team of engineers and UX designers at Google, these components enable a reliable development workflow to build beautiful and functional iOS apps.
@@ -148,4 +142,4 @@
 - [Contributing](../contributing/)
 - [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
 - [Material.io](https://www.material.io) (external site)
-- [Material Design Guidelines](https://material.google.com) (external site)
+- [Material Design Guidelines](https://material.io/guidelines) (external site)
diff --git a/components/ShadowElevations/README.md b/components/ShadowElevations/README.md
index 0cb1b6e..45c1dd0 100644
--- a/components/ShadowElevations/README.md
+++ b/components/ShadowElevations/README.md
@@ -3,10 +3,16 @@
 layout: detail
 section: components
 excerpt: "The Shadow Elevations component provides the most commonly-used Material Design elevations."
+iconId: shadow
+path: /catalog/shadow-elevations/
 -->
 
 # Shadow Elevations
 
+<div class="article__asset article__asset--screenshot">
+  <img src="docs/assets/shadows.png" alt="Shadows" width="375">
+</div>
+
 A shadow elevation specifies the degree of shadow intensity to be displayed beneath an object.
 Higher shadow elevations have greater shadow intensities, akin to raising an object above a
 surface resulting in a more prominent, albeit more diffuse, shadow. This component provides commonly
@@ -16,7 +22,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/what-is-material/elevation-shadows.html">Elevation and Shadows</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/what-is-material/elevation-shadows.html">Elevation and Shadows</a></li>
 </ul>
 
 - - -
diff --git a/components/ShadowElevations/docs/assets/shadows.png b/components/ShadowElevations/docs/assets/shadows.png
new file mode 100644
index 0000000..fad8ce1
--- /dev/null
+++ b/components/ShadowElevations/docs/assets/shadows.png
Binary files differ
diff --git a/components/ShadowLayer/README.md b/components/ShadowLayer/README.md
index e24b6ae..377f25c 100644
--- a/components/ShadowLayer/README.md
+++ b/components/ShadowLayer/README.md
@@ -3,19 +3,15 @@
 layout: detail
 section: components
 excerpt: "The Shadow Layer component implements the Material Design specifications for elevation and shadows."
+iconId: shadow
+path: /catalog/shadow-layers/
 -->
 
 # Shadow Layer
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/shadow_layer.png" width="320">
+  <img src="docs/assets/shadow_layer.png" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/shadow_layer.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 Shadow Layer implements the Material Design specifications for elevation and shadows.
 By simulating the physical properties of paper, elevation and light source, shadows give
@@ -27,7 +23,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/what-is-material/elevation-shadows.html">Elevation and Shadows</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/what-is-material/elevation-shadows.html">Elevation and Shadows</a></li>
 </ul>
 
 ### MDCShadowLayer
diff --git a/components/ShadowLayer/docs/assets/shadow_layer.mp4 b/components/ShadowLayer/docs/assets/shadow_layer.mp4
deleted file mode 100644
index aca459b..0000000
--- a/components/ShadowLayer/docs/assets/shadow_layer.mp4
+++ /dev/null
Binary files differ
diff --git a/components/ShadowLayer/docs/assets/shadow_layer.png b/components/ShadowLayer/docs/assets/shadow_layer.png
index 11cfc69..e9d011d 100644
--- a/components/ShadowLayer/docs/assets/shadow_layer.png
+++ b/components/ShadowLayer/docs/assets/shadow_layer.png
Binary files differ
diff --git a/components/ShadowLayer/src/MDCShadowLayer.h b/components/ShadowLayer/src/MDCShadowLayer.h
index 7fe6b46..1ed3d0a 100644
--- a/components/ShadowLayer/src/MDCShadowLayer.h
+++ b/components/ShadowLayer/src/MDCShadowLayer.h
@@ -43,7 +43,7 @@
  The Material shadow effect.
 
  @see
- https://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-shadows
+ https://material.io/guidelines/what-is-material/elevation-shadows.html#elevation-shadows-shadows
 
  Consider rasterizing your MDCShadowLayer if your view will not generally be animating or
  changing size. If you need to animate a rasterized MDCShadowLayer, disable rasterization first.
diff --git a/components/Slider/README.md b/components/Slider/README.md
index e6e4775..7d00ca8 100644
--- a/components/Slider/README.md
+++ b/components/Slider/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "The Slider component provides a Material Design control for selecting a value from a continuous range or discrete set of values."
 iconId: slider
+path: /catalog/sliders/
 -->
 
 # Slider
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/slider.png" alt="Slider" width="320">
+  <img src="docs/assets/slider.png" alt="Slider" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/slider.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The `MDCSlider` object is a Material Design control used to select a value from a continuous range
 or discrete set of values.
@@ -25,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/components/sliders.html">Sliders</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/sliders.html">Sliders</a></li>
 </ul>
 
 - - -
diff --git a/components/Slider/docs/assets/slider.mp4 b/components/Slider/docs/assets/slider.mp4
deleted file mode 100644
index fa22b6c..0000000
--- a/components/Slider/docs/assets/slider.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Slider/docs/assets/slider.png b/components/Slider/docs/assets/slider.png
index 339481a..aa36111 100644
--- a/components/Slider/docs/assets/slider.png
+++ b/components/Slider/docs/assets/slider.png
Binary files differ
diff --git a/components/Slider/examples/SliderCollectionViewController.m b/components/Slider/examples/SliderCollectionViewController.m
index 7cde136..bf26b74 100644
--- a/components/Slider/examples/SliderCollectionViewController.m
+++ b/components/Slider/examples/SliderCollectionViewController.m
@@ -23,7 +23,7 @@
 static CGFloat const kSliderHorizontalMargin = 16.f;
 static CGFloat const kSliderVerticalMargin = 12.f;
 
-// From http://www.google.com/design/spec/style/color.html#color-color-palette .
+// From https://material.io/guidelines/style/color.html#color-color-palette .
 static const uint32_t MDCGreenColor = 0x4CAF50;
 static const uint32_t MDCDeepOrangeColor = 0xFF5722;
 static const uint32_t MDCPurpleColor = 0x9C27B0;
diff --git a/components/Slider/src/MDCSlider.h b/components/Slider/src/MDCSlider.h
index 018e462..22e92d3 100644
--- a/components/Slider/src/MDCSlider.h
+++ b/components/Slider/src/MDCSlider.h
@@ -21,7 +21,7 @@
 /**
  A Material slider.
 
- @see https://www.google.com/design/spec/components/sliders.html for full details.
+ @see https://material.io/guidelines/components/sliders.html for full details.
 
  Differences between UISlider and MDCSlider:
    Does not have api to
diff --git a/components/Slider/src/MDCSlider.m b/components/Slider/src/MDCSlider.m
index ee831e1..14ff47a 100644
--- a/components/Slider/src/MDCSlider.m
+++ b/components/Slider/src/MDCSlider.m
@@ -26,7 +26,7 @@
 static const CGFloat kSliderAccessibilityIncrement = 0.1f;  // Matches UISlider's percent increment.
 static const CGFloat kSliderLightThemeTrackAlpha = 0.26f;
 
-// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
 static const uint32_t MDCBlueColor = 0x2196F3;
 
 // Creates a UIColor from a 24-bit RGB color encoded as an integer.
diff --git a/components/Slider/tests/unit/SliderTests.m b/components/Slider/tests/unit/SliderTests.m
index d51ccac..55be692 100644
--- a/components/Slider/tests/unit/SliderTests.m
+++ b/components/Slider/tests/unit/SliderTests.m
@@ -22,7 +22,7 @@
 static const NSUInteger kNumberOfRepeats = 20;
 static const CGFloat kEpsilonAccuracy = 0.001f;
 
-// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+// Blue 500 from https://material.io/guidelines/style/color.html#color-color-palette .
 static const uint32_t MDCBlueColor = 0x2196F3;
 
 // Creates a UIColor from a 24-bit RGB color encoded as an integer.
diff --git a/components/Snackbar/README.md b/components/Snackbar/README.md
index 78b4981..37e5c59 100644
--- a/components/Snackbar/README.md
+++ b/components/Snackbar/README.md
@@ -4,19 +4,14 @@
 section: components
 excerpt: "Snackbars provide brief feedback about an operation through a message at the bottom of the screen."
 iconId: toast
+path: /catalog/snackbars/
 -->
 
 # Snackbar
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/snackbar.png" alt="Snackbar" width="320">
+  <img src="docs/assets/snackbar.png" alt="Snackbar" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/snackbar.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 Snackbars provide brief feedback about an operation through a message at the bottom of the screen.
 Snackbars contain up to two lines of text directly related to the operation performed. They may
@@ -26,7 +21,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://material.google.com/components/snackbars-toasts.html">Snackbars</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/snackbars-toasts.html">Snackbars</a></li>
 </ul>
 
 - - -
diff --git a/components/Snackbar/docs/assets/snackbar.mp4 b/components/Snackbar/docs/assets/snackbar.mp4
deleted file mode 100644
index 2266390..0000000
--- a/components/Snackbar/docs/assets/snackbar.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Snackbar/docs/assets/snackbar.png b/components/Snackbar/docs/assets/snackbar.png
index 68fc311..8e27eea 100644
--- a/components/Snackbar/docs/assets/snackbar.png
+++ b/components/Snackbar/docs/assets/snackbar.png
Binary files differ
diff --git a/components/Snackbar/examples/SnackbarActionExample.m b/components/Snackbar/examples/SnackbarActionExample.m
deleted file mode 100644
index 1010293..0000000
--- a/components/Snackbar/examples/SnackbarActionExample.m
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#import <UIKit/UIKit.h>
-
-#import "MaterialSnackbar.h"
-#import "SnackbarExampleSupplemental.h"
-
-@implementation SnackbarActionExample
-
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  [self setupExampleViews];
-  self.title = @"Snackbar Multi-line Action Message";
-}
-
-#pragma mark - Event Handling
-
-- (void)handleShowSnackbarButtonTapped:(id)sender {
-  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
-  message.text = @"A red flair silhouetted the jagged edge of a sublime wing.";
-  MDCSnackbarMessageAction *action = [[MDCSnackbarMessageAction alloc] init];
-  void (^actionHandler)() = ^() {
-    MDCSnackbarMessage *answerMessage = [[MDCSnackbarMessage alloc] init];
-    answerMessage.text = @"The sky was cloudless and of a deep dark blue.";
-    [MDCSnackbarManager showMessage:answerMessage];
-  };
-  action.handler = actionHandler;
-  action.title = @"Action";
-  message.action = action;
-
-  [MDCSnackbarManager showMessage:message];
-}
-
-@end
diff --git a/components/Snackbar/examples/SnackbarBoldExample.m b/components/Snackbar/examples/SnackbarBoldExample.m
deleted file mode 100644
index 3f9a53c..0000000
--- a/components/Snackbar/examples/SnackbarBoldExample.m
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- */
-
-#import <UIKit/UIKit.h>
-
-#import "MaterialSnackbar.h"
-#import "SnackbarExampleSupplemental.h"
-
-@implementation SnackbarBoldExample
-
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  [self setupExampleViews];
-  self.title = @"Snackbar Bold Message";
-}
-
-#pragma mark - Event Handling
-
-- (void)handleShowSnackbarButtonTapped:(id)sender {
-  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
-  NSMutableAttributedString *text = [[NSMutableAttributedString alloc] init];
-  [text appendAttributedString:[[NSAttributedString alloc]
-                                   initWithString:@"Boldly"
-                                       attributes:@{
-                                         MDCSnackbarMessageBoldAttributeName : @YES
-                                       }]];
-  [text appendAttributedString:[[NSAttributedString alloc]
-                                   initWithString:@" go where no one has gone before."]];
-  message.attributedText = text;
-
-  [MDCSnackbarManager showMessage:message];
-}
-
-@end
diff --git a/components/Snackbar/examples/SnackbarOverlayViewExample.m b/components/Snackbar/examples/SnackbarOverlayViewExample.m
index f5e1c45..52e3e5e 100644
--- a/components/Snackbar/examples/SnackbarOverlayViewExample.m
+++ b/components/Snackbar/examples/SnackbarOverlayViewExample.m
@@ -27,7 +27,7 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
-  [self setupExampleViews];
+  [self setupExampleViews:@[@"Show Snackbar"]];
   self.title = @"Snackbar Overlay View";
 
   // Make sure we're listening for overlay notifications.
@@ -43,6 +43,11 @@
   fabFrame.origin.x = CGRectGetMaxX(self.view.bounds) - CGRectGetWidth(fabFrame) - kFABSideOffset;
   fabFrame.origin.y =
       CGRectGetMaxY(self.view.bounds) - CGRectGetHeight(fabFrame) - kFABBottomOffset;
+  [self.floatingButton setBackgroundColor:[UIColor colorWithRed:11/255.0f
+                                                          green:232/255.0f
+                                                           blue:94/255.0f
+                                                          alpha:1]
+                                 forState:UIControlStateNormal];
   self.floatingButton.frame = fabFrame;
   self.floatingButton.autoresizingMask =
       (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin);
@@ -50,11 +55,13 @@
 
 #pragma mark - Event Handling
 
-- (void)handleShowSnackbarButtonTapped:(id)sender {
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
   NSString *text = @"Snackbar Message";
   MDCSnackbarMessage *message = [MDCSnackbarMessage messageWithText:text];
   message.duration = 5.0f;
   [MDCSnackbarManager showMessage:message];
+  return;
 }
 
 #pragma mark - Overlay Transitions
diff --git a/components/Snackbar/examples/SnackbarSimpleExample.m b/components/Snackbar/examples/SnackbarSimpleExample.m
index 4d49aa9..c69488d 100644
--- a/components/Snackbar/examples/SnackbarSimpleExample.m
+++ b/components/Snackbar/examples/SnackbarSimpleExample.m
@@ -23,16 +23,91 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
-  [self setupExampleViews];
+  [self setupExampleViews:@[
+      @"Simple Snackbar",
+      @"Snackbar with Action Button",
+      @"Snackbar with Long Text",
+      @"Attributed Text Example"
+  ]];
   self.title = @"Snackbar";
 }
 
 #pragma mark - Event Handling
 
-- (void)handleShowSnackbarButtonTapped:(id)sender {
+- (void)showSimpleSnackbar:(id)sender {
   MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
   message.text = @"Snackbar Message";
   [MDCSnackbarManager showMessage:message];
 }
 
+- (void)showSnackbarWithAction:(id)sender {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  message.text = @"Snackbar Message";
+  [MDCSnackbarManager showMessage:message];
+  MDCSnackbarMessageAction *action = [[MDCSnackbarMessageAction alloc] init];
+  action.title = @"Tap Me";
+  message.action = action;
+  message.buttonTextColor =
+      [UIColor colorWithRed:11/255.0f green:232/255.0f blue:94/255.0f alpha:1];
+  [MDCSnackbarManager showMessage:message];
+}
+
+
+- (void)showLongSnackbarMessage:(id)sender {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  message.text = @"A red flair silhouetted the jagged edge of a sublime wing.";
+  MDCSnackbarMessageAction *action = [[MDCSnackbarMessageAction alloc] init];
+  void (^actionHandler)() = ^() {
+    MDCSnackbarMessage *answerMessage = [[MDCSnackbarMessage alloc] init];
+    answerMessage.text = @"The sky was cloudless and of a deep dark blue.";
+    [MDCSnackbarManager showMessage:answerMessage];
+  };
+  action.handler = actionHandler;
+  action.title = @"Action";
+  message.action = action;
+  message.buttonTextColor =
+      [UIColor colorWithRed:11/255.0f green:232/255.0f blue:94/255.0f alpha:1];
+
+  [MDCSnackbarManager showMessage:message];
+}
+
+
+- (void)showBoldSnackbar:(id)sender {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  NSMutableAttributedString *text = [[NSMutableAttributedString alloc] init];
+  [text appendAttributedString:[[NSAttributedString alloc]
+                                initWithString:@"Boldly"
+                                attributes:@{
+                                             MDCSnackbarMessageBoldAttributeName : @YES
+                                             }]];
+  [text appendAttributedString:[[NSAttributedString alloc]
+                                initWithString:@" go where no one has gone before."]];
+  message.attributedText = text;
+  
+  [MDCSnackbarManager showMessage:message];
+}
+
+
+
+#pragma mark - UICollectionView
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+  switch (indexPath.row) {
+    case 0:
+      [self showSimpleSnackbar:nil];
+      break;
+    case 1:
+      [self showSnackbarWithAction:nil];
+      break;
+    case 2:
+      [self showLongSnackbarMessage:nil];
+      break;
+    case 3:
+      [self showBoldSnackbar:nil];
+    default:
+      break;
+  }
+}
+
 @end
diff --git a/components/Snackbar/examples/SnackbarSuspensionExample.m b/components/Snackbar/examples/SnackbarSuspensionExample.m
index ebc0ebc..8dfa9ef 100644
--- a/components/Snackbar/examples/SnackbarSuspensionExample.m
+++ b/components/Snackbar/examples/SnackbarSuspensionExample.m
@@ -39,8 +39,14 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
-  [self setupExampleViews];
-  self.title = @"Snackbar Suspension";
+  [self setupExampleViews:@[
+      @"Show Category A Message",
+      @"Show Category B Message",
+      @"Show Message with no category",
+      @"Suspend Category A",
+      @"Suspend Category B",
+      @"Suspend All"]];
+  self.title = @"Message Suspension";
 }
 
 - (void)showMessageWithPrefix:(NSString *)prefix category:(NSString *)category {
@@ -93,13 +99,20 @@
 
 #pragma mark - Event Handling
 
-- (void)handleShowTapped:(id)sender {
-  if (sender == self.groupAButton) {
-    [self showMessageWithPrefix:@"Category A" category:kCategoryA];
-  } else if (sender == self.groupBButton) {
-    [self showMessageWithPrefix:@"Category B" category:kCategoryB];
-  } else if (sender == self.allMessagesButton) {
-    [self showMessageWithPrefix:@"No Category" category:nil];
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+  switch (indexPath.row) {
+    case 0:
+      [self showMessageWithPrefix:@"Category A Message" category:kCategoryA];
+      break;
+    case 1:
+      [self showMessageWithPrefix:@"Category B Message" category:kCategoryB];
+      break;
+    case 2:
+      [self showMessageWithPrefix:@"No Category Message" category:nil];
+      break;
+    default:
+      break;
   }
 }
 
@@ -107,11 +120,11 @@
   BOOL suspended = sender.on;
 
   // Figure out which token we're dealing with based on which switch sent this message.
-  if (sender == self.groupASwitch) {
+  if (sender.tag == 3) {
     [self setSuspendedGroupA:suspended];
-  } else if (sender == self.groupBSwitch) {
+  } else if (sender.tag == 4) {
     [self setSuspendedGroupB:suspended];
-  } else if (sender == self.allMessagesSwitch) {
+  } else if (sender.tag == 5) {
     [self setSuspendedAllMessages:suspended];
   }
 }
diff --git a/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.h b/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.h
index e73501b..bdcc4cc 100644
--- a/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.h
+++ b/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.h
@@ -18,21 +18,11 @@
 
 #import "MaterialButtons.h"
 #import "MaterialTypography.h"
+#import "MaterialCollections.h"
 
-@interface SnackbarExample : UIViewController
-
-@property(nonatomic) MDCRaisedButton *snackbarButton;
-
-- (void)setupExampleViews;
-
-@end
-
-@interface SnackbarActionExample : SnackbarExample
-
-@end
-
-@interface SnackbarBoldExample : SnackbarExample
-
+@interface SnackbarExample : MDCCollectionViewController
+@property(nonatomic) NSArray *choices;
+- (void)setupExampleViews:(NSArray *)choices;
 @end
 
 @interface SnackbarOverlayViewExample : SnackbarExample
@@ -43,24 +33,10 @@
 @end
 
 @interface SnackbarSimpleExample : SnackbarExample
-- (void)handleShowSnackbarButtonTapped:(id)sender;
 @end
 
 @interface SnackbarSuspensionExample : SnackbarExample
 
-@property(nonatomic) MDCRaisedButton *groupAButton;
-@property(nonatomic) MDCRaisedButton *groupBButton;
-@property(nonatomic) MDCRaisedButton *allMessagesButton;
-
-@property(nonatomic) UISwitch *groupASwitch;
-@property(nonatomic) UISwitch *groupBSwitch;
-@property(nonatomic) UISwitch *allMessagesSwitch;
-
-@property(nonatomic) UILabel *groupALabel;
-@property(nonatomic) UILabel *groupBLabel;
-@property(nonatomic) UILabel *allLabel;
-
-- (void)handleShowTapped:(id)sender;
 - (void)handleSuspendStateChanged:(UISwitch *)sender;
 
 @end
diff --git a/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.m b/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.m
index bf635dd..f9c8cb4 100644
--- a/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.m
+++ b/components/Snackbar/examples/supplemental/SnackbarExampleSupplemental.m
@@ -18,42 +18,32 @@
 
 #import "SnackbarExampleSupplemental.h"
 
+static NSString * const kCellIdentifier = @"Cell";
+
 @implementation SnackbarExample
 
-- (void)setupExampleViews {
+- (void)setupExampleViews:(NSArray *)choices {
+  self.choices = choices;
   self.view.backgroundColor = [UIColor whiteColor];
-
-  // Set up the button.
-  self.snackbarButton = [[MDCRaisedButton alloc] init];
-  [self.snackbarButton setTitle:@"Present Snackbar" forState:UIControlStateNormal];
-  [self.snackbarButton addTarget:self
-                          action:@selector(handleShowSnackbarButtonTapped:)
-                forControlEvents:UIControlEventTouchUpInside];
-  [self.view addSubview:self.snackbarButton];
-
-  // Position the button.
-  CGRect snackFrame = CGRectMake(0, 100.0f, 200.0f, 40.0f);
-  snackFrame.origin.x = CGRectGetMidX(self.view.bounds) - CGRectGetWidth(snackFrame) / 2.0f;
-  snackFrame = CGRectIntegral(snackFrame);
-  self.snackbarButton.frame = snackFrame;
-  self.snackbarButton.autoresizingMask =
-      (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
+  [self.collectionView registerClass:[MDCCollectionViewTextCell class]
+          forCellWithReuseIdentifier:kCellIdentifier];
 }
 
-@end
+#pragma mark - UICollectionView
 
-@implementation SnackbarActionExample (CatalogByConvention)
-
-+ (NSArray *)catalogBreadcrumbs {
-  return @[ @"Snackbar", @"Snackbar Multi-line Action Message" ];
+- (NSInteger)collectionView:(UICollectionView *)collectionView
+     numberOfItemsInSection:(NSInteger)section {
+  return self.choices.count;
 }
 
-@end
 
-@implementation SnackbarBoldExample (CatalogByConvention)
-
-+ (NSArray *)catalogBreadcrumbs {
-  return @[ @"Snackbar", @"Snackbar Bold Message" ];
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  MDCCollectionViewTextCell *cell =
+      [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier
+                                                forIndexPath:indexPath];
+  cell.textLabel.text = self.choices[indexPath.row];
+  return cell;
 }
 
 @end
@@ -83,133 +73,27 @@
 
 @end
 
-@implementation SnackbarSuspensionExample (Layout)
+@implementation SnackbarSuspensionExample (CollectionView)
 
-- (void)setupExampleViews {
-  self.view.backgroundColor = [UIColor whiteColor];
-
-  self.groupAButton = [[MDCRaisedButton alloc] init];
-  [self.groupAButton setTitle:@"Show Category A Message" forState:UIControlStateNormal];
-  [self.groupAButton addTarget:self
-                        action:@selector(handleShowTapped:)
-              forControlEvents:UIControlEventTouchUpInside];
-  self.groupAButton.autoresizingMask =
-      (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
-  [self.view addSubview:self.groupAButton];
-
-  self.groupBButton = [[MDCRaisedButton alloc] init];
-  [self.groupBButton setTitle:@"Show Category B Message" forState:UIControlStateNormal];
-  [self.groupBButton addTarget:self
-                        action:@selector(handleShowTapped:)
-              forControlEvents:UIControlEventTouchUpInside];
-  self.groupBButton.autoresizingMask =
-      (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
-  [self.view addSubview:self.groupBButton];
-
-  self.allMessagesButton = [[MDCRaisedButton alloc] init];
-  [self.allMessagesButton setTitle:@"Show Standard Message" forState:UIControlStateNormal];
-  [self.allMessagesButton addTarget:self
-                             action:@selector(handleShowTapped:)
-                   forControlEvents:UIControlEventTouchUpInside];
-  self.allMessagesButton.autoresizingMask =
-      (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
-  [self.view addSubview:self.allMessagesButton];
-
-  self.groupASwitch = [[UISwitch alloc] init];
-  self.groupASwitch.on = NO;
-  [self.groupASwitch addTarget:self
-                        action:@selector(handleSuspendStateChanged:)
-              forControlEvents:UIControlEventValueChanged];
-  [self.view addSubview:self.groupASwitch];
-
-  self.groupBSwitch = [[UISwitch alloc] init];
-  self.groupBSwitch.on = NO;
-  [self.groupBSwitch addTarget:self
-                        action:@selector(handleSuspendStateChanged:)
-              forControlEvents:UIControlEventValueChanged];
-  [self.view addSubview:self.groupBSwitch];
-
-  self.allMessagesSwitch = [[UISwitch alloc] init];
-  self.allMessagesSwitch.on = NO;
-  [self.allMessagesSwitch addTarget:self
-                             action:@selector(handleSuspendStateChanged:)
-                   forControlEvents:UIControlEventValueChanged];
-  [self.view addSubview:self.allMessagesSwitch];
-
-  self.groupALabel = [[UILabel alloc] init];
-  self.groupALabel.text = @"Suspend Catagory A Messages";
-  self.groupALabel.font = [MDCTypography captionFont];
-  self.groupALabel.alpha = [MDCTypography captionFontOpacity];
-  [self.view addSubview:self.groupALabel];
-
-  self.groupBLabel = [[UILabel alloc] init];
-  self.groupBLabel.text = @"Suspend Catagory B Messages";
-  self.groupBLabel.font = [MDCTypography captionFont];
-  self.groupBLabel.alpha = [MDCTypography captionFontOpacity];
-  [self.view addSubview:self.groupBLabel];
-
-  self.allLabel = [[UILabel alloc] init];
-  self.allLabel.text = @"Suspend All Messages";
-  self.allLabel.font = [MDCTypography captionFont];
-  self.allLabel.alpha = [MDCTypography captionFontOpacity];
-  [self.view addSubview:self.allLabel];
-}
-
-- (void)viewWillLayoutSubviews {
-  CGFloat buttonWidth = 250.0f;
-  CGFloat buttonHeight = 40.0f;
-  CGFloat buttonYOffset = 60.0f;
-
-  CGFloat switchWidth = self.groupASwitch.frame.size.width;
-  CGFloat switchYOffset = 48.0f;
-  if (self.view.frame.size.height > self.view.frame.size.width) {
-    buttonYOffset = 80.f;
-    switchYOffset = 50.0f;
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  MDCCollectionViewTextCell *cell =
+  [collectionView dequeueReusableCellWithReuseIdentifier:kCellIdentifier
+                                            forIndexPath:indexPath];
+  
+  cell.textLabel.text = self.choices[indexPath.row];
+  if (indexPath.row > 2) {
+    UISwitch *editingSwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
+    [editingSwitch setTag:indexPath.row];
+    [editingSwitch addTarget:self
+                      action:@selector(handleSuspendStateChanged:)
+            forControlEvents:UIControlEventValueChanged];
+    cell.accessoryView = editingSwitch;
+  } else {
+    cell.accessoryView = nil;
   }
-
-  CGFloat labelWidth = 200.0f;
-  CGFloat labelHeight = 27.0f;
-  CGFloat labelXOffset = switchWidth + 5.0f;
-
-  CGFloat spacing = self.view.frame.size.height / 3.5f;
-
-  CGRect catAButtonFrame = CGRectMake(0, spacing - buttonYOffset, buttonWidth, buttonHeight);
-  catAButtonFrame.origin.x =
-      CGRectGetMidX(self.view.bounds) - CGRectGetWidth(catAButtonFrame) / 2.0f;
-  catAButtonFrame = CGRectIntegral(catAButtonFrame);
-  self.groupAButton.frame = catAButtonFrame;
-
-  CGRect catBButtonFrame = CGRectMake(0, 2.f * spacing - buttonYOffset, buttonWidth, buttonHeight);
-  catBButtonFrame.origin.x =
-      CGRectGetMidX(self.view.bounds) - CGRectGetWidth(catBButtonFrame) / 2.0f;
-  catBButtonFrame = CGRectIntegral(catBButtonFrame);
-  self.groupBButton.frame = catBButtonFrame;
-
-  CGRect allMessagesButtonFrame =
-      CGRectMake(0, 3.f * spacing - buttonYOffset, buttonWidth, buttonHeight);
-  allMessagesButtonFrame.origin.x =
-      CGRectGetMidX(self.view.bounds) - CGRectGetWidth(allMessagesButtonFrame) / 2.0f;
-  allMessagesButtonFrame = CGRectIntegral(allMessagesButtonFrame);
-  self.allMessagesButton.frame = allMessagesButtonFrame;
-
-  self.groupASwitch.frame =
-      CGRectMake(self.groupAButton.frame.origin.x, self.groupAButton.frame.origin.y + switchYOffset,
-                 switchWidth, labelHeight);
-  self.groupBSwitch.frame =
-      CGRectMake(self.groupBButton.frame.origin.x, self.groupBButton.frame.origin.y + switchYOffset,
-                 switchWidth, labelHeight);
-  self.allMessagesSwitch.frame =
-      CGRectMake(self.allMessagesButton.frame.origin.x,
-                 self.allMessagesButton.frame.origin.y + switchYOffset, switchWidth, labelHeight);
-  self.groupALabel.frame =
-      CGRectMake(self.groupAButton.frame.origin.x + labelXOffset,
-                 self.groupAButton.frame.origin.y + switchYOffset, labelWidth, labelHeight);
-  self.groupBLabel.frame =
-      CGRectMake(self.groupBButton.frame.origin.x + labelXOffset,
-                 self.groupBButton.frame.origin.y + switchYOffset, labelWidth, labelHeight);
-  self.allLabel.frame =
-      CGRectMake(self.allMessagesButton.frame.origin.x + labelXOffset,
-                 self.allMessagesButton.frame.origin.y + switchYOffset, labelWidth, labelHeight);
+  
+  return cell;
 }
 
 @end
diff --git a/components/Tabs/README.md b/components/Tabs/README.md
index 59a94a2..e30ae72 100644
--- a/components/Tabs/README.md
+++ b/components/Tabs/README.md
@@ -2,21 +2,15 @@
 title: "Tabs"
 layout: detail
 section: components
-excerpt: "TODO(shyndman): Excerpt needed."
 iconId: tabs
+path: /catalog/tabs/
 -->
 
 # Tabs
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/tabs.png" alt="Tabs" width="320">
+  <img src="docs/assets/tabs.png" alt="Tabs" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/tab_bar.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 Tabs are bars of buttons used to navigate between groups of content.
 <!--{: .article__intro }-->
@@ -24,7 +18,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://material.google.com/components/tabs.html">Tabs</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/components/tabs.html">Tabs</a></li>
 </ul>
 
 - - -
diff --git a/components/Tabs/docs/assets/tabs.mp4 b/components/Tabs/docs/assets/tabs.mp4
deleted file mode 100644
index dae8e51..0000000
--- a/components/Tabs/docs/assets/tabs.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Tabs/docs/assets/tabs.png b/components/Tabs/docs/assets/tabs.png
index c50b31a..9d49543 100644
--- a/components/Tabs/docs/assets/tabs.png
+++ b/components/Tabs/docs/assets/tabs.png
Binary files differ
diff --git a/components/Tabs/examples/TabBarIconExample.m b/components/Tabs/examples/TabBarIconExample.m
index e2dc1b9..291305c 100644
--- a/components/Tabs/examples/TabBarIconExample.m
+++ b/components/Tabs/examples/TabBarIconExample.m
@@ -72,14 +72,14 @@
   // Give the second item a badge
   [tabBar.items[1] setBadgeValue:@"1"];
 
-  UIColor *color = [[MDCPalette bluePalette] tint500];
+  UIColor *green =  [UIColor colorWithRed:11/255.0f green:232/255.0f blue:94/255.0f alpha:1];
 
-  tabBar.barTintColor = [UIColor whiteColor];
-  tabBar.tintColor = color;
+  tabBar.barTintColor = [UIColor colorWithWhite:0.1f alpha:1.0];
+  tabBar.tintColor = green;
+  tabBar.inkColor = [[UIColor whiteColor] colorWithAlphaComponent:0.1];
+  tabBar.selectedItemTintColor = [[UIColor whiteColor] colorWithAlphaComponent:.87f];
+  tabBar.unselectedItemTintColor = [[UIColor whiteColor] colorWithAlphaComponent:.38f];
   tabBar.itemAppearance = MDCTabBarItemAppearanceTitledImages;
-  tabBar.selectedItemTintColor = [[UIColor blackColor] colorWithAlphaComponent:.87];
-  tabBar.unselectedItemTintColor = [[UIColor blackColor] colorWithAlphaComponent:.38];
-  tabBar.inkColor = color;
 
   self.tabBar = tabBar;
   self.appBar.headerStackView.bottomBar = self.tabBar;
diff --git a/components/Tabs/examples/TabBarTextOnlyExample.m b/components/Tabs/examples/TabBarTextOnlyExample.m
index fcbc73b..99cc6c7 100644
--- a/components/Tabs/examples/TabBarTextOnlyExample.m
+++ b/components/Tabs/examples/TabBarTextOnlyExample.m
@@ -16,19 +16,28 @@
 
 #import <UIKit/UIKit.h>
 
+#import "MaterialAppBar.h"
 #import "MaterialButtons.h"
+#import "MaterialCollections.h"
 #import "MaterialTabs.h"
 
 #import "TabBarTextOnlyExampleSupplemental.h"
 
+
 @implementation TabBarTextOnlyExample
 
+- (id)initWithCollectionViewLayout:(UICollectionViewLayout *)layout {
+  self = [super initWithCollectionViewLayout:layout];
+  if (self) {
+    [self setupExampleViews:@[@"Change Alignment", @"Toggle Case"]];
+  }
+  return self;
+}
+
 - (void)viewDidLoad {
   [super viewDidLoad];
-
-  [self setupExampleViews];
-
   [self loadTabBar];
+  self.appBar.headerStackView.bottomBar = self.tabBar;
 }
 
 #pragma mark - Action
@@ -45,7 +54,6 @@
   // Long tab bar with lots of items of varying length. Also demonstrates configurable accent color.
   self.tabBar =
       [[MDCTabBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(bounds) - 20.0f, 0)];
-  self.tabBar.center = CGPointMake(CGRectGetMidX(self.view.bounds), 250);
   self.tabBar.items = @[
     [[UITabBarItem alloc] initWithTitle:@"This Is" image:nil tag:0],
     [[UITabBarItem alloc] initWithTitle:@"A" image:nil tag:0],
@@ -55,16 +63,15 @@
   ];
 
   // Give it a white appearance to show dark text and customize the unselected title color.
-  self.tabBar.selectedItemTintColor = [UIColor blackColor];
+  self.tabBar.selectedItemTintColor = [UIColor whiteColor];
   self.tabBar.unselectedItemTintColor = [UIColor grayColor];
-  self.tabBar.tintColor = [UIColor redColor];
-  self.tabBar.barTintColor = [UIColor whiteColor];
-  self.tabBar.inkColor = [UIColor colorWithWhite:0.0 alpha:0.1];
+  self.tabBar.tintColor = [UIColor colorWithRed:11/255.0 green:232/255.0 blue:94/255.0 alpha:1];
+  self.tabBar.barTintColor = [UIColor colorWithWhite:0.1 alpha:1];
+  self.tabBar.inkColor = [UIColor colorWithWhite:1 alpha:0.1];
 
   self.tabBar.autoresizingMask =
       UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
   [self.tabBar sizeToFit];
-  [self.view addSubview:self.tabBar];
 }
 
 - (void)changeAlignment:(id)sender {
@@ -99,4 +106,16 @@
   [self.tabBar setAlignment:alignment animated:YES];
 }
 
+#pragma mark - Options in Collection View
+
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
+  if (indexPath.row == 0) {
+    [self changeAlignment:collectionView];
+  } else {
+    [self toggleCase:collectionView];
+  }
+}
+
 @end
diff --git a/components/Tabs/examples/supplemental/TabBarIconExampleSupplemental.m b/components/Tabs/examples/supplemental/TabBarIconExampleSupplemental.m
index e1c7f16..43b88de 100644
--- a/components/Tabs/examples/supplemental/TabBarIconExampleSupplemental.m
+++ b/components/Tabs/examples/supplemental/TabBarIconExampleSupplemental.m
@@ -59,6 +59,8 @@
       .active = YES;
 
   [self.alignmentButton setTitle:@"Change Alignment" forState:UIControlStateNormal];
+  [self.alignmentButton setBackgroundColor:[UIColor blackColor] forState:UIControlStateNormal];
+  [self.alignmentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
   [self.alignmentButton addTarget:self
                            action:@selector(changeAlignment:)
                  forControlEvents:UIControlEventTouchUpInside];
@@ -70,10 +72,14 @@
   self.appBar = [[MDCAppBar alloc] init];
   [self addChildViewController:self.appBar.headerViewController];
 
-  self.appBar.headerViewController.headerView.backgroundColor = [UIColor whiteColor];
+  self.appBar.headerViewController.headerView.tintColor = [UIColor whiteColor];
+  self.appBar.headerViewController.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
   self.appBar.headerViewController.headerView.minimumHeight = 76 + 72;
-  self.appBar.headerViewController.headerView.tintColor = [[MDCPalette bluePalette] tint500];
 
+  self.appBar.navigationBar.titleTextAttributes = @{
+    NSForegroundColorAttributeName: [UIColor whiteColor],
+    NSFontAttributeName: [UIFont fontWithName:@"RobotoMono-Regular" size:14] };
+  
   [self.appBar addSubviewsToParent];
 
   UIBarButtonItem *badgeIncrementItem =
@@ -117,11 +123,11 @@
   UIView *infoPage = [[UIView alloc] initWithFrame:CGRectZero];
   infoPage.translatesAutoresizingMaskIntoConstraints = NO;
   [self.scrollView addSubview:infoPage];
-  infoPage.backgroundColor = [[MDCPalette lightBluePalette] tint300];
+  infoPage.backgroundColor = [UIColor whiteColor];
 
   UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectZero];
   infoLabel.translatesAutoresizingMaskIntoConstraints = NO;
-  infoLabel.textColor = [UIColor whiteColor];
+  infoLabel.textColor = [UIColor colorWithRed:0.459 green:0.459 blue:0.459 alpha:0.87f];
   infoLabel.numberOfLines = 0;
   infoLabel.text =
       @"Tabs enable content organization at a high level, such as switching between views";
@@ -239,6 +245,11 @@
   return self.appBar.headerViewController;
 }
 
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  // Ensure that our status bar is white.
+  return UIStatusBarStyleLightContent;
+}
+
 @end
 
 @implementation TabBarIconExample (CatalogByConvention)
diff --git a/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.h b/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.h
index ef95f56..ac64ff7 100644
--- a/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.h
+++ b/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.h
@@ -19,18 +19,21 @@
 
 #import <UIKit/UIKit.h>
 
+@import MaterialComponents.MaterialCollections;
+
+@class MDCAppBar;
 @class MDCTabBar;
-@class MDCRaisedButton;
 
-@interface TabBarTextOnlyExample : UIViewController
 
-@property MDCTabBar *_Nullable tabBar;
-@property MDCRaisedButton *_Nullable alignmentButton;
+@interface TabBarTextOnlyExample : MDCCollectionViewController
 
+@property(nullable) MDCAppBar *appBar;
+@property(nullable) MDCTabBar *tabBar;
+@property(nullable) NSArray *choices;
 @end
 
 @interface TabBarTextOnlyExample (Supplemental)
 
-- (void)setupExampleViews;
+- (void)setupExampleViews:(nullable NSArray *)choices;
 
 @end
diff --git a/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.m b/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.m
index df647f1..2b67395 100644
--- a/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.m
+++ b/components/Tabs/examples/supplemental/TabBarTextOnlyExampleSupplemental.m
@@ -20,34 +20,101 @@
 
 #import <Foundation/Foundation.h>
 
+#import "MaterialAppBar.h"
+#import "MaterialTabs.h"
+
 #import "TabBarTextOnlyExampleSupplemental.h"
 
-#import "MaterialButtons.h"
-#import "MaterialTabs.h"
+static CGFloat const kStatusBarHeight = 20;
+static CGFloat const kAppBarMinHeight = 56;
+static CGFloat const kTabBarHeight = 48;
+
+static NSString * const kReusableIdentifierItem = @"Cell";
 
 @implementation TabBarTextOnlyExample (Supplemental)
 
-- (void)setupExampleViews {
-  self.view.backgroundColor = [UIColor whiteColor];
+- (UIViewController *)childViewControllerForStatusBarStyle {
+  return self.appBar.headerViewController;
+}
 
-  UIBarButtonItem *toggleCaseItem = [[UIBarButtonItem alloc] initWithTitle:@"Toggle Case"
-                                                                     style:UIBarButtonItemStylePlain
-                                                                    target:self
-                                                                    action:@selector(toggleCase:)];
-  self.navigationItem.rightBarButtonItem = toggleCaseItem;
+- (UIViewController *)childViewControllerForStatusBarHidden {
+  return self.appBar.headerViewController;
+}
 
-  // Button to change tab alignments.
-  self.alignmentButton = [[MDCRaisedButton alloc] init];
-  [self.alignmentButton setTitle:@"Change Alignment" forState:UIControlStateNormal];
-  [self.alignmentButton sizeToFit];
-  self.alignmentButton.center = CGPointMake(CGRectGetMidX(self.view.bounds), 100);
-  self.alignmentButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin |
-                                          UIViewAutoresizingFlexibleBottomMargin |
-                                          UIViewAutoresizingFlexibleRightMargin;
-  [self.alignmentButton addTarget:self
-                           action:@selector(changeAlignment:)
-                 forControlEvents:UIControlEventTouchUpInside];
-  [self.view addSubview:self.alignmentButton];
+- (void)setupExampleViews:(NSArray *)choices {
+  self.choices = choices;
+  self.title = @"Text Tabs";
+
+  self.appBar = [[MDCAppBar alloc] init];
+  [self addChildViewController:self.appBar.headerViewController];
+
+  self.appBar.headerViewController.headerView.trackingScrollView = self.collectionView;
+  self.appBar.headerViewController.headerView.shiftBehavior =
+      MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar;
+
+  self.appBar.navigationBar.tintColor = [UIColor whiteColor];
+  self.appBar.headerViewController.headerView.tintColor = [UIColor whiteColor];
+  self.appBar.headerViewController.headerView.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0];
+  self.appBar.headerViewController.headerView.minimumHeight =
+      kStatusBarHeight + kTabBarHeight;
+  self.appBar.headerViewController.headerView.maximumHeight =
+      kStatusBarHeight + kAppBarMinHeight + kTabBarHeight;
+  
+  self.appBar.navigationBar.titleTextAttributes = @{
+      NSForegroundColorAttributeName: [UIColor whiteColor],
+      NSFontAttributeName: [UIFont fontWithName:@"RobotoMono-Regular" size:14] };
+  [self.appBar addSubviewsToParent];
+  
+  
+  [self.collectionView registerClass:[MDCCollectionViewTextCell class]
+          forCellWithReuseIdentifier:kReusableIdentifierItem];
+}
+
+#pragma mark - UICollectionView
+
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView
+     numberOfItemsInSection:(NSInteger)section {
+  return self.choices.count;
+}
+
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  MDCCollectionViewTextCell *cell =
+      [collectionView dequeueReusableCellWithReuseIdentifier:kReusableIdentifierItem
+                                                forIndexPath:indexPath];
+  cell.textLabel.text = self.choices[indexPath.row];
+  return cell;
+}
+
+#pragma mark - UIScrollViewDelegate Forwarding.
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+  if (scrollView == self.appBar.headerViewController.headerView.trackingScrollView) {
+    [self.appBar.headerViewController.headerView trackingScrollViewDidScroll];
+  }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+  if (scrollView == self.appBar.headerViewController.headerView.trackingScrollView) {
+    [self.appBar.headerViewController.headerView trackingScrollViewDidEndDecelerating];
+  }
+}
+
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
+  if (scrollView == self.appBar.headerViewController.headerView.trackingScrollView) {
+    [self.appBar.headerViewController.headerView trackingScrollViewDidEndDraggingWillDecelerate:decelerate];
+  }
+}
+
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
+                     withVelocity:(CGPoint)velocity
+              targetContentOffset:(inout CGPoint *)targetContentOffset {
+  if (scrollView == self.appBar.headerViewController.headerView.trackingScrollView) {
+    [self.appBar.headerViewController.headerView trackingScrollViewWillEndDraggingWithVelocity:velocity
+                                                                           targetContentOffset:targetContentOffset];
+  }
 }
 
 @end
@@ -55,15 +122,19 @@
 @implementation TabBarTextOnlyExample (CatalogByConvention)
 
 + (NSArray *)catalogBreadcrumbs {
-  return @[ @"Tab Bar", @"No Icons" ];
+  return @[ @"Tab Bar", @"Text Tabs" ];
+}
+
++ (NSString *)catalogDescription {
+  return @"The tab bar is a component for switching between views of grouped content.";
 }
 
 + (BOOL)catalogIsPrimaryDemo {
   return YES;
 }
 
-+ (NSString *)catalogDescription {
-  return @"The tab bar is a component for switching between views of grouped content.";
+- (BOOL)catalogShouldHideNavigation {
+  return YES;
 }
 
 @end
diff --git a/components/Tabs/src/MDCTabBar.h b/components/Tabs/src/MDCTabBar.h
index 701cd43..0abc204 100644
--- a/components/Tabs/src/MDCTabBar.h
+++ b/components/Tabs/src/MDCTabBar.h
@@ -30,7 +30,7 @@
 
  Note: This class is not intended to be subclassed.
 
- @see https://www.google.com/design/spec/components/tabs.html
+ @see https://material.io/guidelines/components/tabs.html
  */
 IB_DESIGNABLE
 @interface MDCTabBar : UIView
diff --git a/components/Tabs/src/MDCTabBar.m b/components/Tabs/src/MDCTabBar.m
index 77659de..96834db 100644
--- a/components/Tabs/src/MDCTabBar.m
+++ b/components/Tabs/src/MDCTabBar.m
@@ -28,7 +28,7 @@
 /// Adjustment added to spec measurements to compensate for internal paddings.
 static const CGFloat kImageTitlePaddingAdjustment = -3;
 
-// Heights based on the spec: https://www.google.com/design/spec/components/tabs.html
+// Heights based on the spec: https://material.io/guidelines/components/tabs.html
 
 /// Height for image-only tab bars, in points.
 static const CGFloat kImageOnlyBarHeight = 48;
diff --git a/components/Tabs/src/private/MDCItemBarCell.m b/components/Tabs/src/private/MDCItemBarCell.m
index 049924d..bd1d71d 100644
--- a/components/Tabs/src/private/MDCItemBarCell.m
+++ b/components/Tabs/src/private/MDCItemBarCell.m
@@ -93,7 +93,7 @@
 #pragma mark - Public
 
 + (UIEdgeInsets)edgeInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
-  // Padding from spec: https://www.google.com/design/spec/components/tabs.html
+  // Padding from spec: https://material.io/guidelines/components/tabs.html
   CGFloat outerPadding = (sizeClass == UIUserInterfaceSizeClassRegular) ? 24.0f : 12.0f;
   return UIEdgeInsetsMake(0.0, outerPadding, 0.0, outerPadding);
 }
diff --git a/components/Typography/README.md b/components/Typography/README.md
index 0a75f06..078c7b4 100644
--- a/components/Typography/README.md
+++ b/components/Typography/README.md
@@ -3,19 +3,15 @@
 layout: detail
 section: components
 excerpt: "The Typography component provides methods for displaying text using the type sizes and opacities from the Material Design specifications."
+iconId: typography
+path: /catalog/typography/
 -->
 
 # Typography
 
-<!--{% if site.link_to_site == "true" %}-->
 <div class="article__asset article__asset--screenshot">
-  <img src="docs/assets/typography.png" alt="Typography" width="320">
+  <img src="docs/assets/typography.png" alt="Typography" width="375">
 </div>
-<!--{% else %}
-<div class="article__asset article__asset--screenshot" markdown="1">
-  <video src="docs/assets/typography.mp4" autoplay loop></video>
-</div>
-{% endif %}-->
 
 The Typography component provides methods for displaying text using the type sizes and opacities
 from the Material Design specifications.
@@ -24,7 +20,7 @@
 ## Design & API Documentation
 
 <ul class="icon-list">
-  <li class="icon-list-item icon-list-item--spec"><a href="https://www.google.com/design/spec/style/typography.html">Typography</a></li>
+  <li class="icon-list-item icon-list-item--spec"><a href="https://material.io/guidelines/style/typography.html">Typography</a></li>
 </ul>
 
 ## Installation
diff --git a/components/Typography/docs/assets/typography.mp4 b/components/Typography/docs/assets/typography.mp4
deleted file mode 100644
index a892d1a..0000000
--- a/components/Typography/docs/assets/typography.mp4
+++ /dev/null
Binary files differ
diff --git a/components/Typography/docs/assets/typography.png b/components/Typography/docs/assets/typography.png
index 0ae1bdd..f1e7104 100644
--- a/components/Typography/docs/assets/typography.png
+++ b/components/Typography/docs/assets/typography.png
Binary files differ
diff --git a/components/Typography/src/MDCTypography.h b/components/Typography/src/MDCTypography.h
index 5949cc7..4f5d386 100644
--- a/components/Typography/src/MDCTypography.h
+++ b/components/Typography/src/MDCTypography.h
@@ -22,7 +22,7 @@
  The spec defines the Roboto font family and uses three fonts in the named styles. Use this
  protocol to define your own fonts if there is a brand need.
 
- @see https://www.google.com/design/spec/style/typography.html#typography-styles
+ @see https://material.io/guidelines/style/typography.html#typography-styles
  */
 @protocol MDCTypographyFontLoading <NSObject>
 @required
@@ -72,7 +72,7 @@
 
  To use these fonts, you must add MaterialTypography.bundle to your target.
 
- @see https://www.google.com/design/spec/style/typography.html#typography-styles
+ @see https://material.io/guidelines/style/typography.html#typography-styles
  */
 @interface MDCTypography : NSObject
 
diff --git a/contributing/README.md b/contributing/README.md
index 410ddae..3b048cd 100644
--- a/contributing/README.md
+++ b/contributing/README.md
@@ -1,7 +1,8 @@
 <!--docs:
 title: "Contributing"
 layout: landing
-section: contributing
+section: docs
+path: /docs/contributing/
 -->
 
 # General Contributing Guidelines
@@ -67,4 +68,4 @@
 - [Demo Apps](../demos/)
 - [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
 - [Material.io](https://www.material.io) (external site)
-- [Material Design Guidelines](https://material.google.com) (external site)
+- [Material Design Guidelines](https://material.io/guidelines) (external site)
diff --git a/contributing/checklist.md b/contributing/checklist.md
index da69d35..ce8692b 100644
--- a/contributing/checklist.md
+++ b/contributing/checklist.md
@@ -168,7 +168,7 @@
 ### VoiceOver Support
 
 
-Custom controls should support VoiceOver. 
+Custom controls should support VoiceOver.
 See Apple's [Accessibility Programming Guide for iOS](https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/iPhoneAccessibility/Accessibility_on_iPhone/Accessibility_on_iPhone.html) for further information.
 
 1. Test your control on a device in VoiceOver mode and ensure the bahavior is at least as robust as UIKit.
@@ -181,7 +181,7 @@
 Comments are useful when used properly. In addition, they are necessary for the system of documentation generation used in MDC.
 
 1. Carefully review all comments for necessity and brevity.
-1. Make sure all classes have complete header comments that comply with [HeaderDoc](https://developer.apple.com/legacy/library/documentation/DeveloperTools/Conceptual/HeaderDoc/tags/tags.html) for [Jazzy](https://github.com/realm/jazzy) parsing. 
+1. Make sure all classes have complete header comments that comply with [HeaderDoc](https://developer.apple.com/legacy/library/documentation/DeveloperTools/Conceptual/HeaderDoc/tags/tags.html) for [Jazzy](https://github.com/realm/jazzy) parsing.
 1. Enter YES or NO
 
 
@@ -190,7 +190,7 @@
 
 Every component has to support all features outlined for it in the Material Design guidelines. It can support additional features or customization.
 
-1. Review what the [Material Design Guidelines](https://material.google.com/) says about the component and make sure the component can *at least* satisfy those requirements.
+1. Review what the [Material Design Guidelines](https://material.io/guidelines/) says about the component and make sure the component can *at least* satisfy those requirements.
 1. Enter YES or NO
 
 
@@ -312,7 +312,7 @@
 
 
 #### Articles on Auto Layout:
-[Advanced Auto Layout Toolbox](https://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/)  
+[Advanced Auto Layout Toolbox](https://www.objc.io/issues/3-views/advanced-auto-layout-toolbox/)
 [Auto Layout Performance on iOS](http://floriankugler.com/2013/04/22/auto-layout-performance-on-ios/)
 
 
@@ -392,7 +392,7 @@
 scripts/check_components
 ```
 
-To run the checks against particular components, list their directories on the command line: 
+To run the checks against particular components, list their directories on the command line:
 
 ```bash
 scripts/check_components components/ActivityIndicator components/Buttons
diff --git a/contributing/site_development.md b/contributing/site_development.md
index 925cefa..b9acafc 100644
--- a/contributing/site_development.md
+++ b/contributing/site_development.md
@@ -49,7 +49,7 @@
 - _sass: the style of the document site
 
     - base.scss: the basic style of the default html tags. Most of the styles respect [material
-      design guideline](https://www.google.com/design/spec/)
+      design guideline](https://material.io/guidelines/)
 
     - _globals.scss: the variables and responsive grid definitions.
 
diff --git a/contributing/writing_readmes.md b/contributing/writing_readmes.md
index b0f483f..6745201 100644
--- a/contributing/writing_readmes.md
+++ b/contributing/writing_readmes.md
@@ -17,7 +17,7 @@
 
     <ul class="icon-list">
       <li class="icon-list-item icon-list-item--spec">
-        <a href="https://www.google.com/design/spec/<TODO: link to spec>">
+        <a href="https://material.io/guidelines/<TODO: link to spec>">
           TODO: link to spec
         </a>
       </li>
diff --git a/demos/Bare/Podfile b/demos/Bare/Podfile
index dfdec3e..ef704b1 100644
--- a/demos/Bare/Podfile
+++ b/demos/Bare/Podfile
@@ -1,4 +1,6 @@
 target 'Bare' do
+  platform :ios, '8.0'
+  project 'Bare.xcodeproj'
   pod 'MaterialComponents', :path => '../../'
 end
 
diff --git a/demos/Bare/Podfile.lock b/demos/Bare/Podfile.lock
index 6c8dd4e..920b7c6 100644
--- a/demos/Bare/Podfile.lock
+++ b/demos/Bare/Podfile.lock
@@ -1,35 +1,35 @@
 PODS:
-  - MaterialComponents (23.0.2):
-    - MaterialComponents/ActivityIndicator (= 23.0.2)
-    - MaterialComponents/AnimationTiming (= 23.0.2)
-    - MaterialComponents/AppBar (= 23.0.2)
-    - MaterialComponents/ButtonBar (= 23.0.2)
-    - MaterialComponents/Buttons (= 23.0.2)
-    - MaterialComponents/CollectionCells (= 23.0.2)
-    - MaterialComponents/CollectionLayoutAttributes (= 23.0.2)
-    - MaterialComponents/Collections (= 23.0.2)
-    - MaterialComponents/Dialogs (= 23.0.2)
-    - MaterialComponents/FeatureHighlight (= 23.0.2)
-    - MaterialComponents/FlexibleHeader (= 23.0.2)
-    - MaterialComponents/HeaderStackView (= 23.0.2)
-    - MaterialComponents/Ink (= 23.0.2)
-    - MaterialComponents/NavigationBar (= 23.0.2)
-    - MaterialComponents/OverlayWindow (= 23.0.2)
-    - MaterialComponents/PageControl (= 23.0.2)
-    - MaterialComponents/Palettes (= 23.0.2)
-    - MaterialComponents/private (= 23.0.2)
-    - MaterialComponents/ProgressView (= 23.0.2)
-    - MaterialComponents/ShadowElevations (= 23.0.2)
-    - MaterialComponents/ShadowLayer (= 23.0.2)
-    - MaterialComponents/Slider (= 23.0.2)
-    - MaterialComponents/Snackbar (= 23.0.2)
-    - MaterialComponents/Tabs (= 23.0.2)
-    - MaterialComponents/Typography (= 23.0.2)
-  - MaterialComponents/ActivityIndicator (23.0.2):
+  - MaterialComponents (23.1.0):
+    - MaterialComponents/ActivityIndicator (= 23.1.0)
+    - MaterialComponents/AnimationTiming (= 23.1.0)
+    - MaterialComponents/AppBar (= 23.1.0)
+    - MaterialComponents/ButtonBar (= 23.1.0)
+    - MaterialComponents/Buttons (= 23.1.0)
+    - MaterialComponents/CollectionCells (= 23.1.0)
+    - MaterialComponents/CollectionLayoutAttributes (= 23.1.0)
+    - MaterialComponents/Collections (= 23.1.0)
+    - MaterialComponents/Dialogs (= 23.1.0)
+    - MaterialComponents/FeatureHighlight (= 23.1.0)
+    - MaterialComponents/FlexibleHeader (= 23.1.0)
+    - MaterialComponents/HeaderStackView (= 23.1.0)
+    - MaterialComponents/Ink (= 23.1.0)
+    - MaterialComponents/NavigationBar (= 23.1.0)
+    - MaterialComponents/OverlayWindow (= 23.1.0)
+    - MaterialComponents/PageControl (= 23.1.0)
+    - MaterialComponents/Palettes (= 23.1.0)
+    - MaterialComponents/private (= 23.1.0)
+    - MaterialComponents/ProgressView (= 23.1.0)
+    - MaterialComponents/ShadowElevations (= 23.1.0)
+    - MaterialComponents/ShadowLayer (= 23.1.0)
+    - MaterialComponents/Slider (= 23.1.0)
+    - MaterialComponents/Snackbar (= 23.1.0)
+    - MaterialComponents/Tabs (= 23.1.0)
+    - MaterialComponents/Typography (= 23.1.0)
+  - MaterialComponents/ActivityIndicator (23.1.0):
     - MaterialComponents/private/Application
     - MaterialComponents/private/RTL
-  - MaterialComponents/AnimationTiming (23.0.2)
-  - MaterialComponents/AppBar (23.0.2):
+  - MaterialComponents/AnimationTiming (23.1.0)
+  - MaterialComponents/AppBar (23.1.0):
     - MaterialComponents/FlexibleHeader
     - MaterialComponents/HeaderStackView
     - MaterialComponents/NavigationBar
@@ -38,17 +38,17 @@
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
-  - MaterialComponents/ButtonBar (23.0.2):
+  - MaterialComponents/ButtonBar (23.1.0):
     - MaterialComponents/Buttons
     - MaterialComponents/private/RTL
-  - MaterialComponents/Buttons (23.0.2):
+  - MaterialComponents/Buttons (23.1.0):
     - MaterialComponents/Ink
     - MaterialComponents/private/Math
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/CollectionCells (23.0.2):
+  - MaterialComponents/CollectionCells (23.1.0):
     - MaterialComponents/CollectionLayoutAttributes
     - MaterialComponents/Ink
     - MaterialComponents/private/Icons/ic_check
@@ -60,91 +60,91 @@
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
     - MaterialComponents/Typography
-  - MaterialComponents/CollectionLayoutAttributes (23.0.2)
-  - MaterialComponents/Collections (23.0.2):
+  - MaterialComponents/CollectionLayoutAttributes (23.1.0)
+  - MaterialComponents/Collections (23.1.0):
     - MaterialComponents/CollectionCells
     - MaterialComponents/CollectionLayoutAttributes
     - MaterialComponents/Ink
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
-  - MaterialComponents/Dialogs (23.0.2):
+  - MaterialComponents/Dialogs (23.1.0):
     - MaterialComponents/Buttons
     - MaterialComponents/private/KeyboardWatcher
     - MaterialComponents/private/RTL
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
-  - MaterialComponents/FeatureHighlight (23.0.2):
+  - MaterialComponents/FeatureHighlight (23.1.0):
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/FlexibleHeader (23.0.2):
+  - MaterialComponents/FlexibleHeader (23.1.0):
     - MaterialComponents/private/Application
     - MDFTextAccessibility
-  - MaterialComponents/HeaderStackView (23.0.2)
-  - MaterialComponents/Ink (23.0.2)
-  - MaterialComponents/NavigationBar (23.0.2):
+  - MaterialComponents/HeaderStackView (23.1.0)
+  - MaterialComponents/Ink (23.1.0)
+  - MaterialComponents/NavigationBar (23.1.0):
     - MaterialComponents/ButtonBar
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/OverlayWindow (23.0.2):
+  - MaterialComponents/OverlayWindow (23.1.0):
     - MaterialComponents/private/Application
-  - MaterialComponents/PageControl (23.0.2)
-  - MaterialComponents/Palettes (23.0.2)
-  - MaterialComponents/private (23.0.2):
-    - MaterialComponents/private/Application (= 23.0.2)
-    - MaterialComponents/private/Icons (= 23.0.2)
-    - MaterialComponents/private/KeyboardWatcher (= 23.0.2)
-    - MaterialComponents/private/Math (= 23.0.2)
-    - MaterialComponents/private/Overlay (= 23.0.2)
-    - MaterialComponents/private/RTL (= 23.0.2)
-    - MaterialComponents/private/ThumbTrack (= 23.0.2)
-  - MaterialComponents/private/Application (23.0.2)
-  - MaterialComponents/private/Icons (23.0.2):
-    - MaterialComponents/private/Icons/Base (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_arrow_back (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_check (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_check_circle (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_chevron_right (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_info (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.0.2)
-    - MaterialComponents/private/Icons/ic_reorder (= 23.0.2)
-  - MaterialComponents/private/Icons/Base (23.0.2)
-  - MaterialComponents/private/Icons/ic_arrow_back (23.0.2):
+  - MaterialComponents/PageControl (23.1.0)
+  - MaterialComponents/Palettes (23.1.0)
+  - MaterialComponents/private (23.1.0):
+    - MaterialComponents/private/Application (= 23.1.0)
+    - MaterialComponents/private/Icons (= 23.1.0)
+    - MaterialComponents/private/KeyboardWatcher (= 23.1.0)
+    - MaterialComponents/private/Math (= 23.1.0)
+    - MaterialComponents/private/Overlay (= 23.1.0)
+    - MaterialComponents/private/RTL (= 23.1.0)
+    - MaterialComponents/private/ThumbTrack (= 23.1.0)
+  - MaterialComponents/private/Application (23.1.0)
+  - MaterialComponents/private/Icons (23.1.0):
+    - MaterialComponents/private/Icons/Base (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_arrow_back (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_check (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_check_circle (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_chevron_right (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_info (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.1.0)
+    - MaterialComponents/private/Icons/ic_reorder (= 23.1.0)
+  - MaterialComponents/private/Icons/Base (23.1.0)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_check (23.0.2):
+  - MaterialComponents/private/Icons/ic_check (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_check_circle (23.0.2):
+  - MaterialComponents/private/Icons/ic_check_circle (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_chevron_right (23.0.2):
+  - MaterialComponents/private/Icons/ic_chevron_right (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_info (23.0.2):
+  - MaterialComponents/private/Icons/ic_info (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.2):
+  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_reorder (23.0.2):
+  - MaterialComponents/private/Icons/ic_reorder (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/KeyboardWatcher (23.0.2):
+  - MaterialComponents/private/KeyboardWatcher (23.1.0):
     - MaterialComponents/private/Application
-  - MaterialComponents/private/Math (23.0.2)
-  - MaterialComponents/private/Overlay (23.0.2)
-  - MaterialComponents/private/RTL (23.0.2)
-  - MaterialComponents/private/ThumbTrack (23.0.2):
+  - MaterialComponents/private/Math (23.1.0)
+  - MaterialComponents/private/Overlay (23.1.0)
+  - MaterialComponents/private/RTL (23.1.0)
+  - MaterialComponents/private/ThumbTrack (23.1.0):
     - MaterialComponents/Ink
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
-  - MaterialComponents/ProgressView (23.0.2):
+  - MaterialComponents/ProgressView (23.1.0):
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
-  - MaterialComponents/ShadowElevations (23.0.2)
-  - MaterialComponents/ShadowLayer (23.0.2)
-  - MaterialComponents/Slider (23.0.2):
+  - MaterialComponents/ShadowElevations (23.1.0)
+  - MaterialComponents/ShadowLayer (23.1.0)
+  - MaterialComponents/Slider (23.1.0):
     - MaterialComponents/private/ThumbTrack
-  - MaterialComponents/Snackbar (23.0.2):
+  - MaterialComponents/Snackbar (23.1.0):
     - MaterialComponents/AnimationTiming
     - MaterialComponents/Buttons
     - MaterialComponents/OverlayWindow
@@ -152,12 +152,12 @@
     - MaterialComponents/private/KeyboardWatcher
     - MaterialComponents/private/Overlay
     - MaterialComponents/Typography
-  - MaterialComponents/Tabs (23.0.2):
+  - MaterialComponents/Tabs (23.1.0):
     - MaterialComponents/AnimationTiming
     - MaterialComponents/Ink
     - MaterialComponents/private/RTL
     - MaterialComponents/Typography
-  - MaterialComponents/Typography (23.0.2):
+  - MaterialComponents/Typography (23.1.0):
     - MaterialComponents/private/Application
   - MDFTextAccessibility (1.2.0)
 
@@ -169,9 +169,9 @@
     :path: "../../"
 
 SPEC CHECKSUMS:
-  MaterialComponents: fc0b6f9725db1f434aa3f8d7feb7832ac99a3692
+  MaterialComponents: 7979134f28cca6654f9d3786e96a8d1bff26dfc6
   MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
 
-PODFILE CHECKSUM: 44e7c616a05bb4ce24db557c3de4bfbe915c2f56
+PODFILE CHECKSUM: 8c6ad4fe8e5aa667e06c9b43f3f5d4d6430b1322
 
 COCOAPODS: 1.2.1
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/AppDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/AppDelegate.h
new file mode 100644
index 0000000..52e80c4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/AppDelegate.h
@@ -0,0 +1,24 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/AppDelegate.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/AppDelegate.m
new file mode 100644
index 0000000..dfabd8a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/AppDelegate.m
@@ -0,0 +1,67 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "AppDelegate.h"
+#import "ProductGridViewController.h"
+#import "ProductStorageHelper.h"
+
+#import "MaterialSnackbar.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+  // Instantiate a UITabBarController with 3 ProductGridViewControllers
+  NSString *const mainStoryboardName = @"ProductGrid";
+  ProductGridViewController *home = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil].instantiateInitialViewController;
+  home.isHome = YES;
+  home.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -4);
+  home.tabBarItem.title = @"Home";
+  home.tabBarItem.image = [UIImage imageNamed:@"Diamond"];
+  home.products = productsFor(ProductCategoryHome);
+
+  ProductGridViewController *clothing = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil].instantiateInitialViewController;
+  clothing.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -4);
+  clothing.tabBarItem.title = @"Clothing";
+  clothing.tabBarItem.image = [UIImage imageNamed:@"HeartFull"];
+  clothing.products = productsFor(ProductCategoryClothing);
+
+  ProductGridViewController *popsicles = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil].instantiateInitialViewController;
+  popsicles.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -4);
+  popsicles.tabBarItem.title = @"Popsicles";
+  popsicles.tabBarItem.image = [UIImage imageNamed:@"Cart"];
+  popsicles.products = productsFor(ProductCategoryPopsicles);
+
+  UITabBarController *tabBarController = [[UITabBarController alloc] init];
+  tabBarController.viewControllers = @[ clothing, home, popsicles ];
+  tabBarController.tabBar.tintColor = [UIColor colorWithRed:96/255.0 green:125/255.0 blue:139/255.0 alpha:1];
+  tabBarController.selectedIndex = 1;
+
+  // Make the UITabBarController the main interface of the app
+  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+  self.window.rootViewController = tabBarController;
+  [self.window makeKeyAndVisible];
+
+  [MDCSnackbarManager setBottomOffset:tabBarController.tabBar.bounds.size.height];
+
+  return YES;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..e21c852
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "logo2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "logo3x.png",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "logo_76.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "logo_76_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "83.5x83.5",
+      "idiom" : "ipad",
+      "filename" : "logo_167.png",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo2x.png
new file mode 100644
index 0000000..c72c0c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo3x.png
new file mode 100644
index 0000000..01a53b6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_167.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_167.png
new file mode 100644
index 0000000..8843740
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_167.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76.png
new file mode 100644
index 0000000..b55437f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76_2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76_2x.png
new file mode 100644
index 0000000..d36c2e4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76_2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart.png
new file mode 100644
index 0000000..4eec7bb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@2x.png
new file mode 100644
index 0000000..c92dc6e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@3x.png
new file mode 100644
index 0000000..fc24519
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Contents.json
new file mode 100644
index 0000000..f8c76ae
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "Cart.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Cart@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Cart@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Contents.json
new file mode 100644
index 0000000..08bad59
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "Diamond.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Diamond@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Diamond@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond.png
new file mode 100644
index 0000000..bf00e92
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@2x.png
new file mode 100644
index 0000000..ac2cd5a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@3x.png
new file mode 100644
index 0000000..d3c667e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/Contents.json
new file mode 100644
index 0000000..fa1c88e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "HeartEmpty.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartEmpty@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartEmpty@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty.png
new file mode 100644
index 0000000..97115f7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@2x.png
new file mode 100644
index 0000000..85b0f2b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@3x.png
new file mode 100644
index 0000000..11ee824
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/Contents.json
new file mode 100644
index 0000000..bce9af1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "HeartOpaque.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartOpaque@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartOpaque@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque.png
new file mode 100644
index 0000000..37796f8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@2x.png
new file mode 100644
index 0000000..5b7d16e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@3x.png
new file mode 100644
index 0000000..78b13e6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Contents.json
new file mode 100644
index 0000000..9978607
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "Shrine_logo_launchscreen.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Shrine_logo_launchscreen.pdf b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Shrine_logo_launchscreen.pdf
new file mode 100644
index 0000000..beb3e1e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Shrine_logo_launchscreen.pdf
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/Contents.json
new file mode 100644
index 0000000..2d8fc36
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "shrine_logo_withicon.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/shrine_logo_withicon.pdf b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/shrine_logo_withicon.pdf
new file mode 100644
index 0000000..a16bede
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/shrine_logo_withicon.pdf
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/Contents.json
new file mode 100644
index 0000000..35488c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "shrine_text_logo.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/shrine_text_logo.pdf b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/shrine_text_logo.pdf
new file mode 100644
index 0000000..4842ea2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/shrine_text_logo.pdf
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Base.lproj/LaunchScreen.storyboard b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..fdf3f97
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Base.lproj/ProductGrid.storyboard b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Base.lproj/ProductGrid.storyboard
new file mode 100644
index 0000000..042ad8a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Base.lproj/ProductGrid.storyboard
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="a5o-Vp-6qw">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+        <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Product Grid View Controller-->
+        <scene sceneID="Lyg-Jc-kew">
+            <objects>
+                <collectionViewController id="a5o-Vp-6qw" customClass="ProductGridViewController" sceneMemberID="viewController">
+                    <collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="KFO-tS-zxM">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="U4F-Lr-tIB">
+                            <size key="itemSize" width="157" height="191"/>
+                            <size key="headerReferenceSize" width="0.0" height="0.0"/>
+                            <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                            <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                        </collectionViewFlowLayout>
+                        <cells>
+                            <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="Cs7-hN-5ih" customClass="ProductCollectionViewCell">
+                                <rect key="frame" x="0.0" y="0.0" width="157" height="191"/>
+                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                                    <rect key="frame" x="0.0" y="0.0" width="157" height="191"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ujR-N6-x2H">
+                                            <rect key="frame" x="4" y="4" width="149" height="149"/>
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" secondItem="ujR-N6-x2H" secondAttribute="height" id="Jsg-SG-uqa"/>
+                                            </constraints>
+                                        </imageView>
+                                        <button opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vRd-OH-xYh" customClass="MDCFlatButton">
+                                            <rect key="frame" x="119" y="153" width="38" height="38"/>
+                                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" secondItem="vRd-OH-xYh" secondAttribute="height" id="9NK-Of-LLD"/>
+                                                <constraint firstAttribute="width" constant="38" id="Yu0-Un-EAx"/>
+                                            </constraints>
+                                            <color key="tintColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <state key="normal" image="HeartEmpty"/>
+                                            <state key="selected" image="HeartFull"/>
+                                        </button>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="$XX" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aNr-ue-aFb">
+                                            <rect key="frame" x="115" y="8" width="34" height="21"/>
+                                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
+                                            <color key="textColor" red="0.035294117647058823" green="0.19215686274509802" blue="0.25882352941176467" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                    </subviews>
+                                </view>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                <constraints>
+                                    <constraint firstAttribute="trailing" secondItem="aNr-ue-aFb" secondAttribute="trailing" constant="8" id="6v7-id-quN"/>
+                                    <constraint firstAttribute="trailing" secondItem="ujR-N6-x2H" secondAttribute="trailing" constant="4" id="EXQ-Gu-gxF"/>
+                                    <constraint firstAttribute="bottom" secondItem="vRd-OH-xYh" secondAttribute="bottom" id="GU2-mP-pdc"/>
+                                    <constraint firstItem="ujR-N6-x2H" firstAttribute="leading" secondItem="Cs7-hN-5ih" secondAttribute="leading" constant="4" id="eZb-A2-2J0"/>
+                                    <constraint firstAttribute="trailing" secondItem="vRd-OH-xYh" secondAttribute="trailing" id="l5g-6E-n42"/>
+                                    <constraint firstItem="ujR-N6-x2H" firstAttribute="top" secondItem="Cs7-hN-5ih" secondAttribute="top" constant="4" id="qNY-Y8-cuL"/>
+                                    <constraint firstItem="aNr-ue-aFb" firstAttribute="top" secondItem="Cs7-hN-5ih" secondAttribute="top" constant="8" id="vYS-Gb-pED"/>
+                                </constraints>
+                                <connections>
+                                    <outlet property="favoriteButton" destination="vRd-OH-xYh" id="y7v-5O-akJ"/>
+                                    <outlet property="imageView" destination="ujR-N6-x2H" id="LYp-6N-Kxm"/>
+                                    <outlet property="priceLabel" destination="aNr-ue-aFb" id="bQh-HB-Rbd"/>
+                                </connections>
+                            </collectionViewCell>
+                        </cells>
+                        <connections>
+                            <outlet property="dataSource" destination="a5o-Vp-6qw" id="Fmh-r6-bYu"/>
+                            <outlet property="delegate" destination="a5o-Vp-6qw" id="5Wf-zl-fAA"/>
+                        </connections>
+                    </collectionView>
+                    <connections>
+                        <outlet property="headerContentView" destination="Wgr-bd-yYT" id="GOd-dQ-Wb2"/>
+                        <outlet property="shrineLogo" destination="664-A7-GNa" id="9ob-Jw-aKp"/>
+                    </connections>
+                </collectionViewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Bum-ch-p73" userLabel="First Responder" sceneMemberID="firstResponder"/>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ShrineLogo" id="664-A7-GNa">
+                    <rect key="frame" x="0.0" y="0.0" width="136" height="52"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                </imageView>
+                <view contentMode="scaleToFill" id="Wgr-bd-yYT" userLabel="HeaderContentView" customClass="HomeHeaderView">
+                    <rect key="frame" x="0.0" y="0.0" width="320" height="420"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="fishbowl.png" translatesAutoresizingMaskIntoConstraints="NO" id="dJV-WH-exb">
+                            <rect key="frame" x="-70" y="0.0" width="320" height="420"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="420" id="IhW-sV-TVC"/>
+                            </constraints>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Best Gift for Teen Girls" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="78U-jz-TLC">
+                            <rect key="frame" x="131" y="186" width="189" height="81.5"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="189" id="svA-re-Txy"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="34"/>
+                            <color key="textColor" red="0.035294117647058823" green="0.19215686274509802" blue="0.25882352941176467" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Choose fun, exciting, and unique gifts every girl will love." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="i9y-di-e68">
+                            <rect key="frame" x="133" y="272.5" width="187" height="29"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                            <color key="textColor" red="0.035294117647058823" green="0.19215686274509802" blue="0.25882352941176467" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ShrineTextLogo" translatesAutoresizingMaskIntoConstraints="NO" id="abA-kk-gjn">
+                            <rect key="frame" x="131" y="169" width="89" height="17"/>
+                        </imageView>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="78U-jz-TLC" secondAttribute="trailing" id="G05-qm-bnJ"/>
+                        <constraint firstItem="78U-jz-TLC" firstAttribute="leading" secondItem="abA-kk-gjn" secondAttribute="leading" id="LwH-zL-HId"/>
+                        <constraint firstItem="dJV-WH-exb" firstAttribute="leading" secondItem="Wgr-bd-yYT" secondAttribute="leading" constant="-70" id="QHB-jn-Yck"/>
+                        <constraint firstAttribute="bottom" secondItem="dJV-WH-exb" secondAttribute="bottom" id="Rzm-wk-8i1"/>
+                        <constraint firstAttribute="trailing" secondItem="i9y-di-e68" secondAttribute="trailing" id="hjZ-oC-zI1"/>
+                        <constraint firstItem="78U-jz-TLC" firstAttribute="top" secondItem="abA-kk-gjn" secondAttribute="bottom" id="kct-lJ-PSa"/>
+                        <constraint firstItem="i9y-di-e68" firstAttribute="top" secondItem="78U-jz-TLC" secondAttribute="bottom" constant="5" id="q8S-am-z3h"/>
+                        <constraint firstAttribute="trailing" secondItem="dJV-WH-exb" secondAttribute="trailing" constant="70" id="qjz-2J-hIJ"/>
+                        <constraint firstAttribute="bottom" secondItem="i9y-di-e68" secondAttribute="bottom" constant="118.5" id="yc3-UC-Skv"/>
+                        <constraint firstItem="i9y-di-e68" firstAttribute="leading" secondItem="78U-jz-TLC" secondAttribute="leading" constant="2" id="z0J-BQ-Up7"/>
+                    </constraints>
+                    <connections>
+                        <outlet property="backgroundImage" destination="dJV-WH-exb" id="M37-lX-kJy"/>
+                        <outlet property="descLabel" destination="i9y-di-e68" id="vLN-Z0-XeX"/>
+                        <outlet property="textLogo" destination="abA-kk-gjn" id="LoF-SO-j4N"/>
+                        <outlet property="titleLabel" destination="78U-jz-TLC" id="3gR-7M-u3W"/>
+                    </connections>
+                </view>
+            </objects>
+            <point key="canvasLocation" x="584.79999999999995" y="389.95502248875567"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="HeartEmpty" width="20" height="18"/>
+        <image name="HeartFull" width="20" height="18"/>
+        <image name="ShrineLogo" width="100" height="30"/>
+        <image name="ShrineTextLogo" width="89" height="17"/>
+        <image name="fishbowl.png" width="1000" height="1000"/>
+    </resources>
+</document>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Info.plist
new file mode 100644
index 0000000..0482c40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Info.plist
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UIStatusBarTintParameters</key>
+	<dict>
+		<key>UINavigationBar</key>
+		<dict>
+			<key>Style</key>
+			<string>UIBarStyleDefault</string>
+			<key>Translucent</key>
+			<false/>
+		</dict>
+	</dict>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/ProductGridViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/ProductGridViewController.h
new file mode 100644
index 0000000..f197111
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/ProductGridViewController.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import "MaterialCollections.h"
+
+@class Product;
+
+@interface ProductGridViewController : MDCCollectionViewController
+
+@property(nonatomic) BOOL isHome;
+@property(nonatomic) NSArray <Product *> *products;
+
+@end
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/ProductGridViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/ProductGridViewController.m
new file mode 100644
index 0000000..e8fe1f7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/ProductGridViewController.m
@@ -0,0 +1,211 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "ProductGridViewController.h"
+#import "ProductCollectionViewCell.h"
+#import "Product.h"
+#import "HomeHeaderView.h"
+
+#import "MaterialButtons.h"
+#import "MaterialAppBar.h"
+#import "MaterialSnackbar.h"
+
+@interface ProductGridViewController ()
+
+@property(nonatomic) MDCAppBar *appBar;
+@property(nonatomic) IBOutlet HomeHeaderView *headerContentView;
+@property(nonatomic) IBOutlet UIImageView *shrineLogo;
+
+@end
+
+@implementation ProductGridViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  self.collectionView.contentInset = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.bounds.size.height, 0);
+
+  self.appBar = [[MDCAppBar alloc] init];
+  [self addChildViewController:self.appBar.headerViewController];
+  [self.appBar addSubviewsToParent];
+  self.appBar.headerViewController.headerView.trackingScrollView = self.collectionView;
+  self.appBar.headerViewController.headerView.backgroundColor = [UIColor whiteColor];
+  self.appBar.headerViewController.headerView.maximumHeight = 440;
+  self.appBar.headerViewController.headerView.minimumHeight = 72;
+
+  if (self.isHome) {
+    [self setupHeaderContentView];
+    [self setupHeaderLogo];
+  }
+
+  self.title = self.tabBarItem.title;
+
+  self.styler.cellStyle = MDCCollectionViewCellStyleCard;
+  self.styler.cellLayoutType = MDCCollectionViewCellLayoutTypeGrid;
+  self.styler.gridPadding = 8;
+  [self updateLayout];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+  [self updateLayout];
+}
+
+#pragma mark - Rotation and Screen size
+
+- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+  [self updateLayout];
+}
+
+- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
+  [super traitCollectionDidChange:previousTraitCollection];
+  [self updateLayout];
+}
+
+- (void)updateLayout {
+  [self sizeHeaderView];
+
+  if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
+    self.styler.gridColumnCount = 5;
+  } else {
+    switch (self.traitCollection.horizontalSizeClass) {
+      case UIUserInterfaceSizeClassCompact:
+        self.styler.gridColumnCount = 2;
+        break;
+      case UIUserInterfaceSizeClassUnspecified:
+      case UIUserInterfaceSizeClassRegular:
+        self.styler.gridColumnCount = 3;
+        break;
+    }
+  }
+
+  [self.collectionView.collectionViewLayout invalidateLayout];
+}
+
+#pragma mark - Header
+
+- (void)setupHeaderContentView {
+  [self.appBar.headerViewController.headerView addSubview:self.headerContentView];
+  self.headerContentView.frame = self.appBar.headerViewController.headerView.frame;
+  self.headerContentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+}
+
+- (void)sizeHeaderView {
+  MDCFlexibleHeaderView *headerView = self.appBar.headerViewController.headerView;
+  CGRect bounds = [UIScreen mainScreen].bounds;
+  if (self.isHome && bounds.size.width < bounds.size.height) {
+    headerView.maximumHeight = 440;
+  } else {
+    headerView.maximumHeight = 72;
+  }
+  headerView.minimumHeight = 72;
+}
+
+- (void)setupHeaderLogo {
+  [self.appBar.headerViewController.headerView addSubview:self.shrineLogo];
+  [self.shrineLogo.topAnchor constraintEqualToAnchor:self.shrineLogo.superview.topAnchor constant:24].active = YES;
+  [self.shrineLogo.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
+  self.shrineLogo.translatesAutoresizingMaskIntoConstraints = NO;
+
+  self.shrineLogo.alpha = 0;
+}
+
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+  [self.appBar.headerViewController scrollViewDidScroll:scrollView];
+  CGFloat scrollOffsetY = scrollView.contentOffset.y;
+  CGFloat opacity = 1.0;
+
+  if (scrollOffsetY > -240) {
+    opacity = 0;
+  }
+
+  CGFloat logoOpacity = 0.0;
+
+  if (scrollOffsetY > -200) {
+    logoOpacity = 1.0;
+  }
+
+  [UIView animateWithDuration:0.5 animations:^{
+    self.headerContentView.backgroundImage.alpha = opacity;
+    self.headerContentView.descLabel.alpha = opacity;
+    self.headerContentView.titleLabel.alpha = opacity;
+
+    self.shrineLogo.alpha = logoOpacity;
+  }];
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+  if (scrollView == self.appBar.headerViewController.headerView.trackingScrollView) {
+    [self.appBar.headerViewController.headerView trackingScrollViewDidEndDecelerating];
+  }
+}
+
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
+  MDCFlexibleHeaderView *headerView = self.appBar.headerViewController.headerView;
+  if (scrollView == headerView.trackingScrollView) {
+    [headerView trackingScrollViewDidEndDraggingWillDecelerate:decelerate];
+  }
+}
+
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
+                     withVelocity:(CGPoint)velocity
+              targetContentOffset:(inout CGPoint *)targetContentOffset {
+  MDCFlexibleHeaderView *headerView = self.appBar.headerViewController.headerView;
+  if (scrollView == headerView.trackingScrollView) {
+    [headerView trackingScrollViewWillEndDraggingWithVelocity:velocity
+                                          targetContentOffset:targetContentOffset];
+  }
+}
+
+#pragma mark - Target / Action
+
+- (void)favoriteButtonDidTouch:(UIButton *)sender {
+  Product *product = self.products[sender.tag];
+  product.isFavorite = !product.isFavorite;
+  [self.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:sender.tag inSection:0]]];
+
+  if (product.isFavorite) {
+    [MDCSnackbarManager showMessage:[MDCSnackbarMessage messageWithText:@"Added to favorites!"]];
+  }
+}
+
+#pragma mark - CollectionView DataSource
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  ProductCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
+  cell.product = self.products[indexPath.item];
+
+  cell.favoriteButton.tag = indexPath.item;
+  if (![cell.favoriteButton.allTargets containsObject:self]) {
+    [cell.favoriteButton addTarget:self action:@selector(favoriteButtonDidTouch:) forControlEvents:UIControlEventTouchUpInside];
+  }
+
+  return cell;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+  return self.products.count;
+}
+
+#pragma mark - MDCCollectionViewStylingDelegate
+
+- (CGFloat)collectionView:(UICollectionView *)collectionView cellHeightAtIndexPath:(NSIndexPath *)indexPath {
+  return (collectionView.bounds.size.width - (self.styler.gridColumnCount + 1) * self.styler.gridColumnCount) * 5/4.f / self.styler.gridColumnCount;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/backpack.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/backpack.png
new file mode 100644
index 0000000..c6d3c11
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/backpack.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/binoculars.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/binoculars.png
new file mode 100644
index 0000000..c759674
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/binoculars.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/chucks.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/chucks.png
new file mode 100755
index 0000000..9a893f6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/chucks.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/flippers.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/flippers.png
new file mode 100755
index 0000000..f9acb2e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/flippers.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/heels.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/heels.png
new file mode 100755
index 0000000..cbdbb56
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/heels.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/helmet.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/helmet.png
new file mode 100755
index 0000000..b39a8c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/helmet.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/lipstick.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/lipstick.png
new file mode 100755
index 0000000..eab0c25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/lipstick.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/shoes.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/shoes.png
new file mode 100755
index 0000000..92030a8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/shoes.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/sunnies.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/sunnies.png
new file mode 100755
index 0000000..771c609
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/sunnies.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/umbrella.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/umbrella.png
new file mode 100755
index 0000000..c778e2c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Clothing/umbrella.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/beachball.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/beachball.png
new file mode 100755
index 0000000..22248fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/beachball.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/brush.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/brush.png
new file mode 100755
index 0000000..9ab9dbc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/brush.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/chair.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/chair.png
new file mode 100755
index 0000000..038fd42
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/chair.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/clock.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/clock.png
new file mode 100755
index 0000000..3fb14fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/clock.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/fishbowl.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/fishbowl.png
new file mode 100755
index 0000000..34d22f4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/fishbowl.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/lamp.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/lamp.png
new file mode 100755
index 0000000..fab2ffc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/lamp.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/lawnchair.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/lawnchair.png
new file mode 100755
index 0000000..bae60d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/lawnchair.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/pen.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/pen.png
new file mode 100755
index 0000000..7e35d40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/pen.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/radio.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/radio.png
new file mode 100755
index 0000000..e724064
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/radio.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/surfboard.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/surfboard.png
new file mode 100755
index 0000000..5eaf34d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/surfboard.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/teapot.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/teapot.png
new file mode 100755
index 0000000..5bdb62d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/teapot.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/tools.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/tools.png
new file mode 100755
index 0000000..f9b9383
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/tools.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/typewriter.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/typewriter.png
new file mode 100755
index 0000000..d2790bf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Home/typewriter.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/HomeHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/HomeHeaderView.h
new file mode 100644
index 0000000..4b4c7b3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/HomeHeaderView.h
@@ -0,0 +1,26 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface HomeHeaderView : UIView
+
+@property (weak, nonatomic) IBOutlet UIImageView *backgroundImage;
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
+@property (weak, nonatomic) IBOutlet UIImageView *textLogo;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/HomeHeaderView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/HomeHeaderView.m
new file mode 100644
index 0000000..209540b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/HomeHeaderView.m
@@ -0,0 +1,21 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "HomeHeaderView.h"
+
+@implementation HomeHeaderView
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Images/fishbowl.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Images/fishbowl.png
new file mode 100755
index 0000000..34d22f4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Images/fishbowl.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Images/popsicle.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Images/popsicle.png
new file mode 100755
index 0000000..e35e8a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Images/popsicle.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Product.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Product.h
new file mode 100644
index 0000000..0dee839
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Product.h
@@ -0,0 +1,25 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface Product : NSObject
+
+@property(nonatomic) NSString *imagePath;
+@property(nonatomic) NSString *price;
+@property(nonatomic) BOOL isFavorite;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Product.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Product.m
new file mode 100644
index 0000000..592cf20
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/Product.m
@@ -0,0 +1,38 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "Product.h"
+
+@implementation Product
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    // Random price
+    int price = arc4random() % 100;
+    self.price = [NSString stringWithFormat:@"$%d", price];
+  }
+  return self;
+}
+
+- (BOOL)isEqual:(id)object {
+  return [object isMemberOfClass:[self class]] &&
+  [((Product*)object).price isEqualToString:self.price] &&
+  [((Product*)object).imagePath isEqualToString:self.imagePath] &&
+  ((Product*)object).isFavorite == self.isFavorite;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.h
new file mode 100644
index 0000000..bf17633
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class Product;
+@class MDCButton;
+
+@interface ProductCollectionViewCell : UICollectionViewCell
+
+@property(nonatomic) Product *product;
+@property(nonatomic) IBOutlet MDCButton *favoriteButton;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.m
new file mode 100644
index 0000000..c96644f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.m
@@ -0,0 +1,51 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "ProductCollectionViewCell.h"
+#import "Product.h"
+
+#import "MaterialButtons.h"
+
+@interface ProductCollectionViewCell ()
+
+@property(nonatomic) IBOutlet UIImageView *imageView;
+@property(nonatomic) IBOutlet UILabel *priceLabel;
+
+@end
+
+@implementation ProductCollectionViewCell
+
+- (void)awakeFromNib {
+  [super awakeFromNib];
+  self.favoriteButton.contentEdgeInsets = UIEdgeInsetsZero;
+  UIImage *image = [[self.favoriteButton imageForState:UIControlStateNormal] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  [self.favoriteButton setImage:image forState:UIControlStateNormal];
+
+  image = [[self.favoriteButton imageForState:UIControlStateSelected] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  [self.favoriteButton setImage:image forState:UIControlStateSelected];
+}
+
+- (void)setProduct:(Product *)product {
+  if (![_product isEqual:product]) {
+    _product = product;
+
+    self.imageView.image = [UIImage imageWithContentsOfFile:product.imagePath];
+    self.priceLabel.text = product.price;
+    self.favoriteButton.selected = product.isFavorite;
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductStorageHelper.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductStorageHelper.h
new file mode 100644
index 0000000..3c476f7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/Supplemental/ProductStorageHelper.h
@@ -0,0 +1,62 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "Product.h"
+
+@class Product;
+
+typedef NS_ENUM(NSUInteger, ProductCategory) {
+  ProductCategoryHome,
+  ProductCategoryClothing,
+  ProductCategoryPopsicles,
+};
+
+static inline NSArray <Product *> *productsFor(ProductCategory category) {
+  NSString *const pngExtension = @"png";
+  NSString *folderPath;
+  NSMutableArray <NSString *> *files = [NSMutableArray array];
+
+  switch (category) {
+    case ProductCategoryPopsicles: {
+      // 16 popsicles
+      for (int i = 0; i < 16; ++i) {
+        [files addObject:[[NSBundle mainBundle] pathForResource:@"popsicle" ofType:pngExtension]];
+      }
+    }
+      break;
+    case ProductCategoryClothing:
+      folderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Clothing"];
+      // Fallthru
+    case ProductCategoryHome:
+      folderPath = folderPath ?: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Home"];
+      
+      NSError *error;
+      NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error];
+      for (NSString *fileName in fileNames) {
+        [files addObject:[folderPath stringByAppendingPathComponent:fileName]];
+      }
+      break;
+  }
+
+  NSMutableArray *mutableProducts = [NSMutableArray array];
+  for (NSString *path in files) {
+    Product *product = [[Product alloc] init];
+    product.imagePath = path;
+    [mutableProducts addObject:product];
+  }
+  return [NSArray arrayWithArray:mutableProducts];
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/main.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/main.m
new file mode 100644
index 0000000..9028428
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulApps/main.m
@@ -0,0 +1,16 @@
+//
+//  main.m
+//  ShrineCodelabObjc
+//
+//  Created by Will Larche on 4/19/17.
+//  Copyright © 2017 Will Larche. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+  @autoreleasepool {
+      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+  }
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/project.pbxproj b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..fe43429
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/project.pbxproj
@@ -0,0 +1,460 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		36625A771EA869DA00A0E2AD /* HomeHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 36625A761EA869DA00A0E2AD /* HomeHeaderView.m */; };
+		36625A791EA86D3200A0E2AD /* fishbowl.png in Resources */ = {isa = PBXBuildFile; fileRef = 36625A781EA86D3200A0E2AD /* fishbowl.png */; };
+		36DABBA51EA7F0E700906586 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBA41EA7F0E700906586 /* main.m */; };
+		36DABBA81EA7F0E700906586 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBA71EA7F0E700906586 /* AppDelegate.m */; };
+		36DABBAB1EA7F0E700906586 /* ProductGridViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBAA1EA7F0E700906586 /* ProductGridViewController.m */; };
+		36DABBB11EA7F0E700906586 /* ProductGrid.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBAF1EA7F0E700906586 /* ProductGrid.storyboard */; };
+		36DABBB31EA7F0E700906586 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBB21EA7F0E700906586 /* Assets.xcassets */; };
+		36DABBB61EA7F0E700906586 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBB41EA7F0E700906586 /* LaunchScreen.storyboard */; };
+		36DABBBF1EA812B200906586 /* ProductCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBBE1EA812B200906586 /* ProductCollectionViewCell.m */; };
+		36DABBC21EA8166200906586 /* Product.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBC11EA8166200906586 /* Product.m */; };
+		36DABBF91EA82E5800906586 /* popsicle.png in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBE11EA82E5800906586 /* popsicle.png */; };
+		36DABC301EA833A700906586 /* Clothing in Resources */ = {isa = PBXBuildFile; fileRef = 36DABC2E1EA833A700906586 /* Clothing */; };
+		36DABC311EA833A700906586 /* Home in Resources */ = {isa = PBXBuildFile; fileRef = 36DABC2F1EA833A700906586 /* Home */; };
+		EB711BFCEEE7BF2237D99896 /* libPods-BuildingBeautifulApps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D967962C61FD651D0BC490A2 /* libPods-BuildingBeautifulApps.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		14F6B115B062FC99E50F1F41 /* Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulAppsObjcComplete/Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig"; sourceTree = "<group>"; };
+		1E77988AD077916A17CF5F2D /* libPods-ShrineCodelabObjc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ShrineCodelabObjc.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		26364F6243F3061661E5BB6A /* Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulAppsObjcComplete/Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig"; sourceTree = "<group>"; };
+		36625A751EA869DA00A0E2AD /* HomeHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HomeHeaderView.h; path = ../Supplemental/HomeHeaderView.h; sourceTree = "<group>"; };
+		36625A761EA869DA00A0E2AD /* HomeHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HomeHeaderView.m; path = ../Supplemental/HomeHeaderView.m; sourceTree = "<group>"; };
+		36625A781EA86D3200A0E2AD /* fishbowl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fishbowl.png; sourceTree = "<group>"; };
+		36DABBA01EA7F0E700906586 /* BuildingBeautifulApps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BuildingBeautifulApps.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		36DABBA41EA7F0E700906586 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		36DABBA61EA7F0E700906586 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		36DABBA71EA7F0E700906586 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		36DABBA91EA7F0E700906586 /* ProductGridViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProductGridViewController.h; sourceTree = "<group>"; };
+		36DABBAA1EA7F0E700906586 /* ProductGridViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ProductGridViewController.m; sourceTree = "<group>"; };
+		36DABBB01EA7F0E700906586 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/ProductGrid.storyboard; sourceTree = "<group>"; };
+		36DABBB21EA7F0E700906586 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		36DABBB51EA7F0E700906586 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		36DABBB71EA7F0E700906586 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		36DABBBD1EA812B200906586 /* ProductCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductCollectionViewCell.h; sourceTree = "<group>"; };
+		36DABBBE1EA812B200906586 /* ProductCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductCollectionViewCell.m; sourceTree = "<group>"; };
+		36DABBC01EA8166200906586 /* Product.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Product.h; sourceTree = "<group>"; };
+		36DABBC11EA8166200906586 /* Product.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Product.m; sourceTree = "<group>"; };
+		36DABBC41EA8194900906586 /* ProductStorageHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductStorageHelper.h; sourceTree = "<group>"; };
+		36DABBE11EA82E5800906586 /* popsicle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = popsicle.png; sourceTree = "<group>"; };
+		36DABC2E1EA833A700906586 /* Clothing */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Clothing; sourceTree = "<group>"; };
+		36DABC2F1EA833A700906586 /* Home */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Home; sourceTree = "<group>"; };
+		475C1BCD7153021C09BABEA7 /* Pods-BuildingBeautifulApps.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulApps.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig"; sourceTree = "<group>"; };
+		5FF09E137DA3C50D9A38C1C3 /* libPods-BuildingBeautifulAppsObjcComplete.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BuildingBeautifulAppsObjcComplete.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		84F26C556113B9B6F06AE5E0 /* Pods-BuildingBeautifulApps.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulApps.release.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig"; sourceTree = "<group>"; };
+		9D1E5807E130C987D54DAE15 /* Pods-ShrineCodelabObjc.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShrineCodelabObjc.release.xcconfig"; path = "Pods/Target Support Files/Pods-ShrineCodelabObjc/Pods-ShrineCodelabObjc.release.xcconfig"; sourceTree = "<group>"; };
+		D967962C61FD651D0BC490A2 /* libPods-BuildingBeautifulApps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BuildingBeautifulApps.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		F0B0363E04251F4B2787BD47 /* Pods-ShrineCodelabObjc.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShrineCodelabObjc.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShrineCodelabObjc/Pods-ShrineCodelabObjc.debug.xcconfig"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		36DABB9D1EA7F0E700906586 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				EB711BFCEEE7BF2237D99896 /* libPods-BuildingBeautifulApps.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		1EB15273881A22502C68AA78 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				1E77988AD077916A17CF5F2D /* libPods-ShrineCodelabObjc.a */,
+				5FF09E137DA3C50D9A38C1C3 /* libPods-BuildingBeautifulAppsObjcComplete.a */,
+				D967962C61FD651D0BC490A2 /* libPods-BuildingBeautifulApps.a */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		36DABB971EA7F0E700906586 = {
+			isa = PBXGroup;
+			children = (
+				36DABBA21EA7F0E700906586 /* BuildingBeautifulApps */,
+				36DABBA11EA7F0E700906586 /* Products */,
+				80F36927416F68DD55EC31B8 /* Pods */,
+				1EB15273881A22502C68AA78 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		36DABBA11EA7F0E700906586 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				36DABBA01EA7F0E700906586 /* BuildingBeautifulApps.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		36DABBA21EA7F0E700906586 /* BuildingBeautifulApps */ = {
+			isa = PBXGroup;
+			children = (
+				36DABBA61EA7F0E700906586 /* AppDelegate.h */,
+				36DABBA71EA7F0E700906586 /* AppDelegate.m */,
+				36DABBA91EA7F0E700906586 /* ProductGridViewController.h */,
+				36DABBAA1EA7F0E700906586 /* ProductGridViewController.m */,
+				36DABBAF1EA7F0E700906586 /* ProductGrid.storyboard */,
+				36DABBC31EA8169C00906586 /* Supplemental */,
+				36DABBB21EA7F0E700906586 /* Assets.xcassets */,
+				36DABBB41EA7F0E700906586 /* LaunchScreen.storyboard */,
+				36DABBB71EA7F0E700906586 /* Info.plist */,
+				36DABBA31EA7F0E700906586 /* Supporting Files */,
+			);
+			path = BuildingBeautifulApps;
+			sourceTree = "<group>";
+		};
+		36DABBA31EA7F0E700906586 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				36DABBA41EA7F0E700906586 /* main.m */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		36DABBC31EA8169C00906586 /* Supplemental */ = {
+			isa = PBXGroup;
+			children = (
+				36DABC2E1EA833A700906586 /* Clothing */,
+				36DABC2F1EA833A700906586 /* Home */,
+				36DABBC71EA82E5800906586 /* Images */,
+				36DABBC01EA8166200906586 /* Product.h */,
+				36DABBC11EA8166200906586 /* Product.m */,
+				36DABBBD1EA812B200906586 /* ProductCollectionViewCell.h */,
+				36DABBBE1EA812B200906586 /* ProductCollectionViewCell.m */,
+				36625A751EA869DA00A0E2AD /* HomeHeaderView.h */,
+				36625A761EA869DA00A0E2AD /* HomeHeaderView.m */,
+				36DABBC41EA8194900906586 /* ProductStorageHelper.h */,
+			);
+			path = Supplemental;
+			sourceTree = "<group>";
+		};
+		36DABBC71EA82E5800906586 /* Images */ = {
+			isa = PBXGroup;
+			children = (
+				36625A781EA86D3200A0E2AD /* fishbowl.png */,
+				36DABBE11EA82E5800906586 /* popsicle.png */,
+			);
+			path = Images;
+			sourceTree = "<group>";
+		};
+		80F36927416F68DD55EC31B8 /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				F0B0363E04251F4B2787BD47 /* Pods-ShrineCodelabObjc.debug.xcconfig */,
+				9D1E5807E130C987D54DAE15 /* Pods-ShrineCodelabObjc.release.xcconfig */,
+				14F6B115B062FC99E50F1F41 /* Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig */,
+				26364F6243F3061661E5BB6A /* Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig */,
+				475C1BCD7153021C09BABEA7 /* Pods-BuildingBeautifulApps.debug.xcconfig */,
+				84F26C556113B9B6F06AE5E0 /* Pods-BuildingBeautifulApps.release.xcconfig */,
+			);
+			name = Pods;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		36DABB9F1EA7F0E700906586 /* BuildingBeautifulApps */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 36DABBBA1EA7F0E700906586 /* Build configuration list for PBXNativeTarget "BuildingBeautifulApps" */;
+			buildPhases = (
+				2ED5460D364563253D57F229 /* [CP] Check Pods Manifest.lock */,
+				36DABB9C1EA7F0E700906586 /* Sources */,
+				36DABB9D1EA7F0E700906586 /* Frameworks */,
+				36DABB9E1EA7F0E700906586 /* Resources */,
+				749A29FFDF664C69E2CF0C41 /* [CP] Embed Pods Frameworks */,
+				8D73756F76B06B68032DC382 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = BuildingBeautifulApps;
+			productName = ShrineCodelabObjc;
+			productReference = 36DABBA01EA7F0E700906586 /* BuildingBeautifulApps.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		36DABB981EA7F0E700906586 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0830;
+				ORGANIZATIONNAME = "Will Larche";
+				TargetAttributes = {
+					36DABB9F1EA7F0E700906586 = {
+						CreatedOnToolsVersion = 8.3.2;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = 36DABB9B1EA7F0E700906586 /* Build configuration list for PBXProject "BuildingBeautifulAppsObjcComplete" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 36DABB971EA7F0E700906586;
+			productRefGroup = 36DABBA11EA7F0E700906586 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				36DABB9F1EA7F0E700906586 /* BuildingBeautifulApps */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		36DABB9E1EA7F0E700906586 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				36DABBB61EA7F0E700906586 /* LaunchScreen.storyboard in Resources */,
+				36DABBB31EA7F0E700906586 /* Assets.xcassets in Resources */,
+				36625A791EA86D3200A0E2AD /* fishbowl.png in Resources */,
+				36DABBF91EA82E5800906586 /* popsicle.png in Resources */,
+				36DABBB11EA7F0E700906586 /* ProductGrid.storyboard in Resources */,
+				36DABC301EA833A700906586 /* Clothing in Resources */,
+				36DABC311EA833A700906586 /* Home in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		2ED5460D364563253D57F229 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			showEnvVarsInLog = 0;
+		};
+		749A29FFDF664C69E2CF0C41 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		8D73756F76B06B68032DC382 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Copy Pods Resources";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		36DABB9C1EA7F0E700906586 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				36DABBA81EA7F0E700906586 /* AppDelegate.m in Sources */,
+				36DABBC21EA8166200906586 /* Product.m in Sources */,
+				36625A771EA869DA00A0E2AD /* HomeHeaderView.m in Sources */,
+				36DABBAB1EA7F0E700906586 /* ProductGridViewController.m in Sources */,
+				36DABBBF1EA812B200906586 /* ProductCollectionViewCell.m in Sources */,
+				36DABBA51EA7F0E700906586 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		36DABBAF1EA7F0E700906586 /* ProductGrid.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				36DABBB01EA7F0E700906586 /* Base */,
+			);
+			name = ProductGrid.storyboard;
+			sourceTree = "<group>";
+		};
+		36DABBB41EA7F0E700906586 /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				36DABBB51EA7F0E700906586 /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		36DABBB81EA7F0E700906586 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		36DABBB91EA7F0E700906586 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		36DABBBB1EA7F0E700906586 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 475C1BCD7153021C09BABEA7 /* Pods-BuildingBeautifulApps.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				INFOPLIST_FILE = "$(SRCROOT)/BuildingBeautifulApps/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.mux.ShrineCodelabObjc;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		36DABBBC1EA7F0E700906586 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 84F26C556113B9B6F06AE5E0 /* Pods-BuildingBeautifulApps.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				INFOPLIST_FILE = "$(SRCROOT)/BuildingBeautifulApps/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.mux.ShrineCodelabObjc;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		36DABB9B1EA7F0E700906586 /* Build configuration list for PBXProject "BuildingBeautifulAppsObjcComplete" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				36DABBB81EA7F0E700906586 /* Debug */,
+				36DABBB91EA7F0E700906586 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		36DABBBA1EA7F0E700906586 /* Build configuration list for PBXNativeTarget "BuildingBeautifulApps" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				36DABBBB1EA7F0E700906586 /* Debug */,
+				36DABBBC1EA7F0E700906586 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 36DABB981EA7F0E700906586 /* Project object */;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..b5c5dd2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:ShrineCodelabObjc.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/xcshareddata/xcschemes/BuildingBeautifulAppsObjcComplete.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/xcshareddata/xcschemes/BuildingBeautifulAppsObjcComplete.xcscheme
new file mode 100644
index 0000000..077549c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcodeproj/xcshareddata/xcschemes/BuildingBeautifulAppsObjcComplete.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0830"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+               BuildableName = "BuildingBeautifulApps.app"
+               BlueprintName = "BuildingBeautifulApps"
+               ReferencedContainer = "container:BuildingBeautifulAppsObjcComplete.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+            BuildableName = "BuildingBeautifulApps.app"
+            BlueprintName = "BuildingBeautifulApps"
+            ReferencedContainer = "container:BuildingBeautifulAppsObjcComplete.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+            BuildableName = "BuildingBeautifulApps.app"
+            BlueprintName = "BuildingBeautifulApps"
+            ReferencedContainer = "container:BuildingBeautifulAppsObjcComplete.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+            BuildableName = "BuildingBeautifulApps.app"
+            BlueprintName = "BuildingBeautifulApps"
+            ReferencedContainer = "container:BuildingBeautifulAppsObjcComplete.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcworkspace/contents.xcworkspacedata b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..626eda3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/BuildingBeautifulAppsObjcComplete.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:BuildingBeautifulAppsObjcComplete.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Podfile b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Podfile
new file mode 100644
index 0000000..5528ac1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Podfile
@@ -0,0 +1,10 @@
+# Uncomment the next line to define a global platform for your project
+platform :ios, '9.0'
+
+target 'BuildingBeautifulApps' do
+  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
+  # use_frameworks!
+
+  # Pods for ShrineCodelabObjc
+  pod 'MaterialComponents'
+end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Podfile.lock b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Podfile.lock
new file mode 100644
index 0000000..c2ab666
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Podfile.lock
@@ -0,0 +1,166 @@
+PODS:
+  - MaterialComponents (23.0.1):
+    - MaterialComponents/ActivityIndicator (= 23.0.1)
+    - MaterialComponents/AnimationTiming (= 23.0.1)
+    - MaterialComponents/AppBar (= 23.0.1)
+    - MaterialComponents/ButtonBar (= 23.0.1)
+    - MaterialComponents/Buttons (= 23.0.1)
+    - MaterialComponents/CollectionCells (= 23.0.1)
+    - MaterialComponents/CollectionLayoutAttributes (= 23.0.1)
+    - MaterialComponents/Collections (= 23.0.1)
+    - MaterialComponents/Dialogs (= 23.0.1)
+    - MaterialComponents/FeatureHighlight (= 23.0.1)
+    - MaterialComponents/FlexibleHeader (= 23.0.1)
+    - MaterialComponents/HeaderStackView (= 23.0.1)
+    - MaterialComponents/Ink (= 23.0.1)
+    - MaterialComponents/NavigationBar (= 23.0.1)
+    - MaterialComponents/OverlayWindow (= 23.0.1)
+    - MaterialComponents/PageControl (= 23.0.1)
+    - MaterialComponents/Palettes (= 23.0.1)
+    - MaterialComponents/private (= 23.0.1)
+    - MaterialComponents/ProgressView (= 23.0.1)
+    - MaterialComponents/ShadowElevations (= 23.0.1)
+    - MaterialComponents/ShadowLayer (= 23.0.1)
+    - MaterialComponents/Slider (= 23.0.1)
+    - MaterialComponents/Snackbar (= 23.0.1)
+    - MaterialComponents/Tabs (= 23.0.1)
+    - MaterialComponents/Typography (= 23.0.1)
+  - MaterialComponents/ActivityIndicator (23.0.1):
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/RTL
+  - MaterialComponents/AnimationTiming (23.0.1)
+  - MaterialComponents/AppBar (23.0.1):
+    - MaterialComponents/FlexibleHeader
+    - MaterialComponents/HeaderStackView
+    - MaterialComponents/NavigationBar
+    - MaterialComponents/private/Icons/ic_arrow_back
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ButtonBar (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/RTL
+  - MaterialComponents/Buttons (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/CollectionCells (23.0.1):
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/private/Icons/ic_check
+    - MaterialComponents/private/Icons/ic_check_circle
+    - MaterialComponents/private/Icons/ic_chevron_right
+    - MaterialComponents/private/Icons/ic_info
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked
+    - MaterialComponents/private/Icons/ic_reorder
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/CollectionLayoutAttributes (23.0.1)
+  - MaterialComponents/Collections (23.0.1):
+    - MaterialComponents/CollectionCells
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/Dialogs (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+  - MaterialComponents/FeatureHighlight (23.0.1):
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/FlexibleHeader (23.0.1):
+    - MaterialComponents/private/Application
+    - MDFTextAccessibility
+  - MaterialComponents/HeaderStackView (23.0.1)
+  - MaterialComponents/Ink (23.0.1)
+  - MaterialComponents/NavigationBar (23.0.1):
+    - MaterialComponents/ButtonBar
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/OverlayWindow (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/PageControl (23.0.1)
+  - MaterialComponents/Palettes (23.0.1)
+  - MaterialComponents/private (23.0.1):
+    - MaterialComponents/private/Application (= 23.0.1)
+    - MaterialComponents/private/Icons (= 23.0.1)
+    - MaterialComponents/private/KeyboardWatcher (= 23.0.1)
+    - MaterialComponents/private/Overlay (= 23.0.1)
+    - MaterialComponents/private/RTL (= 23.0.1)
+    - MaterialComponents/private/ThumbTrack (= 23.0.1)
+  - MaterialComponents/private/Application (23.0.1)
+  - MaterialComponents/private/Icons (23.0.1):
+    - MaterialComponents/private/Icons/Base (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_arrow_back (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check_circle (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_chevron_right (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_info (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_reorder (= 23.0.1)
+  - MaterialComponents/private/Icons/Base (23.0.1)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check_circle (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_chevron_right (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_info (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_reorder (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/KeyboardWatcher (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/private/Overlay (23.0.1)
+  - MaterialComponents/private/RTL (23.0.1)
+  - MaterialComponents/private/ThumbTrack (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ProgressView (23.0.1):
+    - MaterialComponents/private/RTL
+  - MaterialComponents/ShadowElevations (23.0.1)
+  - MaterialComponents/ShadowLayer (23.0.1)
+  - MaterialComponents/Slider (23.0.1):
+    - MaterialComponents/private/ThumbTrack
+  - MaterialComponents/Snackbar (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Buttons
+    - MaterialComponents/OverlayWindow
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/Overlay
+    - MaterialComponents/Typography
+  - MaterialComponents/Tabs (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/Typography (23.0.1):
+    - MaterialComponents/private/Application
+  - MDFTextAccessibility (1.2.0)
+
+DEPENDENCIES:
+  - MaterialComponents
+
+SPEC CHECKSUMS:
+  MaterialComponents: 8666bde1128660f2a3525d03d6b460d2bc34dc3b
+  MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
+
+PODFILE CHECKSUM: abed8eea0ed77b9de5377b2d8f0b9fd29abd1705
+
+COCOAPODS: 1.2.1
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/.DS_Store b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/.DS_Store
new file mode 100644
index 0000000..cf1136a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/.DS_Store
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFColorCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFColorCalculations.h
new file mode 120000
index 0000000..fa89574
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFColorCalculations.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/private/MDFColorCalculations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFImageCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFImageCalculations.h
new file mode 120000
index 0000000..474b2cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFImageCalculations.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/private/MDFImageCalculations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility-Bridging-Header.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility-Bridging-Header.h
new file mode 120000
index 0000000..d562af0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility-Bridging-Header.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
new file mode 120000
index 0000000..6bf2534
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/MDFTextAccessibility.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/NSArray+MDFUtils.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/NSArray+MDFUtils.h
new file mode 120000
index 0000000..32c1020
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/NSArray+MDFUtils.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/private/NSArray+MDFUtils.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
new file mode 120000
index 0000000..20d501f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCActivityIndicator.h
new file mode 120000
index 0000000..44abaed
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAlertController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAlertController.h
new file mode 120000
index 0000000..aaf6589
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAlertController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCAlertController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBar.h
new file mode 120000
index 0000000..6bc15b0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBarButtonBarBuilder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBarButtonBarBuilder.h
new file mode 120000
index 0000000..83435f4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBarButtonBarBuilder.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBarContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBarContainerViewController.h
new file mode 120000
index 0000000..90f2e9c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCAppBarContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButton+Subclassing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButton+Subclassing.h
new file mode 120000
index 0000000..a1eafff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButton+Subclassing.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButton.h
new file mode 120000
index 0000000..35e4667
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButtonBar+Private.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButtonBar+Private.h
new file mode 120000
index 0000000..6246a17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButtonBar+Private.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButtonBar.h
new file mode 120000
index 0000000..433abfb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionGridBackgroundView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionGridBackgroundView.h
new file mode 120000
index 0000000..16b703f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionGridBackgroundView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionInfoBarView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionInfoBarView.h
new file mode 120000
index 0000000..315c699
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionInfoBarView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionStringResources.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionStringResources.h
new file mode 120000
index 0000000..284d457
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionStringResources.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewCell.h
new file mode 120000
index 0000000..f8b8942
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewController.h
new file mode 120000
index 0000000..17318d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditing.h
new file mode 120000
index 0000000..f822353
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditing.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditingDelegate.h
new file mode 120000
index 0000000..36cda64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditor.h
new file mode 120000
index 0000000..a59328f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditor.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewFlowLayout.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewFlowLayout.h
new file mode 120000
index 0000000..1259cc1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewFlowLayout.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewLayoutAttributes.h
new file mode 120000
index 0000000..7e572fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyler.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyler.h
new file mode 120000
index 0000000..c38fd37
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyler.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyling.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyling.h
new file mode 120000
index 0000000..afe2a2d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyling.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStylingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStylingDelegate.h
new file mode 120000
index 0000000..7e7a85c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStylingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewTextCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewTextCell.h
new file mode 120000
index 0000000..36307b4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCCollectionViewTextCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogPresentationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogPresentationController.h
new file mode 120000
index 0000000..c8812b5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogPresentationController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogShadowedView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogShadowedView.h
new file mode 120000
index 0000000..e559378
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogShadowedView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogTransitionController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogTransitionController.h
new file mode 120000
index 0000000..3510b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCDialogTransitionController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightAnimationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightAnimationController.h
new file mode 120000
index 0000000..ff58aa3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightAnimationController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightLayer.h
new file mode 120000
index 0000000..b91ac22
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightView.h
new file mode 120000
index 0000000..c9d7a09
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightViewController.h
new file mode 120000
index 0000000..80dfbbc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlatButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlatButton.h
new file mode 120000
index 0000000..a706599
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlatButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFlatButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
new file mode 120000
index 0000000..2f397d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderView.h
new file mode 120000
index 0000000..8bf8ccd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderViewController.h
new file mode 120000
index 0000000..49ebdb2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFloatingButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFloatingButton.h
new file mode 120000
index 0000000..53cd131
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFloatingButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFloatingButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFontTextStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFontTextStyle.h
new file mode 120000
index 0000000..28be954
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFontTextStyle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCFontTextStyle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFontTraits.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFontTraits.h
new file mode 120000
index 0000000..18f8a54
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCFontTraits.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/private/MDCFontTraits.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCHeaderStackView.h
new file mode 120000
index 0000000..098d7a2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCIcons+BundleLoader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCIcons+BundleLoader.h
new file mode 120000
index 0000000..83bb369
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCIcons+BundleLoader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCIcons.h
new file mode 120000
index 0000000..f64284e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkGestureRecognizer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkGestureRecognizer.h
new file mode 120000
index 0000000..41c61fe
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkGestureRecognizer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkLayer.h
new file mode 120000
index 0000000..ed548c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/private/MDCInkLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkTouchController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkTouchController.h
new file mode 120000
index 0000000..deff05c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkTouchController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkTouchController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkView.h
new file mode 120000
index 0000000..71f0259
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCInkView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBar.h
new file mode 120000
index 0000000..01beb92
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarAlignment.h
new file mode 120000
index 0000000..41ea67b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarAlignment.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarCell.h
new file mode 120000
index 0000000..e864dbb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarStringConstants.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarStringConstants.h
new file mode 120000
index 0000000..2857d7b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarStringConstants.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarStyle.h
new file mode 120000
index 0000000..1e9aea6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCItemBarStyle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCKeyboardWatcher.h
new file mode 120000
index 0000000..6748571
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCNavigationBar.h
new file mode 120000
index 0000000..be1e2df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCNumericValueLabel.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCNumericValueLabel.h
new file mode 120000
index 0000000..05fc677
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCNumericValueLabel.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayAnimationObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayAnimationObserver.h
new file mode 120000
index 0000000..8aef920
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayAnimationObserver.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayImplementor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayImplementor.h
new file mode 120000
index 0000000..dd6c72c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayImplementor.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserver.h
new file mode 120000
index 0000000..734f36b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserver.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverOverlay.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverOverlay.h
new file mode 120000
index 0000000..d4afb1a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverOverlay.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverTransition.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverTransition.h
new file mode 120000
index 0000000..f8b8b7f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverTransition.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayTransitioning.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayTransitioning.h
new file mode 120000
index 0000000..d819f9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayTransitioning.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayUtilities.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayUtilities.h
new file mode 120000
index 0000000..61dd343
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayUtilities.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayWindow.h
new file mode 120000
index 0000000..b4f521f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControl.h
new file mode 120000
index 0000000..436f689
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MDCPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControlIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControlIndicator.h
new file mode 120000
index 0000000..86ca489
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControlIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControlTrackLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControlTrackLayer.h
new file mode 120000
index 0000000..70b335d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPageControlTrackLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPaletteExpansions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPaletteExpansions.h
new file mode 120000
index 0000000..bb723ea
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPaletteExpansions.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPaletteNames.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPaletteNames.h
new file mode 120000
index 0000000..b14ada4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPaletteNames.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPalettes.h
new file mode 120000
index 0000000..9fbd2c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MDCPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCProgressView.h
new file mode 120000
index 0000000..355e6bc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MDCProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCRTL.h
new file mode 120000
index 0000000..0f5cb64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MDCRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCRaisedButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCRaisedButton.h
new file mode 120000
index 0000000..ccef7c0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCRaisedButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCRaisedButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCShadowElevations.h
new file mode 120000
index 0000000..884db2c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCShadowLayer.h
new file mode 120000
index 0000000..662ce66
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSlider.h
new file mode 120000
index 0000000..c6d28f3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MDCSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSlider_Subclassable.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSlider_Subclassable.h
new file mode 120000
index 0000000..de1e86e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSlider_Subclassable.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarManager.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarManager.h
new file mode 120000
index 0000000..bd47604
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarManager.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessage.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessage.h
new file mode 120000
index 0000000..ca85673
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessage.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageInternal.h
new file mode 120000
index 0000000..8c946d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageInternal.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageView.h
new file mode 120000
index 0000000..bd504ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageViewInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageViewInternal.h
new file mode 120000
index 0000000..88ee640
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageViewInternal.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarOverlayView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarOverlayView.h
new file mode 120000
index 0000000..8db1860
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCSnackbarOverlayView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCStatusBarShifter.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCStatusBarShifter.h
new file mode 120000
index 0000000..b56f8eb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCStatusBarShifter.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBar.h
new file mode 120000
index 0000000..1ae3c01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBarAlignment.h
new file mode 120000
index 0000000..0837a68
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBarAlignment.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBarItemAppearance.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBarItemAppearance.h
new file mode 120000
index 0000000..25eda76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTabBarItemAppearance.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCThumbTrack.h
new file mode 120000
index 0000000..d562391
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCThumbView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCThumbView.h
new file mode 120000
index 0000000..f268b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCThumbView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTypography.h
new file mode 120000
index 0000000..92f1672
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MDCTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialActivityIndicator.h
new file mode 120000
index 0000000..cdc04d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialAnimationTiming.h
new file mode 120000
index 0000000..47c524c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialAppBar.h
new file mode 120000
index 0000000..9b9b359
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MaterialAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialApplication.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialApplication.h
new file mode 120000
index 0000000..84d4230
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialApplication.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/MaterialApplication.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialButtonBar.h
new file mode 120000
index 0000000..03f519d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialButtons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialButtons.h
new file mode 120000
index 0000000..e201bb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialButtons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MaterialButtons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionCells.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionCells.h
new file mode 120000
index 0000000..fcebe0b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionCells.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionLayoutAttributes.h
new file mode 120000
index 0000000..12203fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollections.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollections.h
new file mode 120000
index 0000000..c651483
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollections.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MaterialCollections.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings.h
new file mode 120000
index 0000000..470ca4d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings_table.h
new file mode 120000
index 0000000..b3f6e7c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings_table.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialDialogs.h
new file mode 120000
index 0000000..9fa87cb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialFeatureHighlight.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialFeatureHighlight.h
new file mode 120000
index 0000000..408b3da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialFeatureHighlight.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialFlexibleHeader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialFlexibleHeader.h
new file mode 120000
index 0000000..a0ff5eb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialFlexibleHeader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialHeaderStackView.h
new file mode 120000
index 0000000..e489f50
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_arrow_back.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_arrow_back.h
new file mode 120000
index 0000000..d217414
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_arrow_back.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check.h
new file mode 120000
index 0000000..2ed904e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check_circle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check_circle.h
new file mode 120000
index 0000000..ca1cb59
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check_circle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_chevron_right.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_chevron_right.h
new file mode 120000
index 0000000..c5e2145
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_chevron_right.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_info.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_info.h
new file mode 120000
index 0000000..8f6a835
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_info.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
new file mode 120000
index 0000000..5bef137
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_reorder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_reorder.h
new file mode 120000
index 0000000..414fed9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_reorder.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons.h
new file mode 120000
index 0000000..a5fd2c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MaterialIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialInk.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialInk.h
new file mode 120000
index 0000000..d342e27
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialInk.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MaterialInk.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialKeyboardWatcher.h
new file mode 120000
index 0000000..4d746e2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialNavigationBar.h
new file mode 120000
index 0000000..4d955df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialOverlayWindow.h
new file mode 120000
index 0000000..91896d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialOverlays.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialOverlays.h
new file mode 120000
index 0000000..29fe249
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialOverlays.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControl.h
new file mode 120000
index 0000000..7803abc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MaterialPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings.h
new file mode 120000
index 0000000..cd39ffa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings_table.h
new file mode 120000
index 0000000..434acfa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings_table.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPalettes.h
new file mode 120000
index 0000000..592e442
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MaterialPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialProgressView.h
new file mode 120000
index 0000000..2bf7929
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MaterialProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialRTL.h
new file mode 120000
index 0000000..e146eb8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialShadowElevations.h
new file mode 120000
index 0000000..fae8446
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialShadowLayer.h
new file mode 120000
index 0000000..9b2b29d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialSlider.h
new file mode 120000
index 0000000..c5876b7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MaterialSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialSnackbar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialSnackbar.h
new file mode 120000
index 0000000..dbfbe01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialSnackbar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialTabs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialTabs.h
new file mode 120000
index 0000000..4268edf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialTabs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MaterialTabs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialThumbTrack.h
new file mode 120000
index 0000000..dd6979f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialTypography.h
new file mode 120000
index 0000000..19f03c3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIApplication+AppExtensions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIApplication+AppExtensions.h
new file mode 120000
index 0000000..7de802f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIApplication+AppExtensions.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypography.h
new file mode 120000
index 0000000..1459935
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypographyPrivate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypographyPrivate.h
new file mode 120000
index 0000000..153aa0a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypographyPrivate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFontDescriptor+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFontDescriptor+MaterialTypography.h
new file mode 120000
index 0000000..58f36cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIFontDescriptor+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIImage+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIImage+MaterialRTL.h
new file mode 120000
index 0000000..fe3b980
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIImage+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIView+MDCTimingFunction.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIView+MDCTimingFunction.h
new file mode 120000
index 0000000..1c20698
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIView+MDCTimingFunction.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIView+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIView+MaterialRTL.h
new file mode 120000
index 0000000..b45713a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIView+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIViewController+MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIViewController+MaterialDialogs.h
new file mode 120000
index 0000000..0e65c76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Private/MaterialComponents/UIViewController+MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
new file mode 120000
index 0000000..6bf2534
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/MDFTextAccessibility.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
new file mode 120000
index 0000000..20d501f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCActivityIndicator.h
new file mode 120000
index 0000000..44abaed
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAlertController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAlertController.h
new file mode 120000
index 0000000..aaf6589
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAlertController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCAlertController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAppBar.h
new file mode 120000
index 0000000..6bc15b0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAppBarContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAppBarContainerViewController.h
new file mode 120000
index 0000000..90f2e9c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCAppBarContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCButton.h
new file mode 120000
index 0000000..35e4667
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCButtonBar.h
new file mode 120000
index 0000000..433abfb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewCell.h
new file mode 120000
index 0000000..f8b8942
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewController.h
new file mode 120000
index 0000000..17318d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditing.h
new file mode 120000
index 0000000..f822353
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditing.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditingDelegate.h
new file mode 120000
index 0000000..36cda64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewFlowLayout.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewFlowLayout.h
new file mode 120000
index 0000000..1259cc1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewFlowLayout.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewLayoutAttributes.h
new file mode 120000
index 0000000..7e572fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStyling.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStyling.h
new file mode 120000
index 0000000..afe2a2d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStyling.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStylingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStylingDelegate.h
new file mode 120000
index 0000000..7e7a85c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStylingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewTextCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewTextCell.h
new file mode 120000
index 0000000..36307b4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCCollectionViewTextCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCDialogPresentationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCDialogPresentationController.h
new file mode 120000
index 0000000..c8812b5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCDialogPresentationController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCDialogTransitionController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCDialogTransitionController.h
new file mode 120000
index 0000000..3510b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCDialogTransitionController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFeatureHighlightViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFeatureHighlightViewController.h
new file mode 120000
index 0000000..80dfbbc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFeatureHighlightViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlatButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlatButton.h
new file mode 120000
index 0000000..a706599
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlatButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFlatButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
new file mode 120000
index 0000000..2f397d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderView.h
new file mode 120000
index 0000000..8bf8ccd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderViewController.h
new file mode 120000
index 0000000..49ebdb2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFloatingButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFloatingButton.h
new file mode 120000
index 0000000..53cd131
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFloatingButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFloatingButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFontTextStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFontTextStyle.h
new file mode 120000
index 0000000..28be954
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCFontTextStyle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCFontTextStyle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCHeaderStackView.h
new file mode 120000
index 0000000..098d7a2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCIcons+BundleLoader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCIcons+BundleLoader.h
new file mode 120000
index 0000000..83bb369
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCIcons+BundleLoader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCIcons.h
new file mode 120000
index 0000000..f64284e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkGestureRecognizer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkGestureRecognizer.h
new file mode 120000
index 0000000..41c61fe
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkGestureRecognizer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkTouchController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkTouchController.h
new file mode 120000
index 0000000..deff05c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkTouchController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkTouchController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkView.h
new file mode 120000
index 0000000..71f0259
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCInkView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCKeyboardWatcher.h
new file mode 120000
index 0000000..6748571
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCNavigationBar.h
new file mode 120000
index 0000000..be1e2df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCNumericValueLabel.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCNumericValueLabel.h
new file mode 120000
index 0000000..05fc677
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCNumericValueLabel.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayImplementor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayImplementor.h
new file mode 120000
index 0000000..dd6c72c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayImplementor.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayObserver.h
new file mode 120000
index 0000000..734f36b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayObserver.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayTransitioning.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayTransitioning.h
new file mode 120000
index 0000000..d819f9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayTransitioning.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayWindow.h
new file mode 120000
index 0000000..b4f521f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCPageControl.h
new file mode 120000
index 0000000..436f689
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MDCPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCPalettes.h
new file mode 120000
index 0000000..9fbd2c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MDCPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCProgressView.h
new file mode 120000
index 0000000..355e6bc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MDCProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCRTL.h
new file mode 120000
index 0000000..0f5cb64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MDCRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCRaisedButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCRaisedButton.h
new file mode 120000
index 0000000..ccef7c0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCRaisedButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCRaisedButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCShadowElevations.h
new file mode 120000
index 0000000..884db2c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCShadowLayer.h
new file mode 120000
index 0000000..662ce66
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSlider.h
new file mode 120000
index 0000000..c6d28f3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MDCSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarManager.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarManager.h
new file mode 120000
index 0000000..bd47604
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarManager.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessage.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessage.h
new file mode 120000
index 0000000..ca85673
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessage.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessageView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessageView.h
new file mode 120000
index 0000000..bd504ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessageView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBar.h
new file mode 120000
index 0000000..1ae3c01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBarAlignment.h
new file mode 120000
index 0000000..0837a68
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBarAlignment.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBarItemAppearance.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBarItemAppearance.h
new file mode 120000
index 0000000..25eda76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTabBarItemAppearance.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCThumbTrack.h
new file mode 120000
index 0000000..d562391
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCThumbView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCThumbView.h
new file mode 120000
index 0000000..f268b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCThumbView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTypography.h
new file mode 120000
index 0000000..92f1672
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MDCTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialActivityIndicator.h
new file mode 120000
index 0000000..cdc04d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialAnimationTiming.h
new file mode 120000
index 0000000..47c524c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialAppBar.h
new file mode 120000
index 0000000..9b9b359
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MaterialAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialApplication.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialApplication.h
new file mode 120000
index 0000000..84d4230
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialApplication.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/MaterialApplication.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialButtonBar.h
new file mode 120000
index 0000000..03f519d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialButtons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialButtons.h
new file mode 120000
index 0000000..e201bb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialButtons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MaterialButtons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollectionCells.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollectionCells.h
new file mode 120000
index 0000000..fcebe0b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollectionCells.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollectionLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollectionLayoutAttributes.h
new file mode 120000
index 0000000..12203fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollectionLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollections.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollections.h
new file mode 120000
index 0000000..c651483
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialCollections.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MaterialCollections.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialDialogs.h
new file mode 120000
index 0000000..9fa87cb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialFeatureHighlight.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialFeatureHighlight.h
new file mode 120000
index 0000000..408b3da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialFeatureHighlight.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialFlexibleHeader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialFlexibleHeader.h
new file mode 120000
index 0000000..a0ff5eb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialFlexibleHeader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialHeaderStackView.h
new file mode 120000
index 0000000..e489f50
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_arrow_back.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_arrow_back.h
new file mode 120000
index 0000000..d217414
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_arrow_back.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check.h
new file mode 120000
index 0000000..2ed904e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check_circle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check_circle.h
new file mode 120000
index 0000000..ca1cb59
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check_circle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_chevron_right.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_chevron_right.h
new file mode 120000
index 0000000..c5e2145
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_chevron_right.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_info.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_info.h
new file mode 120000
index 0000000..8f6a835
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_info.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
new file mode 120000
index 0000000..5bef137
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_reorder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_reorder.h
new file mode 120000
index 0000000..414fed9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_reorder.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons.h
new file mode 120000
index 0000000..a5fd2c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MaterialIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialInk.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialInk.h
new file mode 120000
index 0000000..d342e27
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialInk.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MaterialInk.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialKeyboardWatcher.h
new file mode 120000
index 0000000..4d746e2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialNavigationBar.h
new file mode 120000
index 0000000..4d955df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialOverlayWindow.h
new file mode 120000
index 0000000..91896d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialOverlays.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialOverlays.h
new file mode 120000
index 0000000..29fe249
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialOverlays.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialPageControl.h
new file mode 120000
index 0000000..7803abc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MaterialPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialPalettes.h
new file mode 120000
index 0000000..592e442
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MaterialPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialProgressView.h
new file mode 120000
index 0000000..2bf7929
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MaterialProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialRTL.h
new file mode 120000
index 0000000..e146eb8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialShadowElevations.h
new file mode 120000
index 0000000..fae8446
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialShadowLayer.h
new file mode 120000
index 0000000..9b2b29d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialSlider.h
new file mode 120000
index 0000000..c5876b7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MaterialSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialSnackbar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialSnackbar.h
new file mode 120000
index 0000000..dbfbe01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialSnackbar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialTabs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialTabs.h
new file mode 120000
index 0000000..4268edf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialTabs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MaterialTabs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialThumbTrack.h
new file mode 120000
index 0000000..dd6979f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialTypography.h
new file mode 120000
index 0000000..19f03c3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIApplication+AppExtensions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIApplication+AppExtensions.h
new file mode 120000
index 0000000..7de802f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIApplication+AppExtensions.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIFont+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIFont+MaterialTypography.h
new file mode 120000
index 0000000..1459935
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIFont+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIFontDescriptor+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIFontDescriptor+MaterialTypography.h
new file mode 120000
index 0000000..58f36cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIFontDescriptor+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIImage+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIImage+MaterialRTL.h
new file mode 120000
index 0000000..fe3b980
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIImage+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIView+MDCTimingFunction.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIView+MDCTimingFunction.h
new file mode 120000
index 0000000..1c20698
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIView+MDCTimingFunction.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIView+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIView+MaterialRTL.h
new file mode 120000
index 0000000..b45713a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIView+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIViewController+MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIViewController+MaterialDialogs.h
new file mode 120000
index 0000000..0e65c76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Headers/Public/MaterialComponents/UIViewController+MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/LICENSE b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/README.md b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/README.md
new file mode 100644
index 0000000..6010bea
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/README.md
@@ -0,0 +1,106 @@
+MDFTextAccessibility assists in selecting text colors that will meet the
+[W3C standards for accessibility](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html).
+
+[![Build Status](https://travis-ci.org/material-foundation/material-text-accessibility-ios.svg?branch=develop)](https://travis-ci.org/material-foundation/material-text-accessibility-ios)
+[![Code Coverage](http://codecov.io/github/material-foundation/material-text-accessibility-ios/coverage.svg?branch=develop)](http://codecov.io/github/material-foundation/material-text-accessibility-ios?branch=develop)
+
+*May 24, 2016: We're still staging MDFTextAccessibility, feel free to poke
+around, but non-code things like CocoaPods support and continuous integration
+testing will be ramping up over the next few weeks. The API is relatively stable
+at this point.*
+
+## Accessibility of text
+
+Apps created for the widest range of users should ensure that users can read
+text presented over any background. While the legibility of text depends on many
+things, a great start is to provide a sufficiently large *contrast ratio*
+between foreground text colors and their background colors. The contrast ratio
+of two colors is a measurement of how much the brightness of two colors differ.
+For example, white on dark grey might have a contrast ratio of 9:1, while white
+on medium grey might only have a contrast ratio of 4:1. In general, larger
+contrast ratios are better and will ensure the widest range of users can easily
+read the text in your app.
+
+The [W3C](https://www.w3.org)'s
+[Web Content Accessibility Guidelines](https://www.w3.org/TR/WCAG/#visual-audio-contrast)
+contains two recommendations for text contrast ratios:
+
+1. Minimum contrast: text should have a contrast ratio of at least 4.5:1,
+   except for "large" text, which can have a contrast ratio of 3:1.
+2. Enhanced contrast: text should have a contrast ratio of at least 7:1, except
+   for large text, which can have a contrast ratio of 4.5:1.
+
+"Large" text is nominally defined as at least 18pt in a normal font face or at
+least 14pt in a bold font face. For more information (including some important
+exceptions), see the
+[Guidelines](https://www.w3.org/TR/WCAG/#visual-audio-contrast).
+
+## Computing contrast ratios
+
+Computing acceptable contrast ratios involves the foreground color, the
+background color, the text size, and the transparency of the foreground color,
+if any. MDFTextAccessibility provides convenient access to colors that will
+automatically give acceptable contrast ratios.
+
+For methods that return a UIColor, the color along with its alpha is guaranteed
+to provide a contrast ratio meeting the minimum ratios recommended by the W3C.
+The returned alpha may be greater than the requested alpha to ensure acceptable
+contrast ratios, that is, the returned color may be more opaque than requested
+to ensure that the text remains legible.
+
+## Legible text on images
+
+Displaying text legibly on arbitrary images is difficult because the image
+content can conflict with the text. Images with smooth gradients or blurred
+regions are likely to result in more legible text; images with many details and
+high contrast are less likely to result in legible text.
+
+MDFTextAccessibility provides methods that attempt to select a good color for
+displaying text on a particular image, but the quality of the results will
+depend on the contents of the image. If the content of the image is not known
+(for example, when images provided by the user), then consider using a
+semi-transparent shim between the image and the text to increase contrast.
+
+## Usage
+
+### Basic usage
+
+The simplest usage is to select between black and white text depending on the
+background color, irrespective of the font:
+
+```objective-c
+label.textColor = [MDFTextAccessibility textColorOnBackgroundColor:label.backgroundColor
+                                                         textAlpha:1
+                                                              font:nil];
+```
+
+Many design standards for user interfaces use text colors that are not fully
+opaque. However, transparent text can reduce legibility, so you can request a
+color that is as close as possible to a particular alpha value while still being
+legible:
+
+```objective-c
+label.textColor = [MDFTextAccessibility textColorOnBackgroundColor:label.backgroundColor
+                                                   targetTextAlpha:0.85
+                                                              font:nil];
+```
+
+Since the W3C recommends different contrast ratios for "normal" and "large"
+text, including the font can result in a text color closer to your target alpha
+when appropriate:
+
+```objective-c
+label.textColor = [MDFTextAccessibility textColorOnBackgroundColor:label.backgroundColor
+                                                         textAlpha:0.85
+                                                              font:label.font];
+```
+
+### Advanced usage
+
+For more advanced usage, such as selecting from a set of colors other than white
+and black, see MDFTextAccessibility's
+`textColorFromChoices:onBackgroundColor:options:`.
+
+## License
+
+MDFTextAccessiblity is licensed under the [Apache License Version 2.0](LICENSE).
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h
new file mode 100644
index 0000000..ea88e56
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFTextAccessibility.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility.h
new file mode 100644
index 0000000..34a13d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility.h
@@ -0,0 +1,199 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Options for selecting text colors that provide acceptable contrast ratios. */
+typedef NS_OPTIONS(NSUInteger, MDFTextAccessibilityOptions) {
+  /** No options. */
+  MDFTextAccessibilityOptionsNone = 0,
+
+  /** Font size is at least 14pt bold or 18pt normal. */
+  MDFTextAccessibilityOptionsLargeFont = 1 << 0,
+
+  /** Do not modify alpha values to find good colors. */
+  MDFTextAccessibilityOptionsPreserveAlpha = 1 << 1,
+
+  /** Prefer darker colors to lighter colors. */
+  MDFTextAccessibilityOptionsPreferDarker = 1 << 2,
+
+  /** Prefer lighter colors to darker colors. */
+  MDFTextAccessibilityOptionsPreferLighter = 1 << 3,
+
+  /** Use enhanced contrast ratios (level AAA) instead of minimum ratios (level AA). */
+  MDFTextAccessibilityOptionsEnhancedContrast = 1 << 4,
+};
+
+/**
+ MDFTextAccessiblity provides methods to compute accessible text colors.
+ */
+@interface MDFTextAccessibility : NSObject
+
+/**
+ An optionally transparent text color suitable for displaying on a background color with a
+ particular font.
+
+ The color returned will be white or black with an alpha value of targetTextAlpha, unless the
+ contrast ratio is insufficient, in which case the alpha is increased (made more opaque).
+
+ If the passed font is nil, then a conservative guess is used.
+
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param targetTextAlpha The target alpha of the text.
+ @param font The font the text will use or nil.
+ @return A color with acceptable contrast ratio for displaying text on |color|.
+ */
++ (nonnull UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                targetTextAlpha:(CGFloat)targetTextAlpha
+                                           font:(nullable UIFont *)font;
+
+/**
+ An optionally transparent text color suitable for displaying on a background image with a
+ particular font.
+
+ The color returned will be white or black with an alpha value of targetTextAlpha, unless the
+ contrast ratio is insufficient, in which case the alpha is increased (made more opaque).
+
+ If the passed font is nil, then a conservative guess is used.
+
+ The content of the background image is simply averaged to make an average color, which is then used
+ as if it were the background color of the text. Depending on the contents of the image, this
+ approximation may or may not result in legible text.
+
+ The supplied image region will be intersected with the image's bounds. If the resulting region is
+ null or empty then this method returns nil.
+
+ @param backgroundImage The opaque background image the text will be displayed on.
+ @param region The region in which the text will be displayed. Can be conservatively large.
+ @param targetTextAlpha The target alpha of the text.
+ @param font The font to be used to display the text. Can be nil.
+ @return A color with acceptable contrast ratio, or nil if the region is out of bounds of the image.
+ */
++ (nullable UIColor *)textColorOnBackgroundImage:(nonnull UIImage *)backgroundImage
+                                        inRegion:(CGRect)region
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                            font:(nullable UIFont *)font;
+
+#pragma mark Advanced methods
+
+/**
+ An optionally transparent text color suitable for displaying text on a given opaque background
+ color.
+
+ This method calls textColorFromChoices:onColor:options: with the choices [white, black], both
+ with their alpha set to targetTextAlpha.
+
+ If MDFTextAccessibilityOptionsPreserveAlpha is included in the options, then the algorithm will not
+ modify the alpha values, which may result in no color being returned at all.
+
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param targetTextAlpha The target alpha of the text.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return A color with acceptable contrast ratio or nil if no such color exists.
+ */
++ (nullable UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                         options:(MDFTextAccessibilityOptions)options;
+
+/**
+ A color selected from a set which is suitable for displaying text on a given opaque background
+ color.
+
+ Since the minimum ratio for "large" text is less stringent, set
+ the MDFTextAccessibilityOptionsLargeFont bit if the font size will be greater than or
+ equal to 18pt normal or 14pt bold. If in doubt or if the text size can vary, be conservative and do
+ not specify MDFTextAccessibilityOptionsLargeFont in the options.
+
+ By default, the first acceptable color in |choices| will be returned. If
+ MDFTextAccessibilityOptionsPreferLighter is set, then the lightest acceptable color will be
+ returned, and if MDFTextAccessibilityOptionsPreferDarker is set, then the darkest acceptable color
+ will be returned. This allows for a standard set of text colors to be used in different situations.
+
+ By default, the algorithm will attempt to modify the alpha value of colors in |choices| instead
+ of switching to an alternate color, under the assumption that text with slightly different
+ alpha values is less noticible than, for example, black text where white text is usually used.
+ If MDFTextAccessibilityOptionsPreserveAlpha is included in the options, then the algorithm will not
+ modify the alpha values, which may result in no color being returned at all.
+
+ @param choices An array of text color UIColor objects with optional alpha values.
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return A color with acceptable contrast ratio or nil if no such color exists.
+ */
++ (nullable UIColor *)textColorFromChoices:(nonnull NSArray<UIColor *> *)choices
+                         onBackgroundColor:(nonnull UIColor *)backgroundColor
+                                   options:(MDFTextAccessibilityOptions)options;
+
+/**
+ The minimum alpha that text can have and still have an acceptable contrast ratio. Depending on
+ color combinations, the minimum useable alpha can vary.
+
+ Since the minimum ratio for "large" text is less stringent, set
+ the MDFTextAccessibilityOptionsLargeFont bit if the font size will be greater than or
+ equal to 18pt normal or 14pt bold. If in doubt or if the text size can vary, be conservative and do
+ not specify MDFTextAccessibilityOptionsLargeFont in the options.
+
+ @note There are some color combinations (white on white) for which an acceptable alpha value
+ doesn't exist.
+
+ @param textColor The text color (alpha is ignored).
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return The minimum alpha value to use in this situation, or -1 if there is no such alpha.
+ */
++ (CGFloat)minAlphaOfTextColor:(nonnull UIColor *)textColor
+             onBackgroundColor:(nonnull UIColor *)backgroundColor
+                       options:(MDFTextAccessibilityOptions)options;
+
+/**
+ The contrast ratio of a text color when displayed on an opaque background color.
+
+ @param textColor A text color with optional transparency.
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @return The contrast ratio of the text color on the background color.
+ */
++ (CGFloat)contrastRatioForTextColor:(nonnull UIColor *)textColor
+                   onBackgroundColor:(nonnull UIColor *)backgroundColor;
+
+/**
+ Whether a text color passes accessibility standards when displayed on an opaque background color.
+
+ MDFTextAccessibilityOptionsLargeFont and MDFTextAccessibilityOptionsEnhancedContrast are relevant
+ options for this method.
+
+ @param textColor A text color with optional transparency.
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return YES if the text color would meet accessibility standards.
+ */
++ (BOOL)textColor:(nonnull UIColor *)textColor
+    passesOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                    options:(MDFTextAccessibilityOptions)options;
+
+/**
+ Whether a particular font would be considered "large" for the purposes of calculating
+ contrast ratios.
+
+ Large fonts are defined as greater than 18pt normal or 14pt bold. If the passed font is nil, then
+ this method returns NO.
+ For more see: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
+
+ @param font The font to examine, or nil.
+ @return YES if the font is non-nil and is considered "large".
+ */
++ (BOOL)isLargeForContrastRatios:(nullable UIFont *)font;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility.m
new file mode 100644
index 0000000..5e10ddf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/MDFTextAccessibility.m
@@ -0,0 +1,185 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFTextAccessibility.h"
+
+#import "private/MDFColorCalculations.h"
+#import "private/MDFImageCalculations.h"
+#import "private/NSArray+MDFUtils.h"
+
+static const CGFloat kMinContrastRatioNormalText = 4.5f;
+static const CGFloat kMinContrastRatioLargeText = 3.0f;
+static const CGFloat kMinContrastRatioNormalTextEnhanced = 7.0f;
+static const CGFloat kMinContrastRatioLargeTextEnhanced = 4.5f;
+
+@implementation MDFTextAccessibility
+
++ (nonnull UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                targetTextAlpha:(CGFloat)targetTextAlpha
+                                           font:(nullable UIFont *)font {
+  MDFTextAccessibilityOptions options = 0;
+  if ([self isLargeForContrastRatios:font]) {
+    options |= MDFTextAccessibilityOptionsLargeFont;
+  }
+  return [self textColorOnBackgroundColor:backgroundColor
+                          targetTextAlpha:targetTextAlpha
+                                  options:options];
+}
+
++ (nullable UIColor *)textColorOnBackgroundImage:(nonnull UIImage *)backgroundImage
+                                        inRegion:(CGRect)region
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                            font:(nullable UIFont *)font {
+  UIColor *backgroundColor = MDFAverageColorOfOpaqueImage(backgroundImage, region);
+  if (!backgroundColor) {
+    return nil;
+  }
+
+  return
+      [self textColorOnBackgroundColor:backgroundColor targetTextAlpha:targetTextAlpha font:font];
+}
+
++ (nullable UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                         options:(MDFTextAccessibilityOptions)options {
+  NSArray *colors = @[
+    [UIColor colorWithWhite:1 alpha:targetTextAlpha],
+    [UIColor colorWithWhite:0 alpha:targetTextAlpha]
+  ];
+  UIColor *textColor =
+      [self textColorFromChoices:colors onBackgroundColor:backgroundColor options:options];
+  return textColor;
+}
+
++ (nullable UIColor *)textColorFromChoices:(nonnull NSArray<UIColor *> *)choices
+                         onBackgroundColor:(nonnull UIColor *)backgroundColor
+                                   options:(MDFTextAccessibilityOptions)options {
+  [choices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+    NSAssert([obj isKindOfClass:[UIColor class]], @"Choices must be UIColors.");
+  }];
+
+  // Sort by luminance if requested.
+  if ((options & MDFTextAccessibilityOptionsPreferLighter) ||
+      (options & MDFTextAccessibilityOptionsPreferDarker)) {
+    NSArray *luminances = [choices mdf_arrayByMappingObjects:^id(id object) {
+      return @([self luminanceOfColor:object]);
+    }];
+
+    BOOL inverse = (options & MDFTextAccessibilityOptionsPreferDarker) ? YES : NO;
+    choices = [luminances mdf_sortArray:choices
+                        usingComparator:^NSComparisonResult(id obj1, id obj2) {
+                          float first = inverse ? [obj1 floatValue] : [obj2 floatValue];
+                          float second = inverse ? [obj2 floatValue] : [obj1 floatValue];
+
+                          if (first < second) {
+                            return NSOrderedAscending;
+                          } else if (first > second) {
+                            return NSOrderedDescending;
+                          } else {
+                            return NSOrderedSame;
+                          }
+                        }];
+  }
+
+  // Search the array for a color that can be used, adjusting alpha values upwards if requested.
+  // The first acceptable color (adjusted or not) is returned.
+  BOOL adjustAlphas = (options & MDFTextAccessibilityOptionsPreserveAlpha) ? NO : YES;
+  for (UIColor *choice in choices) {
+    if ([self textColor:choice passesOnBackgroundColor:backgroundColor options:options]) {
+      return choice;
+    }
+
+    if (!adjustAlphas) {
+      continue;
+    }
+
+    CGFloat alpha = CGColorGetAlpha(choice.CGColor);
+    CGFloat minAlpha =
+        [self minAlphaOfTextColor:choice onBackgroundColor:backgroundColor options:options];
+    if (minAlpha > 0) {
+      if (alpha > minAlpha) {
+        NSAssert(NO,
+                 @"Logic error: computed an acceptable minimum alpha (%f) that is *less* than the "
+                 @"unacceptable current alpha (%f).",
+                 minAlpha, alpha);
+        continue;
+      }
+      return [choice colorWithAlphaComponent:minAlpha];
+    }
+  }
+
+  return nil;
+}
+
++ (CGFloat)minAlphaOfTextColor:(nonnull UIColor *)textColor
+             onBackgroundColor:(nonnull UIColor *)backgroundColor
+                       options:(MDFTextAccessibilityOptions)options {
+  CGFloat minContrastRatio = [self minContrastRatioForOptions:options];
+  return MDFMinAlphaOfColorOnBackgroundColor(textColor, backgroundColor, minContrastRatio);
+}
+
++ (CGFloat)contrastRatioForTextColor:(UIColor *)textColor
+                   onBackgroundColor:(UIColor *)backgroundColor {
+  CGFloat colorComponents[4];
+  CGFloat backgroundColorComponents[4];
+  MDFCopyRGBAComponents(textColor.CGColor, colorComponents);
+  MDFCopyRGBAComponents(backgroundColor.CGColor, backgroundColorComponents);
+
+  NSAssert(backgroundColorComponents[3] == 1,
+           @"Background color %@ must be opaque for a valid contrast ratio calculation.",
+           backgroundColor);
+  backgroundColorComponents[3] = 1;
+
+  return MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+}
+
++ (BOOL)textColor:(nonnull UIColor *)textColor
+    passesOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                    options:(MDFTextAccessibilityOptions)options {
+  CGFloat minContrastRatio = [self minContrastRatioForOptions:options];
+  CGFloat ratio = [self contrastRatioForTextColor:textColor onBackgroundColor:backgroundColor];
+  return ratio >= minContrastRatio ? YES : NO;
+}
+
++ (BOOL)isLargeForContrastRatios:(nullable UIFont *)font {
+  UIFontDescriptor *fontDescriptor = font.fontDescriptor;
+  BOOL isBold =
+      (fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold;
+  return font.pointSize >= 18 || (isBold && font.pointSize >= 14);
+}
+
+#pragma mark - Private methods
+
++ (CGFloat)luminanceOfColor:(UIColor *)color {
+  CGFloat colorComponents[4];
+  MDFCopyRGBAComponents(color.CGColor, colorComponents);
+  return MDFRelativeLuminanceOfRGBComponents(colorComponents);
+}
+
++ (CGFloat)minContrastRatioForOptions:(MDFTextAccessibilityOptions)options {
+  BOOL isLarge =
+      (options & MDFTextAccessibilityOptionsLargeFont) == MDFTextAccessibilityOptionsLargeFont;
+  BOOL isEnhanced = (options & MDFTextAccessibilityOptionsEnhancedContrast) ==
+                    MDFTextAccessibilityOptionsEnhancedContrast;
+
+  if (isEnhanced) {
+    return isLarge ? kMinContrastRatioLargeTextEnhanced : kMinContrastRatioNormalTextEnhanced;
+  } else {
+    return isLarge ? kMinContrastRatioLargeText : kMinContrastRatioNormalText;
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.h
new file mode 100644
index 0000000..3e2f78f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.h
@@ -0,0 +1,70 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Copies the RGBA components of color, expanding greyscale colors out to RGBA if necessary.
+
+ @param color The color to extract the components from.
+ @param rgbaComponents A pointer to four CGFloat values.
+ */
+void MDFCopyRGBAComponents(CGColorRef color, CGFloat *rgbaComponents);
+
+/**
+ Returns the contrast ratio of a foreground color blended on top of a background color.
+
+ @param foregroundColorComponents A pointer to four RGBA CGFloats of the foreground color.
+ @param backgroundColorComponents A pointer to four RGBA CGFloats of the background color.
+ @return The contrast ratio of the two colors after blending.
+ */
+CGFloat MDFContrastRatioOfRGBAComponents(const CGFloat *foregroundColorComponents,
+                                         const CGFloat *backgroundColorComponents);
+
+/**
+ Calculates the relative luminance of a sRGB color from its components (ignores alpha).
+ @see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+
+ @param components A pointer to three RGB CGFloat values of the color.
+ @return The relative luminance of the color.
+ */
+CGFloat MDFRelativeLuminanceOfRGBComponents(const CGFloat *components);
+
+/**
+ Calculates the minimum alpha that a foreground color can have such that, when it's blended on top
+ of an opaque background color, the resulting contrast ratio is higher than a minimum contrast
+ ratio.
+
+ If there is no such acceptable contrast ratio, then -1 is returned. This is the case when even a
+ completely opaque foreground color can't produce a high enough contrast ratio. For example, light
+ grey on white will have a low contrast ratio for any alpha value assigned to the light grey.
+
+ @param color The foreground color (alpha ignored).
+ @param backgroundColor The background color (assumed to be opaque).
+ @param minContrastRatio The minimum allowable contrast ratio.
+ @return The minimum acceptable alpha of the foreground color, or -1 if no such alpha exists.
+ */
+CGFloat MDFMinAlphaOfColorOnBackgroundColor(UIColor *color,
+                                            UIColor *backgroundColor,
+                                            CGFloat minContrastRatio);
+
+#if defined __cplusplus
+}  // extern "C"
+#endif
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.m
new file mode 100644
index 0000000..a804fbd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.m
@@ -0,0 +1,185 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFColorCalculations.h"
+
+/**
+ The number of iterations required to find the minimum acceptable alpha is
+ ceil(log2(1/kMinAlphaSearchPrecision)), or 7 for a precision of 0.01. If you adjust the precision
+ then also adjust the max iterations, which is used as a safety check.
+ */
+static const CGFloat kMinAlphaSearchPrecision = 0.01f;
+static const NSUInteger kMinAlphaSearchMaxIterations = 10;
+
+/** Returns value raised to exponent. */
+static inline CGFloat MDFPow(CGFloat value, CGFloat exponent) {
+#if CGFLOAT_IS_DOUBLE
+  return pow(value, exponent);
+#else
+  return powf(value, exponent);
+#endif
+}
+
+/**
+ Calculate a linear RGB component from a sRGB component for calculating luminance.
+ @see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ */
+static inline CGFloat LinearRGBComponent(CGFloat component) {
+  if (component <= 0.03928f) {
+    return component / 12.92f;
+  } else {
+    return MDFPow(((component + 0.055f) / 1.055f), 2.4f);
+  }
+}
+
+/**
+ Blend a foreground color with alpha on a opaque background color.
+ @note The background color must be opaque for this to be valid.
+ @see http://en.wikipedia.org/wiki/Alpha_compositing
+ */
+static inline void BlendColorOnOpaqueBackground(const CGFloat *foregroundColor,
+                                                const CGFloat *backgroundColor,
+                                                CGFloat *blendedColor) {
+  for (int i = 0; i < 3; ++i) {
+    blendedColor[i] =
+        foregroundColor[i] * foregroundColor[3] + backgroundColor[i] * (1 - foregroundColor[3]);
+  }
+  blendedColor[3] = 1.0f;
+}
+
+static inline CGFloat ContrastRatioOfRGBComponents(const CGFloat *firstComponents,
+                                                   const CGFloat *secondComponents) {
+  CGFloat firstLuminance = MDFRelativeLuminanceOfRGBComponents(firstComponents);
+  CGFloat secondLuminance = MDFRelativeLuminanceOfRGBComponents(secondComponents);
+
+  if (secondLuminance > firstLuminance) {
+    CGFloat temp = firstLuminance;
+    firstLuminance = secondLuminance;
+    secondLuminance = temp;
+  }
+
+  return (firstLuminance + 0.05f) / (secondLuminance + 0.05f);
+}
+
+CGFloat MDFContrastRatioOfRGBAComponents(const CGFloat *foregroundColorComponents,
+                                         const CGFloat *backgroundColorComponents) {
+  CGFloat blendedColor[4];
+  BlendColorOnOpaqueBackground(foregroundColorComponents, backgroundColorComponents, blendedColor);
+  return ContrastRatioOfRGBComponents(blendedColor, backgroundColorComponents);
+}
+
+void MDFCopyRGBAComponents(CGColorRef color, CGFloat *rgbaComponents) {
+  CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(CGColorGetColorSpace(color));
+  if (!(colorSpaceModel == kCGColorSpaceModelRGB ||
+        colorSpaceModel == kCGColorSpaceModelMonochrome)) {
+    NSCAssert(NO, @"Can't compute luminance for non-RGB color space model %i.", colorSpaceModel);
+    for (int i = 0; i < 4; ++i) {
+      rgbaComponents[i] = 0;
+    }
+    return;
+  }
+
+  size_t numComponents = CGColorGetNumberOfComponents(color);
+  const CGFloat *components = CGColorGetComponents(color);
+  switch (numComponents) {
+    // Greyscale + alpha
+    case 2:
+      for (int i = 0; i < 3; ++i) {
+        rgbaComponents[i] = components[0];
+      }
+      rgbaComponents[3] = components[1];
+      break;
+
+    // RGB + alpha
+    case 4:
+      for (int i = 0; i < 4; ++i) {
+        rgbaComponents[i] = components[i];
+      }
+      break;
+
+    default:
+      NSCAssert(NO, @"Unexpected number of color components: %zu.", numComponents);
+  }
+}
+
+CGFloat MDFRelativeLuminanceOfRGBComponents(const CGFloat *components) {
+  CGFloat linearRGB[3];
+  for (int i = 0; i < 3; ++i) {
+    linearRGB[i] = LinearRGBComponent(components[i]);
+  }
+  return 0.2126f * linearRGB[0] + 0.7152f * linearRGB[1] + 0.0722f * linearRGB[2];
+}
+
+CGFloat MDFMinAlphaOfColorOnBackgroundColor(UIColor *color,
+                                            UIColor *backgroundColor,
+                                            CGFloat minContrastRatio) {
+  CGFloat colorComponents[4];
+  CGFloat backgroundColorComponents[4];
+  MDFCopyRGBAComponents(color.CGColor, colorComponents);
+  MDFCopyRGBAComponents(backgroundColor.CGColor, backgroundColorComponents);
+
+  NSCAssert(backgroundColorComponents[3] == 1,
+            @"Background color %@ must be opaque for a valid contrast ratio calculation.",
+            backgroundColor);
+  backgroundColorComponents[3] = 1;
+
+  NSCAssert(minContrastRatio > 0, @"Invalid min contrast ratio %g.", (double)minContrastRatio);
+  CGFloat minAlpha = 0;
+  CGFloat maxAlpha = 1;
+
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+  colorComponents[3] = minAlpha;
+  CGFloat minAlphaRatio =
+      MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+  NSCAssert(minAlphaRatio < minContrastRatio, @"Transparent color cannot be a valid color.");
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+  // maxAlphaRatio is the best contrast ratio we can acheive by modifying the alpha of this color.
+  // If it's not good enough, then return now and inform the caller.
+  colorComponents[3] = maxAlpha;
+  CGFloat maxAlphaRatio =
+      MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+  if (maxAlphaRatio < minContrastRatio) {
+    return -1;
+  }
+
+  // Classic binary search of a range.
+  NSUInteger numIterations = 0;
+  while (numIterations <= kMinAlphaSearchMaxIterations &&
+         (maxAlpha - minAlpha) > kMinAlphaSearchPrecision) {
+    CGFloat testAlpha = (minAlpha + maxAlpha) / 2;
+    colorComponents[3] = testAlpha;
+    CGFloat testRatio =
+        MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+
+    if (testRatio < minContrastRatio) {
+      minAlpha = testAlpha;
+    } else {
+      maxAlpha = testAlpha;
+    }
+
+    ++numIterations;
+  }
+
+  if (numIterations > kMinAlphaSearchMaxIterations) {
+    NSCAssert(NO, @"Too many iterations (%i) while finding min alpha of text color %@ on %@.",
+              (int)numIterations, color, backgroundColor);
+    return -1;
+  }
+
+  // Conservatively return the max of the range of possible alphas, which is known to pass.
+  return maxAlpha;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.h
new file mode 100644
index 0000000..7cdb664
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Return the average color of an image in a particular region.
+
+ The region will be intersected with the image's bounds. If the resulting region is empty (or the
+ input region was null) then this function returns nil.
+
+ @param image The image to examine.
+ @param region The region of the image to average, or CGRectInfinite for the entire image.
+ @return The average color, or nil if the region was invalid.
+ */
+UIColor *MDFAverageColorOfOpaqueImage(UIImage *image, CGRect region);
+
+#if defined __cplusplus
+}  // extern "C"
+#endif
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.m
new file mode 100644
index 0000000..0f11f3d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.m
@@ -0,0 +1,52 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFImageCalculations.h"
+
+UIColor *MDFAverageColorOfOpaqueImage(UIImage *image, CGRect region) {
+  CGImageRef imageRef = image.CGImage;
+  CGImageRef cropped = CGImageCreateWithImageInRect(imageRef, region);
+
+  // Empty/null regions will cause cropped to be nil.
+  if (!cropped) {
+    return nil;
+  }
+
+  UIGraphicsBeginImageContext(CGSizeMake(1, 1));
+
+  uint8_t argb[4];
+  CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
+  CGContextRef context =
+      CGBitmapContextCreate(argb,  // data
+                            1,     // width
+                            1,     // height
+                            8,     // Bits per component
+                            4,     // Bytes per row
+                            colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big);
+  CGColorSpaceRelease(colorspace);
+  CGContextSetInterpolationQuality(context, kCGInterpolationMedium);
+  CGContextSetBlendMode(context, kCGBlendModeCopy);
+  CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), cropped);
+  CGContextRelease(context);
+  CGImageRelease(cropped);
+
+  CGFloat alpha = argb[0] / (CGFloat)255;
+  CGFloat scale = alpha > 0 ? 1 / (alpha * 255) : 0;
+  UIColor *color =
+      [UIColor colorWithRed:scale * argb[1] green:scale * argb[2] blue:scale * argb[3] alpha:alpha];
+  UIGraphicsEndImageContext();
+  return color;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.h
new file mode 100644
index 0000000..57784b3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.h
@@ -0,0 +1,53 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef id (^MDFMappingFunction)(id object);
+
+/** Functional extensions to NSArray. */
+@interface NSArray (MDFUtils)
+
+/**
+ * Returns an array consisting of applying |function| to each element of self in order.
+ *
+ * @param function A block mapping an input element to an output element.
+ * @return An array of the same size as self containing elements mapped through the function.
+ */
+- (NSArray *)mdf_arrayByMappingObjects:(MDFMappingFunction)function;
+
+/**
+ * Returns a sorted version of |array| by using the passed comparator on self.
+ *
+ * @note The comparator acts of elements of self, @em not |array|.
+ *
+ * Example:
+ * @code
+ * NSArray *weights = @[ 100, 200, 50 ];
+ * NSArray *dogs = @[ @"Bruno", @"Tiger", @"Spot" ];
+ * NSComparator *ascending = ... NSString comparator ...
+ * NSArray *sortedDogs = [weights mdf_sortArray:dogs
+ *                              usingComparator:ascending];
+ * // sortedDogs is @[ @"Spot", @"Bruno", @"Tiger" ].
+ * @endcode
+ *
+ * @param array The array to sort.
+ * @param comparator A comparator acting on elements of self.
+ * @return A sorted copy of |array|.
+ */
+- (NSArray *)mdf_sortArray:(NSArray *)array usingComparator:(NSComparator)comparator;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.m
new file mode 100644
index 0000000..9758611
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.m
@@ -0,0 +1,68 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "NSArray+MDFUtils.h"
+
+@implementation NSArray (MDFUtils)
+
+- (NSArray *)mdf_arrayByMappingObjects:(MDFMappingFunction)function {
+  NSAssert(function, @"Mapping block must not be NULL.");
+  NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[self count]];
+  [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+    [array addObject:function(obj)];
+  }];
+  return [array copy];
+}
+
+- (BOOL)mdf_anyObjectPassesTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
+  NSIndexSet *indices = [self indexesOfObjectsPassingTest:predicate];
+  return [indices count] > 0;
+}
+
+- (BOOL)mdf_allObjectsPassTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
+  NSIndexSet *indices = [self indexesOfObjectsPassingTest:predicate];
+  return [indices count] == [self count];
+}
+
+- (NSArray *)mdf_sortArray:(NSArray *)array usingComparator:(NSComparator)comparator {
+  NSAssert(comparator, @"Comparator block must not be NULL.");
+
+  NSUInteger numElements = [self count];
+  NSAssert([array count] == numElements, @"Array %@ must have length %lu.", array,
+           (unsigned long)numElements);
+
+  // Create a permutation array by sorting self with comparator.
+  NSMutableArray *permutation = [[NSMutableArray alloc] initWithCapacity:numElements];
+  for (NSUInteger i = 0; i < numElements; ++i) {
+    [permutation addObject:@(i)];
+  }
+
+  NSArray *sortedPermutation = [permutation sortedArrayUsingComparator:^(id a, id b) {
+    NSUInteger firstIndex = [a unsignedIntegerValue];
+    NSUInteger secondIndex = [b unsignedIntegerValue];
+    return comparator(self[firstIndex], self[secondIndex]);
+  }];
+
+  // Permute array into order.
+  NSMutableArray *sorted = [[NSMutableArray alloc] initWithCapacity:numElements];
+  for (NSUInteger i = 0; i < numElements; ++i) {
+    NSUInteger index = [sortedPermutation[i] unsignedIntegerValue];
+    [sorted addObject:array[index]];
+  }
+  return [sorted copy];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Manifest.lock b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Manifest.lock
new file mode 100644
index 0000000..c2ab666
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Manifest.lock
@@ -0,0 +1,166 @@
+PODS:
+  - MaterialComponents (23.0.1):
+    - MaterialComponents/ActivityIndicator (= 23.0.1)
+    - MaterialComponents/AnimationTiming (= 23.0.1)
+    - MaterialComponents/AppBar (= 23.0.1)
+    - MaterialComponents/ButtonBar (= 23.0.1)
+    - MaterialComponents/Buttons (= 23.0.1)
+    - MaterialComponents/CollectionCells (= 23.0.1)
+    - MaterialComponents/CollectionLayoutAttributes (= 23.0.1)
+    - MaterialComponents/Collections (= 23.0.1)
+    - MaterialComponents/Dialogs (= 23.0.1)
+    - MaterialComponents/FeatureHighlight (= 23.0.1)
+    - MaterialComponents/FlexibleHeader (= 23.0.1)
+    - MaterialComponents/HeaderStackView (= 23.0.1)
+    - MaterialComponents/Ink (= 23.0.1)
+    - MaterialComponents/NavigationBar (= 23.0.1)
+    - MaterialComponents/OverlayWindow (= 23.0.1)
+    - MaterialComponents/PageControl (= 23.0.1)
+    - MaterialComponents/Palettes (= 23.0.1)
+    - MaterialComponents/private (= 23.0.1)
+    - MaterialComponents/ProgressView (= 23.0.1)
+    - MaterialComponents/ShadowElevations (= 23.0.1)
+    - MaterialComponents/ShadowLayer (= 23.0.1)
+    - MaterialComponents/Slider (= 23.0.1)
+    - MaterialComponents/Snackbar (= 23.0.1)
+    - MaterialComponents/Tabs (= 23.0.1)
+    - MaterialComponents/Typography (= 23.0.1)
+  - MaterialComponents/ActivityIndicator (23.0.1):
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/RTL
+  - MaterialComponents/AnimationTiming (23.0.1)
+  - MaterialComponents/AppBar (23.0.1):
+    - MaterialComponents/FlexibleHeader
+    - MaterialComponents/HeaderStackView
+    - MaterialComponents/NavigationBar
+    - MaterialComponents/private/Icons/ic_arrow_back
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ButtonBar (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/RTL
+  - MaterialComponents/Buttons (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/CollectionCells (23.0.1):
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/private/Icons/ic_check
+    - MaterialComponents/private/Icons/ic_check_circle
+    - MaterialComponents/private/Icons/ic_chevron_right
+    - MaterialComponents/private/Icons/ic_info
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked
+    - MaterialComponents/private/Icons/ic_reorder
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/CollectionLayoutAttributes (23.0.1)
+  - MaterialComponents/Collections (23.0.1):
+    - MaterialComponents/CollectionCells
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/Dialogs (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+  - MaterialComponents/FeatureHighlight (23.0.1):
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/FlexibleHeader (23.0.1):
+    - MaterialComponents/private/Application
+    - MDFTextAccessibility
+  - MaterialComponents/HeaderStackView (23.0.1)
+  - MaterialComponents/Ink (23.0.1)
+  - MaterialComponents/NavigationBar (23.0.1):
+    - MaterialComponents/ButtonBar
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/OverlayWindow (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/PageControl (23.0.1)
+  - MaterialComponents/Palettes (23.0.1)
+  - MaterialComponents/private (23.0.1):
+    - MaterialComponents/private/Application (= 23.0.1)
+    - MaterialComponents/private/Icons (= 23.0.1)
+    - MaterialComponents/private/KeyboardWatcher (= 23.0.1)
+    - MaterialComponents/private/Overlay (= 23.0.1)
+    - MaterialComponents/private/RTL (= 23.0.1)
+    - MaterialComponents/private/ThumbTrack (= 23.0.1)
+  - MaterialComponents/private/Application (23.0.1)
+  - MaterialComponents/private/Icons (23.0.1):
+    - MaterialComponents/private/Icons/Base (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_arrow_back (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check_circle (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_chevron_right (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_info (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_reorder (= 23.0.1)
+  - MaterialComponents/private/Icons/Base (23.0.1)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check_circle (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_chevron_right (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_info (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_reorder (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/KeyboardWatcher (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/private/Overlay (23.0.1)
+  - MaterialComponents/private/RTL (23.0.1)
+  - MaterialComponents/private/ThumbTrack (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ProgressView (23.0.1):
+    - MaterialComponents/private/RTL
+  - MaterialComponents/ShadowElevations (23.0.1)
+  - MaterialComponents/ShadowLayer (23.0.1)
+  - MaterialComponents/Slider (23.0.1):
+    - MaterialComponents/private/ThumbTrack
+  - MaterialComponents/Snackbar (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Buttons
+    - MaterialComponents/OverlayWindow
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/Overlay
+    - MaterialComponents/Typography
+  - MaterialComponents/Tabs (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/Typography (23.0.1):
+    - MaterialComponents/private/Application
+  - MDFTextAccessibility (1.2.0)
+
+DEPENDENCIES:
+  - MaterialComponents
+
+SPEC CHECKSUMS:
+  MaterialComponents: 8666bde1128660f2a3525d03d6b460d2bc34dc3b
+  MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
+
+PODFILE CHECKSUM: abed8eea0ed77b9de5377b2d8f0b9fd29abd1705
+
+COCOAPODS: 1.2.1
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/LICENSE b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/README.md b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/README.md
new file mode 100644
index 0000000..5df3c30
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/README.md
@@ -0,0 +1,160 @@
+# Material Components for iOS
+
+<img align="right" src="mdc_hero.png" width="300px">
+
+[![Build Status](https://travis-ci.org/material-components/material-components-ios.svg?branch=develop)](https://travis-ci.org/material-components/material-components-ios)
+[![Code coverage](https://img.shields.io/codecov/c/github/material-components/material-components-ios/develop.svg)](https://codecov.io/gh/material-components/material-components-ios/branch/develop)
+
+Material Components for iOS (MDC-iOS) helps developers execute [Material Design](https://www.material.io). Developed by a core team of engineers and UX designers at Google, these components enable a reliable development workflow to build beautiful and functional iOS apps. Learn more about how Material Design supports design and usability best practices across platforms in the  [Material Design Platform Adaptation guidelines](https://material.io/guidelines/platforms/platform-adaptation.html).
+
+Material Components for iOS are written in Objective-C and support Swift and Interface Builder.
+
+## Useful Links
+
+- [How To Use MDC-iOS](howto/)
+- [All Components](components/)
+- [Demo Apps](demos/)
+- [Contributing](contributing/)
+- [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
+- [Material.io](https://www.material.io) (external site)
+- [Material Design Guidelines](https://material.google.com) (external site)
+
+## Trying out Material Components
+
+Our [catalog](catalog/) showcases Material Components. You can use the `pod try` command from anywhere on your machine to try the components, even if you haven't checked out the repo yet:
+
+~~~ bash
+pod try MaterialComponents
+~~~
+
+In case you have already checked out the repo, run the following command:
+
+~~~ bash
+pod install --project-directory=catalog/
+~~~
+
+If you want to take a look at the implementation of the components, you can find the code inside the `Development Pods` folder.
+Use `cmd-1` to open the project navigator within Xcode. Peal open the `Pods` project and inside the `Development Pods` folder you will find the component source code.
+
+## Installation
+
+### Getting Started with a New Project
+
+Check out our [tutorial](howto/tutorial) for a step-by-step guide to setting up a new project using Material Components.
+
+### Adding Material Components to an Existing Project
+
+[CocoaPods](https://cocoapods.org/) is the easiest way to get started (if you're new to CocoaPods,
+check out their [getting started documentation](https://guides.cocoapods.org/using/getting-started.html).)
+
+To install CocoaPods, run the following commands:
+
+~~~ bash
+sudo gem install cocoapods
+~~~
+
+To integrate Material Components in your existing application, first create a new Podfile:
+
+~~~ bash
+cd your-project-directory
+pod init
+~~~
+
+Next, add the
+[Material Components for iOS pod](https://cocoapods.org/pods/MaterialComponentsIOS)
+to your target in your Podfile:
+
+~~~ ruby
+target "MyApp" do
+  ...
+  pod 'MaterialComponents'
+end
+~~~
+
+If you are using Swift, don’t forget to uncomment the `use_frameworks!` line
+at the top of your Podfile.
+
+Then run the command:
+
+~~~ bash
+pod install
+~~~
+
+Now you're ready to get started in Xcode. Don't forget to open the workspace Cocoapods created for you instead of the original project:
+
+~~~ bash
+open your-project.xcworkspace
+~~~
+
+### Usage
+
+The components are built upon familiar UIKit classes and can be added to a view with just a couple of lines. Simply import the Material Components header for the component you're interested in, and add it to your view.
+
+#### Swift
+
+~~~ swift
+import MaterialComponents.MaterialButtons
+
+class ViewController: UIViewController {
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        let raiseButton = MDCRaisedButton.init();
+        raiseButton.setTitle("Raised Button", forState: .Normal);
+        raiseButton.sizeToFit();
+        raiseButton.addTarget(self, action: #selector(tapped), forControlEvents: .TouchUpInside);
+        self.view.addSubview(raiseButton);
+    }
+
+    func tapped(sender: UIButton!){
+        NSLog("Button was tapped!");
+    }
+
+}
+~~~
+
+#### Objective-C
+
+~~~ objc
+#import "MaterialButtons.h"
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  MDCRaisedButton *raisedButton = [MDCRaisedButton new];
+  [raisedButton setTitle:@"Raised Button" forState:UIControlStateNormal];
+  [raisedButton sizeToFit];
+  [raisedButton addTarget:self
+                   action:@selector(tapped:)
+         forControlEvents:UIControlEventTouchUpInside];
+
+  [self.view addSubview:raisedButton];
+}
+
+- (void)tapped:(id)sender {
+  NSLog(@"Button was tapped!");
+}
+
+@end
+~~~
+
+## Attributions
+
+Material Components for iOS uses
+[Material Design icons](https://github.com/google/material-design-icons),
+copyright Google Inc. and licensed under
+[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
+
+Several components use
+[MDFTextAccessibility](https://github.com/material-foundation/material-text-accessibility-ios),
+copyright Google Inc. and licensed under
+[Apache 2.0](https://github.com/material-foundation/material-text-accessibility-ios/blob/master/LICENSE)
+without a NOTICE file.
+
+MDCCatalog uses the
+[Roboto font](https://github.com/google/fonts/tree/master/apache/roboto),
+copyright 2011 Google Inc. and licensed under
+[Apache 2.0](https://github.com/google/fonts/blob/master/apache/roboto/LICENSE.txt)
+without a NOTICE file.
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
new file mode 100644
index 0000000..db0b8b0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
@@ -0,0 +1,132 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCActivityIndicatorDelegate;
+
+/**
+ Different operating modes for the activity indicator.
+
+ This component can be used as a determinate progress indicator or an indeterminate activity
+ indicator.
+
+ Default value is MDCActivityIndicatorModeIndeterminate.
+ */
+typedef NS_ENUM(NSInteger, MDCActivityIndicatorMode) {
+  /** Indeterminate indicators visualize an unspecified wait time. */
+  MDCActivityIndicatorModeIndeterminate,
+  /** Determinate indicators display how long an operation will take. */
+  MDCActivityIndicatorModeDeterminate,
+};
+
+/**
+ A Material Design activity indicator.
+
+ The activity indicator is a circular spinner that shows progress of an operation. By default the
+ activity indicator assumes indeterminate progress of an unspecified length of time. In contrast to
+ a standard UIActivityIndicator, MDCActivityIndicator supports showing determinate progress and uses
+ custom Material Design animation for indeterminate progress.
+
+ See https://www.google.com/design/spec/components/progress-activity.html
+ */
+IB_DESIGNABLE
+@interface MDCActivityIndicator : UIView
+
+/**
+ The callback delegate. See @c MDCActivityIndicatorDelegate.
+ */
+@property(nonatomic, weak, nullable) id<MDCActivityIndicatorDelegate> delegate;
+
+/**
+ Whether or not the activity indicator is currently animating.
+ */
+@property(nonatomic, assign, getter=isAnimating) BOOL animating;
+
+/**
+ Spinner radius width. Defaults to 12dp (24x24dp circle), constrained to range [8dp, 72dp]. The
+ spinner is centered in the view's bounds. If the bounds are smaller than the diameter of the
+ spinner, the spinner may be clipped when clipToBounds is true.
+ */
+@property(nonatomic, assign) CGFloat radius UI_APPEARANCE_SELECTOR;
+
+/**
+ Spinner stroke width. Defaults to 2dp.
+ */
+@property(nonatomic, assign) CGFloat strokeWidth UI_APPEARANCE_SELECTOR;
+
+/**
+ Show a faint ink track along the path of the indicator. Should be enabled when the activity
+ indicator wraps around another circular element, such as an avatar or a FAB. Defaults to NO.
+ */
+@property(nonatomic, assign) IBInspectable BOOL trackEnabled;
+
+/**
+ The mode of the activity indicator. Default is MDCActivityIndicatorModeIndeterminate. If
+ currently animating, it will animate the transition between the current mode to the new mode.
+ */
+@property(nonatomic, assign) IBInspectable MDCActivityIndicatorMode indicatorMode;
+
+/**
+ Set the mode of the activity indicator. If currently animating, it will animate the transition
+ between the current mode to the new mode. Default is MDCActivityIndicatorModeIndeterminate with no
+ animation.
+ */
+- (void)setIndicatorMode:(MDCActivityIndicatorMode)mode animated:(BOOL)animated;
+
+/**
+ Progress is the extent to which the activity indicator circle is drawn to completion when
+ indicatorMode is MDCActivityIndicatorModeDeterminate. Progress is drawn clockwise to complete a
+ circle. Valid range is between [0-1]. Default is zero. 0.5 progress is half the circle. The
+ transitions between progress levels are animated.
+ */
+@property(nonatomic, assign) IBInspectable float progress;
+
+/**
+ The array of colors that are cycled through when animating the spinner. Populated with default
+ colors of blue, red, yellow and green on initialization. An empty array results in a blue spinner
+ with no color cycling.
+ */
+@property(nonatomic, copy, nonnull) NSArray<UIColor *> *cycleColors UI_APPEARANCE_SELECTOR;
+
+/**
+ Starts the animated activity indicator. Does nothing if the spinner is already animating.
+ */
+- (void)startAnimating;
+
+/**
+ Stops the animated activity indicator with a short opacity and stroke width animation. Does nothing
+ if the spinner is not animating.
+ */
+- (void)stopAnimating;
+
+@end
+
+/**
+ Delegate protocol for the MDCActivityIndicator.
+ */
+@protocol MDCActivityIndicatorDelegate <NSObject>
+
+@optional
+/**
+ When stop is called, the spinner gracefully animates out using opacity and stroke width.
+ This method is called after that fade-out animation completes.
+
+ @param activityIndicator Caller
+ */
+- (void)activityIndicatorAnimationDidFinish:(nonnull MDCActivityIndicator *)activityIndicator;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.m
new file mode 100644
index 0000000..58d3d23
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.m
@@ -0,0 +1,798 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCActivityIndicator.h"
+
+#import "MaterialRTL.h"
+#import "UIApplication+AppExtensions.h"
+
+static const NSInteger kMDCActivityIndicatorTotalDetentCount = 5;
+static const NSTimeInterval kMDCActivityIndicatorAnimateOutDuration = 0.1f;
+static const NSTimeInterval kMDCActivityIndicatorPointCycleDuration = 4.0f / 3.0f;
+static const NSTimeInterval kMDCActivityIndicatorPointCycleMinimumVariableDuration =
+    kMDCActivityIndicatorPointCycleDuration / 8;
+static const CGFloat kCycleRotation = 3.0f / 2.0f;
+static const CGFloat kOuterRotationIncrement =
+    (1.0f / kMDCActivityIndicatorTotalDetentCount) * (CGFloat)M_PI;
+static const CGFloat kSpinnerRadius = 12.f;
+static const CGFloat kStrokeLength = 0.75f;
+
+/**
+ Total rotation (outer rotation + stroke rotation) per _cycleCount. One turn is 2.0f.
+ */
+static const CGFloat kSingleCycleRotation =
+    2 * kStrokeLength + kCycleRotation + 1.0f / kMDCActivityIndicatorTotalDetentCount;
+
+/*
+ States for the internal state machine. The states represent the last animation completed.
+ It provides information required to select the next animation.
+ */
+typedef NS_ENUM(NSInteger, MDCActivityIndicatorState) {
+  MDCActivityIndicatorStateIndeterminate,
+  MDCActivityIndicatorStateTransitionToDeterminate,
+  MDCActivityIndicatorStateDeterminate,
+  MDCActivityIndicatorStateTransitionToIndeterminate,
+};
+
+@interface MDCActivityIndicator ()
+
+/**
+ The minimum stroke difference to use when collapsing the stroke to a dot. Based on current
+ radius and stroke width.
+ */
+@property(nonatomic, assign, readonly) CGFloat minStrokeDifference;
+
+/**
+ The current color count for the spinner. Subclasses can change this value to start the spinner at
+ a different color.
+ */
+@property(nonatomic, assign) NSUInteger currentColorCount;
+
+/**
+ The current cycle count.
+ */
+@property(nonatomic, assign, readonly) NSInteger cycleCount;
+
+/**
+ The cycle index at which to start the activity spinner animation. Default is 0, which corresponds
+ to the top of the spinner (12 o'clock position). Spinner cycle indices are based on a 5-point
+ star.
+ */
+@property(nonatomic, assign) NSInteger cycleStartIndex;
+
+/**
+ The outer layer that handles cycle rotations and houses the stroke layer.
+ */
+@property(nonatomic, strong, readonly, nullable) CALayer *outerRotationLayer;
+
+/**
+ The shape layer that handles the animating stroke.
+ */
+@property(nonatomic, strong, readonly, nullable) CAShapeLayer *strokeLayer;
+
+/**
+ The shape layer that shows a faint, circular track along the path of the stroke layer. Enabled
+ via the trackEnabled property.
+ */
+@property(nonatomic, strong, readonly, nullable) CAShapeLayer *trackLayer;
+
+@end
+
+@implementation MDCActivityIndicator {
+  BOOL _animatingOut;
+  BOOL _animationsAdded;
+  BOOL _animationInProgress;
+  BOOL _backgrounded;
+  BOOL _cycleInProgress;
+  CGFloat _currentProgress;
+  CGFloat _lastProgress;
+}
+
+#pragma mark - Init
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCActivityIndicatorInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder {
+  self = [super initWithCoder:coder];
+  if (self) {
+    [self commonMDCActivityIndicatorInit];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self applyPropertiesWithoutAnimation:^{
+    // Resize and recenter rotation layer.
+    _outerRotationLayer.bounds = self.bounds;
+    _outerRotationLayer.position =
+        CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
+
+    _strokeLayer.bounds = _outerRotationLayer.bounds;
+    _strokeLayer.position = _outerRotationLayer.position;
+
+    [self updateStrokePath];
+  }];
+}
+
+- (void)commonMDCActivityIndicatorInit {
+  // Register notifications for foreground and background if needed.
+  [self registerForegroundAndBackgroundNotificationObserversIfNeeded];
+
+  // The activity indicator reflects the passage of time (a spatial semantic context) and so
+  // will not be mirrored in RTL languages.
+  self.mdc_semanticContentAttribute = UISemanticContentAttributeSpatial;
+
+  _cycleStartIndex = 0;
+  _indicatorMode = MDCActivityIndicatorModeIndeterminate;
+
+  // Property defaults.
+  _radius = kSpinnerRadius;
+  _strokeWidth = 2.0f;
+
+  // Colors.
+  _cycleColors = [MDCActivityIndicator defaultColors];
+  _currentColorCount = 0;
+
+  // Track layer.
+  _trackLayer = [CAShapeLayer layer];
+  _trackLayer.lineWidth = _strokeWidth;
+  _trackLayer.fillColor = [UIColor clearColor].CGColor;
+  [self.layer addSublayer:_trackLayer];
+  _trackLayer.hidden = YES;
+
+  // Rotation layer.
+  _outerRotationLayer = [CALayer layer];
+  [self.layer addSublayer:_outerRotationLayer];
+
+  // Stroke layer.
+  _strokeLayer = [CAShapeLayer layer];
+  _strokeLayer.lineWidth = _strokeWidth;
+  _strokeLayer.fillColor = [UIColor clearColor].CGColor;
+  _strokeLayer.strokeStart = 0;
+  _strokeLayer.strokeEnd = 0;
+  [_outerRotationLayer addSublayer:_strokeLayer];
+}
+
+#pragma mark - UIView
+
+- (void)willMoveToWindow:(UIWindow *)newWindow {
+  // If the activity indicator is removed from the window, we should
+  // immediately stop animating, otherwise it will start chewing up CPU.
+  if (!newWindow) {
+    [self actuallyStopAnimating];
+  } else if (_animating && !_backgrounded) {
+    [self actuallyStartAnimating];
+  }
+}
+
+- (CGSize)intrinsicContentSize {
+  CGFloat edge = 2 * _radius + _strokeWidth;
+  return CGSizeMake(edge, edge);
+}
+
+#pragma mark - Public methods
+
+- (void)startAnimating {
+  if (_animatingOut) {
+    [self removeAnimations];
+  }
+
+  if (_animating) {
+    return;
+  }
+
+  _animating = YES;
+
+  if (self.window && !_backgrounded) {
+    [self actuallyStartAnimating];
+  }
+}
+
+- (void)stopAnimating {
+  if (!_animating) {
+    return;
+  }
+
+  _animating = NO;
+
+  [self animateOut];
+}
+
+- (void)stopAnimatingImmediately {
+  if (!_animating) {
+    return;
+  }
+
+  _animating = NO;
+
+  [self actuallyStopAnimating];
+
+  if ([_delegate respondsToSelector:@selector(activityIndicatorAnimationDidFinish:)]) {
+    [_delegate activityIndicatorAnimationDidFinish:self];
+  }
+}
+
+- (void)resetStrokeColor {
+  _currentColorCount = 0;
+
+  [self updateStrokeColor];
+}
+
+- (void)setStrokeColor:(UIColor *)strokeColor {
+  _strokeLayer.strokeColor = strokeColor.CGColor;
+  _trackLayer.strokeColor = [strokeColor colorWithAlphaComponent:0.3f].CGColor;
+}
+
+- (void)setIndicatorMode:(MDCActivityIndicatorMode)indicatorMode {
+  if (_indicatorMode == indicatorMode) {
+    return;
+  }
+  _indicatorMode = indicatorMode;
+  if (_animating && !_animationInProgress) {
+    switch (indicatorMode) {
+      case MDCActivityIndicatorModeDeterminate:
+        [self addTransitionToDeterminateCycle];
+        break;
+      case MDCActivityIndicatorModeIndeterminate:
+        [self addTransitionToIndeterminateCycle];
+        break;
+    }
+  }
+}
+
+- (void)setIndicatorMode:(MDCActivityIndicatorMode)mode animated:(BOOL)animated {
+  [self setIndicatorMode:mode];
+}
+
+- (void)setProgress:(float)progress {
+  _progress = MAX(0.0f, MIN(progress, 1.0f));
+  if (_progress == _currentProgress) {
+    return;
+  }
+  if (_animating && !_animationInProgress) {
+    switch (_indicatorMode) {
+      case MDCActivityIndicatorModeDeterminate:
+        // Currently animating the determinate mode but no animation queued.
+        [self addProgressAnimation];
+        break;
+      case MDCActivityIndicatorModeIndeterminate:
+        break;
+    }
+  }
+}
+
+#pragma mark - Properties
+
+- (void)setStrokeWidth:(CGFloat)strokeWidth {
+  _strokeWidth = strokeWidth;
+  _strokeLayer.lineWidth = _strokeWidth;
+  _trackLayer.lineWidth = _strokeWidth;
+
+  [self updateStrokePath];
+}
+
+- (void)setRadius:(CGFloat)radius {
+  _radius = MIN(MAX(radius, 5.0f), 72.0f);
+
+  [self updateStrokePath];
+}
+
+- (void)setTrackEnabled:(BOOL)trackEnabled {
+  _trackEnabled = trackEnabled;
+
+  _trackLayer.hidden = !_trackEnabled;
+}
+
+#pragma mark - Private methods
+
+/**
+ If this class is not being run in an extension, register for foreground changes and initialize
+ the app background state in case UI is created when the app is backgrounded. (Extensions always
+ return UIApplicationStateBackground for |[UIApplication sharedApplication].applicationState|.)
+ */
+- (void)registerForegroundAndBackgroundNotificationObserversIfNeeded {
+  if ([UIApplication mdc_isAppExtension]) {
+    return;
+  }
+
+  _backgrounded =
+      [UIApplication mdc_safeSharedApplication].applicationState == UIApplicationStateBackground;
+  NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+  [notificationCenter addObserver:self
+                         selector:@selector(controlAnimatingOnForegroundChange:)
+                             name:UIApplicationWillEnterForegroundNotification
+                           object:nil];
+  [notificationCenter addObserver:self
+                         selector:@selector(controlAnimatingOnForegroundChange:)
+                             name:UIApplicationDidEnterBackgroundNotification
+                           object:nil];
+}
+
+- (void)controlAnimatingOnForegroundChange:(NSNotification *)notification {
+  // Stop or restart animating if the app has a foreground change.
+  _backgrounded = [notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification];
+  if (_animating) {
+    if (_backgrounded) {
+      [self actuallyStopAnimating];
+    } else if (self.window) {
+      [self actuallyStartAnimating];
+    }
+  }
+}
+
+- (void)actuallyStartAnimating {
+  if (_animationsAdded) {
+    return;
+  }
+  _animationsAdded = YES;
+  _cycleCount = _cycleStartIndex;
+
+  [self applyPropertiesWithoutAnimation:^{
+    _strokeLayer.strokeStart = 0.0f;
+    _strokeLayer.strokeEnd = 0.001f;
+    _strokeLayer.lineWidth = _strokeWidth;
+    _trackLayer.lineWidth = _strokeWidth;
+
+    [self resetStrokeColor];
+    [self updateStrokePath];
+  }];
+
+  switch (_indicatorMode) {
+    case MDCActivityIndicatorModeIndeterminate:
+      [self addStrokeRotationCycle];
+      break;
+    case MDCActivityIndicatorModeDeterminate:
+      [self addProgressAnimation];
+      break;
+  }
+}
+
+- (void)actuallyStopAnimating {
+  if (!_animationsAdded) {
+    return;
+  }
+
+  [self removeAnimations];
+  [self applyPropertiesWithoutAnimation:^{
+    _strokeLayer.strokeStart = 0.0f;
+    _strokeLayer.strokeEnd = 0.0f;
+  }];
+}
+
+- (void)updateStrokePath {
+  CGFloat offsetRadius = _radius - _strokeLayer.lineWidth / 2.0f;
+  UIBezierPath *strokePath = [UIBezierPath bezierPathWithArcCenter:_strokeLayer.position
+                                                            radius:offsetRadius
+                                                        startAngle:-1.0f * (CGFloat)M_PI_2
+                                                          endAngle:3.0f * (CGFloat)M_PI_2
+                                                         clockwise:YES];
+  _strokeLayer.path = strokePath.CGPath;
+  _trackLayer.path = strokePath.CGPath;
+
+  _minStrokeDifference = _strokeLayer.lineWidth / ((CGFloat)M_PI * 2 * _radius);
+}
+
+- (void)updateStrokeColor {
+  if (_cycleColors.count > 0) {
+    [self setStrokeColor:_cycleColors[_currentColorCount]];
+  } else {
+    [self setStrokeColor:[MDCActivityIndicator defaultColors][0]];
+  }
+}
+
+- (void)addStrokeRotationCycle {
+  if (_animationInProgress) {
+    return;
+  }
+
+  [CATransaction begin];
+  {
+    [CATransaction setCompletionBlock:^{
+      [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateIndeterminate];
+    }];
+
+    // Outer 5-point star detent rotation.
+    CABasicAnimation *outerRotationAnimation =
+        [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+    outerRotationAnimation.duration = kMDCActivityIndicatorPointCycleDuration;
+    outerRotationAnimation.fromValue = @(kOuterRotationIncrement * _cycleCount);
+    outerRotationAnimation.toValue = @(kOuterRotationIncrement * (_cycleCount + 1));
+    outerRotationAnimation.fillMode = kCAFillModeForwards;
+    outerRotationAnimation.removedOnCompletion = NO;
+    [_outerRotationLayer addAnimation:outerRotationAnimation forKey:@"transform.rotation.z"];
+
+    // Stroke rotation.
+    CGFloat startRotation = _cycleCount * (CGFloat)M_PI;
+    CGFloat endRotation = startRotation + kCycleRotation * (CGFloat)M_PI;
+
+    CABasicAnimation *strokeRotationAnimation =
+        [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+    strokeRotationAnimation.duration = kMDCActivityIndicatorPointCycleDuration;
+    strokeRotationAnimation.fromValue = @(startRotation);
+    strokeRotationAnimation.toValue = @(endRotation);
+    strokeRotationAnimation.fillMode = kCAFillModeForwards;
+    strokeRotationAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeRotationAnimation forKey:@"transform.rotation.z"];
+
+    // Stroke start.
+    CABasicAnimation *strokeStartPathAnimation =
+        [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+    strokeStartPathAnimation.duration = kMDCActivityIndicatorPointCycleDuration / 2;
+    // It is always critical to convertTime:fromLayer: for animations, since changes to layer.speed
+    // on this layer or parent layers will alter the offset of beginTime.
+    CFTimeInterval currentTime = [_strokeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
+    strokeStartPathAnimation.beginTime = currentTime + kMDCActivityIndicatorPointCycleDuration / 2;
+    strokeStartPathAnimation.fromValue = @(0.0f);
+    strokeStartPathAnimation.toValue = @(kStrokeLength);
+    strokeStartPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeStartPathAnimation.fillMode = kCAFillModeBoth;
+    strokeStartPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeStartPathAnimation forKey:@"strokeStart"];
+
+    // Stroke end.
+    CABasicAnimation *strokeEndPathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+    strokeEndPathAnimation.duration =
+        kMDCActivityIndicatorPointCycleDuration * ABS(_lastProgress - _currentProgress);
+    // Ensure the stroke never completely disappears on start by animating from non-zero start and
+    // to a value slightly larger than the strokeStart's final value.
+    strokeEndPathAnimation.fromValue = @(_minStrokeDifference);
+    strokeEndPathAnimation.toValue = @(kStrokeLength + _minStrokeDifference);
+    strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+    strokeEndPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+  }
+  [CATransaction commit];
+
+  _animationInProgress = YES;
+}
+
+- (void)addTransitionToIndeterminateCycle {
+  if (_animationInProgress) {
+    return;
+  }
+  // Find the nearest cycle to transition through.
+  NSInteger nearestCycle = 0;
+  CGFloat nearestDistance = CGFLOAT_MAX;
+  const CGFloat normalizedProgress = MAX(_lastProgress - _minStrokeDifference, 0.0f);
+  for (NSInteger cycle = 0; cycle < kMDCActivityIndicatorTotalDetentCount; cycle++) {
+    const CGFloat currentRotation = [self normalizedRotationForCycle:cycle];
+    if (currentRotation >= normalizedProgress) {
+      if (nearestDistance >= (currentRotation - normalizedProgress)) {
+        nearestDistance = currentRotation - normalizedProgress;
+        nearestCycle = cycle;
+      }
+    }
+  }
+
+  if (nearestCycle == 0 && _lastProgress <= _minStrokeDifference) {
+    // Special case for 0% progress.
+    _cycleCount = nearestCycle;
+    [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToIndeterminate];
+    return;
+  }
+
+  _cycleCount = nearestCycle;
+
+  CGFloat targetRotation = [self normalizedRotationForCycle:nearestCycle];
+  if (targetRotation <= 0.001f) {
+    targetRotation = 1.0f;
+  }
+  CGFloat normalizedDuration = 2 * (targetRotation + _currentProgress) / kSingleCycleRotation *
+                               (CGFloat)kMDCActivityIndicatorPointCycleDuration;
+  CGFloat strokeEndTravelDistance = targetRotation - _currentProgress + _minStrokeDifference;
+  CGFloat totalDistance = targetRotation + strokeEndTravelDistance;
+  CGFloat strokeStartDuration =
+      MAX(normalizedDuration * targetRotation / totalDistance,
+          (CGFloat)kMDCActivityIndicatorPointCycleMinimumVariableDuration);
+  CGFloat strokeEndDuration = MAX(normalizedDuration * strokeEndTravelDistance / totalDistance,
+                                  (CGFloat)kMDCActivityIndicatorPointCycleMinimumVariableDuration);
+
+  [CATransaction begin];
+  {
+    [CATransaction setCompletionBlock:^{
+      [self
+          strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToIndeterminate];
+    }];
+
+    // Stroke start.
+    CABasicAnimation *strokeStartPathAnimation =
+        [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+    strokeStartPathAnimation.duration = strokeStartDuration;
+    CFTimeInterval currentTime = [_strokeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
+    strokeStartPathAnimation.beginTime = currentTime + strokeEndDuration;
+    strokeStartPathAnimation.fromValue = @(0.0f);
+    strokeStartPathAnimation.toValue = @(targetRotation);
+    strokeStartPathAnimation.timingFunction = [self materialEaseInOut];
+    ;
+    strokeStartPathAnimation.fillMode = kCAFillModeBoth;
+    strokeStartPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeStartPathAnimation forKey:@"strokeStart"];
+
+    // Stroke end.
+    CABasicAnimation *strokeEndPathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+    strokeEndPathAnimation.duration = strokeEndDuration;
+    // Ensure the stroke never completely disappears on start by animating from non-zero start and
+    // to a value slightly larger than the strokeStart's final value.
+    strokeEndPathAnimation.fromValue = @(_currentProgress);
+    strokeEndPathAnimation.toValue = @(targetRotation + _minStrokeDifference);
+    strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+    strokeEndPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+  }
+  [CATransaction commit];
+
+  _animationInProgress = YES;
+}
+
+- (void)addTransitionToDeterminateCycle {
+  if (_animationInProgress) {
+    return;
+  }
+  if (!_cycleCount) {
+    // The animation period is complete: no need for transition.
+    [_strokeLayer removeAllAnimations];
+    [_outerRotationLayer removeAllAnimations];
+    // Necessary for transition from indeterminate to determinate when cycle == 0.
+    _currentProgress = 0.0f;
+    _lastProgress = _currentProgress;
+    [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToDeterminate];
+  } else {
+    _currentProgress = MAX(_progress, _minStrokeDifference);
+
+    CGFloat rotationDelta = 1.0f - [self normalizedRotationForCycle:_cycleCount];
+
+    // Change the duration relative to the distance in order to keep same relative speed.
+    CGFloat duration = 2.0f * (rotationDelta + _currentProgress) / kSingleCycleRotation *
+                       (CGFloat)kMDCActivityIndicatorPointCycleDuration;
+
+    duration = MAX(duration, (CGFloat)kMDCActivityIndicatorPointCycleMinimumVariableDuration);
+    [CATransaction begin];
+    {
+      [CATransaction setCompletionBlock:^{
+        [self
+            strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToDeterminate];
+      }];
+
+      // Outer 5-point star detent rotation. Required for passing from transitionToIndeterminate to
+      // transitionToDeterminate.
+      CABasicAnimation *outerRotationAnimation =
+          [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+      outerRotationAnimation.duration = duration;
+      outerRotationAnimation.fromValue = @(kOuterRotationIncrement * _cycleCount);
+      outerRotationAnimation.toValue = @(kOuterRotationIncrement * _cycleCount);
+      outerRotationAnimation.fillMode = kCAFillModeForwards;
+      outerRotationAnimation.removedOnCompletion = NO;
+      [_outerRotationLayer addAnimation:outerRotationAnimation forKey:@"transform.rotation.z"];
+
+      // Stroke rotation.
+      CGFloat startRotation = _cycleCount * (CGFloat)M_PI;
+      CGFloat endRotation = startRotation + rotationDelta * 2.0f * (CGFloat)M_PI;
+
+      CABasicAnimation *strokeRotationAnimation =
+          [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+      strokeRotationAnimation.duration = duration;
+      strokeRotationAnimation.fromValue = @(startRotation);
+      strokeRotationAnimation.toValue = @(endRotation);
+      strokeRotationAnimation.fillMode = kCAFillModeForwards;
+      strokeRotationAnimation.removedOnCompletion = NO;
+      [_strokeLayer addAnimation:strokeRotationAnimation forKey:@"transform.rotation.z"];
+
+      // Stroke start.
+      CABasicAnimation *strokeStartPathAnimation =
+          [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+      strokeStartPathAnimation.duration = duration;
+      // It is always critical to convertTime:fromLayer: for animations, since changes to
+      // layer.speed on this layer or parent layers will alter the offset of beginTime.
+      CFTimeInterval currentTime = [_strokeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
+      strokeStartPathAnimation.beginTime = currentTime;
+      strokeStartPathAnimation.fromValue = @(0.0f);
+      strokeStartPathAnimation.toValue = @(0.0f);
+      strokeStartPathAnimation.timingFunction = [self materialEaseInOut];
+      strokeStartPathAnimation.fillMode = kCAFillModeBoth;
+      strokeStartPathAnimation.removedOnCompletion = NO;
+      [_strokeLayer addAnimation:strokeStartPathAnimation forKey:@"strokeStart"];
+
+      // Stroke end.
+      CABasicAnimation *strokeEndPathAnimation =
+          [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+      strokeEndPathAnimation.duration = duration;
+      // Ensure the stroke never completely disappears on start by animating from non-zero start and
+      // to a value slightly larger than the strokeStart's final value.
+      strokeEndPathAnimation.fromValue = @(_minStrokeDifference);
+      strokeEndPathAnimation.toValue = @(_currentProgress);
+      strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+      strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+      strokeEndPathAnimation.removedOnCompletion = NO;
+      [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+    }
+    [CATransaction commit];
+
+    _animationInProgress = YES;
+    _lastProgress = _currentProgress;
+  }
+}
+
+- (CAMediaTimingFunction *)materialEaseInOut {
+  // This curve is slow both at the beginning and end.
+  // Visualization of curve  http://cubic-bezier.com/#.4,0,.2,1
+  return [[CAMediaTimingFunction alloc] initWithControlPoints:0.4f:0.0f:0.2f:1.0f];
+}
+
+- (void)addProgressAnimation {
+  if (_animationInProgress) {
+    return;
+  }
+
+  _currentProgress = MAX(_progress, _minStrokeDifference);
+
+  [CATransaction begin];
+  {
+    [CATransaction setCompletionBlock:^{
+      [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateDeterminate];
+    }];
+
+    // Stroke end.
+    CABasicAnimation *strokeEndPathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+    strokeEndPathAnimation.duration = kMDCActivityIndicatorPointCycleDuration / 2;
+    strokeEndPathAnimation.fromValue = @(_lastProgress);
+    strokeEndPathAnimation.toValue = @(_currentProgress);
+    strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+    strokeEndPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+  }
+
+  [CATransaction commit];
+
+  _lastProgress = _currentProgress;
+  _animationInProgress = YES;
+}
+
+- (void)strokeRotationCycleFinishedFromState:(MDCActivityIndicatorState)state {
+  _animationInProgress = NO;
+
+  if (!_animationsAdded) {
+    return;
+  }
+  if (state == MDCActivityIndicatorStateIndeterminate) {
+    if (_cycleColors.count > 0) {
+      _currentColorCount = (_currentColorCount + 1) % _cycleColors.count;
+      [self updateStrokeColor];
+    }
+    _cycleCount = (_cycleCount + 1) % kMDCActivityIndicatorTotalDetentCount;
+  }
+
+  switch (_indicatorMode) {
+    case MDCActivityIndicatorModeDeterminate:
+      switch (state) {
+        case MDCActivityIndicatorStateDeterminate:
+        case MDCActivityIndicatorStateTransitionToDeterminate:
+          [self addProgressAnimationIfRequired];
+          break;
+        case MDCActivityIndicatorStateIndeterminate:
+        case MDCActivityIndicatorStateTransitionToIndeterminate:
+          [self addTransitionToDeterminateCycle];
+          break;
+      }
+      break;
+    case MDCActivityIndicatorModeIndeterminate:
+      switch (state) {
+        case MDCActivityIndicatorStateDeterminate:
+        case MDCActivityIndicatorStateTransitionToDeterminate:
+          [self addTransitionToIndeterminateCycle];
+          break;
+        case MDCActivityIndicatorStateIndeterminate:
+        case MDCActivityIndicatorStateTransitionToIndeterminate:
+          [self addStrokeRotationCycle];
+          break;
+      }
+      break;
+  }
+}
+
+- (void)addProgressAnimationIfRequired {
+  if (_indicatorMode == MDCActivityIndicatorModeDeterminate) {
+    if (MAX(_progress, _minStrokeDifference) != _currentProgress) {
+      // The values were changes in the while animating or animation is starting.
+      [self addProgressAnimation];
+    }
+  }
+}
+
+/**
+ Rotation that a given cycle has. Represented between 0.0f (cycle has no rotation) and 1.0f.
+ */
+- (CGFloat)normalizedRotationForCycle:(NSInteger)cycle {
+  CGFloat cycleRotation = cycle * kSingleCycleRotation / 2.0f;
+  return cycleRotation - ((NSInteger)cycleRotation);
+}
+
+- (void)animateOut {
+  _animatingOut = YES;
+
+  [CATransaction begin];
+
+  [CATransaction setCompletionBlock:^{
+    if (_animatingOut) {
+      [self removeAnimations];
+      if ([_delegate respondsToSelector:@selector(activityIndicatorAnimationDidFinish:)]) {
+        [_delegate activityIndicatorAnimationDidFinish:self];
+      }
+    }
+  }];
+  [CATransaction setAnimationDuration:kMDCActivityIndicatorAnimateOutDuration];
+
+  _strokeLayer.lineWidth = 0;
+  _trackLayer.lineWidth = 0;
+
+  [CATransaction commit];
+}
+
+- (void)removeAnimations {
+  _animationsAdded = NO;
+  _animatingOut = NO;
+  [_strokeLayer removeAllAnimations];
+  [_outerRotationLayer removeAllAnimations];
+
+  // Reset cycle count to 0 rather than cycleStart to reflect default starting position (top).
+  _cycleCount = 0;
+  // However _animationInProgress represents the CATransaction that hasn't finished, so we leave it
+  // alone here.
+}
+
++ (CGFloat)defaultHeight {
+  return kSpinnerRadius * 2.f;
+}
+
+- (void)applyPropertiesWithoutAnimation:(void (^)(void))setPropBlock {
+  [CATransaction begin];
+
+  // Disable implicit CALayer animations
+  [CATransaction setDisableActions:YES];
+  setPropBlock();
+
+  [CATransaction commit];
+}
+
++ (NSArray<UIColor *> *)defaultColors {
+  static NSArray *defaultColors;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    defaultColors = @[
+      [[UIColor alloc] initWithRed:0.129f green:0.588f blue:0.953f alpha:1],
+      [[UIColor alloc] initWithRed:0.957f green:0.263f blue:0.212f alpha:1],
+      [[UIColor alloc] initWithRed:1.0f green:0.922f blue:0.231f alpha:1],
+      [[UIColor alloc] initWithRed:0.298f green:0.686f blue:0.314f alpha:1]
+    ];
+  });
+  return defaultColors;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
new file mode 100644
index 0000000..0273f25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCActivityIndicator.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
new file mode 100644
index 0000000..18b9c05
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
@@ -0,0 +1,70 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+/**
+ Material Design easing curve animation values.
+
+ Use these easing curves to create smooth and consistent motion that conforms to Material Design.
+ */
+typedef NS_ENUM(NSUInteger, MDCAnimationTimingFunction) {
+  /**
+   This is the most frequently used interpolation curve for Material Design animations. This curve
+   is slow both at the beginning and end. It has similar characteristics to the system's EaseInOut.
+   This is known as FastOutSlowIn in the Material Design spec.
+   */
+  MDCAnimationTimingFunctionEaseInOut,
+
+  /**
+   This curve should be used for motion when entering frame or when fading in from 0% opacity. This
+   curve is slow at the end. It has similar characteristics to the system's EaseOut. This is known
+   as LinearOutSlowIn in the Material Design spec.
+   */
+  MDCAnimationTimingFunctionEaseOut,
+
+  /**
+   This curve should be used for motion when exiting frame or when fading out to 0% opacity. This
+   curve is slow at the beginning. It has similar characteristics to the system's EaseIn. This
+   is known as FastOutLinearIn in the Material Design spec.
+   */
+  MDCAnimationTimingFunctionEaseIn,
+
+  /**
+   Aliases for various specific timing curve recommendations.
+   */
+  MDCAnimationTimingFunctionTranslate = MDCAnimationTimingFunctionEaseInOut,
+  MDCAnimationTimingFunctionTranslateOnScreen = MDCAnimationTimingFunctionEaseOut,
+  MDCAnimationTimingFunctionTranslateOffScreen = MDCAnimationTimingFunctionEaseIn,
+  MDCAnimationTimingFunctionFadeIn = MDCAnimationTimingFunctionEaseOut,
+  MDCAnimationTimingFunctionFadeOut = MDCAnimationTimingFunctionEaseIn,
+};
+
+/**
+ Material Design animation curves.
+ */
+@interface CAMediaTimingFunction (MDCAnimationTiming)
+
+/**
+ Returns the corresponding CAMediaTimingFunction for the given curve specified by an enum. The most
+ common curve is MDCAnimationTimingFunctionEaseInOut.
+
+ @param type A Material Design media timing function.
+ */
++ (CAMediaTimingFunction *)mdc_functionWithType:(MDCAnimationTimingFunction)type;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m
new file mode 100644
index 0000000..b3fc894
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m
@@ -0,0 +1,35 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "CAMediaTimingFunction+MDCAnimationTiming.h"
+
+@implementation CAMediaTimingFunction (MDCAnimationTiming)
+
++ (CAMediaTimingFunction *)mdc_functionWithType:(MDCAnimationTimingFunction)type {
+  switch (type) {
+    case MDCAnimationTimingFunctionEaseInOut:
+      return [[CAMediaTimingFunction alloc] initWithControlPoints:0.4f:0.0f:0.2f:1.0f];
+    case MDCAnimationTimingFunctionEaseOut:
+      return [[CAMediaTimingFunction alloc] initWithControlPoints:0.0f:0.0f:0.2f:1.0f];
+    case MDCAnimationTimingFunctionEaseIn:
+      return [[CAMediaTimingFunction alloc] initWithControlPoints:0.4f:0.0f:1.0f:1.0f];
+  }
+  NSAssert(NO, @"Invalid MDCAnimationTimingFunction value %i.", (int)type);
+  // Reasonable default to use in Release mode for garbage input.
+  return nil;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
new file mode 100644
index 0000000..70431dc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "CAMediaTimingFunction+MDCAnimationTiming.h"
+#import "UIView+MDCTimingFunction.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
new file mode 100644
index 0000000..8002488
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
@@ -0,0 +1,39 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface UIView (MDCTimingFunction)
+
+/**
+ A convienence method for applying a timing function to animations.
+
+ @param timingFunction A timing function for the easing curve animation.
+ @param duration The time the animation takes.
+ @param delay The time to wait before the animation begins.
+ @param options Configuration options for the timing function.
+ @param animations Animations to which the timing function will apply.
+ @param completion A completion block fired after the animations complete.
+ */
++ (void)mdc_animateWithTimingFunction:(CAMediaTimingFunction *)timingFunction
+                             duration:(NSTimeInterval)duration
+                                delay:(NSTimeInterval)delay
+                              options:(UIViewAnimationOptions)options
+                           animations:(void (^)(void))animations
+                           completion:(void (^)(BOOL finished))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.m
new file mode 100644
index 0000000..5d4f393
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIView+MDCTimingFunction.h"
+
+@implementation UIView (MDCTimingFunction)
+
++ (void)mdc_animateWithTimingFunction:(CAMediaTimingFunction *)timingFunction
+                             duration:(NSTimeInterval)duration
+                                delay:(NSTimeInterval)delay
+                              options:(UIViewAnimationOptions)options
+                           animations:(void (^)(void))animations
+                           completion:(void (^)(BOOL finished))completion {
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:timingFunction];
+  [UIView animateWithDuration:duration
+                        delay:delay
+                      options:options
+                   animations:animations
+                   completion:completion];
+  [CATransaction commit];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.h
new file mode 100644
index 0000000..c4260c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.h
@@ -0,0 +1,55 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MaterialFlexibleHeader.h"
+#import "MaterialHeaderStackView.h"
+#import "MaterialNavigationBar.h"
+
+/**
+ The MDCAppBar class creates and configures the constellation of components required to represent a
+ Material App Bar.
+
+ A Material App Bar consists of a Flexible View with a shadow, a Navigation Bar, and space for
+ flexible content such as a photo.
+
+ Learn more at the [Material
+ spec](https://www.google.com/design/spec/patterns/scrolling-techniques.html)
+
+ ### Dependencies
+
+ AppBar depends on the FlexibleHeader, HeaderStackView, and NavigationBar Material Components.
+ */
+@interface MDCAppBar : NSObject
+
+/**
+ Adds headerViewController.view to headerViewController.parentViewController.view and registers
+ navigationItem observation on headerViewController.parentViewController.
+ */
+- (void)addSubviewsToParent;
+
+/** The header view controller instance manages the App Bar's flexible header view behavior. */
+@property(nonatomic, strong, nonnull, readonly)
+    MDCFlexibleHeaderViewController *headerViewController;
+
+/** The navigation bar. */
+@property(nonatomic, strong, nonnull, readonly) MDCNavigationBar *navigationBar;
+
+/**
+ The header stack view that owns the navigationBar (as the top bar) and an optional bottom bar.
+ */
+@property(nonatomic, strong, nonnull, readonly) MDCHeaderStackView *headerStackView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.m
new file mode 100644
index 0000000..785a34a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.m
@@ -0,0 +1,286 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBar.h"
+
+#import "MDCAppBarContainerViewController.h"
+
+#import "MaterialFlexibleHeader.h"
+#import "MaterialIcons+ic_arrow_back.h"
+#import "MaterialRTL.h"
+#import "MaterialShadowElevations.h"
+#import "MaterialShadowLayer.h"
+#import "MaterialTypography.h"
+
+static NSString *const kBarStackKey = @"barStack";
+static NSString *const kStatusBarHeightKey = @"statusBarHeight";
+static NSString *const MDCAppBarHeaderViewControllerKey = @"MDCAppBarHeaderViewControllerKey";
+static NSString *const MDCAppBarNavigationBarKey = @"MDCAppBarNavigationBarKey";
+static NSString *const MDCAppBarHeaderStackViewKey = @"MDCAppBarHeaderStackViewKey";
+static const CGFloat kStatusBarHeight = 20;
+
+@class MDCAppBarViewController;
+
+@interface MDCAppBar ()
+
+@property(nonatomic, strong) MDCAppBarViewController *appBarController;
+
+@end
+
+@interface MDCAppBarViewController : UIViewController
+
+@property(nonatomic, strong) MDCHeaderStackView *headerStackView;
+@property(nonatomic, strong) MDCNavigationBar *navigationBar;
+
+@end
+
+@implementation MDCAppBar
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    [self commonMDCAppBarInit];
+    [self commonMDCAppBarViewSetup];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super init];
+  if (self) {
+    [self commonMDCAppBarInit];
+    if ([aDecoder containsValueForKey:MDCAppBarHeaderViewControllerKey]) {
+      _headerViewController = [aDecoder decodeObjectForKey:MDCAppBarHeaderViewControllerKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCAppBarNavigationBarKey]) {
+      _navigationBar = [aDecoder decodeObjectForKey:MDCAppBarNavigationBarKey];
+      _appBarController.navigationBar = _navigationBar;
+    }
+
+    if ([aDecoder containsValueForKey:MDCAppBarHeaderStackViewKey]) {
+      _headerStackView = [aDecoder decodeObjectForKey:MDCAppBarHeaderStackViewKey];
+      _appBarController.headerStackView = _headerStackView;
+    }
+
+    [self commonMDCAppBarViewSetup];
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [aCoder encodeObject:self.headerViewController forKey:MDCAppBarHeaderViewControllerKey];
+  [aCoder encodeObject:self.navigationBar forKey:MDCAppBarNavigationBarKey];
+  [aCoder encodeObject:self.headerStackView forKey:MDCAppBarHeaderStackViewKey];
+}
+
+- (void)commonMDCAppBarInit {
+  _headerViewController = [[MDCFlexibleHeaderViewController alloc] init];
+
+  // Shadow layer
+  MDCFlexibleHeaderView *headerView = _headerViewController.headerView;
+  MDCFlexibleHeaderShadowIntensityChangeBlock intensityBlock =
+      ^(CALayer *_Nonnull shadowLayer, CGFloat intensity) {
+        CGFloat elevation = MDCShadowElevationAppBar * intensity;
+        [(MDCShadowLayer *)shadowLayer setElevation:elevation];
+      };
+  [headerView setShadowLayer:[MDCShadowLayer layer] intensityDidChangeBlock:intensityBlock];
+  _appBarController = [[MDCAppBarViewController alloc] init];
+  _headerStackView = _appBarController.headerStackView;
+  _navigationBar = _appBarController.navigationBar;
+}
+
+- (void)commonMDCAppBarViewSetup {
+  [_headerViewController addChildViewController:_appBarController];
+  _appBarController.view.frame = _headerViewController.view.bounds;
+  [_headerViewController.view addSubview:_appBarController.view];
+  [_appBarController didMoveToParentViewController:_headerViewController];
+
+  [_headerViewController.headerView forwardTouchEventsForView:_appBarController.headerStackView];
+  [_headerViewController.headerView forwardTouchEventsForView:_appBarController.navigationBar];
+}
+
+- (void)addHeaderViewControllerToParentViewController:
+        (nonnull UIViewController *)parentViewController {
+  [parentViewController addChildViewController:_headerViewController];
+}
+
+- (void)addSubviewsToParent {
+  MDCFlexibleHeaderViewController *fhvc = self.headerViewController;
+  NSAssert(fhvc.parentViewController,
+           @"headerViewController does not have a parentViewController. "
+           @"Use [self addChildViewController:appBar.headerViewController]. "
+           @"This warning only appears in DEBUG builds");
+  if (fhvc.view.superview == fhvc.parentViewController.view) {
+    return;
+  }
+
+  // Enforce the header's desire to fully cover the width of its parent view.
+  CGRect frame = fhvc.view.frame;
+  frame.origin.x = 0;
+  frame.size.width = fhvc.parentViewController.view.bounds.size.width;
+  fhvc.view.frame = frame;
+
+  [fhvc.parentViewController.view addSubview:fhvc.view];
+  [fhvc didMoveToParentViewController:fhvc.parentViewController];
+
+  [self.navigationBar observeNavigationItem:fhvc.parentViewController.navigationItem];
+}
+
+@end
+
+@implementation MDCAppBarViewController
+
+- (MDCHeaderStackView *)headerStackView {
+  // Removed call to loadView here as we should never be calling it manually.
+  // It previously replaced loadViewIfNeeded call that is only iOS 9.0+ to
+  // make backwards compatible.
+  // Underlying issue is you need view loaded before accessing. Below change will accomplish that
+  // by calling for view.bounds initializing the stack view
+  if (!_headerStackView) {
+    _headerStackView = [[MDCHeaderStackView alloc] initWithFrame:CGRectZero];
+  }
+  return _headerStackView;
+}
+
+- (MDCNavigationBar *)navigationBar {
+  if (!_navigationBar) {
+    _navigationBar = [[MDCNavigationBar alloc] init];
+  }
+  return _navigationBar;
+}
+
+- (UIViewController *)flexibleHeaderParentViewController {
+  NSAssert([self.parentViewController isKindOfClass:[MDCFlexibleHeaderViewController class]],
+           @"Expected the parent of %@ to be a type of %@", NSStringFromClass([self class]),
+           NSStringFromClass([MDCFlexibleHeaderViewController class]));
+  return self.parentViewController.parentViewController;
+}
+
+- (UIBarButtonItem *)backButtonItem {
+  UIViewController *fhvParent = self.flexibleHeaderParentViewController;
+  UINavigationController *navigationController = fhvParent.navigationController;
+
+  NSArray<UIViewController *> *viewControllerStack = navigationController.viewControllers;
+
+  // This will be zero if there is no navigation controller, so a view controller which is not
+  // inside a navigation controller will be treated the same as a view controller at the root of a
+  // navigation controller
+  NSUInteger index = [viewControllerStack indexOfObject:fhvParent];
+
+  UIViewController *iterator = fhvParent;
+
+  // In complex cases it might actually be a parent of @c fhvParent which is on the nav stack.
+  while (index == NSNotFound && iterator && ![iterator isEqual:navigationController]) {
+    iterator = iterator.parentViewController;
+    index = [viewControllerStack indexOfObject:iterator];
+  }
+
+  if (index == NSNotFound) {
+    NSCAssert(NO, @"View controller not present in its own navigation controller.");
+    // This is not something which should ever happen, but just in case.
+    return nil;
+  }
+  if (index == 0) {
+    // The view controller is at the root of a navigation stack (or not in one).
+    return nil;
+  }
+  UIViewController *previousViewControler = navigationController.viewControllers[index - 1];
+  if ([previousViewControler isKindOfClass:[MDCAppBarContainerViewController class]]) {
+    // Special case: if the previous view controller is a container controller, use its content
+    // view controller.
+    MDCAppBarContainerViewController *chvc =
+        (MDCAppBarContainerViewController *)previousViewControler;
+    previousViewControler = chvc.contentViewController;
+  }
+  UIBarButtonItem *backBarButtonItem = previousViewControler.navigationItem.backBarButtonItem;
+  if (!backBarButtonItem) {
+    UIImage *backButtonImage = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_arrow_back]];
+    backButtonImage = [backButtonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+    if (self.navigationBar.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      backButtonImage = [backButtonImage mdc_imageFlippedForRightToLeftLayoutDirection];
+    }
+    backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:backButtonImage
+                                                         style:UIBarButtonItemStyleDone
+                                                        target:self
+                                                        action:@selector(didTapBackButton:)];
+  }
+  backBarButtonItem.accessibilityIdentifier = @"back_bar_button";
+  return backBarButtonItem;
+}
+
++ (NSBundle *)baseBundle {
+  static NSBundle *bundle = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    // We may not be included by the main bundle, but rather by an embedded framework, so figure out
+    // to which bundle our code is compiled, and use that as the starting point for bundle loading.
+    bundle = [NSBundle bundleForClass:[self class]];
+  });
+
+  return bundle;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.headerStackView.translatesAutoresizingMaskIntoConstraints = NO;
+  self.headerStackView.topBar = self.navigationBar;
+
+  [self.view addSubview:self.headerStackView];
+
+  // Bar stack expands vertically, but has a margin above it for the status bar.
+
+  NSArray<NSLayoutConstraint *> *horizontalConstraints = [NSLayoutConstraint
+      constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|[%@]|", kBarStackKey]
+                          options:0
+                          metrics:nil
+                            views:@{kBarStackKey : self.headerStackView}];
+  [self.view addConstraints:horizontalConstraints];
+
+  NSArray<NSLayoutConstraint *> *verticalConstraints = [NSLayoutConstraint
+      constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-%@-[%@]|", kStatusBarHeightKey,
+                                                             kBarStackKey]
+                          options:0
+                          metrics:@{
+                            kStatusBarHeightKey : @(kStatusBarHeight)
+                          }
+                            views:@{kBarStackKey : self.headerStackView}];
+  [self.view addConstraints:verticalConstraints];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+
+  UIBarButtonItem *backBarButtonItem = [self backButtonItem];
+  if (backBarButtonItem && !self.navigationBar.backItem) {
+    self.navigationBar.backItem = backBarButtonItem;
+  }
+}
+
+#pragma mark User actions
+
+- (void)didTapBackButton:(id)sender {
+  UIViewController *pvc = self.flexibleHeaderParentViewController;
+  if (pvc.navigationController && pvc.navigationController.viewControllers.count > 1) {
+    [pvc.navigationController popViewControllerAnimated:YES];
+  } else {
+    [pvc dismissViewControllerAnimated:YES completion:nil];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
new file mode 100644
index 0000000..cdbd53a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
@@ -0,0 +1,63 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCAppBar;
+@class MDCFlexibleHeaderViewController;
+
+/**
+ The MDCAppBarContainerViewController controller provides an interface for placing a
+ UIViewController behind an App Bar.
+
+ The MDCAppBarContainerViewController class is commonly referred to as the "wrapper API" for the
+ Material App Bar. This contrasts with the "injection" APIs as represented by the APIs in
+ MDCAppBar.h.
+
+ Use the MDCAppBarContainerViewController class when you do not own and cannot alter a view
+ controller to which you want to add an App Bar. If you do own and can modify a view controller
+ it is recommended that you use the MDCAppBar.h APIs instead.
+
+ ### Why we recommend using the MDCAppBar.h APIs over this one
+
+ Wrapping a view controller affects your app code in a variety of not-so-nice ways.
+
+ 1. Wrapped view controllers often need to be unwrapped in a variety of settings.
+ 2. The wrapped view controller's parentViewController is now a level of indirection from its
+    previous parent.
+ 3. Wrapping a view controller can affect things like "isMovingToParentViewController" in
+    wonderfully subtle ways.
+ */
+@interface MDCAppBarContainerViewController : UIViewController
+
+/**
+ Initializes an App Bar container view controller instance with the given content view controller.
+ */
+- (nonnull instancetype)initWithContentViewController:
+        (nonnull UIViewController *)contentViewController NS_DESIGNATED_INITIALIZER;
+
+- (nonnull instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
+                                 bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/** The App Bar views that will be presented in front of the contentViewController's view. */
+@property(nonatomic, strong, nonnull, readonly) MDCAppBar *appBar;
+
+/** The content view controller to be displayed behind the header. */
+@property(nonatomic, strong, nonnull, readonly) UIViewController *contentViewController;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.m
new file mode 100644
index 0000000..966e9c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.m
@@ -0,0 +1,76 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBarContainerViewController.h"
+
+#import "MDCAppBar.h"
+
+#import "MaterialFlexibleHeader.h"
+
+@implementation MDCAppBarContainerViewController {
+  MDCAppBar *_appBar;
+}
+
+- (instancetype)initWithContentViewController:(UIViewController *)contentViewController {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _appBar = [[MDCAppBar alloc] init];
+
+    [self addChildViewController:_appBar.headerViewController];
+
+    _contentViewController = contentViewController;
+    [self addChildViewController:contentViewController];
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  [self.view addSubview:self.contentViewController.view];
+  [self.contentViewController didMoveToParentViewController:self];
+
+  [_appBar addSubviewsToParent];
+
+  [_appBar.navigationBar observeNavigationItem:_contentViewController.navigationItem];
+}
+
+- (void)viewWillLayoutSubviews {
+  [super viewWillLayoutSubviews];
+  [_appBar.headerViewController updateTopLayoutGuide];
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return self.appBar.headerViewController.prefersStatusBarHidden;
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  return self.appBar.headerViewController.preferredStatusBarStyle;
+}
+
+- (BOOL)shouldAutorotate {
+  return self.contentViewController.shouldAutorotate;
+}
+
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
+  return self.contentViewController.supportedInterfaceOrientations;
+}
+
+- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
+  return self.contentViewController.preferredInterfaceOrientationForPresentation;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MaterialAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MaterialAppBar.h
new file mode 100644
index 0000000..04904d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/AppBar/src/MaterialAppBar.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBar.h"
+#import "MDCAppBarContainerViewController.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
new file mode 100644
index 0000000..a95f186
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
@@ -0,0 +1,147 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The position of the button bar, typically aligned with the leading or trailing edge of the screen.
+
+ Default: MDCBarButtonLayoutPositionNone
+ */
+typedef NS_OPTIONS(NSUInteger, MDCButtonBarLayoutPosition) {
+  MDCButtonBarLayoutPositionNone = 0,
+
+  /** The button bar is on the leading side of the screen. */
+  MDCButtonBarLayoutPositionLeading = 1 << 0,
+  MDCButtonBarLayoutPositionLeft = MDCButtonBarLayoutPositionLeading,
+
+  /** The button bar is on the trailing side of the screen. */
+  MDCButtonBarLayoutPositionTrailing = 1 << 1,
+  MDCButtonBarLayoutPositionRight = MDCButtonBarLayoutPositionTrailing,
+};
+
+@protocol MDCButtonBarDelegate;
+
+/**
+ The MDCButtonBar class provides a view comprised of a horizontal list of buttons.
+
+ This view will register KVO listeners on the provided button items for the following properties:
+
+ - enabled
+ - title
+ - image
+
+ If any of the above properties change, the MDCButtonBar will immediately reflect the change
+ in the visible UIButton instance.
+ */
+IB_DESIGNABLE
+@interface MDCButtonBar : UIView
+
+#pragma mark Button Items
+
+/**
+ An array of UIBarButtonItem objects that will be used to populate the button views in this bar.
+
+ Setting a new array of items will result in immediate recreation of the button views.
+
+ Once set, changes made to the UIBarButtonItem properties will be observed and applied to the
+ created button views.
+
+ ### Item target/action method signature
+
+ The complete action method signature is:
+
+ - (void)didTap:(UIBarButtonItem *)item event:(UIEvent *)event button:(UIButton *)button;
+
+ Each argument can be optionally-specified. E.g. @selector(didTap) is an acceptable action.
+
+ ### iPad popover support
+
+ MDCButtonBar is not able to associate UIBarButtonItem instances with their corresponding UIButton
+ instance, so certain UIKit methods that accept a UIBarButtonItem cannot be used. This includes,
+ but may not be limited to:
+
+ - UIPopoverController::presentPopoverFromBarButtonItem:permittedArrowDirections:animated:
+ - UIPrinterPickerController::presentFromBarButtonItem:animated:completionHandler:
+ - UIPrintInteractionController::presentFromBarButtonItem:animated:completionHandler:
+ - UIDocumentInteractionController::presentOptionsMenuFromBarButtonItem:animated:
+ - UIDocumentInteractionController::presentOpenInMenuFromBarButtonItem:animated:
+
+ Instead, you must use the related -FromRect: variant which requires a CGRect and view. You can
+ use the provided UIButton by implementing the complete action method signature:
+
+ - (void)didTap:(UIBarButtonItem *)item event:(UIEvent *)event button:(UIButton *)button;
+ */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *items;
+
+/**
+ If greater than zero, will ensure that any UIButton with a title is aligned to the provided
+ baseline.
+
+ The baseline is expressed in number of points from the top edge of the receiver’s
+ bounds.
+
+ Default: 0
+ */
+@property(nonatomic) CGFloat buttonTitleBaseline;
+
+/**
+ The position of the button bar, usually positioned on the leading or trailing edge of the screen.
+
+ Default: MDCBarButtonLayoutPositionNone
+ */
+@property(nonatomic) MDCButtonBarLayoutPosition layoutPosition;
+
+/**
+ Returns a height adhering to the Material spec for Bars and a width that is able to accommodate
+ every item present in the `items` property. The provided size is ignored.
+ */
+- (CGSize)sizeThatFits:(CGSize)size;
+
+@end
+
+typedef NS_OPTIONS(NSUInteger, MDCBarButtonItemLayoutHints) {
+  MDCBarButtonItemLayoutHintsNone = 0,
+
+  /** Whether or not this bar button item is the first button in the list. */
+  MDCBarButtonItemLayoutHintsIsFirstButton = 1 << 0,
+
+  /** Whether or not this bar button item is the last button in the list. */
+  MDCBarButtonItemLayoutHintsIsLastButton = 1 << 1,
+};
+
+/**
+ The MDCButtonBarDelegate protocol defines the means by which MDCButtonBar can request that a
+ view be created for a bar button item.
+
+ An object that conforms to this protocol must forward UIControlEventTouchUpInside events to the
+ button bar's didTapButton:event: method signature in order to pass the correct UIBarButtonItem
+ argument to the item's target/action invocation. This method signature is made available by
+ importing the MDCAppBarButtonBarBuilder.h header. The MDCAppBarButtonBarBuilder.h header should
+ *only* be
+ imported in files that implement objects conforming to MDCButtonBarDelegate.
+
+ @seealso MDCBarButtonItemLayoutHints
+ */
+@protocol MDCButtonBarDelegate <NSObject>
+@required
+
+/** Asks the receiver to return a view that represents the given bar button item. */
+- (nonnull UIView *)buttonBar:(nonnull MDCButtonBar *)buttonBar
+                  viewForItem:(nonnull UIBarButtonItem *)barButtonItem
+                  layoutHints:(MDCBarButtonItemLayoutHints)layoutHints;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.m
new file mode 100644
index 0000000..5a888e9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.m
@@ -0,0 +1,392 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButtonBar.h"
+#import "MDCButton.h"
+
+#import "MaterialRTL.h"
+#import "private/MDCAppBarButtonBarBuilder.h"
+
+static const CGFloat kDefaultHeight = 56;
+static const CGFloat kDefaultPadHeight = 64;
+
+// KVO contexts
+static char *const kKVOContextMDCButtonBar = "kKVOContextMDCButtonBar";
+
+// This is required because @selector(enabled) throws a compiler warning of unrecognized selector.
+static NSString *const kEnabledSelector = @"enabled";
+
+static NSString *const MDCButtonBarItemsKey = @"MDCButtonBarItemsKey";
+static NSString *const MDCButtonBarButtonTitleBaselineKey = @"MDCButtonBarButtonTitleBaselineKey";
+static NSString *const MDCButtonBarButtonLayoutPositionKey = @"MDCButtonBarButtonLayoutPositionKey";
+
+@implementation MDCButtonBar {
+  id _buttonItemsLock;
+  NSArray<__kindof UIView *> *_buttonViews;
+
+  MDCAppBarButtonBarBuilder *_defaultBuilder;
+}
+
+- (void)dealloc {
+  self.items = nil;
+}
+
+- (void)commonMDCButtonBarInit {
+  _buttonItemsLock = [[NSObject alloc] init];
+  _layoutPosition = MDCButtonBarLayoutPositionNone;
+
+  _defaultBuilder = [[MDCAppBarButtonBarBuilder alloc] init];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCButtonBarInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder {
+  self = [super initWithCoder:coder];
+  if (self) {
+    [self commonMDCButtonBarInit];
+    if ([coder containsValueForKey:MDCButtonBarItemsKey]) {
+      _items = [coder decodeObjectForKey:MDCButtonBarItemsKey];
+    }
+
+    if ([coder containsValueForKey:MDCButtonBarButtonTitleBaselineKey]) {
+      _buttonTitleBaseline = (CGFloat)[coder decodeDoubleForKey:MDCButtonBarButtonTitleBaselineKey];
+    }
+
+    if ([coder containsValueForKey:MDCButtonBarButtonLayoutPositionKey]) {
+      _layoutPosition = [coder decodeIntegerForKey:MDCButtonBarButtonLayoutPositionKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  if (self.items && self.items.count > 0) {
+    [aCoder encodeObject:self.items forKey:MDCButtonBarItemsKey];
+  }
+  [aCoder encodeDouble:self.buttonTitleBaseline forKey:MDCButtonBarButtonTitleBaselineKey];
+  [aCoder encodeInteger:self.layoutPosition forKey:MDCButtonBarButtonLayoutPositionKey];
+}
+
+- (void)alignButtonBaseline:(UIButton *)button {
+  CGRect contentRect = [button contentRectForBounds:button.bounds];
+  CGRect titleRect = [button titleRectForContentRect:contentRect];
+
+  // Calculate baseline information based on frame that the title text appears in.
+  CGFloat baseline = CGRectGetMaxY(titleRect) + button.titleLabel.font.descender;
+  CGFloat buttonBaseline = button.frame.origin.y + baseline;
+
+  // When modifying insets, be sure to add/subtract equal amounts on opposite sides.
+  UIEdgeInsets insets = button.titleEdgeInsets;
+  CGFloat baselineOffset = _buttonTitleBaseline - buttonBaseline;
+
+  insets.top += baselineOffset;
+  insets.bottom -= baselineOffset;
+  button.titleEdgeInsets = insets;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size shouldLayout:(BOOL)shouldLayout {
+  CGFloat totalWidth = 0;
+
+  CGFloat edge;
+  switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      edge = 0;
+      break;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      edge = size.width;
+      break;
+  }
+
+  BOOL shouldAlignBaselines = _buttonTitleBaseline > 0;
+
+  NSEnumerator<__kindof UIView *> *positionedButtonViews =
+      self.layoutPosition == MDCButtonBarLayoutPositionTrailing
+          ? [_buttonViews reverseObjectEnumerator]
+          : [_buttonViews objectEnumerator];
+
+  for (UIView *view in positionedButtonViews) {
+    CGFloat width = view.frame.size.width;
+    switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+      case UIUserInterfaceLayoutDirectionLeftToRight:
+        break;
+      case UIUserInterfaceLayoutDirectionRightToLeft:
+        edge -= width;
+        break;
+    }
+    if (shouldLayout) {
+      view.frame = CGRectMake(edge, 0, width, size.height);
+
+      if (shouldAlignBaselines && [view isKindOfClass:[UIButton class]]) {
+        if ([(UIButton *)view titleForState:UIControlStateNormal].length > 0) {
+          [self alignButtonBaseline:(UIButton *)view];
+        }
+      }
+    }
+    switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+      case UIUserInterfaceLayoutDirectionLeftToRight:
+        edge += width;
+        break;
+      case UIUserInterfaceLayoutDirectionRightToLeft:
+        break;
+    }
+    totalWidth += width;
+  }
+  // TODO(featherless): Take into account compact/regular sizes rather than the device idiom.
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+  CGFloat height = isPad ? kDefaultPadHeight : kDefaultHeight;
+  return CGSizeMake(totalWidth, height);
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return [self sizeThatFits:size shouldLayout:NO];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self sizeThatFits:self.bounds.size shouldLayout:YES];
+}
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  _defaultBuilder.buttonTitleColor = self.tintColor;
+  [self updateButtonTitleColors];
+}
+
+#pragma mark - Private
+
+- (void)updateButtonTitleColors {
+  for (UIView *viewObj in _buttonViews) {
+    if ([viewObj isKindOfClass:[MDCButton class]]) {
+      MDCButton *buttonView = (MDCButton *)viewObj;
+      buttonView.customTitleColor = self.tintColor;
+    }
+  }
+}
+
+- (NSArray<UIView *> *)viewsForItems:(NSArray<UIBarButtonItem *> *)barButtonItems {
+  if (![barButtonItems count]) {
+    return nil;
+  }
+  id<MDCButtonBarDelegate> delegate = _defaultBuilder;
+
+  NSMutableArray<UIView *> *views = [NSMutableArray array];
+  [barButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem *item, NSUInteger idx, BOOL *stop) {
+    MDCBarButtonItemLayoutHints hints = MDCBarButtonItemLayoutHintsNone;
+    if (idx == 0) {
+      hints |= MDCBarButtonItemLayoutHintsIsFirstButton;
+    }
+    if (idx == [barButtonItems count] - 1) {
+      hints |= MDCBarButtonItemLayoutHintsIsLastButton;
+    }
+    UIView *view = [delegate buttonBar:self viewForItem:item layoutHints:hints];
+    if (!view) {
+      return;
+    }
+
+    [view sizeToFit];
+    if (item.width > 0) {
+      CGRect frame = view.frame;
+      frame.size.width = item.width;
+      view.frame = frame;
+    }
+
+    [self addSubview:view];
+    [views addObject:view];
+  }];
+  return views;
+}
+
+#pragma mark - KVO
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context {
+  if (context == kKVOContextMDCButtonBar) {
+    void (^mainThreadWork)(void) = ^{
+      @synchronized(_buttonItemsLock) {
+        NSUInteger itemIndex = [_items indexOfObject:object];
+        if (itemIndex == NSNotFound || itemIndex > [_buttonViews count]) {
+          return;
+        }
+        UIButton *button = _buttonViews[itemIndex];
+
+        id newValue = [object valueForKey:keyPath];
+        if (newValue == [NSNull null]) {
+          newValue = nil;
+        }
+
+        if ([keyPath isEqualToString:kEnabledSelector]) {
+          if ([button respondsToSelector:@selector(setEnabled:)]) {
+            [button setValue:newValue forKey:keyPath];
+          }
+
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(title))]) {
+          [button setTitle:newValue forState:UIControlStateNormal];
+
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(image))]) {
+          [button setImage:newValue forState:UIControlStateNormal];
+
+        } else {
+          NSLog(@"Unknown key path notification received by %@ for %@.",
+                NSStringFromClass([self class]), keyPath);
+        }
+      }
+    };
+
+    // Ensure that UIKit modifications occur on the main thread.
+    if ([NSThread isMainThread]) {
+      mainThreadWork();
+    } else {
+      [[NSOperationQueue mainQueue] addOperationWithBlock:mainThreadWork];
+    }
+
+  } else {
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+  }
+}
+
+#pragma mark - Button target selector
+
+- (void)didTapButton:(UIButton *)button event:(UIEvent *)event {
+  NSUInteger buttonIndex = [_buttonViews indexOfObject:button];
+  if (buttonIndex == NSNotFound || buttonIndex > [self.buttonItems count]) {
+    return;
+  }
+
+  UIBarButtonItem *item = self.buttonItems[buttonIndex];
+
+  if (item.action == nil) {
+    return;
+  }
+
+  id target = item.target;
+
+  // As per Apple's documentation on UIBarButtonItem:
+  // https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIBarButtonItem_Class/#//apple_ref/occ/instp/UIBarButtonItem/action
+  // "If nil, the action message is passed up the responder chain where it may be handled by any
+  // object implementing a method corresponding to the selector held by the action property."
+  if (target == nil && [self respondsToSelector:@selector(targetForAction:withSender:)]) {
+    // iOS 7 and up.
+    target = [self targetForAction:item.action withSender:self];
+  }
+
+  // If we ultimately couldn't find a target, bail out.
+  if (!target) {
+    return;
+  }
+
+  if (![target respondsToSelector:item.action]) {
+    return;
+  }
+
+  NSMethodSignature *signature = [target methodSignatureForSelector:item.action];
+  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+  invocation.selector = item.action;
+
+  if ([invocation.methodSignature numberOfArguments] > 2) {
+    [invocation setArgument:&item atIndex:2];
+  }
+  if ([invocation.methodSignature numberOfArguments] > 3) {
+    [invocation setArgument:&event atIndex:3];
+  }
+
+  // UIKit methods that present from a UIBarButtonItem will not work with our items because we
+  // can't set the necessary private ivars that associate the item with the button. So we pass the
+  // button as well so that clients can present from the button's frame instead.
+  // This is not part of the standard UIKit method signature.
+  if ([invocation.methodSignature numberOfArguments] > 4) {
+    [invocation setArgument:&button atIndex:4];
+  }
+
+  [invocation invokeWithTarget:target];
+}
+
+#pragma mark - Public
+
+- (NSArray<UIBarButtonItem *> *)buttonItems {
+  return self.items;
+}
+
+- (void)setButtonItems:(NSArray<UIBarButtonItem *> *)buttonItems {
+  self.items = buttonItems;
+}
+
+- (void)setItems:(NSArray<UIBarButtonItem *> *)items {
+  @synchronized(_buttonItemsLock) {
+    if (_items == items || [_items isEqualToArray:items]) {
+      return;
+    }
+
+    NSArray<NSString *> *keyPaths = @[
+      kEnabledSelector, NSStringFromSelector(@selector(title)),
+      NSStringFromSelector(@selector(image))
+    ];
+
+    // Remove old observers
+    for (UIBarButtonItem *item in _items) {
+      for (NSString *keyPath in keyPaths) {
+        [item removeObserver:self forKeyPath:keyPath context:kKVOContextMDCButtonBar];
+      }
+    }
+
+    _items = [items copy];
+
+    // Register new observers
+    for (UIBarButtonItem *item in _items) {
+      for (NSString *keyPath in keyPaths) {
+        [item addObserver:self
+               forKeyPath:keyPath
+                  options:NSKeyValueObservingOptionNew
+                  context:kKVOContextMDCButtonBar];
+      }
+    }
+
+    [self reloadButtonViews];
+  }
+}
+
+- (void)mdc_setSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute {
+  [super mdc_setSemanticContentAttribute:semanticContentAttribute];
+  [self reloadButtonViews];
+}
+
+- (void)setButtonTitleBaseline:(CGFloat)buttonTitleBaseline {
+  _buttonTitleBaseline = buttonTitleBaseline;
+
+  [self setNeedsLayout];
+}
+
+- (void)reloadButtonViews {
+  // TODO(featherless): Recycle buttons.
+  for (UIView *view in _buttonViews) {
+    [view removeFromSuperview];
+  }
+  _buttonViews = [self viewsForItems:_items];
+
+  [self setNeedsLayout];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
new file mode 100644
index 0000000..f870aa1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButtonBar.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h
new file mode 100644
index 0000000..587a11e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MaterialButtonBar.h"
+
+/** MDCBarButtonItemBuilder is an implementation of a Material button item factory. */
+@interface MDCAppBarButtonBarBuilder : NSObject <MDCButtonBarDelegate>
+
+/** The title color for the bar button items. */
+@property(nonatomic, strong) UIColor *buttonTitleColor;
+
+/** The underlying color for the bar button items. */
+@property(nonatomic, strong) UIColor *buttonUnderlyingColor;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m
new file mode 100644
index 0000000..166fe4f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m
@@ -0,0 +1,304 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBarButtonBarBuilder.h"
+
+#import "MDCButtonBar+Private.h"
+#import "MaterialButtons.h"
+#import "MaterialRTL.h"
+
+#import <objc/runtime.h>
+
+#define IS_FLAG_SET(value, flag) (((value) & (flag)) == (flag))
+
+static const CGFloat kMinimumItemWidth = 36.f;
+
+// The padding around button contents.
+static const CGFloat kButtonPaddingHorizontal = 12.f;
+
+// Additional insets for the left-most or right-most items, primarily for image buttons.
+static const CGFloat kEdgeButtonAdditionalMarginPhone = 4.f;
+static const CGFloat kEdgeButtonAdditionalMarginPad = 12.f;
+
+// The default MDCButton's alpha for display state is 0.1f which in the context of bar buttons
+// makes it practically invisible. Setting button to a higher opacity is closer to what the
+// button should look like when it is disabled.
+static const CGFloat kDisabledButtonAlpha = 0.45f;
+
+// Content insets for text-only buttons.
+static const UIEdgeInsets kTextOnlyButtonInset = {0, 24.f, 0, 24.f};
+
+// Content insets for image-only buttons.
+static const UIEdgeInsets kImageOnlyButtonInset = {0, 12.0f, 0, 12.0f};
+
+// Indiana Jones style placeholder view for UINavigationBar. Ownership of UIBarButtonItem.customView
+// and UINavigationItem.titleView are normally transferred to UINavigationController but we plan to
+// steal them away. In order to avoid crashing during KVO updates, we steal the view away and
+// replace it with a sandbag view.
+@interface MDCButtonBarSandbagView : UIView
+@end
+
+@interface MDCButtonBarButton : MDCFlatButton
+
+// Content padding for the button.
+@property(nonatomic) UIEdgeInsets contentPadding;
+
+@end
+
+@interface UIBarButtonItem (MDCHeaderInternal)
+
+// Internal version of the standard -customView property. When an item is pushed onto a
+// UINavigationController stack, any -customView object is moved over to this property. This
+// prevents UINavigationController from adding the customView to its own view hierarchy.
+@property(nonatomic, strong, setter=mdc_setCustomView:) UIView *mdc_customView;
+
+@end
+
+@implementation MDCAppBarButtonBarBuilder
+
+#pragma mark - MDCBarButtonItemBuilding
+
+- (UIView *)buttonBar:(MDCButtonBar *)buttonBar
+          viewForItem:(UIBarButtonItem *)buttonItem
+          layoutHints:(MDCBarButtonItemLayoutHints)layoutHints {
+  if (buttonItem == nil) {
+    return nil;
+  }
+
+  // Transfer custom view ownership if necessary.
+  [self transferCustomViewOwnershipForBarButtonItem:buttonItem];
+
+  // Take the real custom view if it exists instead of sandbag view.
+  UIView *customView = buttonItem.mdc_customView ?: buttonItem.customView;
+  if (customView) {
+    return customView;
+  }
+
+// NOTE: This assertion does not occur in release builds because it is accessing a private api.
+#if DEBUG
+  NSAssert(![[buttonItem valueForKey:@"isSystemItem"] boolValue],
+           @"Instances of %@ must not be initialized with %@ when working with %@."
+           @" This is because we cannot extract the system item type from the item.",
+           NSStringFromClass([buttonItem class]),
+           NSStringFromSelector(@selector(initWithBarButtonSystemItem:target:action:)),
+           NSStringFromClass([MDCButtonBar class]));
+#endif
+
+  MDCButtonBarButton *button = [[MDCButtonBarButton alloc] init];
+  [button setBackgroundColor:[UIColor clearColor] forState:UIControlStateNormal];
+  button.disabledAlpha = kDisabledButtonAlpha;
+
+  button.exclusiveTouch = YES;
+  if (buttonItem.title != nil) {
+    [button setTitle:buttonItem.title forState:UIControlStateNormal];
+  }
+  if (buttonItem.image != nil) {
+    [button setImage:buttonItem.image forState:UIControlStateNormal];
+  }
+  if (buttonItem.tintColor != nil) {
+    button.tintColor = buttonItem.tintColor;
+  }
+
+  if (buttonItem.title) {
+    button.inkStyle = MDCInkStyleBounded;
+  } else {
+    button.inkStyle = MDCInkStyleUnbounded;
+  }
+
+  button.tag = buttonItem.tag;
+
+  button.customTitleColor = self.buttonTitleColor;
+  [button setUnderlyingColorHint:self.buttonUnderlyingColor];
+
+  [self updateButton:button withItem:buttonItem barMetrics:UIBarMetricsDefault];
+
+  // Contrary to intuition, UIKit provides the UIBarButtonItem as the action's first argument when
+  // bar buttons are tapped, NOT the button itself. Simply adding the item's target/action to the
+  // button does not allow us to pass the expected argument to the target.
+  //
+  // MDCButtonBar provides didTapButton:event: to which we can pass button events
+  // so that the correct argument is ultimately passed along.
+  [button addTarget:buttonBar
+                action:@selector(didTapButton:event:)
+      forControlEvents:UIControlEventTouchUpInside];
+
+  UIEdgeInsets contentInsets = UIEdgeInsetsZero;
+
+  UIEdgeInsets (^addInsets)(UIEdgeInsets, UIEdgeInsets) = ^(UIEdgeInsets i1, UIEdgeInsets i2) {
+    UIEdgeInsets sum = i1;
+    sum.left += i2.left;
+    sum.top += i2.top;
+    sum.right += i2.right;
+    sum.bottom += i2.bottom;
+    return sum;
+  };
+
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+
+  if ([[button currentTitle] length]) {  // Text-only buttons.
+    contentInsets = addInsets(contentInsets, kTextOnlyButtonInset);
+
+  } else if ([button currentImage]) {  // Image-only buttons.
+    contentInsets = addInsets(contentInsets, kImageOnlyButtonInset);
+
+    if (IS_FLAG_SET(layoutHints, MDCBarButtonItemLayoutHintsIsFirstButton)) {
+      CGFloat additionalInset =
+          (isPad ? kEdgeButtonAdditionalMarginPad : kEdgeButtonAdditionalMarginPhone);
+
+      if (buttonBar.mdc_effectiveUserInterfaceLayoutDirection ==
+          UIUserInterfaceLayoutDirectionLeftToRight) {
+        contentInsets.left += additionalInset;
+      } else {
+        contentInsets.right += additionalInset;
+      }
+    }
+
+    if (IS_FLAG_SET(layoutHints, MDCBarButtonItemLayoutHintsIsLastButton)) {
+      CGFloat additionalInset =
+          (isPad ? kEdgeButtonAdditionalMarginPad : kEdgeButtonAdditionalMarginPhone);
+
+      if (buttonBar.mdc_effectiveUserInterfaceLayoutDirection ==
+          UIUserInterfaceLayoutDirectionLeftToRight) {
+        contentInsets.right += additionalInset;
+      } else {
+        contentInsets.left += additionalInset;
+      }
+    }
+
+  } else {
+    NSAssert(0, @"No button title or image");
+  }
+
+  // Only add padding to the first item of the button bar.
+  if (layoutHints == MDCBarButtonItemLayoutHintsIsFirstButton) {
+    switch (buttonBar.layoutPosition) {
+      case MDCButtonBarLayoutPositionLeading:
+        button.contentPadding =
+            UIEdgeInsetsMake(0, contentInsets.left - kButtonPaddingHorizontal, 0, 0);
+        break;
+      case MDCButtonBarLayoutPositionTrailing:
+        button.contentPadding =
+            UIEdgeInsetsMake(0, 0, 0, contentInsets.right - kButtonPaddingHorizontal);
+      default:
+        break;
+    }
+  }
+
+  button.contentEdgeInsets = contentInsets;
+  button.enabled = buttonItem.enabled;
+  button.accessibilityLabel = buttonItem.accessibilityLabel;
+  button.accessibilityHint = buttonItem.accessibilityHint;
+  button.accessibilityValue = buttonItem.accessibilityValue;
+  button.accessibilityIdentifier = buttonItem.accessibilityIdentifier;
+
+  return button;
+}
+
+#pragma mark - Private
+
+- (void)updateButton:(UIButton *)button
+            withItem:(UIBarButtonItem *)item
+          barMetrics:(UIBarMetrics)barMetrics {
+  [self updateButton:button withItem:item forState:UIControlStateNormal barMetrics:barMetrics];
+  [self updateButton:button withItem:item forState:UIControlStateHighlighted barMetrics:barMetrics];
+  [self updateButton:button withItem:item forState:UIControlStateDisabled barMetrics:barMetrics];
+}
+
+- (void)updateButton:(UIButton *)button
+            withItem:(UIBarButtonItem *)item
+            forState:(UIControlState)state
+          barMetrics:(UIBarMetrics)barMetrics {
+  NSString *title = item.title ?: @"";
+  if ([UIButton instancesRespondToSelector:@selector(setAttributedTitle:forState:)]) {
+    NSMutableDictionary<NSString *, id> *attributes = [NSMutableDictionary dictionary];
+
+    // UIBarButtonItem's appearance proxy values don't appear to come "for free" like they do with
+    // typical UIView instances, so we're attempting to recreate the behavior here.
+    NSArray *appearanceProxies = @[ [item.class appearance] ];
+    for (UIBarButtonItem *appearance in appearanceProxies) {
+      [attributes addEntriesFromDictionary:[appearance titleTextAttributesForState:state]];
+    }
+    [attributes addEntriesFromDictionary:[item titleTextAttributesForState:state]];
+    if ([attributes count] > 0) {
+      [button
+          setAttributedTitle:[[NSAttributedString alloc] initWithString:title attributes:attributes]
+                    forState:state];
+    }
+  } else {
+    [button setTitle:title forState:state];
+  }
+
+  UIImage *backgroundImage = [item backgroundImageForState:state barMetrics:barMetrics];
+  if (backgroundImage) {
+    [button setBackgroundImage:backgroundImage forState:state];
+  }
+}
+
+- (void)transferCustomViewOwnershipForBarButtonItem:(UIBarButtonItem *)barButtonItem {
+  UIView *customView = barButtonItem.customView;
+  if (customView && ![customView isKindOfClass:[MDCButtonBarSandbagView class]]) {
+    // Transfer ownership of any UIBarButtonItem.customView to the internal property
+    // so that UINavigationController won't steal the view from us.
+    barButtonItem.mdc_customView = customView;
+    barButtonItem.customView = [[MDCButtonBarSandbagView alloc] init];
+  }
+}
+
+@end
+
+@implementation MDCButtonBarSandbagView
+@end
+
+@implementation MDCButtonBarButton
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  CGSize fitSize = [super sizeThatFits:size];
+  fitSize.height =
+      self.contentPadding.top + MAX(kMinimumItemWidth, fitSize.height) + self.contentPadding.bottom;
+  fitSize.width =
+      self.contentPadding.left + MAX(kMinimumItemWidth, fitSize.width) + self.contentPadding.right;
+
+  return fitSize;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // TODO(featherless): Remove this conditional and always set the max ripple radius once
+  // https://github.com/material-components/material-components-ios/issues/329 lands.
+  if (self.inkStyle == MDCInkStyleUnbounded) {
+    self.inkMaxRippleRadius = MIN(self.bounds.size.width, self.bounds.size.height) / 2;
+  } else {
+    self.inkMaxRippleRadius = 0;
+  }
+}
+
+@end
+
+@implementation UIBarButtonItem (MDCHeaderInternal)
+
+@dynamic mdc_customView;
+
+- (UIView *)mdc_customView {
+  return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)mdc_setCustomView:(UIView *)customView {
+  objc_setAssociatedObject(self, @selector(mdc_customView), customView,
+                           OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h
new file mode 100644
index 0000000..a82b951
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButtonBar.h"
+
+@interface MDCButtonBar (Builder)
+
+/**
+ Finds the corresponding UIBarButtonItem and calls its target/action with the item as the first
+ parameter.
+ */
+- (void)didTapButton:(UIButton *)button event:(UIEvent *)event;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCButton.h
new file mode 100644
index 0000000..c3532b9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCButton.h
@@ -0,0 +1,186 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <CoreGraphics/CoreGraphics.h>
+#import <UIKit/UIKit.h>
+
+#import "MaterialInk.h"
+
+/**
+ A Material flat, raised or floating button.
+
+ All buttons display animated ink splashes when the user interacts with the button.
+
+ The title color of the button set to have an accessible contrast ratio with the button's
+ background color. To ensure this works for flat buttons (with transparent background), the caller
+ is responsible for setting (and updating, if necessary) the button's underlyingColor property.
+
+ All buttons set the exclusiveTouch property to YES by default, which prevents users from
+ simultaneously interacting with a button and other UI elements.
+
+ @see http://www.google.com/design/spec/components/buttons.html
+ */
+@interface MDCButton : UIButton
+
+/**
+ A color used as the button's @c backgroundColor for @c state.
+
+ @param state The state.
+ @return The background color.
+ */
+- (nullable UIColor *)backgroundColorForState:(UIControlState)state;
+
+/**
+ A color used as the button's @c backgroundColor.
+
+ If left unset or reset to nil for a given state, then a default blue color is used.
+
+ @param backgroundColor The background color.
+ @param state The state.
+ */
+- (void)setBackgroundColor:(nullable UIColor *)backgroundColor forState:(UIControlState)state;
+
+/** The ink style of the button. */
+@property(nonatomic, assign) MDCInkStyle inkStyle;
+
+/** The ink color of the button. */
+@property(nonatomic, strong, null_resettable) UIColor *inkColor;
+
+/*
+ Maximum radius of the button's ink. If the radius <= 0 then half the length of the diagonal of
+ self.bounds is used. This value is ignored if button's @c inkStyle is set to |MDCInkStyleBounded|.
+ */
+@property(nonatomic, assign) CGFloat inkMaxRippleRadius;
+
+/**
+ A custom title color for the non-disabled states. The default is nil, which means that the button
+ chooses its title color automatically based on @c underlyingColor, whether the button is opaque,
+ its current background color, etc.
+
+ Setting this to a non-nil color overrides that logic, and the caller is responsible for ensuring
+ that the title color/background color combination meets the accessibility requirements.
+ */
+@property(nonatomic, strong, nullable) UIColor *customTitleColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The alpha value that will be applied when the button is disabled. Most clients can leave this as
+ the default value to get a semi-transparent button automatically.
+ */
+@property(nonatomic) CGFloat disabledAlpha;
+
+/**
+ If true, converts the button title to uppercase. Changing this property to NO will not update the
+ current title string.
+
+ Default is YES and is recommended whenever possible.
+ */
+@property(nonatomic, getter=isUppercaseTitle) BOOL uppercaseTitle;
+
+/**
+ Insets to apply to the button’s hit area.
+
+ Allows the button to detect touches outside of its bounds. A negative value indicates an
+ extension past the bounds.
+
+ Default is UIEdgeInsetsZero.
+ */
+@property(nonatomic) UIEdgeInsets hitAreaInsets;
+
+/**
+ The apparent background color as seen by the user, i.e. the color of the view behind the button.
+
+ The underlying color hint is used by buttons to calculate accessible title text colors when in
+ states with transparent background colors. The hint is used whenever the button changes state such
+ that the background color changes, for example, setting the background color or disabling the
+ button.
+
+ For flat buttons, this is the color of both the surrounding area and the button's background.
+ For raised and floating buttons, this is the color of view underneath the button.
+
+ The default is nil.  If left unset, buttons will likely have an incorrect appearance when
+ disabled. Additionally, flat buttons might have text colors with low accessibility.
+ */
+@property(nonatomic, strong, nullable) UIColor *underlyingColorHint;
+
+/** Sets the enabled state with optional animation. */
+- (void)setEnabled:(BOOL)enabled animated:(BOOL)animated;
+
+/**
+ Returns the elevation for a particular control state.
+
+ The default values depend on the kind of button, for example, flat buttons in the
+ UIControlStateNormal state have zero elevation.
+
+ @param state The control state to retrieve the elevation.
+ @return The elevation for the requested state.
+ */
+- (CGFloat)elevationForState:(UIControlState)state;
+
+/**
+ Sets the elevation for a particular control state.
+
+ Use resetElevationForState: to reset the button's behavior to the default for a particular state.
+
+ @param elevation The elevation to set.
+ @param state The state to set.
+ */
+- (void)setElevation:(CGFloat)elevation forState:(UIControlState)state;
+
+/**
+ Resets the elevation for a particular control state back to the button's default behavior.
+
+ @param state The control state to reset the elevation.
+ */
+- (void)resetElevationForState:(UIControlState)state;
+
+/*
+ Indicates whether the button should automatically update its font when the device’s
+ UIContentSizeCategory is changed.
+
+ This property is modeled after the adjustsFontForContentSizeCategory property in the
+ UIConnectSizeCategoryAdjusting protocol added by Apple in iOS 10.0.
+
+ If set to YES, this button will base its text font on MDCFontTextStyleButton.
+
+ Defaults value is NO.
+ */
+@property(nonatomic, readwrite, setter=mdc_setAdjustsFontForContentSizeCategory:)
+    BOOL mdc_adjustsFontForContentSizeCategory UI_APPEARANCE_SELECTOR;
+
+#pragma mark - UIButton changes
+
+/**
+ From UIButton's documentation: "If you subclass UIButton, this method does not return an instance
+ of your subclass. If you want to create an instance of a specific subclass, you must alloc/init
+ the button directly."
+ */
++ (nonnull instancetype)buttonWithType:(UIButtonType)buttonType NS_UNAVAILABLE;
+
+#pragma mark - Deprecated
+
+/** Use setBackgroundColor:forState: instead. */
+- (void)setBackgroundColor:(nullable UIColor *)backgroundColor NS_UNAVAILABLE;
+
+@property(nonatomic)
+    BOOL shouldRaiseOnTouch __deprecated_msg("Use MDCFlatButton instead of shouldRaiseOnTouch = NO")
+        ;
+
+@property(nonatomic) BOOL shouldCapitalizeTitle __deprecated_msg("Use uppercaseTitle instead.");
+
+@property(nonatomic, strong, nullable)
+    UIColor *underlyingColor __deprecated_msg("Use underlyingColorHint instead.");
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCButton.m
new file mode 100644
index 0000000..ec37444
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCButton.m
@@ -0,0 +1,729 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+
+#import "MDFTextAccessibility.h"
+#import "MaterialInk.h"
+#import "MaterialShadowElevations.h"
+#import "MaterialShadowLayer.h"
+#import "MaterialTypography.h"
+#import "private/MDCButton+Subclassing.h"
+
+// TODO(ajsecord): Animate title color when animating between enabled/disabled states.
+// Non-trivial: http://corecocoa.wordpress.com/2011/10/04/animatable-text-color-of-uilabel/
+
+static NSString *const MDCButtonEnabledBackgroundColorKey = @"MDCButtonEnabledBackgroundColorKey";
+static NSString *const MDCButtonDisabledBackgroundColorLightKey =
+    @"MDCButtonDisabledBackgroundColorLightKey";
+static NSString *const MDCButtonDisabledBackgroundColorDarkKey =
+    @"MDCButtonDisabledBackgroundColorDarkKey";
+static NSString *const MDCButtonInkViewInkStyleKey = @"MDCButtonInkViewInkStyleKey";
+static NSString *const MDCButtonInkViewInkColorKey = @"MDCButtonInkViewInkColorKey";
+static NSString *const MDCButtonInkViewInkMaxRippleRadiusKey =
+    @"MDCButtonInkViewInkMaxRippleRadiusKey";
+static NSString *const MDCButtonShouldRaiseOnTouchKey = @"MDCButtonShouldRaiseOnTouchKey";
+// Previous value kept for backwards compatibility.
+static NSString *const MDCButtonUppercaseTitleKey = @"MDCButtonShouldCapitalizeTitleKey";
+// Previous value kept for backwards compatibility.
+static NSString *const MDCButtonUnderlyingColorHintKey = @"MDCButtonUnderlyingColorKey";
+static NSString *const MDCButtonDisableAlphaKey = @"MDCButtonDisableAlphaKey";
+static NSString *const MDCButtonCustomTitleColorKey = @"MDCButtonCustomTitleColorKey";
+static NSString *const MDCButtonAreaInsetKey = @"MDCButtonAreaInsetKey";
+
+static NSString *const MDCButtonUserElevationsKey = @"MDCButtonUserElevationsKey";
+static NSString *const MDCButtonBackgroundColorsKey = @"MDCButtonBackgroundColorsKey";
+static NSString *const MDCButtonAccessibilityLabelsKey = @"MDCButtonAccessibilityLabelsKey";
+
+static const NSTimeInterval MDCButtonAnimationDuration = 0.2;
+
+// http://www.google.com/design/spec/components/buttons.html#buttons-main-buttons
+static const CGFloat MDCButtonDisabledAlpha = 0.1f;
+
+// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t MDCButtonDefaultBackgroundColor = 0x2196F3;
+
+// Checks whether the provided floating point number is exactly zero.
+static inline BOOL MDCButtonFloatIsExactlyZero(CGFloat value) {
+  return (value == 0.f);
+}
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+static NSAttributedString *uppercaseAttributedString(NSAttributedString *string) {
+  // Store the attributes.
+  NSMutableArray<NSDictionary *> *attributes = [NSMutableArray array];
+  [string enumerateAttributesInRange:NSMakeRange(0, [string length])
+                             options:0
+                          usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
+                            [attributes addObject:@{
+                              @"attrs" : attrs,
+                              @"range" : [NSValue valueWithRange:range]
+                            }];
+                          }];
+
+  // Make the string uppercase.
+  NSString *uppercaseString = [[string string] uppercaseStringWithLocale:[NSLocale currentLocale]];
+
+  // Apply the text and attributes to a mutable copy of the title attributed string.
+  NSMutableAttributedString *mutableString = [string mutableCopy];
+  [mutableString replaceCharactersInRange:NSMakeRange(0, [string length])
+                               withString:uppercaseString];
+  for (NSDictionary *attribute in attributes) {
+    [mutableString setAttributes:attribute[@"attrs"] range:[attribute[@"range"] rangeValue]];
+  }
+
+  return [mutableString copy];
+}
+
+@interface MDCButton () {
+  NSMutableDictionary<NSNumber *, NSNumber *> *_userElevations;   // For each UIControlState.
+  NSMutableDictionary<NSNumber *, UIColor *> *_backgroundColors;  // For each UIControlState.
+
+  // Cached accessibility settings.
+  NSMutableDictionary<NSNumber *, NSString *> *_accessibilityLabelForState;
+  NSString *_accessibilityLabelExplicitValue;
+
+  BOOL _mdc_adjustsFontForContentSizeCategory;
+}
+@property(nonatomic, strong) MDCInkView *inkView;
+@end
+
+@implementation MDCButton
+
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCButtonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCButtonInit];
+
+    // TODO(randallli): Add backward compatibility to background colors
+    //    if ([aDecoder containsValueForKey:MDCButtonEnabledBackgroundColorKey]) {
+    //      self.enabledBackgroundColor =
+    //          [aDecoder decodeObjectForKey:MDCButtonEnabledBackgroundColorKey];
+    //    }
+    //    if ([aDecoder containsValueForKey:MDCButtonDisabledBackgroundColorLightKey]) {
+    //      self.disabledBackgroundColorLight =
+    //          [aDecoder decodeObjectForKey:MDCButtonDisabledBackgroundColorLightKey];
+    //    }
+    //    if ([aDecoder containsValueForKey:MDCButtonDisabledBackgroundColorDarkKey]) {
+    //      self.disabledBackgroundColorDark =
+    //          [aDecoder decodeObjectForKey:MDCButtonDisabledBackgroundColorDarkKey];
+    //    }
+    if ([aDecoder containsValueForKey:MDCButtonInkViewInkStyleKey]) {
+      self.inkView.inkStyle = [aDecoder decodeIntegerForKey:MDCButtonInkViewInkStyleKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonInkViewInkColorKey]) {
+      self.inkView.inkColor = [aDecoder decodeObjectForKey:MDCButtonInkViewInkColorKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonInkViewInkMaxRippleRadiusKey]) {
+      self.inkView.maxRippleRadius =
+          (CGFloat)[aDecoder decodeDoubleForKey:MDCButtonInkViewInkMaxRippleRadiusKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonShouldRaiseOnTouchKey]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+      self.shouldRaiseOnTouch = [aDecoder decodeBoolForKey:MDCButtonShouldRaiseOnTouchKey];
+#pragma clang diagnostic pop
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonUppercaseTitleKey]) {
+      self.uppercaseTitle = [aDecoder decodeBoolForKey:MDCButtonUppercaseTitleKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonUnderlyingColorHintKey]) {
+      self.underlyingColorHint = [aDecoder decodeObjectForKey:MDCButtonUnderlyingColorHintKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonCustomTitleColorKey]) {
+      self.customTitleColor = [aDecoder decodeObjectForKey:MDCButtonCustomTitleColorKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonDisableAlphaKey]) {
+      self.disabledAlpha = (CGFloat)[aDecoder decodeDoubleForKey:MDCButtonDisableAlphaKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonAreaInsetKey]) {
+      self.hitAreaInsets = [aDecoder decodeUIEdgeInsetsForKey:MDCButtonAreaInsetKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonUserElevationsKey]) {
+      _userElevations = [aDecoder decodeObjectForKey:MDCButtonUserElevationsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonBackgroundColorsKey]) {
+      _backgroundColors = [aDecoder decodeObjectForKey:MDCButtonBackgroundColorsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonAccessibilityLabelsKey]) {
+      _accessibilityLabelForState = [aDecoder decodeObjectForKey:MDCButtonAccessibilityLabelsKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+
+  [aCoder encodeInteger:_inkView.inkStyle forKey:MDCButtonInkViewInkStyleKey];
+  if (_inkView.inkColor) {
+    [aCoder encodeObject:_inkView.inkColor forKey:MDCButtonInkViewInkColorKey];
+  }
+
+  [aCoder encodeDouble:_inkView.maxRippleRadius forKey:MDCButtonInkViewInkMaxRippleRadiusKey];
+  [aCoder encodeBool:_shouldRaiseOnTouch forKey:MDCButtonShouldRaiseOnTouchKey];
+  [aCoder encodeBool:_uppercaseTitle forKey:MDCButtonUppercaseTitleKey];
+  if (_underlyingColorHint) {
+    [aCoder encodeObject:_underlyingColorHint forKey:MDCButtonUnderlyingColorHintKey];
+  }
+  [aCoder encodeDouble:self.disabledAlpha forKey:MDCButtonDisableAlphaKey];
+  if (self.customTitleColor) {
+    [aCoder encodeObject:self.customTitleColor forKey:MDCButtonCustomTitleColorKey];
+  }
+  [aCoder encodeUIEdgeInsets:self.hitAreaInsets forKey:MDCButtonAreaInsetKey];
+  [aCoder encodeObject:_userElevations forKey:MDCButtonUserElevationsKey];
+  [aCoder encodeObject:_backgroundColors forKey:MDCButtonBackgroundColorsKey];
+  [aCoder encodeObject:_accessibilityLabelForState forKey:MDCButtonAccessibilityLabelsKey];
+}
+
+- (void)commonMDCButtonInit {
+  _disabledAlpha = MDCButtonDisabledAlpha;
+  _shouldRaiseOnTouch = YES;
+  _uppercaseTitle = YES;
+  _userElevations = [NSMutableDictionary dictionary];
+  _backgroundColors = [NSMutableDictionary dictionary];
+  _accessibilityLabelForState = [NSMutableDictionary dictionary];
+
+  // Disable default highlight state.
+  self.adjustsImageWhenHighlighted = NO;
+  self.showsTouchWhenHighlighted = NO;
+
+  // Set up title label attributes.
+  self.titleLabel.font = [MDCTypography buttonFont];
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+
+  // Default content insets
+  self.contentEdgeInsets = [self defaultContentEdgeInsets];
+
+  MDCShadowLayer *shadowLayer = [self shadowLayer];
+  shadowLayer.shadowPath = [self boundingPath].CGPath;
+  shadowLayer.shadowColor = [UIColor blackColor].CGColor;
+  shadowLayer.elevation = [self elevationForState:self.state];
+
+  // Set up ink layer.
+  _inkView = [[MDCInkView alloc] initWithFrame:self.bounds];
+  [self insertSubview:_inkView belowSubview:self.imageView];
+
+  // UIButton has a drag enter/exit boundary that is outside of the frame of the button itself.
+  // Because this is not exposed externally, we can't use -touchesMoved: to calculate when to
+  // change ink state. So instead we fall back on adding target/actions for these specific events.
+  [self addTarget:self
+                action:@selector(touchDragEnter:forEvent:)
+      forControlEvents:UIControlEventTouchDragEnter];
+  [self addTarget:self
+                action:@selector(touchDragExit:forEvent:)
+      forControlEvents:UIControlEventTouchDragExit];
+
+  // Block users from activating multiple buttons simultaneously by default.
+  self.exclusiveTouch = YES;
+
+  // Default background colors.
+  [self setBackgroundColor:MDCColorFromRGB(MDCButtonDefaultBackgroundColor)
+                  forState:UIControlStateNormal];
+
+  self.inkColor = [UIColor colorWithWhite:1 alpha:0.2f];
+
+  // Uppercase all titles
+  if (_uppercaseTitle) {
+    [self uppercaseAllTitles];
+  }
+}
+
+- (void)dealloc {
+  [self removeTarget:self action:NULL forControlEvents:UIControlEventAllEvents];
+
+  [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                  name:UIContentSizeCategoryDidChangeNotification
+                                                object:nil];
+}
+
+- (void)setCustomTitleColor:(UIColor *)customTitleColor {
+  _customTitleColor = customTitleColor;
+  [self updateTitleColor];
+}
+
+- (void)setUnderlyingColorHint:(UIColor *)underlyingColorHint {
+  _underlyingColorHint = underlyingColorHint;
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+}
+
+- (void)setDisabledAlpha:(CGFloat)disabledAlpha {
+  _disabledAlpha = disabledAlpha;
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  self.layer.shadowPath = [self boundingPath].CGPath;
+  self.layer.cornerRadius = [self cornerRadius];
+
+  // Center the ink view frame taking into account possible insets using contentRectForBounds.
+
+  CGRect contentRect = [self contentRectForBounds:self.bounds];
+  CGPoint contentCenterPoint = CGPointMake(CGRectGetMidX(contentRect), CGRectGetMidY(contentRect));
+  CGPoint boundsCenterPoint = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
+
+  CGFloat offsetX = contentCenterPoint.x - boundsCenterPoint.x;
+  CGFloat offsetY = contentCenterPoint.y - boundsCenterPoint.y;
+  _inkView.frame = CGRectMake(offsetX, offsetY, self.bounds.size.width, self.bounds.size.height);
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  return CGRectContainsPoint(UIEdgeInsetsInsetRect(self.bounds, _hitAreaInsets), point);
+}
+
+#pragma mark - UIResponder
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesBegan:touches withEvent:event];
+
+  [self handleBeginTouches:touches];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesMoved:touches withEvent:event];
+
+  // Drag events handled by -touchDragExit:forEvent: and -touchDragEnter:forEvent:
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesEnded:touches withEvent:event];
+
+  CGPoint location = [self locationFromTouches:touches];
+  [_inkView startTouchEndedAnimationAtPoint:location completion:nil];
+
+  BOOL inside = CGRectContainsPoint(self.bounds, location);
+  if (inside && _shouldRaiseOnTouch) {
+    [self animateButtonToHeightForState:UIControlStateNormal];
+  }
+}
+
+// Note - in some cases, event may be nil (e.g. view removed from window).
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesCancelled:touches withEvent:event];
+
+  [self evaporateInkToPoint:[self locationFromTouches:touches]];
+}
+
+#pragma mark - UIButton methods
+
+- (void)setEnabled:(BOOL)enabled {
+  [self setEnabled:enabled animated:NO];
+}
+
+- (void)setEnabled:(BOOL)enabled animated:(BOOL)animated {
+  [super setEnabled:enabled];
+  [self updateAlphaAndBackgroundColorAnimated:animated];
+}
+
+#pragma mark - Title Uppercasing
+
+- (void)setUppercaseTitle:(BOOL)uppercaseTitle {
+  _uppercaseTitle = uppercaseTitle;
+  if (_uppercaseTitle) {
+    [self uppercaseAllTitles];
+  }
+}
+
+- (void)uppercaseAllTitles {
+  // This ensures existing titles will get uppercased.
+  UIControlState allControlStates = UIControlStateNormal | UIControlStateHighlighted |
+                                    UIControlStateDisabled | UIControlStateSelected;
+  for (UIControlState state = 0; state <= allControlStates; ++state) {
+    NSString *title = [self titleForState:state];
+    if (title) {
+      [self setTitle:[title uppercaseStringWithLocale:[NSLocale currentLocale]] forState:state];
+    }
+
+    NSAttributedString *attributedTitle = [self attributedTitleForState:state];
+    if (attributedTitle) {
+      [self setAttributedTitle:uppercaseAttributedString(attributedTitle) forState:state];
+    }
+  }
+}
+
+- (void)setTitle:(NSString *)title forState:(UIControlState)state {
+  // Intercept any setting of the title and store a copy in case the accessibilityLabel
+  // is requested and the original non-uppercased version needs to be returned.
+  if ([title length]) {
+    _accessibilityLabelForState[@(state)] = [title copy];
+  } else {
+    [_accessibilityLabelForState removeObjectForKey:@(state)];
+  }
+
+  if (_uppercaseTitle) {
+    title = [title uppercaseStringWithLocale:[NSLocale currentLocale]];
+  }
+  [super setTitle:title forState:state];
+}
+
+- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state {
+  // Intercept any setting of the title and store a copy in case the accessibilityLabel
+  // is requested and the original non-uppercased version needs to be returned.
+  if ([title length]) {
+    _accessibilityLabelForState[@(state)] = [[title string] copy];
+  } else {
+    [_accessibilityLabelForState removeObjectForKey:@(state)];
+  }
+
+  if (_uppercaseTitle) {
+    title = uppercaseAttributedString(title);
+  }
+  [super setAttributedTitle:title forState:state];
+}
+
+#pragma mark - Accessibility
+
+- (void)setAccessibilityLabel:(NSString *)accessibilityLabel {
+  // Intercept any explicit setting of the accessibilityLabel so it can be returned
+  // later before the accessibiilityLabel is inferred from the setTitle:forState:
+  // argument values.
+  _accessibilityLabelExplicitValue = [accessibilityLabel copy];
+  [super setAccessibilityLabel:accessibilityLabel];
+}
+
+- (NSString *)accessibilityLabel {
+  if (!_uppercaseTitle) {
+    return [super accessibilityLabel];
+  }
+
+  NSString *label = _accessibilityLabelExplicitValue;
+  if ([label length]) {
+    return label;
+  }
+
+  label = _accessibilityLabelForState[@(self.state)];
+  if ([label length]) {
+    return label;
+  }
+
+  label = _accessibilityLabelForState[@(UIControlStateNormal)];
+  if ([label length]) {
+    return label;
+  }
+
+  label = [super accessibilityLabel];
+  if ([label length]) {
+    return label;
+  }
+
+  return nil;
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  return [super accessibilityTraits] | UIAccessibilityTraitButton;
+}
+
+#pragma mark - Ink
+
+- (MDCInkStyle)inkStyle {
+  return _inkView.inkStyle;
+}
+
+- (void)setInkStyle:(MDCInkStyle)inkStyle {
+  _inkView.inkStyle = inkStyle;
+}
+
+- (UIColor *)inkColor {
+  return _inkView.inkColor;
+}
+
+- (void)setInkColor:(UIColor *)inkColor {
+  _inkView.inkColor = inkColor;
+}
+
+- (CGFloat)inkMaxRippleRadius {
+  return _inkView.maxRippleRadius;
+}
+
+- (void)setInkMaxRippleRadius:(CGFloat)inkMaxRippleRadius {
+  _inkView.maxRippleRadius = inkMaxRippleRadius;
+}
+
+#pragma mark - Shadows
+
+- (MDCShadowLayer *)shadowLayer {
+  return (MDCShadowLayer *)self.layer;
+}
+
+- (void)animateButtonToHeightForState:(UIControlState)state {
+  [CATransaction begin];
+  [CATransaction setAnimationDuration:MDCButtonAnimationDuration];
+  [self shadowLayer].elevation = [self elevationForState:state];
+  [CATransaction commit];
+}
+
+#pragma mark - BackgroundColor
+
+- (UIColor *)backgroundColorForState:(UIControlState)state {
+  return _backgroundColors[@(state)];
+}
+
+- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state {
+  _backgroundColors[@(state)] = backgroundColor;
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+}
+
+#pragma mark - Elevations
+
+- (CGFloat)elevationForState:(UIControlState)state {
+  NSNumber *elevation = _userElevations[@(state)];
+  return elevation ? (CGFloat)[elevation doubleValue] : [self defaultElevationForState:state];
+}
+
+- (void)setElevation:(CGFloat)elevation forState:(UIControlState)state {
+  _userElevations[@(state)] = @(elevation);
+  [self shadowLayer].elevation = [self elevationForState:self.state];
+
+  // The elevation of the normal state controls whether this button is flat or not, and flat buttons
+  // have different background color requirements than raised buttons.
+  // TODO(ajsecord): Move to MDCFlatButton and update this comment.
+  if (state == UIControlStateNormal) {
+    [self updateAlphaAndBackgroundColorAnimated:NO];
+  }
+}
+
+- (void)resetElevationForState:(UIControlState)state {
+  [_userElevations removeObjectForKey:@(state)];
+  [self shadowLayer].elevation = [self elevationForState:self.state];
+}
+
+#pragma mark - Private methods
+
+- (UIColor *)currentBackgroundColor {
+  UIColor *color = _backgroundColors[@(self.state)];
+  if (color) {
+    return color;
+  }
+  return [self backgroundColorForState:UIControlStateNormal];
+}
+
+/**
+ The background color that a user would see for this button. If self.backgroundColor is not
+ transparent, then returns that. Otherwise, returns self.underlyingColorHint.
+ @note If self.underlyingColorHint is not set, then this method will return nil.
+ */
+- (UIColor *)effectiveBackgroundColor {
+  if (![self isTransparentColor:self.currentBackgroundColor]) {
+    return self.currentBackgroundColor;
+  } else {
+    return self.underlyingColorHint;
+  }
+}
+
+/** Returns YES if the color is not transparent and is a "dark" color. */
+- (BOOL)isDarkColor:(UIColor *)color {
+  // TODO: have a components/private/ColorCalculations/MDCColorCalculations.h|m
+  //  return ![self isTransparentColor:color] && [QTMColorGroup luminanceOfColor:color] < 0.5f;
+  return ![self isTransparentColor:color];
+}
+
+/** Returns YES if the color is transparent (including a nil color). */
+- (BOOL)isTransparentColor:(UIColor *)color {
+  return !color || [color isEqual:[UIColor clearColor]] || CGColorGetAlpha(color.CGColor) == 0.0f;
+}
+
+- (void)touchDragEnter:(MDCButton *)button forEvent:(UIEvent *)event {
+  [self handleBeginTouches:event.allTouches];
+}
+
+- (void)touchDragExit:(MDCButton *)button forEvent:(UIEvent *)event {
+  CGPoint location = [self locationFromTouches:event.allTouches];
+  [self evaporateInkToPoint:location];
+}
+
+- (void)handleBeginTouches:(NSSet *)touches {
+  [_inkView startTouchBeganAnimationAtPoint:[self locationFromTouches:touches] completion:nil];
+  if (_shouldRaiseOnTouch) {
+    [self animateButtonToHeightForState:UIControlStateSelected];
+  }
+}
+
+- (CGPoint)locationFromTouches:(NSSet *)touches {
+  UITouch *touch = [touches anyObject];
+  return [touch locationInView:self];
+}
+
+- (void)evaporateInkToPoint:(CGPoint)toPoint {
+  [_inkView startTouchEndedAnimationAtPoint:toPoint completion:nil];
+  if (_shouldRaiseOnTouch) {
+    [self animateButtonToHeightForState:UIControlStateNormal];
+  }
+}
+
+- (UIBezierPath *)boundingPath {
+  return [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:[self cornerRadius]];
+}
+
+- (CGFloat)cornerRadius {
+  return 2.0f;
+}
+
+- (UIEdgeInsets)defaultContentEdgeInsets {
+  return UIEdgeInsetsMake(8, 16, 8, 16);
+}
+
+- (CGFloat)defaultElevationForState:(UIControlState)state {
+  if (state == UIControlStateNormal) {
+    return 0;
+  }
+
+  if ((state & UIControlStateSelected) == UIControlStateSelected) {
+    CGFloat normalElevation = [self elevationForState:UIControlStateNormal];
+    return normalElevation > 0 ? 2 * normalElevation : 1;
+  }
+
+  return [self elevationForState:UIControlStateNormal];
+}
+
+- (BOOL)shouldHaveOpaqueBackground {
+  BOOL isFlatButton = MDCButtonFloatIsExactlyZero([self elevationForState:UIControlStateNormal]);
+  return !isFlatButton;
+}
+
+- (void)updateAlphaAndBackgroundColorAnimated:(BOOL)animated {
+  void (^animations)() = ^{
+    self.alpha = self.enabled ? 1.0f : _disabledAlpha;
+    [self updateBackgroundColor];
+  };
+
+  if (animated) {
+    [UIView animateWithDuration:MDCButtonAnimationDuration animations:animations];
+  } else {
+    animations();
+  }
+}
+
+- (void)updateBackgroundColor {
+  //  UIColor *color = nil;
+  //  if ([self shouldHaveOpaqueBackground]) {
+  //    if (self.enabled) {
+  ////      color = self.enabledBackgroundColor;
+  //    } else {
+  //      color = [self isDarkColor:_underlyingColorHint] ? _disabledBackgroundColorLight
+  //                                                  : _disabledBackgroundColorDark;
+  //    }
+  //  }
+  [self updateTitleColor];
+  [self updateDisabledTitleColor];
+  super.backgroundColor = self.currentBackgroundColor;
+}
+
+- (void)updateDisabledTitleColor {
+  // Disabled buttons have very low opacity, so we full-opacity text color here to make the text
+  // readable. Also, even for non-flat buttons with opaque backgrounds, the correct background color
+  // to examine is the underlying color, since disabled buttons are so transparent.
+  BOOL darkBackground = [self isDarkColor:[self underlyingColorHint]];
+  [self setTitleColor:darkBackground ? [UIColor whiteColor] : [UIColor blackColor]
+             forState:UIControlStateDisabled];
+}
+
+- (void)updateTitleColor {
+  if (_customTitleColor) {
+    [self setTitleColor:_customTitleColor forState:UIControlStateNormal];
+    return;
+  }
+
+  if (![self isTransparentColor:[self effectiveBackgroundColor]]) {
+    MDFTextAccessibilityOptions options = 0;
+    if ([MDFTextAccessibility isLargeForContrastRatios:self.titleLabel.font]) {
+      options = MDFTextAccessibilityOptionsLargeFont;
+    }
+    UIColor *color =
+        [MDFTextAccessibility textColorOnBackgroundColor:[self effectiveBackgroundColor]
+                                         targetTextAlpha:[MDCTypography buttonFontOpacity]
+                                                 options:options];
+    [self setTitleColor:color forState:UIControlStateNormal];
+  }
+}
+
+- (BOOL)mdc_adjustsFontForContentSizeCategory {
+  return _mdc_adjustsFontForContentSizeCategory;
+}
+
+- (void)mdc_setAdjustsFontForContentSizeCategory:(BOOL)adjusts {
+  _mdc_adjustsFontForContentSizeCategory = adjusts;
+  if (_mdc_adjustsFontForContentSizeCategory) {
+    UIFont *font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleButton];
+    self.titleLabel.font = font;
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(contentSizeCategoryDidChange:)
+                                                 name:UIContentSizeCategoryDidChangeNotification
+                                               object:nil];
+  } else {
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                    name:UIContentSizeCategoryDidChangeNotification
+                                                  object:nil];
+  }
+}
+
+- (void)contentSizeCategoryDidChange:(NSNotification *)notification {
+  UIFont *font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleButton];
+  self.titleLabel.font = font;
+  [self sizeToFit];
+}
+
+#pragma mark - Deprecations
+
+- (BOOL)shouldCapitalizeTitle {
+  return [self isUppercaseTitle];
+}
+
+- (void)setShouldCapitalizeTitle:(BOOL)shouldCapitalizeTitle {
+  [self setUppercaseTitle:shouldCapitalizeTitle];
+}
+
+- (UIColor *)underlyingColor {
+  return [self underlyingColorHint];
+}
+
+- (void)setUnderlyingColor:(UIColor *)underlyingColor {
+  [self setUnderlyingColorHint:underlyingColor];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.h
new file mode 100644
index 0000000..886efe4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.h
@@ -0,0 +1,42 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "MDCButton.h"
+
+/**
+ A "flat" MDCButton.
+
+ Flat buttons should be considered the default button. They do not have their own background color,
+ do not raise when touched, and have uppercased text to indicate to the user that they are buttons.
+ Flat buttons should be used in most situations requiring a button. For layouts with many UI
+ elements in which a flat button might get visually lost, consider using a MDCRaisedButton instead.
+
+ @see http://www.google.com/design/spec/components/buttons.html#buttons-flat-buttons
+ */
+@interface MDCFlatButton : MDCButton
+
+/**
+ Use an opaque background color (default is NO).
+
+ Flat buttons normally have a transparent background and blend seamlessly with their underlying
+ color, but occasionally a flat button with an opaque background will be required. Consider using
+ a raised button instead if possible.
+ */
+@property(nonatomic) BOOL hasOpaqueBackground;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.m
new file mode 100644
index 0000000..4bf35d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.m
@@ -0,0 +1,69 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlatButton.h"
+
+#import "private/MDCButton+Subclassing.h"
+
+static NSString *const MDCFlatButtonHasOpaqueBackground = @"MDCFlatButtonHasOpaqueBackground";
+
+@implementation MDCFlatButton
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCFlatButtonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCFlatButtonHasOpaqueBackground]) {
+      self.hasOpaqueBackground = [aDecoder decodeBoolForKey:MDCFlatButtonHasOpaqueBackground];
+    }
+    [self commonMDCFlatButtonInit];
+  }
+  return self;
+}
+
+- (void)commonMDCFlatButtonInit {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  self.shouldRaiseOnTouch = NO;
+#pragma clang diagnostic pop
+  [self setBackgroundColor:nil forState:UIControlStateNormal];
+  self.inkColor = [UIColor colorWithWhite:0 alpha:0.06f];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeBool:_hasOpaqueBackground forKey:MDCFlatButtonHasOpaqueBackground];
+}
+
+#pragma mark - MDCButton Subclassing
+
+- (void)setHasOpaqueBackground:(BOOL)hasOpaqueBackground {
+  _hasOpaqueBackground = hasOpaqueBackground;
+  [self updateBackgroundColor];
+}
+
+- (BOOL)shouldHaveOpaqueBackground {
+  return [super shouldHaveOpaqueBackground] || self.hasOpaqueBackground;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.h
new file mode 100644
index 0000000..6552b35
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.h
@@ -0,0 +1,87 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <CoreGraphics/CoreGraphics.h>
+#import <Foundation/Foundation.h>
+
+#import "MDCButton.h"
+
+/**
+ Shapes for Material Floating buttons.
+
+ The mini size should only be used when required for visual continuity with other elements on the
+ screen.
+ */
+typedef NS_ENUM(NSInteger, MDCFloatingButtonShape) {
+  MDCFloatingButtonShapeDefault,
+  MDCFloatingButtonShapeMini
+};
+
+/**
+ A "floating" MDCButton.
+
+ Floating action buttons are circular, float a considerable amount above their parent, have
+ their own background color, and also raise briefly when touched. Floating action buttons should
+ only be used rarely, for the main action of a screen.
+
+ @see http://www.google.com/design/spec/components/buttons.html#buttons-main-buttons
+ */
+@interface MDCFloatingButton : MDCButton
+
+/**
+ Returns a MDCFloatingButton with default colors and the given @c shape.
+
+ @param shape Button shape.
+ @return Button with shape.
+ */
++ (nonnull instancetype)floatingButtonWithShape:(MDCFloatingButtonShape)shape;
+
+/**
+ @return The default floating button size dimension.
+ */
++ (CGFloat)defaultDimension;
+
+/**
+ @return The mini floating button size dimension.
+ */
++ (CGFloat)miniDimension;
+
+/**
+ Initializes self to a button with the given @c shape.
+
+ @param frame Button frame.
+ @param shape Button shape.
+ @return Button with shape.
+ */
+- (nonnull instancetype)initWithFrame:(CGRect)frame
+                                shape:(MDCFloatingButtonShape)shape NS_DESIGNATED_INITIALIZER;
+
+/**
+ Initializes self to a button with the MDCFloatingButtonShapeDefault shape.
+
+ @param frame Button frame.
+ @return Button with MDCFloatingButtonShapeDefault shape.
+ */
+- (nonnull instancetype)initWithFrame:(CGRect)frame;
+
+- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
+
+#pragma mark - Deprecations
+
++ (nonnull instancetype)buttonWithShape:(MDCFloatingButtonShape)shape
+    __deprecated_msg("Use floatingButtonWithShape: instead.");
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.m
new file mode 100644
index 0000000..a9b7028
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.m
@@ -0,0 +1,123 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFloatingButton.h"
+
+#import "MaterialShadowElevations.h"
+#import "private/MDCButton+Subclassing.h"
+
+static const CGFloat MDCFloatingButtonDefaultDimension = 56.0f;
+static const CGFloat MDCFloatingButtonMiniDimension = 40.0f;
+static NSString *const MDCFloatingButtonShapeKey = @"MDCFloatingButtonShapeKey";
+
+@implementation MDCFloatingButton {
+  MDCFloatingButtonShape _shape;
+}
+
++ (CGFloat)defaultDimension {
+  return MDCFloatingButtonDefaultDimension;
+}
+
++ (CGFloat)miniDimension {
+  return MDCFloatingButtonMiniDimension;
+}
+
++ (instancetype)floatingButtonWithShape:(MDCFloatingButtonShape)shape {
+  return [[[self class] alloc] initWithFrame:CGRectZero shape:shape];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  return [self initWithFrame:frame shape:MDCFloatingButtonShapeDefault];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame shape:(MDCFloatingButtonShape)shape {
+  self = [super initWithFrame:frame];
+  if (self) {
+    _shape = shape;
+    // The superclass sets contentEdgeInsets from defaultContentEdgeInsets before the _shape is set.
+    // Set contentEdgeInsets again to ensure the defaults are for the correct shape.
+    self.contentEdgeInsets = [self defaultContentEdgeInsets];
+  }
+  return self;
+}
+
+#pragma mark - NSCoding
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    _shape = [aDecoder decodeIntegerForKey:MDCFloatingButtonShapeKey];
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeInteger:_shape forKey:MDCFloatingButtonShapeKey];
+}
+
+#pragma mark - UIView
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  switch (_shape) {
+    case MDCFloatingButtonShapeDefault:
+      return CGSizeMake([[self class] defaultDimension], [[self class] defaultDimension]);
+    case MDCFloatingButtonShapeMini:
+      return CGSizeMake([[self class] miniDimension], [[self class] miniDimension]);
+  }
+}
+
+- (CGSize)intrinsicContentSize {
+  switch (_shape) {
+    case MDCFloatingButtonShapeDefault:
+      return CGSizeMake([[self class] defaultDimension], [[self class] defaultDimension]);
+    case MDCFloatingButtonShapeMini:
+      return CGSizeMake([[self class] miniDimension], [[self class] miniDimension]);
+  }
+}
+
+#pragma mark - Subclassing
+
+- (UIBezierPath *)boundingPath {
+  return [UIBezierPath bezierPathWithOvalInRect:self.bounds];
+}
+
+- (CGFloat)cornerRadius {
+  return CGRectGetWidth(self.bounds) / 2;
+}
+
+- (UIEdgeInsets)defaultContentEdgeInsets {
+  switch (_shape) {
+    case MDCFloatingButtonShapeDefault:
+      return UIEdgeInsetsMake(16, 16, 16, 16);
+    case MDCFloatingButtonShapeMini:
+      return UIEdgeInsetsMake(8, 8, 8, 8);
+  }
+}
+
+- (CGFloat)defaultElevationForState:(UIControlState)state {
+  return (((state & UIControlStateSelected) == UIControlStateSelected)
+              ? MDCShadowElevationFABPressed
+              : MDCShadowElevationFABResting);
+}
+
+#pragma mark - Deprecations
+
++ (instancetype)buttonWithShape:(MDCFloatingButtonShape)shape {
+  return [[self class] floatingButtonWithShape:shape];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.h
new file mode 100644
index 0000000..f71e770
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+
+/**
+ A "raised" MDCButton.
+
+ Raised buttons have their own background color, float above their parent slightly, and raise
+ briefly when touched. Raised buttons should be used when flat buttons would get lost among other
+ UI elements on the screen.
+
+ @see http://www.google.com/design/spec/components/buttons.html#buttons-raised-buttons
+ */
+@interface MDCRaisedButton : MDCButton
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.m
new file mode 100644
index 0000000..e3b7c29
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.m
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCRaisedButton.h"
+
+#import "MaterialShadowElevations.h"
+#import "private/MDCButton+Subclassing.h"
+
+@implementation MDCRaisedButton
+
+#pragma mark - Subclassing
+
+- (CGFloat)defaultElevationForState:(UIControlState)state {
+  return (((state & UIControlStateSelected) == UIControlStateSelected)
+              ? MDCShadowElevationRaisedButtonPressed
+              : MDCShadowElevationRaisedButtonResting);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MaterialButtons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MaterialButtons.h
new file mode 100644
index 0000000..f2908cc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/MaterialButtons.h
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+#import "MDCFlatButton.h"
+#import "MDCFloatingButton.h"
+#import "MDCRaisedButton.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h
new file mode 100644
index 0000000..06a887e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h
@@ -0,0 +1,51 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+
+@class MDCInkView;
+
+@interface MDCButton (Subclassing)
+
+/** Access to the ink view layer. Mainly used for subclasses to override ink properties. */
+@property(nonatomic, readonly, strong, nonnull) MDCInkView *inkView;
+
+/** Whether the background color should be opaque. */
+- (BOOL)shouldHaveOpaqueBackground;
+
+/** Updates the background color based on the button's current configuration. */
+- (void)updateBackgroundColor;
+
+/**
+ Should the button raise when touched?
+
+ Default is YES.
+ */
+@property(nonatomic) BOOL shouldRaiseOnTouch;
+
+/** The bounding path of the button. The shadow will follow that path. */
+- (nonnull UIBezierPath *)boundingPath;
+
+/** The corner radius of the button. The shadow will follow that path. */
+- (CGFloat)cornerRadius;
+
+/** The default content edge insets of the button. They are set at initialization time. */
+- (UIEdgeInsets)defaultContentEdgeInsets;
+
+/** The default elevation for a particular button state (if not set by the calling code). */
+- (CGFloat)defaultElevationForState:(UIControlState)state;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
new file mode 100644
index 0000000..c91e729
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
@@ -0,0 +1,108 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MaterialInk.h"
+
+#import <UIKit/UIKit.h>
+
+/** The available cell accessory view types. Based on UITableViewCellAccessoryType. */
+typedef NS_ENUM(NSUInteger, MDCCollectionViewCellAccessoryType) {
+  /** Default value. No accessory view shown. */
+  MDCCollectionViewCellAccessoryNone,
+
+  /** A chevron accessory view. */
+  MDCCollectionViewCellAccessoryDisclosureIndicator,
+
+  /** A checkmark accessory view. */
+  MDCCollectionViewCellAccessoryCheckmark,
+
+  /** An info button accessory view. */
+  MDCCollectionViewCellAccessoryDetailButton
+};
+
+// String key for accessibility hint of selected cells.
+FOUNDATION_EXPORT NSString *_Nonnull const kSelectedCellAccessibilityHintKey;
+
+// String key for accessibility hint of deselected cells.
+FOUNDATION_EXPORT NSString *_Nonnull const kDeselectedCellAccessibilityHintKey;
+
+/**
+ The MDCCollectionViewCell class provides an implementation of UICollectionViewCell that
+ supports Material Design layout and styling.
+ */
+@interface MDCCollectionViewCell : UICollectionViewCell
+
+/** The accessory type for this cell. Default is MDCCollectionViewCellAccessoryNone. */
+@property(nonatomic) MDCCollectionViewCellAccessoryType accessoryType;
+
+/** If set, use custom view and ignore accessoryType. Defaults to nil. */
+@property(nonatomic, strong, nullable) UIView *accessoryView;
+
+/**
+ The accessory inset for this cell. Only left/right insets are valid as top/bottom insets will
+ be ignored. These insets are used for both accessories and editing mask controls.
+ Defaults to {0, 16.0f, 0, 16.0f}.
+ */
+@property(nonatomic) UIEdgeInsets accessoryInset;
+
+/**
+ Whether to hide the separator for this cell. If not set, the @c shouldHideSeparators property of
+ the collection view styler will be used. Defaults to NO.
+ */
+@property(nonatomic) BOOL shouldHideSeparator;
+
+/**
+ The separator inset for this cell. Only left/right insets are valid as top/bottom insets will be
+ ignored. If this property is not changed, the @c separatorInset property of the collection view
+ styler will be used instead. Defaults to UIEdgeInsetsZero.
+ */
+@property(nonatomic) UIEdgeInsets separatorInset;
+
+/**
+ A boolean value indicating whether a cell permits interactions with subviews of its content while
+ the cell is in editing mode. If NO, then tapping anywhere in the cell will select it instead of
+ permitting the tapped subview to receive the touch. Defaults to NO.
+ */
+@property(nonatomic) BOOL allowsCellInteractionsWhileEditing;
+
+/**
+ A boolean value indicating whether the a cell is being edited. Setting is not animated.
+
+ When set, the cell will shows/hide editing controls with/without animation.
+ */
+@property(nonatomic, getter=isEditing) BOOL editing;
+
+/**
+ The color for the editing selector when the cell is selected.
+
+ The default is a red color.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *editingSelectorColor UI_APPEARANCE_SELECTOR;
+
+/**
+ Set the editing state with optional animations.
+
+ When set, the cell will shows/hide editing controls with/without animation.
+
+ @param editing YES if editing; otherwise, NO.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
+
+/** View containing the ink effect. */
+@property(nonatomic, strong, nullable) MDCInkView *inkView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.m
new file mode 100644
index 0000000..3a8948f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.m
@@ -0,0 +1,532 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewCell.h"
+
+#import "MaterialCollectionLayoutAttributes.h"
+#import "MaterialIcons+ic_check.h"
+#import "MaterialIcons+ic_check_circle.h"
+#import "MaterialIcons+ic_chevron_right.h"
+#import "MaterialIcons+ic_info.h"
+#import "MaterialIcons+ic_radio_button_unchecked.h"
+#import "MaterialIcons+ic_reorder.h"
+#import "MaterialRTL.h"
+
+#define RGBCOLOR(r, g, b) \
+  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
+#define HEXCOLOR(hex) RGBCOLOR((((hex) >> 16) & 0xFF), (((hex) >> 8) & 0xFF), ((hex)&0xFF))
+
+static CGFloat kEditingControlAppearanceOffset = 16.0f;
+
+// Default accessory insets.
+static const UIEdgeInsets kAccessoryInsetDefault = {0, 16.0f, 0, 16.0f};
+
+// Default editing icon colors.
+static const uint32_t kCellGrayColor = 0x626262;
+static const uint32_t kCellRedColor = 0xF44336;
+
+// File name of the bundle (without the '.bundle' extension) containing resources.
+static NSString *const kResourceBundleName = @"MaterialCollectionCells";
+
+// String table name containing localized strings.
+static NSString *const kStringTableName = @"MaterialCollectionCells";
+
+NSString *const kSelectedCellAccessibilityHintKey =
+    @"MaterialCollectionCellsAccessibilitySelectedHint";
+
+NSString *const kDeselectedCellAccessibilityHintKey =
+    @"MaterialCollectionCellsAccessibilityDeselectedHint";
+
+// To be used as accessory view when an accessory type is set. It has no particular functionalities
+// other than being a private class defined here, to check if an accessory view was set via an
+// accessory type, or if the user of MDCCollectionViewCell set a custom accessory view.
+@interface MDCAccessoryTypeImageView : UIImageView
+@end
+@implementation MDCAccessoryTypeImageView
+@end
+
+@implementation MDCCollectionViewCell {
+  MDCCollectionViewLayoutAttributes *_attr;
+  BOOL _usesCellSeparatorHiddenOverride;
+  BOOL _usesCellSeparatorInsetOverride;
+  BOOL _shouldAnimateEditingViews;
+  UIView *_separatorView;
+  UIImageView *_backgroundImageView;
+  UIImageView *_editingReorderImageView;
+  UIImageView *_editingSelectorImageView;
+}
+
+@synthesize inkView = _inkView;
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionViewCellInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionViewCellInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionViewCellInit {
+  // Separator defaults.
+  _separatorView = [[UIImageView alloc] initWithFrame:CGRectZero];
+  [self addSubview:_separatorView];
+
+  // Accessory defaults.
+  _accessoryType = MDCCollectionViewCellAccessoryNone;
+  _accessoryInset = kAccessoryInsetDefault;
+  _editingSelectorColor = HEXCOLOR(kCellRedColor);
+}
+
+#pragma mark - Layout
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+
+  // Accessory defaults.
+  _accessoryType = MDCCollectionViewCellAccessoryNone;
+  _accessoryInset = kAccessoryInsetDefault;
+  [_accessoryView removeFromSuperview];
+  _accessoryView = nil;
+
+  // Reset properties.
+  _shouldAnimateEditingViews = NO;
+  _usesCellSeparatorHiddenOverride = NO;
+  _usesCellSeparatorInsetOverride = NO;
+  _separatorView.hidden = YES;
+
+  [self drawSeparatorIfNeeded];
+  [self updateInterfaceForEditing];
+
+  // Reset cells hidden during swipe deletion.
+  self.hidden = NO;
+
+  [self.inkView cancelAllAnimationsAnimated:NO];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Layout the accessory view and the content view.
+  [self updateInterfaceForEditing];
+  [self layoutForegroundSubviews];
+
+  void (^editingViewLayout)() = ^() {
+    CGFloat txReorderTransform;
+    CGFloat txSelectorTransform;
+    switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+      case UIUserInterfaceLayoutDirectionLeftToRight:
+        txReorderTransform = kEditingControlAppearanceOffset;
+        txSelectorTransform = -kEditingControlAppearanceOffset;
+        break;
+      case UIUserInterfaceLayoutDirectionRightToLeft:
+        txReorderTransform = -kEditingControlAppearanceOffset;
+        txSelectorTransform = kEditingControlAppearanceOffset;
+        break;
+    }
+    _editingReorderImageView.alpha = _attr.shouldShowReorderStateMask ? 1.0f : 0.0f;
+    _editingReorderImageView.transform =
+        _attr.shouldShowReorderStateMask ? CGAffineTransformMakeTranslation(txReorderTransform, 0)
+                                         : CGAffineTransformIdentity;
+
+    _editingSelectorImageView.alpha = _attr.shouldShowSelectorStateMask ? 1.0f : 0.0f;
+    _editingSelectorImageView.transform =
+        _attr.shouldShowSelectorStateMask ? CGAffineTransformMakeTranslation(txSelectorTransform, 0)
+                                          : CGAffineTransformIdentity;
+
+    _accessoryView.alpha = _attr.shouldShowSelectorStateMask ? 0.0f : 1.0f;
+    _accessoryInset.right = _attr.shouldShowSelectorStateMask
+                                ? kAccessoryInsetDefault.right + kEditingControlAppearanceOffset
+                                : kAccessoryInsetDefault.right;
+  };
+
+  // Animate editing controls.
+  if (_shouldAnimateEditingViews) {
+    [UIView animateWithDuration:0.3 animations:editingViewLayout];
+    _shouldAnimateEditingViews = NO;
+  } else {
+    [UIView performWithoutAnimation:editingViewLayout];
+  }
+}
+
+- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
+  [super applyLayoutAttributes:layoutAttributes];
+  if ([layoutAttributes isKindOfClass:[MDCCollectionViewLayoutAttributes class]]) {
+    _attr = (MDCCollectionViewLayoutAttributes *)layoutAttributes;
+
+    if (_attr.representedElementCategory == UICollectionElementCategoryCell) {
+      // Cells are often set to editing via layout attributes so we default to animating.
+      // This can be overridden by ensuring layoutSubviews is called inside a non-animation block.
+      [self setEditing:_attr.editing animated:YES];
+    }
+
+    // Create image view to hold cell background image with shadowing.
+    if (!_backgroundImageView) {
+      _backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
+      self.backgroundView = _backgroundImageView;
+    }
+    _backgroundImageView.image = _attr.backgroundImage;
+
+    // Draw separator if needed.
+    [self drawSeparatorIfNeeded];
+
+    // Layout the accessory view and the content view.
+    [self layoutForegroundSubviews];
+
+    // Animate cell on appearance settings.
+    [self updateAppearanceAnimation];
+  }
+}
+
+- (void)layoutForegroundSubviews {
+  // First lay out the accessory view.
+  _accessoryView.frame = [self accessoryFrame];
+  // Then lay out the content view, inset by the accessory view's width.
+  self.contentView.frame = [self contentViewFrame];
+
+  // If necessary flip subviews for RTL.
+  _accessoryView.frame = MDCRectFlippedForRTL(_accessoryView.frame, CGRectGetWidth(self.bounds),
+                                              self.mdc_effectiveUserInterfaceLayoutDirection);
+  self.contentView.frame = MDCRectFlippedForRTL(self.contentView.frame, CGRectGetWidth(self.bounds),
+                                                self.mdc_effectiveUserInterfaceLayoutDirection);
+}
+
+#pragma mark - Accessory Views
+
+- (void)setAccessoryType:(MDCCollectionViewCellAccessoryType)accessoryType {
+  _accessoryType = accessoryType;
+
+  UIImageView *accessoryImageView = nil;
+  if (!_accessoryView && accessoryType != MDCCollectionViewCellAccessoryNone) {
+    // Add accessory view.
+    accessoryImageView = [[MDCAccessoryTypeImageView alloc] initWithFrame:CGRectZero];
+    _accessoryView = accessoryImageView;
+    _accessoryView.userInteractionEnabled = NO;
+    [self addSubview:_accessoryView];
+  }
+
+  switch (_accessoryType) {
+    case MDCCollectionViewCellAccessoryDisclosureIndicator: {
+      UIImage *image = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_chevron_right]];
+      if (self.mdc_effectiveUserInterfaceLayoutDirection ==
+          UIUserInterfaceLayoutDirectionRightToLeft) {
+        image = [image mdc_imageFlippedForRightToLeftLayoutDirection];
+      }
+      accessoryImageView.image = image;
+      break;
+    }
+    case MDCCollectionViewCellAccessoryCheckmark: {
+      UIImage *image = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_check]];
+      accessoryImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+      break;
+    }
+    case MDCCollectionViewCellAccessoryDetailButton: {
+      UIImage *image = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_info]];
+      accessoryImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+      break;
+    }
+    case MDCCollectionViewCellAccessoryNone: {
+      [_accessoryView removeFromSuperview];
+      _accessoryView = nil;
+      break;
+    }
+  }
+  [_accessoryView sizeToFit];
+}
+
+- (void)setAccessoryView:(UIView *)accessoryView {
+  if (_accessoryView) {
+    [_accessoryView removeFromSuperview];
+  }
+  _accessoryView = accessoryView;
+  if (_accessoryView) {
+    [self addSubview:_accessoryView];
+  }
+}
+
+- (CGRect)accessoryFrame {
+  CGSize size = _accessoryView.frame.size;
+  CGFloat originX = CGRectGetWidth(self.bounds) - size.width - _accessoryInset.right;
+  CGFloat originY = (CGRectGetHeight(self.bounds) - size.height) / 2;
+  return CGRectMake(originX, originY, size.width, size.height);
+}
+
+- (MDCInkView *)inkView {
+  if (!_inkView) {
+    _inkView = [[MDCInkView alloc] initWithFrame:self.bounds];
+    [self addSubview:_inkView];
+  }
+  return _inkView;
+}
+
+- (void)setInkView:(MDCInkView *)inkView {
+  if (inkView == _inkView) {
+    return;
+  }
+  if (_inkView) {
+    [_inkView removeFromSuperview];
+  }
+  if (inkView) {
+    [self addSubview:inkView];
+  }
+  _inkView = inkView;
+}
+
+#pragma mark - Separator
+
+- (void)setShouldHideSeparator:(BOOL)shouldHideSeparator {
+  _usesCellSeparatorHiddenOverride = YES;
+  _shouldHideSeparator = shouldHideSeparator;
+  [self drawSeparatorIfNeeded];
+}
+
+- (void)setSeparatorInset:(UIEdgeInsets)separatorInset {
+  _usesCellSeparatorInsetOverride = YES;
+  _separatorInset = separatorInset;
+  [self drawSeparatorIfNeeded];
+}
+
+- (void)drawSeparatorIfNeeded {
+  // Determine separator spec from attributes and cell overrides. Don't draw separator for bottom
+  // cell or in grid layout cells. Separators are added here as cell subviews instead of decoration
+  // views registered with the layout to overcome inability to animate decoration views in
+  // coordination with cell animations.
+  BOOL isHidden =
+      _usesCellSeparatorHiddenOverride ? _shouldHideSeparator : _attr.shouldHideSeparators;
+  UIEdgeInsets separatorInset =
+      _usesCellSeparatorInsetOverride ? _separatorInset : _attr.separatorInset;
+  BOOL isBottom = _attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalBottom;
+  BOOL isGrid = _attr.isGridLayout;
+
+  BOOL hideSeparator = isBottom || isHidden || isGrid;
+  if (hideSeparator != _separatorView.hidden) {
+    _separatorView.hidden = hideSeparator;
+  }
+
+  if (!hideSeparator) {
+    UIEdgeInsets insets = _attr.backgroundImageViewInsets;
+    // Compute the frame in LTR.
+    CGRect separatorFrame = CGRectMake(
+        insets.left, CGRectGetHeight(self.bounds) - _attr.separatorLineHeight,
+        CGRectGetWidth(self.bounds) - insets.left - insets.right, _attr.separatorLineHeight);
+    separatorFrame = UIEdgeInsetsInsetRect(separatorFrame, separatorInset);
+    _separatorView.frame = MDCRectFlippedForRTL(separatorFrame, CGRectGetWidth(self.bounds),
+                                                self.mdc_effectiveUserInterfaceLayoutDirection);
+    _separatorView.backgroundColor = _attr.separatorColor;
+  }
+}
+
+#pragma mark - Editing
+
+- (void)setEditing:(BOOL)editing {
+  [self setEditing:editing animated:NO];
+}
+
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
+  if (_editing == editing) {
+    return;
+  }
+  _shouldAnimateEditingViews = animated;
+  _editing = editing;
+  [self setNeedsLayout];
+  [self layoutIfNeeded];
+}
+
+- (void)updateInterfaceForEditing {
+  self.contentView.userInteractionEnabled = [self shouldEnableCellInteractions];
+
+  if (_editing) {
+    // Disable implicit animations when setting initial positioning of these subviews.
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+
+    // Create reorder editing controls.
+    if (_attr.shouldShowReorderStateMask) {
+      if (!_editingReorderImageView) {
+        UIImage *reorderImage = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_reorder]];
+        reorderImage = [reorderImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+        _editingReorderImageView = [[UIImageView alloc] initWithImage:reorderImage];
+        _editingReorderImageView.tintColor = HEXCOLOR(kCellGrayColor);
+        _editingReorderImageView.autoresizingMask =
+            MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+        [self addSubview:_editingReorderImageView];
+      }
+      CGAffineTransform transform = _editingReorderImageView.transform;
+      _editingReorderImageView.transform = CGAffineTransformIdentity;
+      CGSize size = _editingReorderImageView.image.size;
+      CGRect frame =
+          CGRectMake(0, (CGRectGetHeight(self.bounds) - size.height) / 2, size.width, size.height);
+      _editingReorderImageView.frame = MDCRectFlippedForRTL(
+          frame, CGRectGetWidth(self.bounds), self.mdc_effectiveUserInterfaceLayoutDirection);
+      _editingReorderImageView.transform = transform;
+      _editingReorderImageView.alpha = 1.0f;
+    } else {
+      _editingReorderImageView.alpha = 0.0f;
+    }
+
+    // Create selector editing controls.
+    if (_attr.shouldShowSelectorStateMask) {
+      if (!_editingSelectorImageView) {
+        UIImage *selectorImage =
+            [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_radio_button_unchecked]];
+        selectorImage = [selectorImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+        _editingSelectorImageView = [[UIImageView alloc] initWithImage:selectorImage];
+        _editingSelectorImageView.tintColor = HEXCOLOR(kCellGrayColor);
+        _editingSelectorImageView.autoresizingMask =
+            MDCAutoresizingFlexibleLeadingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+        [self addSubview:_editingSelectorImageView];
+      }
+      CGAffineTransform transform = _editingSelectorImageView.transform;
+      _editingSelectorImageView.transform = CGAffineTransformIdentity;
+      CGSize size = _editingSelectorImageView.image.size;
+      CGFloat originX = CGRectGetWidth(self.bounds) - size.width;
+      CGFloat originY = (CGRectGetHeight(self.bounds) - size.height) / 2;
+      CGRect frame = (CGRect){{originX, originY}, size};
+      _editingSelectorImageView.frame = MDCRectFlippedForRTL(
+          frame, CGRectGetWidth(self.bounds), self.mdc_effectiveUserInterfaceLayoutDirection);
+      _editingSelectorImageView.transform = transform;
+      _editingSelectorImageView.alpha = 1.0f;
+    } else {
+      _editingSelectorImageView.alpha = 0.0f;
+    }
+    [CATransaction commit];
+  } else {
+    _editingReorderImageView.alpha = 0.0f;
+    _editingSelectorImageView.alpha = 0.0f;
+  }
+
+  // Update accessory view.
+  _accessoryView.alpha = _attr.shouldShowSelectorStateMask ? 0.0f : 1.0f;
+  _accessoryInset.right = _attr.shouldShowSelectorStateMask
+                              ? kAccessoryInsetDefault.right + kEditingControlAppearanceOffset
+                              : kAccessoryInsetDefault.right;
+}
+
+#pragma mark - Selecting
+
+- (void)setSelected:(BOOL)selected {
+  [super setSelected:selected];
+  if (selected) {
+    _editingSelectorImageView.image =
+        [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_check_circle]];
+    _editingSelectorImageView.tintColor = self.editingSelectorColor;
+    self.accessibilityTraits |= UIAccessibilityTraitSelected;
+  } else {
+    _editingSelectorImageView.image =
+        [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_radio_button_unchecked]];
+    _editingSelectorImageView.tintColor = HEXCOLOR(kCellGrayColor);
+    self.accessibilityTraits &= ~UIAccessibilityTraitSelected;
+  }
+  _editingSelectorImageView.image =
+      [_editingSelectorImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+}
+
+- (void)setEditingSelectorColor:(UIColor *)editingSelectorColor {
+  if (editingSelectorColor == nil) {
+    editingSelectorColor = HEXCOLOR(kCellRedColor);
+  }
+  _editingSelectorColor = editingSelectorColor;
+}
+
+#pragma mark - Cell Appearance Animation
+
+- (void)updateAppearanceAnimation {
+  if (_attr.animateCellsOnAppearanceDelay > 0) {
+    // Intially hide content view and separator.
+    self.contentView.alpha = 0;
+    _separatorView.alpha = 0;
+
+    // Animate fade-in after delay.
+    if (!_attr.willAnimateCellsOnAppearance) {
+      [UIView animateWithDuration:_attr.animateCellsOnAppearanceDuration
+                            delay:_attr.animateCellsOnAppearanceDelay
+                          options:UIViewAnimationOptionCurveEaseOut
+                       animations:^{
+                         self.contentView.alpha = 1;
+                         _separatorView.alpha = 1;
+                       }
+                       completion:nil];
+    }
+  }
+}
+
+#pragma mark - RTL
+
+- (void)mdc_setSemanticContentAttribute:(UISemanticContentAttribute)mdc_semanticContentAttribute {
+  [super mdc_setSemanticContentAttribute:mdc_semanticContentAttribute];
+  // Reload the accessory type image if there is one.
+  if ([_accessoryView isKindOfClass:[MDCAccessoryTypeImageView class]]) {
+    self.accessoryType = self.accessoryType;
+  }
+}
+
+#pragma mark - Accessibility
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  UIAccessibilityTraits accessibilityTraits = [super accessibilityTraits];
+  if (self.accessoryType == MDCCollectionViewCellAccessoryCheckmark) {
+    accessibilityTraits |= UIAccessibilityTraitSelected;
+  }
+  return accessibilityTraits;
+}
+
+- (NSString *)accessibilityHint {
+  if (_attr.shouldShowSelectorStateMask) {
+    NSString *localizedHintKey =
+        self.selected ? kSelectedCellAccessibilityHintKey : kDeselectedCellAccessibilityHintKey;
+    return [[self class] localizedStringWithKey:localizedHintKey];
+  }
+  return nil;
+}
+
+#pragma mark - Private
+
++ (NSString *)localizedStringWithKey:(NSString *)key {
+  NSBundle *containingBundle = [NSBundle bundleForClass:self];
+  NSURL *resourceBundleURL =
+      [containingBundle URLForResource:kResourceBundleName withExtension:@"bundle"];
+  NSBundle *resourceBundle = [NSBundle bundleWithURL:resourceBundleURL];
+  return [resourceBundle localizedStringForKey:key value:nil table:kStringTableName];
+}
+
+- (CGRect)contentViewFrame {
+  CGFloat leadingPadding =
+      _attr.shouldShowReorderStateMask
+          ? CGRectGetWidth(_editingReorderImageView.bounds) + kEditingControlAppearanceOffset
+          : 0.f;
+
+  CGFloat accessoryViewPadding =
+      _accessoryView ? CGRectGetWidth(self.bounds) - CGRectGetMinX(_accessoryView.frame) : 0;
+  CGFloat trailingPadding =
+      _attr.shouldShowSelectorStateMask
+          ? CGRectGetWidth(_editingSelectorImageView.bounds) + kEditingControlAppearanceOffset
+          : accessoryViewPadding;
+  UIEdgeInsets insets = UIEdgeInsetsMake(0, leadingPadding, 0, trailingPadding);
+  return UIEdgeInsetsInsetRect(self.bounds, insets);
+}
+
+- (BOOL)shouldEnableCellInteractions {
+  return !_editing || _allowsCellInteractionsWhileEditing;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
new file mode 100644
index 0000000..039747a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
@@ -0,0 +1,75 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewCell.h"
+
+/** Default cell height for single line of text. Defaults to 48.0f. */
+extern const CGFloat MDCCellDefaultOneLineHeight;
+
+/** Default cell height for single line of text with avatar. Defaults to 56.0f. */
+extern const CGFloat MDCCellDefaultOneLineWithAvatarHeight;
+
+/** Default cell height for two lines of text. Defaults to 72.0f. */
+extern const CGFloat MDCCellDefaultTwoLineHeight;
+
+/** Default cell height for three lines of text. Defaults to 88.0f. */
+extern const CGFloat MDCCellDefaultThreeLineHeight;
+
+/**
+ The MDCCollectionViewTextCell class provides an implementation of UICollectionViewCell that
+ supports Material Design layout and styling. It provides two labels for text as well as an
+ image view. The default layout specifications can be found at the following link.
+
+ @see http://www.google.com/design/spec/components/lists.html#lists-specs
+ */
+@interface MDCCollectionViewTextCell : MDCCollectionViewCell
+
+/**
+ A text label. Typically this will be the first line of text in the cell.
+
+ Default text label properties:
+  - text            defaults to nil.
+  - font            defaults to [MDCTypography subheadFont].
+  - textColor       defaults to [UIColor colorWithWhite:0 alpha:MDCTypography subheadFontOpacity]].
+  - shadowColor     defaults to nil.
+  - shadowOffset    defaults to CGSizeZero.
+  - textAlignment   defaults to NSTextAlignmentNatural.
+  - lineBreakMode   defaults to NSLineBreakByTruncatingTail.
+  - numberOfLines   defaults to 1.
+ */
+@property(nonatomic, readonly, strong, nullable) UILabel *textLabel;
+
+/**
+ A detail text label. Typically this will be the second line of text in the cell.
+
+ Default detail text label properties:
+ - text            defaults to nil.
+ - font            defaults to [MDCTypography body1Font].
+ - textColor       defaults to [UIColor colorWithWhite:0 alpha:MDCTypography captionFontOpacity]].
+ - shadowColor     defaults to nil.
+ - shadowOffset    defaults to CGSizeZero.
+ - textAlignment   defaults to NSTextAlignmentNatural.
+ - lineBreakMode   defaults to NSLineBreakByTruncatingTail.
+ - numberOfLines   defaults to 1.
+ */
+@property(nonatomic, readonly, strong, nullable) UILabel *detailTextLabel;
+
+/**
+ An image view on the leading side of cell. Default leading padding is 16.0f.
+ */
+@property(nonatomic, readonly, strong, nullable) UIImageView *imageView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.m
new file mode 100644
index 0000000..fea883b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.m
@@ -0,0 +1,254 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewTextCell.h"
+
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+#import <tgmath.h>
+
+// Default cell heights.
+const CGFloat MDCCellDefaultOneLineHeight = 48.0f;
+const CGFloat MDCCellDefaultOneLineWithAvatarHeight = 56.0f;
+const CGFloat MDCCellDefaultTwoLineHeight = 72.0f;
+const CGFloat MDCCellDefaultThreeLineHeight = 88.0f;
+
+// Default cell fonts.
+#define kCellDefaultTextFont [MDCTypography subheadFont]
+#define kCellDefaultDetailTextFont [MDCTypography body1Font]
+
+// Default cell font opacity.
+#define kCellDefaultTextOpacity [MDCTypography subheadFontOpacity]
+#define kCellDefaultDetailTextFontOpacity [MDCTypography captionFontOpacity]
+
+// Cell padding top/bottom.
+static const CGFloat kCellTwoLinePaddingTop = 20;
+static const CGFloat kCellTwoLinePaddingBottom = 20;
+static const CGFloat kCellThreeLinePaddingTop = 16;
+static const CGFloat kCellThreeLinePaddingBottom = 20;
+// Cell padding leading/trailing.
+static const CGFloat kCellTextNoImagePaddingLeading = 16;
+static const CGFloat kCellTextNoImagePaddingTrailing = 16;
+static const CGFloat kCellTextWithImagePaddingLeading = 72;
+// Cell image view padding.
+static const CGFloat kCellImagePaddingLeading = 16;
+
+static inline CGFloat Ceil(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return ceil(value);
+#else
+  return ceilf(value);
+#endif
+}
+
+static inline CGFloat Floor(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return floor(value);
+#else
+  return floorf(value);
+#endif
+}
+
+// Returns the closest pixel-aligned value higher than |value|, taking the scale factor into
+// account. At a scale of 1, equivalent to Ceil().
+static inline CGFloat AlignValueToUpperPixel(CGFloat value) {
+  CGFloat scale = [[UIScreen mainScreen] scale];
+  return (CGFloat)Ceil(value * scale) / scale;
+}
+
+// Returns the closest pixel-aligned value lower than |value|, taking the scale factor into
+// account. At a scale of 1, equivalent to Floor().
+static inline CGFloat AlignValueToLowerPixel(CGFloat value) {
+  CGFloat scale = [[UIScreen mainScreen] scale];
+  return (CGFloat)Floor(value * scale) / scale;
+}
+
+// Returns the rect resulting from applying AlignSizeToUpperPixel to the rect size.
+static inline CGRect AlignRectToUpperPixel(CGRect rect) {
+  rect = CGRectStandardize(rect);
+  return CGRectMake(AlignValueToLowerPixel(rect.origin.x), AlignValueToLowerPixel(rect.origin.y),
+                    AlignValueToUpperPixel(rect.size.width),
+                    AlignValueToUpperPixel(rect.size.height));
+}
+
+@implementation MDCCollectionViewTextCell {
+  UIView *_contentWrapper;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionViewTextCellInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionViewTextCellInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionViewTextCellInit {
+  _contentWrapper = [[UIView alloc] initWithFrame:self.contentView.bounds];
+  _contentWrapper.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth |
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  _contentWrapper.clipsToBounds = YES;
+  [self.contentView addSubview:_contentWrapper];
+
+  // Text label.
+  _textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  _textLabel.font = kCellDefaultTextFont;
+  _textLabel.textColor = [UIColor colorWithWhite:0 alpha:kCellDefaultTextOpacity];
+  _textLabel.shadowColor = nil;
+  _textLabel.shadowOffset = CGSizeZero;
+  _textLabel.textAlignment = NSTextAlignmentNatural;
+  _textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+  _textLabel.autoresizingMask =
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  [_contentWrapper addSubview:_textLabel];
+
+  // Detail text label.
+  _detailTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  _detailTextLabel.font = kCellDefaultDetailTextFont;
+  _detailTextLabel.textColor = [UIColor colorWithWhite:0 alpha:kCellDefaultDetailTextFontOpacity];
+  _detailTextLabel.shadowColor = nil;
+  _detailTextLabel.shadowOffset = CGSizeZero;
+  _detailTextLabel.textAlignment = NSTextAlignmentNatural;
+  _detailTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+  _detailTextLabel.autoresizingMask =
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  [_contentWrapper addSubview:_detailTextLabel];
+
+  // Image view.
+  _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
+  _imageView.autoresizingMask =
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  [self.contentView addSubview:_imageView];
+}
+
+#pragma mark - Layout
+
+- (void)prepareForReuse {
+  _imageView.image = nil;
+
+  [super prepareForReuse];
+  [self setNeedsLayout];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  [self applyMetrics];
+}
+
+- (CGRect)contentWrapperFrame {
+  CGFloat leadingPadding =
+      _imageView.image ? kCellTextWithImagePaddingLeading : kCellTextNoImagePaddingLeading;
+  CGFloat trailingPadding = kCellTextNoImagePaddingTrailing;
+  UIEdgeInsets insets = MDCInsetsMakeWithLayoutDirection(
+      0, leadingPadding, 0, trailingPadding, self.mdc_effectiveUserInterfaceLayoutDirection);
+  return UIEdgeInsetsInsetRect(self.contentView.bounds, insets);
+}
+
+- (void)applyMetrics {
+  // Set content wrapper frame.
+  _contentWrapper.frame = [self contentWrapperFrame];
+  CGFloat boundsHeight = CGRectGetHeight(_contentWrapper.bounds);
+
+  // Image layout.
+  [_imageView sizeToFit];
+  CGRect imageFrame = _imageView.frame;
+  imageFrame.origin.x = kCellImagePaddingLeading;
+  imageFrame.origin.y =
+      (CGRectGetHeight(self.contentView.frame) / 2) - (imageFrame.size.height / 2);
+
+  // Text layout.
+  CGRect textFrame = CGRectZero;
+  textFrame.size = [self frameSizeForLabel:_textLabel];
+  CGRect detailFrame = CGRectZero;
+  detailFrame.size = [self frameSizeForLabel:_detailTextLabel];
+
+  // Adjust the labels X origin.
+  textFrame.origin.x = 0;
+  detailFrame.origin.x = 0;
+
+  // Adjust the labels Y origin.
+  if ([self numberOfAllVisibleTextLines] == 1) {
+    // Alignment for single line.
+    textFrame.origin.y = (boundsHeight / 2) - (textFrame.size.height / 2);
+    detailFrame.origin.y = (boundsHeight / 2) - (detailFrame.size.height / 2);
+
+  } else if ([self numberOfAllVisibleTextLines] == 2) {
+    if (!CGRectIsEmpty(textFrame) && !CGRectIsEmpty(detailFrame)) {
+      // Alignment for two lines.
+      textFrame.origin.y =
+          kCellTwoLinePaddingTop + _textLabel.font.ascender - textFrame.size.height;
+      detailFrame.origin.y = boundsHeight - kCellTwoLinePaddingBottom - detailFrame.size.height -
+                             _detailTextLabel.font.descender;
+    } else {
+      // Since single wrapped label, just center.
+      textFrame.origin.y = (boundsHeight / 2) - (textFrame.size.height / 2);
+      detailFrame.origin.y = (boundsHeight / 2) - (detailFrame.size.height / 2);
+    }
+
+  } else if ([self numberOfAllVisibleTextLines] == 3) {
+    if (!CGRectIsEmpty(textFrame) && !CGRectIsEmpty(detailFrame)) {
+      // Alignment for three lines.
+      textFrame.origin.y =
+          kCellThreeLinePaddingTop + _textLabel.font.ascender - _textLabel.font.lineHeight;
+      detailFrame.origin.y = boundsHeight - kCellThreeLinePaddingBottom - detailFrame.size.height -
+                             _detailTextLabel.font.descender;
+      imageFrame.origin.y = kCellThreeLinePaddingTop;
+    } else {
+      // Since single wrapped label, just center.
+      textFrame.origin.y = (boundsHeight / 2) - (textFrame.size.height / 2);
+      detailFrame.origin.y = (boundsHeight / 2) - (detailFrame.size.height / 2);
+    }
+  }
+  _textLabel.frame =
+      MDCRectFlippedForRTL(AlignRectToUpperPixel(textFrame), CGRectGetWidth(_contentWrapper.bounds),
+                           self.mdc_effectiveUserInterfaceLayoutDirection);
+  _detailTextLabel.frame = MDCRectFlippedForRTL(AlignRectToUpperPixel(detailFrame),
+                                                CGRectGetWidth(_contentWrapper.bounds),
+                                                self.mdc_effectiveUserInterfaceLayoutDirection);
+  _imageView.frame = MDCRectFlippedForRTL(AlignRectToUpperPixel(imageFrame),
+                                          CGRectGetWidth(self.contentView.bounds),
+                                          self.mdc_effectiveUserInterfaceLayoutDirection);
+}
+
+- (NSInteger)numberOfAllVisibleTextLines {
+  return [self numberOfLinesForLabel:_textLabel] + [self numberOfLinesForLabel:_detailTextLabel];
+}
+
+- (NSInteger)numberOfLinesForLabel:(UILabel *)label {
+  CGSize size = [self frameSizeForLabel:label];
+  return (NSInteger)floor(size.height / label.font.lineHeight);
+}
+
+- (CGSize)frameSizeForLabel:(UILabel *)label {
+  CGFloat width = MIN(CGRectGetWidth(_contentWrapper.bounds),
+                      [label.text sizeWithAttributes:@{NSFontAttributeName : label.font}].width);
+  CGFloat height =
+      [label textRectForBounds:_contentWrapper.bounds limitedToNumberOfLines:label.numberOfLines]
+          .size.height;
+  return CGSizeMake(width, height);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle/Resources/en.lproj/MaterialCollectionCells.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle/Resources/en.lproj/MaterialCollectionCells.strings
new file mode 100644
index 0000000..ce3a9f5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle/Resources/en.lproj/MaterialCollectionCells.strings
@@ -0,0 +1,5 @@
+/* Accessibility hint for selected cells in edit mode. */
+"MaterialCollectionCellsAccessibilitySelectedHint" = "Double tap to deselect.";
+
+/* Accessibility hint for deselected cells in edit mode. */
+"MaterialCollectionCellsAccessibilityDeselectedHint" = "Double tap to select.";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
new file mode 100644
index 0000000..9a0e565
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewCell.h"
+#import "MDCCollectionViewTextCell.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
new file mode 100644
index 0000000..311c16d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
@@ -0,0 +1,118 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Types of cell ordinal positions available within a collectionView. */
+typedef NS_OPTIONS(NSUInteger, MDCCollectionViewOrdinalPosition) {
+  /** Cell visually has top edge within section. */
+  MDCCollectionViewOrdinalPositionVerticalTop = 1 << 0,
+
+  /** Cell visually has no top/bottom edges within section. */
+  MDCCollectionViewOrdinalPositionVerticalCenter = 1 << 1,
+
+  /** Cell visually has bottom edge within section. */
+  MDCCollectionViewOrdinalPositionVerticalBottom = 1 << 2,
+
+  /**
+   Cell visually has both bottom/top edges within section. Typically for a single or inlaid cell.
+   */
+  MDCCollectionViewOrdinalPositionVerticalTopBottom =
+      (MDCCollectionViewOrdinalPositionVerticalTop |
+       MDCCollectionViewOrdinalPositionVerticalBottom),
+
+  /** Cell visually has left edge within section. */
+  MDCCollectionViewOrdinalPositionHorizontalLeft = 1 << 10,
+
+  /** Cell visually has no left/right edges within section. */
+  MDCCollectionViewOrdinalPositionHorizontalCenter = 1 << 11,
+
+  /** Cell visually has right edge within section. */
+  MDCCollectionViewOrdinalPositionHorizontalRight = 1 << 12
+};
+
+/**
+ The MDCCollectionViewLayoutAttributes class allows passing layout attributes to the cells and
+ supplementary views.
+ */
+@interface MDCCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes <NSCopying>
+
+#pragma mark - Cell Styling
+
+/** A boolean value indicating whether the collectionView is being edited. Defaults to NO. */
+@property(nonatomic, getter=isEditing) BOOL editing;
+
+/**
+ A boolean value indicating whether the collectionView cell should be displayed with reorder
+ state mask. Defaults to NO.
+ */
+@property(nonatomic, assign) BOOL shouldShowReorderStateMask;
+
+/**
+ A boolean value indicating whether the collectionView cell should be displayed with selector
+ state mask. Defaults to NO.
+ */
+@property(nonatomic, assign) BOOL shouldShowSelectorStateMask;
+
+/**
+ A Boolean value indicating whether the collection view cell should allow the grid background
+ decoration view to be drawn at the specified index.
+ */
+@property(nonatomic, assign) BOOL shouldShowGridBackground;
+
+/** The image for use as the cells background image. */
+@property(nonatomic, strong, nullable) UIImage *backgroundImage;
+
+/** The background image view edge insets. */
+@property(nonatomic) UIEdgeInsets backgroundImageViewInsets;
+
+/**
+ A boolean value indicating whether the collectionView cell style is set to
+ MDCCollectionViewCellLayoutTypeGrid.
+ */
+@property(nonatomic, assign) BOOL isGridLayout;
+
+/** The ordinal position within the collectionView section. */
+@property(nonatomic, assign) MDCCollectionViewOrdinalPosition sectionOrdinalPosition;
+
+#pragma mark - Cell Separator
+
+/** Separator color. Defaults to #E0E0E0. */
+@property(nonatomic, strong, nullable) UIColor *separatorColor;
+
+/** Separator inset. Defaults to UIEdgeInsetsZero. */
+@property(nonatomic) UIEdgeInsets separatorInset;
+
+/** Separator line height. Defaults to 1.0f */
+@property(nonatomic) CGFloat separatorLineHeight;
+
+/** Whether to hide the cell separators. Defaults to NO. */
+@property(nonatomic) BOOL shouldHideSeparators;
+
+#pragma mark - Cell Appearance Animation
+
+/** Whether cells will animation on appearance. */
+@property(nonatomic, assign) BOOL willAnimateCellsOnAppearance;
+
+/**
+ The cell appearance animation duration. Defaults to MDCCollectionViewAnimatedAppearanceDuration.
+ */
+@property(nonatomic, assign) NSTimeInterval animateCellsOnAppearanceDuration;
+
+/** The cell delay used to stagger fade-in during appearance animation. Defaults to 0. */
+@property(nonatomic, assign) NSTimeInterval animateCellsOnAppearanceDelay;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m
new file mode 100644
index 0000000..bdb1d94
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m
@@ -0,0 +1,93 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewLayoutAttributes.h"
+
+@implementation MDCCollectionViewLayoutAttributes
+
+- (id)copyWithZone:(NSZone *)zone {
+  MDCCollectionViewLayoutAttributes *attributes =
+      (MDCCollectionViewLayoutAttributes *)[super copyWithZone:zone];
+  attributes->_editing = _editing;
+  attributes->_shouldShowReorderStateMask = _shouldShowReorderStateMask;
+  attributes->_shouldShowSelectorStateMask = _shouldShowSelectorStateMask;
+  attributes->_shouldShowGridBackground = _shouldShowGridBackground;
+  attributes->_sectionOrdinalPosition = _sectionOrdinalPosition;
+  attributes->_backgroundImage = _backgroundImage;
+  attributes->_backgroundImageViewInsets = _backgroundImageViewInsets;
+  attributes->_isGridLayout = _isGridLayout;
+  attributes->_separatorColor = _separatorColor;
+  attributes->_separatorInset = _separatorInset;
+  attributes->_separatorLineHeight = _separatorLineHeight;
+  attributes->_shouldHideSeparators = _shouldHideSeparators;
+  attributes->_willAnimateCellsOnAppearance = _willAnimateCellsOnAppearance;
+  attributes->_animateCellsOnAppearanceDuration = _animateCellsOnAppearanceDuration;
+  attributes->_animateCellsOnAppearanceDelay = _animateCellsOnAppearanceDelay;
+  return attributes;
+}
+
+- (BOOL)isEqual:(id)object {
+  if (object == self) {
+    return YES;
+  }
+  if (!object || ![[object class] isEqual:[self class]]) {
+    return NO;
+  }
+
+  // Compare custom properties that affect layout.
+  MDCCollectionViewLayoutAttributes *otherAttrs = (MDCCollectionViewLayoutAttributes *)object;
+  BOOL backgroundImageIdentity = NO;
+  if (self.backgroundImage && otherAttrs.backgroundImage) {
+    backgroundImageIdentity = [self.backgroundImage isEqual:otherAttrs.backgroundImage];
+  } else if (!self.backgroundImage && !otherAttrs.backgroundImage) {
+    backgroundImageIdentity = YES;
+  }
+
+  BOOL separatorColorIdentity = NO;
+  if (self.separatorColor && otherAttrs.separatorColor) {
+    separatorColorIdentity = [self.separatorColor isEqual:otherAttrs.separatorColor];
+  } else if (!self.separatorColor && !otherAttrs.separatorColor) {
+    separatorColorIdentity = YES;
+  }
+
+  if ((otherAttrs.editing != self.editing) ||
+      (otherAttrs.shouldShowReorderStateMask != self.shouldShowReorderStateMask) ||
+      (otherAttrs.shouldShowSelectorStateMask != self.shouldShowSelectorStateMask) ||
+      (otherAttrs.shouldShowGridBackground != self.shouldShowGridBackground) ||
+      (otherAttrs.sectionOrdinalPosition != self.sectionOrdinalPosition) ||
+      !backgroundImageIdentity ||
+      (!UIEdgeInsetsEqualToEdgeInsets(otherAttrs.backgroundImageViewInsets,
+                                      self.backgroundImageViewInsets)) ||
+      (otherAttrs.isGridLayout != self.isGridLayout) || !separatorColorIdentity ||
+      (!UIEdgeInsetsEqualToEdgeInsets(otherAttrs.separatorInset, self.separatorInset)) ||
+      (otherAttrs.separatorLineHeight != self.separatorLineHeight) ||
+      (otherAttrs.shouldHideSeparators != self.shouldHideSeparators) ||
+      (!CGRectEqualToRect(otherAttrs.frame, self.frame))) {
+    return NO;
+  }
+
+  return [super isEqual:object];
+}
+
+- (NSUInteger)hash {
+  return (NSUInteger)self.editing ^ (NSUInteger)self.shouldShowReorderStateMask ^
+         (NSUInteger)self.shouldShowSelectorStateMask ^ (NSUInteger)self.shouldShowGridBackground ^
+         (NSUInteger)self.sectionOrdinalPosition ^ (NSUInteger)self.backgroundImage ^
+         (NSUInteger)self.isGridLayout ^ (NSUInteger)self.separatorColor ^
+         (NSUInteger)self.separatorLineHeight ^ (NSUInteger)self.shouldHideSeparators;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
new file mode 100644
index 0000000..a423edb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewLayoutAttributes.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.h
new file mode 100644
index 0000000..d61c50b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.h
@@ -0,0 +1,77 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCCollectionViewEditing.h"
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MDCCollectionViewStyling.h"
+#import "MDCCollectionViewStylingDelegate.h"
+
+/**
+ Controller that implements a collection view that adheres to Material Design layout
+ and animation styling.
+ */
+@interface MDCCollectionViewController : UICollectionViewController <
+                                             /** Allows for editing notifications/permissions. */
+                                             MDCCollectionViewEditingDelegate,
+
+                                             /** Allows for styling updates. */
+                                             MDCCollectionViewStylingDelegate,
+
+                                             /** Adheres to flow layout. */
+                                             UICollectionViewDelegateFlowLayout>
+
+/** The collection view styler. */
+@property(nonatomic, strong, readonly, nonnull) id<MDCCollectionViewStyling> styler;
+
+/** The collection view editor. */
+@property(nonatomic, strong, readonly, nonnull) id<MDCCollectionViewEditing> editor;
+
+#pragma mark - Subclassing
+
+/**
+ The following methods require a call to super in their overriding implementations to allow
+ this collection view controller to properly configure the collection view when in editing mode
+ as well as ink during the highlight/unhighlight states.
+ */
+
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didHighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didUnhighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldDeselectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didDeselectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionViewWillBeginEditing:(nonnull UICollectionView *)collectionView NS_REQUIRES_SUPER;
+
+- (void)collectionViewWillEndEditing:(nonnull UICollectionView *)collectionView NS_REQUIRES_SUPER;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.m
new file mode 100644
index 0000000..76e5585
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.m
@@ -0,0 +1,601 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewController.h"
+
+#import "MDCCollectionViewFlowLayout.h"
+#import "MaterialCollectionCells.h"
+#import "MaterialInk.h"
+#import "private/MDCCollectionInfoBarView.h"
+#import "private/MDCCollectionStringResources.h"
+#import "private/MDCCollectionViewEditor.h"
+#import "private/MDCCollectionViewStyler.h"
+
+#import <tgmath.h>
+
+@interface MDCCollectionViewController () <MDCCollectionInfoBarViewDelegate,
+                                           MDCInkTouchControllerDelegate>
+@property(nonatomic, assign) BOOL currentlyActiveInk;
+@end
+
+@implementation MDCCollectionViewController {
+  MDCInkTouchController *_inkTouchController;
+  MDCCollectionInfoBarView *_headerInfoBar;
+  MDCCollectionInfoBarView *_footerInfoBar;
+  BOOL _headerInfoBarDismissed;
+  CGPoint _inkTouchLocation;
+}
+
+@synthesize collectionViewLayout = _collectionViewLayout;
+
+- (instancetype)init {
+  return [self initWithCollectionViewLayout:self.collectionViewLayout];
+}
+
+- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout {
+  self = [super initWithCollectionViewLayout:layout];
+  if (self) {
+    _collectionViewLayout = layout;
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  [self.collectionView setCollectionViewLayout:self.collectionViewLayout];
+  self.collectionView.backgroundColor = [UIColor whiteColor];
+  self.collectionView.alwaysBounceVertical = YES;
+
+  _styler = [[MDCCollectionViewStyler alloc] initWithCollectionView:self.collectionView];
+  _styler.delegate = self;
+
+  _editor = [[MDCCollectionViewEditor alloc] initWithCollectionView:self.collectionView];
+  _editor.delegate = self;
+
+  // Set up ink touch controller.
+  _inkTouchController = [[MDCInkTouchController alloc] initWithView:self.collectionView];
+  _inkTouchController.delegate = self;
+}
+
+- (UICollectionViewLayout *)collectionViewLayout {
+  if (!_collectionViewLayout) {
+    _collectionViewLayout = [[MDCCollectionViewFlowLayout alloc] init];
+  }
+  return _collectionViewLayout;
+}
+
+- (void)setCollectionView:(__kindof UICollectionView *)collectionView {
+  [super setCollectionView:collectionView];
+
+  // Reset editor and ink to provided collection view.
+  _editor = [[MDCCollectionViewEditor alloc] initWithCollectionView:collectionView];
+  _editor.delegate = self;
+  _inkTouchController = [[MDCInkTouchController alloc] initWithView:collectionView];
+  _inkTouchController.delegate = self;
+}
+
+#pragma mark - <MDCCollectionInfoBarViewDelegate>
+
+- (void)updateControllerWithInfoBar:(MDCCollectionInfoBarView *)infoBar {
+  // Updates info bar styling for header/footer.
+  if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+    _headerInfoBar = infoBar;
+    _headerInfoBar.message = MDCCollectionStringResources(infoBarGestureHintString);
+    _headerInfoBar.style = MDCCollectionInfoBarViewStyleHUD;
+    [self updateHeaderInfoBarIfNecessary];
+  } else if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+    _footerInfoBar = infoBar;
+    _footerInfoBar.message = MDCCollectionStringResources(deleteButtonString);
+    _footerInfoBar.style = MDCCollectionInfoBarViewStyleActionable;
+    [self updateFooterInfoBarIfNecessary];
+  }
+}
+
+- (void)didTapInfoBar:(MDCCollectionInfoBarView *)infoBar {
+  if ([infoBar isEqual:_footerInfoBar]) {
+    [self deleteIndexPaths:self.collectionView.indexPathsForSelectedItems];
+  }
+}
+
+- (void)infoBar:(MDCCollectionInfoBarView *)infoBar
+    willShowAnimated:(BOOL)animated
+     willAutoDismiss:(BOOL)willAutoDismiss {
+  if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+    [self updateContentWithBottomInset:MDCCollectionInfoBarFooterHeight];
+  }
+}
+
+- (void)infoBar:(MDCCollectionInfoBarView *)infoBar
+    willDismissAnimated:(BOOL)animated
+        willAutoDismiss:(BOOL)willAutoDismiss {
+  if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+    _headerInfoBarDismissed = willAutoDismiss;
+  } else {
+    [self updateContentWithBottomInset:-MDCCollectionInfoBarFooterHeight];
+  }
+}
+
+#pragma mark - <MDCCollectionViewStylingDelegate>
+
+- (MDCCollectionViewCellStyle)collectionView:(UICollectionView *)collectionView
+                         cellStyleForSection:(NSInteger)section {
+  return _styler.cellStyle;
+}
+
+#pragma mark - <UICollectionViewDelegateFlowLayout>
+
+- (CGSize)collectionView:(UICollectionView *)collectionView
+                    layout:(UICollectionViewLayout *)collectionViewLayout
+    sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
+  CGSize size = [self sizeWithAttribute:attr];
+  size = [self inlaidSizeAtIndexPath:indexPath withSize:size];
+  return size;
+}
+
+- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
+                        layout:(UICollectionViewLayout *)collectionViewLayout
+        insetForSectionAtIndex:(NSInteger)section {
+  return [self insetsAtSectionIndex:section];
+}
+
+- (CGFloat)collectionView:(UICollectionView *)collectionView
+                                 layout:(UICollectionViewLayout *)collectionViewLayout
+    minimumLineSpacingForSectionAtIndex:(NSInteger)section {
+  if ([collectionViewLayout isKindOfClass:[UICollectionViewFlowLayout class]]) {
+    if (_styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+      return _styler.gridPadding;
+    }
+    return [(UICollectionViewFlowLayout *)collectionViewLayout minimumLineSpacing];
+  }
+  return 0;
+}
+
+- (CGSize)sizeWithAttribute:(UICollectionViewLayoutAttributes *)attr {
+  CGFloat height = MDCCellDefaultOneLineHeight;
+  if ([_styler.delegate respondsToSelector:@selector(collectionView:cellHeightAtIndexPath:)]) {
+    height =
+        [_styler.delegate collectionView:self.collectionView cellHeightAtIndexPath:attr.indexPath];
+  }
+
+  CGFloat width = [self cellWidthAtSectionIndex:attr.indexPath.section];
+  return CGSizeMake(width, height);
+}
+
+- (CGFloat)cellWidthAtSectionIndex:(NSInteger)section {
+  CGFloat bounds = CGRectGetWidth(
+      UIEdgeInsetsInsetRect(self.collectionView.bounds, self.collectionView.contentInset));
+  UIEdgeInsets sectionInsets = [self insetsAtSectionIndex:section];
+  CGFloat insets = sectionInsets.left + sectionInsets.right;
+  if (_styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    CGFloat cellWidth = bounds - insets - (_styler.gridPadding * (_styler.gridColumnCount - 1));
+    return cellWidth / _styler.gridColumnCount;
+  }
+  return bounds - insets;
+}
+
+- (UIEdgeInsets)insetsAtSectionIndex:(NSInteger)section {
+  // Determine insets based on cell style.
+  CGFloat inset = (CGFloat)floor(MDCCollectionViewCellStyleCardSectionInset);
+  UIEdgeInsets insets = UIEdgeInsetsZero;
+  NSInteger numberOfSections = self.collectionView.numberOfSections;
+  BOOL isTop = (section == 0);
+  BOOL isBottom = (section == numberOfSections - 1);
+  MDCCollectionViewCellStyle cellStyle = [_styler cellStyleAtSectionIndex:section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  // Set left/right insets.
+  if (isCardStyle) {
+    insets.left = inset;
+    insets.right = inset;
+  }
+  // Set top/bottom insets.
+  if (isCardStyle || isGroupedStyle) {
+    insets.top = (CGFloat)floor((isTop) ? inset : inset / 2.0f);
+    insets.bottom = (CGFloat)floor((isBottom) ? inset : inset / 2.0f);
+  }
+  return insets;
+}
+
+- (CGSize)inlaidSizeAtIndexPath:(NSIndexPath *)indexPath withSize:(CGSize)size {
+  // If object is inlaid, return its adjusted size.
+  UICollectionView *collectionView = self.collectionView;
+  if ([_styler isItemInlaidAtIndexPath:indexPath]) {
+    CGFloat inset = MDCCollectionViewCellStyleCardSectionInset;
+    UIEdgeInsets inlayInsets = UIEdgeInsetsZero;
+    BOOL prevCellIsInlaid = NO;
+    BOOL nextCellIsInlaid = NO;
+
+    BOOL hasSectionHeader = NO;
+    if ([self
+            respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)]) {
+      CGSize headerSize = [self collectionView:collectionView
+                                        layout:_collectionViewLayout
+               referenceSizeForHeaderInSection:indexPath.section];
+      hasSectionHeader = !CGSizeEqualToSize(headerSize, CGSizeZero);
+    }
+
+    BOOL hasSectionFooter = NO;
+    if ([self
+            respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)]) {
+      CGSize footerSize = [self collectionView:collectionView
+                                        layout:_collectionViewLayout
+               referenceSizeForFooterInSection:indexPath.section];
+      hasSectionFooter = !CGSizeEqualToSize(footerSize, CGSizeZero);
+    }
+
+    // Check if previous cell is inlaid.
+    if (indexPath.item > 0 || hasSectionHeader) {
+      NSIndexPath *prevIndexPath =
+          [NSIndexPath indexPathForItem:(indexPath.item - 1) inSection:indexPath.section];
+      prevCellIsInlaid = [_styler isItemInlaidAtIndexPath:prevIndexPath];
+      inlayInsets.top = prevCellIsInlaid ? inset / 2 : inset;
+    }
+
+    // Check if next cell is inlaid.
+    if (indexPath.item < [collectionView numberOfItemsInSection:indexPath.section] - 1 ||
+        hasSectionFooter) {
+      NSIndexPath *nextIndexPath =
+          [NSIndexPath indexPathForItem:(indexPath.item + 1) inSection:indexPath.section];
+      nextCellIsInlaid = [_styler isItemInlaidAtIndexPath:nextIndexPath];
+      inlayInsets.bottom = nextCellIsInlaid ? inset / 2 : inset;
+    }
+
+    // Apply top/bottom height adjustments to inlaid object.
+    size.height += inlayInsets.top + inlayInsets.bottom;
+  }
+  return size;
+}
+
+#pragma mark - <MDCInkTouchControllerDelegate>
+
+- (BOOL)inkTouchController:(MDCInkTouchController *)inkTouchController
+    shouldProcessInkTouchesAtTouchLocation:(CGPoint)location {
+  // Only store touch location and do not allow ink processing. This ink location will be used when
+  // manually starting/stopping the ink animation during cell highlight/unhighlight states.
+  if (!self.currentlyActiveInk) {
+    _inkTouchLocation = location;
+  }
+  return NO;
+}
+
+- (MDCInkView *)inkTouchController:(MDCInkTouchController *)inkTouchController
+            inkViewAtTouchLocation:(CGPoint)location {
+  NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:location];
+  UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
+  MDCInkView *ink = nil;
+
+  if ([_styler.delegate
+          respondsToSelector:@selector(collectionView:inkTouchController:inkViewAtIndexPath:)]) {
+    return [_styler.delegate collectionView:self.collectionView
+                         inkTouchController:inkTouchController
+                         inkViewAtIndexPath:indexPath];
+  }
+  if ([cell isKindOfClass:[MDCCollectionViewCell class]]) {
+    MDCCollectionViewCell *inkCell = (MDCCollectionViewCell *)cell;
+    if ([inkCell respondsToSelector:@selector(inkView)]) {
+      // Set cell ink.
+      ink = [cell performSelector:@selector(inkView)];
+    }
+  }
+
+  return ink;
+}
+
+#pragma mark - <UICollectionViewDataSource>
+
+- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
+           viewForSupplementaryElementOfKind:(NSString *)kind
+                                 atIndexPath:(NSIndexPath *)indexPath {
+  // TODO (shepj): This implementation of registering cell classes in data source methods should be
+  // rethought. This causes a crash without a workaround when collections with headers or
+  // footers entering editing mode. Also, we should find a way around implementing a data source
+  // method in a super class.
+  // Issue: https://github.com/material-components/material-components-ios/issues/1208
+  // Editing info bar.
+  if ([kind isEqualToString:MDCCollectionInfoBarKindHeader] ||
+      [kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+    NSString *identifier = NSStringFromClass([MDCCollectionInfoBarView class]);
+    identifier = [identifier stringByAppendingFormat:@".%@", kind];
+    [collectionView registerClass:[MDCCollectionInfoBarView class]
+        forSupplementaryViewOfKind:kind
+               withReuseIdentifier:identifier];
+
+    UICollectionReusableView *supplementaryView =
+        [collectionView dequeueReusableSupplementaryViewOfKind:kind
+                                           withReuseIdentifier:identifier
+                                                  forIndexPath:indexPath];
+
+    // Update info bar.
+    if ([supplementaryView isKindOfClass:[MDCCollectionInfoBarView class]]) {
+      MDCCollectionInfoBarView *infoBar = (MDCCollectionInfoBarView *)supplementaryView;
+      infoBar.delegate = self;
+      infoBar.kind = kind;
+      [self updateControllerWithInfoBar:infoBar];
+    }
+    return supplementaryView;
+  }
+  return nil;
+}
+
+#pragma mark - <UICollectionViewDelegate>
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
+  if ([_styler.delegate respondsToSelector:@selector(collectionView:hidesInkViewAtIndexPath:)]) {
+    return ![_styler.delegate collectionView:collectionView hidesInkViewAtIndexPath:indexPath];
+  }
+  return YES;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
+  CGPoint location = [collectionView convertPoint:_inkTouchLocation toView:cell];
+
+  // Start cell ink show animation.
+  MDCInkView *inkView;
+  if ([cell respondsToSelector:@selector(inkView)]) {
+    inkView = [cell performSelector:@selector(inkView)];
+  } else {
+    return;
+  }
+
+  // Update ink color if necessary.
+  if ([_styler.delegate respondsToSelector:@selector(collectionView:inkColorAtIndexPath:)]) {
+    inkView.inkColor =
+        [_styler.delegate collectionView:collectionView inkColorAtIndexPath:indexPath];
+    if (!inkView.inkColor) {
+      inkView.inkColor = inkView.defaultInkColor;
+    }
+  }
+  self.currentlyActiveInk = YES;
+  [inkView startTouchBeganAnimationAtPoint:location completion:nil];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
+  CGPoint location = [collectionView convertPoint:_inkTouchLocation toView:cell];
+
+  // Start cell ink evaporate animation.
+  MDCInkView *inkView;
+  if ([cell respondsToSelector:@selector(inkView)]) {
+    inkView = [cell performSelector:@selector(inkView)];
+  } else {
+    return;
+  }
+
+  self.currentlyActiveInk = NO;
+  [inkView startTouchEndedAnimationAtPoint:location completion:nil];
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  if (_editor.isEditing) {
+    if ([self collectionView:collectionView canEditItemAtIndexPath:indexPath]) {
+      return [self collectionView:collectionView canSelectItemDuringEditingAtIndexPath:indexPath];
+    }
+    return NO;
+  }
+  return YES;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
+  return collectionView.allowsMultipleSelection;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [self updateFooterInfoBarIfNecessary];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [self updateFooterInfoBarIfNecessary];
+}
+
+#pragma mark - <MDCCollectionViewEditingDelegate>
+
+- (BOOL)collectionViewAllowsEditing:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (void)collectionViewWillBeginEditing:(UICollectionView *)collectionView {
+  if (self.currentlyActiveInk) {
+    MDCInkView *activeInkView =
+        [self inkTouchController:_inkTouchController inkViewAtTouchLocation:_inkTouchLocation];
+    [activeInkView startTouchEndedAnimationAtPoint:_inkTouchLocation completion:nil];
+  }
+  // Inlay all items.
+  _styler.allowsItemInlay = YES;
+  _styler.allowsMultipleItemInlays = YES;
+  [_styler applyInlayToAllItemsAnimated:YES];
+  [self updateHeaderInfoBarIfNecessary];
+}
+
+- (void)collectionViewWillEndEditing:(UICollectionView *)collectionView {
+  // Remove inlay of all items.
+  [_styler removeInlayFromAllItemsAnimated:YES];
+  [self updateFooterInfoBarIfNecessary];
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canEditItemAtIndexPath:(NSIndexPath *)indexPath {
+  return [self collectionViewAllowsEditing:collectionView];
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canSelectItemDuringEditingAtIndexPath:(NSIndexPath *)indexPath {
+  if ([self collectionViewAllowsEditing:collectionView]) {
+    return [self collectionView:collectionView canEditItemAtIndexPath:indexPath];
+  }
+  return NO;
+}
+
+#pragma mark - Item Moving
+
+- (BOOL)collectionViewAllowsReordering:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(NSIndexPath *)indexPath {
+  return ([self collectionViewAllowsEditing:collectionView] &&
+          [self collectionViewAllowsReordering:collectionView]);
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(NSIndexPath *)indexPath
+               toIndexPath:(NSIndexPath *)newIndexPath {
+  // First ensure both source and target items can be moved.
+  return ([self collectionView:collectionView canMoveItemAtIndexPath:indexPath] &&
+          [self collectionView:collectionView canMoveItemAtIndexPath:newIndexPath]);
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didMoveItemAtIndexPath:(NSIndexPath *)indexPath
+               toIndexPath:(NSIndexPath *)newIndexPath {
+  [collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
+}
+
+#pragma mark - Swipe-To-Dismiss-Items
+
+- (BOOL)collectionViewAllowsSwipeToDismissItem:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canSwipeToDismissItemAtIndexPath:(NSIndexPath *)indexPath {
+  return [self collectionViewAllowsSwipeToDismissItem:collectionView];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didEndSwipeToDismissItemAtIndexPath:(NSIndexPath *)indexPath {
+  [self deleteIndexPaths:@[ indexPath ]];
+}
+
+#pragma mark - Swipe-To-Dismiss-Sections
+
+- (BOOL)collectionViewAllowsSwipeToDismissSection:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canSwipeToDismissSection:(NSInteger)section {
+  return [self collectionViewAllowsSwipeToDismissSection:collectionView];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didEndSwipeToDismissSection:(NSInteger)section {
+  [self deleteSections:[NSIndexSet indexSetWithIndex:section]];
+}
+
+#pragma mark - Private
+
+- (void)deleteIndexPaths:(NSArray<NSIndexPath *> *)indexPaths {
+  if ([self respondsToSelector:@selector(collectionView:willDeleteItemsAtIndexPaths:)]) {
+    void (^batchUpdates)() = ^{
+      // Notify delegate to delete data.
+      [self collectionView:self.collectionView willDeleteItemsAtIndexPaths:indexPaths];
+
+      // Delete index paths.
+      [self.collectionView deleteItemsAtIndexPaths:indexPaths];
+    };
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      [self updateFooterInfoBarIfNecessary];
+      // Notify delegate of deletion.
+      if ([self respondsToSelector:@selector(collectionView:didDeleteItemsAtIndexPaths:)]) {
+        [self collectionView:self.collectionView didDeleteItemsAtIndexPaths:indexPaths];
+      }
+    };
+
+    // Animate deletion.
+    [self.collectionView performBatchUpdates:batchUpdates completion:completionBlock];
+  }
+}
+
+- (void)deleteSections:(NSIndexSet *)sections {
+  if ([self respondsToSelector:@selector(collectionView:willDeleteSections:)]) {
+    void (^batchUpdates)() = ^{
+      // Notify delegate to delete data.
+      [self collectionView:self.collectionView willDeleteSections:sections];
+
+      // Delete sections.
+      [self.collectionView deleteSections:sections];
+    };
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      [self updateFooterInfoBarIfNecessary];
+      // Notify delegate of deletion.
+      if ([self respondsToSelector:@selector(collectionView:didDeleteSections:)]) {
+        [self collectionView:self.collectionView didDeleteSections:sections];
+      }
+    };
+
+    // Animate deletion.
+    [self.collectionView performBatchUpdates:batchUpdates completion:completionBlock];
+  }
+}
+
+- (void)updateHeaderInfoBarIfNecessary {
+  if (_editor.isEditing) {
+    // Show HUD only once before autodissmissing.
+    BOOL allowsSwipeToDismissItem = NO;
+    if ([self respondsToSelector:@selector(collectionViewAllowsSwipeToDismissItem:)]) {
+      allowsSwipeToDismissItem = [self collectionViewAllowsSwipeToDismissItem:self.collectionView];
+    }
+
+    if (!_headerInfoBar.isVisible && !_headerInfoBarDismissed && allowsSwipeToDismissItem) {
+      [_headerInfoBar showAnimated:YES];
+    } else {
+      [_headerInfoBar dismissAnimated:YES];
+    }
+  }
+}
+
+- (void)updateFooterInfoBarIfNecessary {
+  NSInteger selectedItemCount = [self.collectionView.indexPathsForSelectedItems count];
+  if (_editor.isEditing) {
+    // Invalidate layout to add info bar if necessary.
+    [self.collectionView.collectionViewLayout invalidateLayout];
+    if (_footerInfoBar) {
+      if (selectedItemCount > 0 && !_footerInfoBar.isVisible) {
+        [_footerInfoBar showAnimated:YES];
+      } else if (selectedItemCount == 0 && _footerInfoBar.isVisible) {
+        [_footerInfoBar dismissAnimated:YES];
+      }
+    }
+  } else if (selectedItemCount == 0 && _footerInfoBar.isVisible) {
+    [_footerInfoBar dismissAnimated:YES];
+  }
+}
+
+- (void)updateContentWithBottomInset:(CGFloat)inset {
+  // Update bottom inset to account for footer info bar.
+  UIEdgeInsets contentInset = self.collectionView.contentInset;
+  contentInset.bottom += inset;
+  [UIView animateWithDuration:MDCCollectionInfoBarAnimationDuration
+                   animations:^{
+                     self.collectionView.contentInset = contentInset;
+                   }];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
new file mode 100644
index 0000000..de25f58
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
@@ -0,0 +1,60 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCCollectionViewEditingDelegate;
+
+/** The MDCCollectionViewEditing protocol defines the editing state for a UICollectionView. */
+@protocol MDCCollectionViewEditing <NSObject>
+
+/** The associated collection view. */
+@property(nonatomic, readonly, weak, nullable) UICollectionView *collectionView;
+
+/** The delegate will be informed of editing state changes. */
+@property(nonatomic, weak, nullable) id<MDCCollectionViewEditingDelegate> delegate;
+
+/** The index path of the cell being moved or reordered, if any. */
+@property(nonatomic, readonly, strong, nullable) NSIndexPath *reorderingCellIndexPath;
+
+/** The index path of the cell being dragged for dismissal, if any. */
+@property(nonatomic, readonly, strong, nullable) NSIndexPath *dismissingCellIndexPath;
+
+/** The index of the section being dragged for dismissal, or NSNotFound if none. */
+@property(nonatomic, readonly, assign) NSInteger dismissingSection;
+
+/**
+ A Boolean value indicating whether the a visible cell within the collectionView is being
+ edited.
+
+ When set, all rows show or hide editing controls without animation. To animate the state change see
+ @c setEditing:animated:. Setting the editing state of this class does not propagate to the parent
+ view controller's editing state.
+ */
+@property(nonatomic, getter=isEditing) BOOL editing;
+
+/**
+ Set the editing state with optional animations.
+
+ When set, row shows or hides editing controls with/without animation. Setting the editing
+ state of this class does not propagate to the parent view controller's editing state.
+
+ @param editing YES if editing; otherwise, NO.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
new file mode 100644
index 0000000..b28683d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
@@ -0,0 +1,329 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ A delegate protocol that provides editing notifications for three types of collection view
+ gestural interations:
+
+  - Cells that are dragging/moved vertically for reordering.
+  - Individual cells being swiped horizontally for dismissal.
+  - Entire cell sections being swiped horizontally for dismissal.
+ */
+@protocol MDCCollectionViewEditingDelegate <NSObject>
+
+@optional
+
+#pragma mark - CollectionView Item Editing
+
+/**
+ If YES, the collectionView will allow editing of its items. Permissions for individual
+ index paths are set by implementing the delegate -collectionView:canEditItemAtIndexPath method.
+ If not implemented, will default to NO.
+ */
+- (BOOL)collectionViewAllowsEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view will begin editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to YES.
+ This will be called before any animations to editing state will begin.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewWillBeginEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view did begin editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to YES.
+ This is called after animations to editing state have completed.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewDidBeginEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view will end editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to NO.
+ This will be called before any animations from editing state begin.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewWillEndEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view did end editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to NO.
+ This is called after animations from editing state have completed.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewDidEndEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver for permission to edit an item at this collection view index path.
+ Returning NO here will prevent editing the designated index path. If not implemented, will
+ default to NO.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ @return if the collection view index path can be edited.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canEditItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver for permission to select an item at this collection view index path
+ during collection view editing. Returning NO here will prevent selecting the designated
+ index path. If not implemented, will default to NO.
+
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ @return if the collection view index path can be selected.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canSelectItemDuringEditingAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+#pragma mark - CollectionView Item Moving
+
+/**
+ If YES, the collectionView will allow reordering of its items. Permissions for individual
+ index paths are be set by the -collectionView:canMoveItemAtIndexPath and/or the
+ -collectionView:canMoveItemAtIndexPath:toIndexPath methods. If not implemented, will default
+ to NO.
+
+ */
+- (BOOL)collectionViewAllowsReordering:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver for permission to move an item at this collection view index path.
+ Returning NO here will prevent moving the designated index path. If not implemented, will
+ default to NO.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ @return if the collection view index path can be moved.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver for permission to move an item at this collection view index path to
+ a new index path. Returning NO here will prevent moving the designated index path. If not
+ implemented, will default to NO.
+
+ @param collectionView The collection view.
+ @param indexPath The current index path of the collection view.
+ @param newIndexPath The propsed new index path of the collection view.
+ @return if the collection view index path can be moved.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath
+               toIndexPath:(nonnull NSIndexPath *)newIndexPath;
+
+/**
+ Sent to the receiver when the collection view will move an item from its previous index path
+ to the new index path.
+
+ @param collectionView The collection view.
+ @param indexPath The previous index path of the collection view.
+ @param newIndexPath The new index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath
+                toIndexPath:(nonnull NSIndexPath *)newIndexPath;
+
+/**
+ Sent to the receiver when the collection view did move an item from its previous index path
+ to the new index path.
+
+ @param collectionView The collection view.
+ @param indexPath The previous index path of the collection view.
+ @param newIndexPath The new index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath
+               toIndexPath:(nonnull NSIndexPath *)newIndexPath;
+
+/**
+ Sent to the receiver when a collection view item at specified index path will begin dragging.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willBeginDraggingItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver when a collection view item at specified index path has finished dragging.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didEndDraggingItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+#pragma mark - CollectionView Item Deletions
+
+/**
+ Sent to the receiver when an array of index paths will be deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths to be deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willDeleteItemsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+/**
+ Sent to the receiver after an array of index paths did get deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didDeleteItemsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+#pragma mark - CollectionView Section Deletions
+
+/**
+ Sent to the receiver when an array of index paths will be deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param sections An index set of sections to deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willDeleteSections:(nonnull NSIndexSet *)sections;
+
+/**
+ Sent to the receiver after an array of index paths did get deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param sections An index set of sections deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+     didDeleteSections:(nonnull NSIndexSet *)sections;
+
+#pragma mark - CollectionView Swipe To Dismiss Items
+
+/**
+ If YES, the collectionView will allow swiping to dismiss an item. If allowed, swiping is enabled
+ for all items (excluding headers, and footers). Permissions for individual items can be set by
+ implementing the protocol -collectionView:canSwipeToDismissItemAtIndexPath method. If not
+ implemented, will default to NO.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @return if the collection view can swipe to dismiss an item.
+ */
+- (BOOL)collectionViewAllowsSwipeToDismissItem:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when a collection view index path begins to swipe for dismissal. The
+ delegate method -collectionViewAllowsSwipeToDismissItem must return true in order for this
+ subsequent delegate method to be called. The collection view is NOT required to be in
+ edit mode to allow swipe-to-dismiss items. Returning NO here will prevent swiping the
+ designated item at index path. If not implemented, will default to NO.
+
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ @return if the collection view index path can be swiped for dismissal.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver when the collection view index path begins to swipe for dismissal.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willBeginSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver after the collection view item has been dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didEndSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver when the collection view index path has reset without being dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didCancelSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+#pragma mark - CollectionView Swipe To Dismiss Sections
+
+/**
+ If YES, the collectionView will allow swiping to dismiss a section. If allowed, swiping is enabled
+ for all section items, headers, and footers. Permissions for individual sections can be
+ set by implementing the protocol -collectionView:canSwipeToDismissSection method. If not
+ implemented, will default to NO.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @return if the collection view can swipe to dismiss a section.
+ */
+- (BOOL)collectionViewAllowsSwipeToDismissSection:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when a collection view section begins to swipe for dismissal. The
+ collection view property @c allowsSwipeToDismissSection must be true in order for this
+ subsequent delegate method to be called. The collection view is NOT required to be in
+ edit mode to allow swipe-to-dismiss sections. Returning NO here will prevent swiping the
+ designated section. If not implemented, will default to NO.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ @return if the collection view section can be swiped for dismissal.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canSwipeToDismissSection:(NSInteger)section;
+
+/**
+ Sent to the receiver when the collection view section begins to swipe for dismissal.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willBeginSwipeToDismissSection:(NSInteger)section;
+
+/**
+ Sent to the receiver after the collection view section has been dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didEndSwipeToDismissSection:(NSInteger)section;
+
+/**
+ Sent to the receiver when the collection view section has reset without being dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didCancelSwipeToDismissSection:(NSInteger)section;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
new file mode 100644
index 0000000..fdce1ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The MDCCollectionViewFlowLayout class provides a Material Design layout implementation of a
+ UICollectionViewFlowLayout layout.
+
+ Learn more at the
+ [Material spec](https://www.google.com/design/spec/components/lists.html#lists-specs)
+ */
+@interface MDCCollectionViewFlowLayout : UICollectionViewFlowLayout
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.m
new file mode 100644
index 0000000..9ef9bd5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.m
@@ -0,0 +1,775 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewFlowLayout.h"
+
+#import "MDCCollectionViewController.h"
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MDCCollectionViewStyling.h"
+#import "MaterialCollectionLayoutAttributes.h"
+#import "private/MDCCollectionGridBackgroundView.h"
+#import "private/MDCCollectionInfoBarView.h"
+#import "private/MDCCollectionViewEditor.h"
+
+#import <tgmath.h>
+
+/** The grid background decoration view kind. */
+NSString *const kCollectionDecorationView = @"MDCCollectionDecorationView";
+
+static const NSInteger kSupplementaryViewZIndex = 99;
+
+@implementation MDCCollectionViewFlowLayout {
+  NSMutableArray<NSIndexPath *> *_deletedIndexPaths;
+  NSMutableArray<NSIndexPath *> *_insertedIndexPaths;
+  NSMutableIndexSet *_deletedSections;
+  NSMutableIndexSet *_insertedSections;
+  NSMutableIndexSet *_headerSections;
+  NSMutableIndexSet *_footerSections;
+  NSMutableDictionary *_decorationViewAttributeCache;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    // Defaults.
+    self.minimumLineSpacing = 0;
+    self.minimumInteritemSpacing = 0;
+    self.scrollDirection = UICollectionViewScrollDirectionVertical;
+    self.sectionInset = UIEdgeInsetsZero;
+
+    // Register decoration view for grid background.
+    _decorationViewAttributeCache = [NSMutableDictionary dictionary];
+    [self registerClass:[MDCCollectionGridBackgroundView class]
+        forDecorationViewOfKind:kCollectionDecorationView];
+  }
+  return self;
+}
+
+- (id<MDCCollectionViewEditing>)editor {
+  if ([self.collectionView.delegate isKindOfClass:[MDCCollectionViewController class]]) {
+    MDCCollectionViewController *controller =
+        (MDCCollectionViewController *)self.collectionView.delegate;
+    return controller.editor;
+  }
+  return nil;
+}
+
+- (id<MDCCollectionViewStyling>)styler {
+  if ([self.collectionView.delegate isKindOfClass:[MDCCollectionViewController class]]) {
+    MDCCollectionViewController *controller =
+        (MDCCollectionViewController *)self.collectionView.delegate;
+    return controller.styler;
+  }
+  return nil;
+}
+
+#pragma mark - UICollectionViewLayout (SubclassingHooks)
+
+- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:
+        (CGRect)rect {
+  // If performing appearance animation, increase bounds height in order to retrieve additional
+  // offscreen attributes needed during animation.
+  rect = [self boundsForAppearanceAnimationWithInitialBounds:rect];
+  NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *attributes =
+      [[NSMutableArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect]
+                                  copyItems:YES];
+
+  // Store index path sections of any headers/footers within these attributes.
+  [self storeSupplementaryViewsWithAttributes:attributes];
+
+  // Set layout attributes.
+  for (MDCCollectionViewLayoutAttributes *attr in attributes) {
+    [self updateAttribute:attr];
+  }
+
+  // Add info bar header/footer supplementary view if necessary.
+  [self addInfoBarAttributesIfNecessary:attributes];
+
+  // Begin cell appearance animation if necessary.
+  [self beginCellAppearanceAnimationIfNecessary:attributes];
+
+  // Add a grid background decoration view for each section if necessary.
+  [self addDecorationViewIfNecessary:attributes];
+
+  return attributes;
+}
+
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
+  if (!CGSizeEqualToSize(self.collectionView.bounds.size, newBounds.size) ||
+      self.editor.isEditing) {
+    // Invalidate the layout to force cells to respect the new collection view bounds. Doing here
+    // removes necessity to implement methods -willRotateToInterfaceOrientation:duration: and/or
+    // -viewWillTransitionToSize:withTransitionCoordinator: on the collection view controller.
+    [self invalidateLayout];
+    return YES;
+  }
+  return NO;
+}
+
+- (void)invalidateLayout {
+  [super invalidateLayout];
+
+  // Clear decoration attribute cache.
+  [_decorationViewAttributeCache removeAllObjects];
+}
+
+#pragma mark - UICollectionViewLayout (UISubclassingHooks)
+
++ (Class)layoutAttributesClass {
+  return [MDCCollectionViewLayoutAttributes class];
+}
+
+- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
+  return [self updateAttribute:(MDCCollectionViewLayoutAttributes *)attr];
+}
+
+- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
+                                                                     atIndexPath:
+                                                                         (NSIndexPath *)indexPath {
+  UICollectionViewLayoutAttributes *attr;
+
+  if ([kind isEqualToString:UICollectionElementKindSectionHeader] ||
+      [kind isEqualToString:UICollectionElementKindSectionFooter]) {
+    // Update section headers/Footers attributes.
+    attr = [[super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath] copy];
+    if (!attr) {
+      attr =
+          [MDCCollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:kind
+                                                                          withIndexPath:indexPath];
+    }
+    [self updateAttribute:(MDCCollectionViewLayoutAttributes *)attr];
+
+  } else {
+    // Update editing info bar attributes.
+    attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:kind
+                                                                          withIndexPath:indexPath];
+
+    // Force the info bar supplementary views to stay fixed to their respective positions
+    // at top/bottom of the collectionView bounds.
+    CGFloat offsetY = 0;
+    CGRect currentBounds = self.collectionView.bounds;
+    attr.zIndex = kSupplementaryViewZIndex;
+
+    if ([kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+      attr.size = CGSizeMake(CGRectGetWidth(currentBounds), MDCCollectionInfoBarHeaderHeight);
+      // Allow header to move upwards with scroll, but prevent from moving downwards with scroll.
+      CGFloat insetTop = self.collectionView.contentInset.top;
+      CGFloat boundsY = currentBounds.origin.y;
+      CGFloat maxOffsetY = MAX(boundsY + insetTop, 0);
+      offsetY = boundsY + (attr.size.height / 2) + insetTop - maxOffsetY;
+    } else if ([kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+      attr.size = CGSizeMake(CGRectGetWidth(currentBounds), MDCCollectionInfoBarFooterHeight);
+      offsetY = currentBounds.origin.y + currentBounds.size.height - (attr.size.height / 2);
+    }
+    attr.center = CGPointMake(CGRectGetMidX(currentBounds), offsetY);
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)
+    layoutAttributesForDecorationViewOfKind:(NSString *)elementKind
+                                atIndexPath:(NSIndexPath *)indexPath {
+  // Check cache for decoration view attributes, and add to cache if they don't exist.
+  MDCCollectionViewLayoutAttributes *decorationAttr =
+      [_decorationViewAttributeCache objectForKey:indexPath];
+  if (!decorationAttr) {
+    decorationAttr =
+        [MDCCollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind
+                                                                     withIndexPath:indexPath];
+    [_decorationViewAttributeCache setObject:decorationAttr forKey:indexPath];
+  }
+
+  // Determine section frame by summing all of its item frames.
+  CGRect sectionFrame = CGRectNull;
+  for (NSInteger i = 0; i < [self numberOfItemsInSection:indexPath.section]; ++i) {
+    indexPath = [NSIndexPath indexPathForItem:i inSection:indexPath.section];
+    UICollectionViewLayoutAttributes *attribute =
+        [self layoutAttributesForItemAtIndexPath:indexPath];
+    if (!CGRectIsNull(attribute.frame)) {
+      sectionFrame = CGRectUnion(sectionFrame, attribute.frame);
+    }
+  }
+  decorationAttr.frame = sectionFrame;
+  decorationAttr.zIndex = -1;
+  return decorationAttr;
+}
+
+- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset {
+  // Return current contentOffset to prevent any layout animations from jumping to new offset.
+  return [super targetContentOffsetForProposedContentOffset:self.collectionView.contentOffset];
+}
+
+#pragma mark - UICollectionViewLayout (UIUpdateSupportHooks)
+
+- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems {
+  [super prepareForCollectionViewUpdates:updateItems];
+  _deletedIndexPaths = [NSMutableArray array];
+  _insertedIndexPaths = [NSMutableArray array];
+  _deletedSections = [NSMutableIndexSet indexSet];
+  _insertedSections = [NSMutableIndexSet indexSet];
+
+  for (UICollectionViewUpdateItem *item in updateItems) {
+    if (item.updateAction == UICollectionUpdateActionDelete) {
+      // Store deleted sections or indexPaths.
+      if (item.indexPathBeforeUpdate.item == NSNotFound) {
+        [_deletedSections addIndex:item.indexPathBeforeUpdate.section];
+      } else {
+        [_deletedIndexPaths addObject:item.indexPathBeforeUpdate];
+      }
+
+    } else if (item.updateAction == UICollectionUpdateActionInsert) {
+      // Store inserted sections or indexPaths.
+      if (item.indexPathAfterUpdate.item == NSNotFound) {
+        [_insertedSections addIndex:item.indexPathAfterUpdate.section];
+      } else {
+        [_insertedIndexPaths addObject:item.indexPathAfterUpdate];
+      }
+    }
+  }
+}
+
+- (void)finalizeCollectionViewUpdates {
+  [super finalizeCollectionViewUpdates];
+  _deletedIndexPaths = nil;
+  _insertedIndexPaths = nil;
+  _deletedSections = nil;
+  _insertedSections = nil;
+}
+
+- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:
+        (NSIndexPath *)itemIndexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath] copy];
+  // Adding new section or item.
+  if ([_insertedSections containsIndex:itemIndexPath.section] ||
+      [_insertedIndexPaths containsObject:itemIndexPath]) {
+    attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+  } else {
+    attr.alpha = 1;
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)
+    initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind
+                                                      atIndexPath:(NSIndexPath *)elementIndexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super initialLayoutAttributesForAppearingSupplementaryElementOfKind:elementKind
+                                                                atIndexPath:elementIndexPath] copy];
+  if ([elementKind isEqualToString:UICollectionElementKindSectionHeader] ||
+      [elementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+    // Adding new section header or footer.
+    if ([_insertedSections containsIndex:elementIndexPath.section]) {
+      attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+    } else {
+      attr.alpha = 1;
+    }
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:
+        (NSIndexPath *)itemIndexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath] copy];
+  // Deleting section or item.
+  if ([_deletedSections containsIndex:itemIndexPath.section] ||
+      [_deletedIndexPaths containsObject:itemIndexPath]) {
+    attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+  } else {
+    attr.alpha = 1;
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)
+    finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind
+                                                       atIndexPath:(NSIndexPath *)elementIndexPath {
+  UICollectionViewLayoutAttributes *attr = [[super
+      finalLayoutAttributesForDisappearingSupplementaryElementOfKind:elementKind
+                                                         atIndexPath:elementIndexPath] copy];
+  if ([elementKind isEqualToString:UICollectionElementKindSectionHeader] ||
+      [elementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+    // Deleting section header or footer.
+    if ([_deletedSections containsIndex:elementIndexPath.section]) {
+      attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+    } else {
+      attr.alpha = 1;
+    }
+  }
+  return attr;
+}
+
+#pragma mark - Header/Footer Caching
+
+- (void)storeSupplementaryViewsWithAttributes:
+        (NSArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  _headerSections = [NSMutableIndexSet indexSet];
+  _footerSections = [NSMutableIndexSet indexSet];
+
+  // Store index path sections for headers/footers.
+  for (MDCCollectionViewLayoutAttributes *attr in attributes) {
+    if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
+      [_headerSections addIndex:attr.indexPath.section];
+    } else if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+      [_footerSections addIndex:attr.indexPath.section];
+    }
+  }
+}
+
+#pragma mark - Private
+
+- (MDCCollectionViewLayoutAttributes *)updateAttribute:(MDCCollectionViewLayoutAttributes *)attr {
+  if (attr.representedElementCategory == UICollectionElementCategoryCell) {
+    attr.editing = self.editor.isEditing;
+  }
+  attr.isGridLayout = NO;
+  if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeList) {
+    attr.sectionOrdinalPosition = [self ordinalPositionForListElementWithAttribute:attr];
+  } else if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    attr.sectionOrdinalPosition = [self ordinalPositionForGridElementWithAttribute:attr];
+    attr.isGridLayout = YES;
+  }
+
+  [self updateCellStateMaskWithAttribute:attr];
+
+  if (attr.representedElementCategory == UICollectionElementCategorySupplementaryView) {
+    attr = [self updateSupplementaryViewAttribute:attr];
+  }
+
+  // Set cell background.
+  attr.backgroundImage = [self.styler backgroundImageForCellLayoutAttributes:attr];
+  attr.backgroundImageViewInsets =
+      [self.styler backgroundImageViewOutsetsForCellWithAttribute:attr];
+
+  // Set separator styling.
+  attr.separatorColor = self.styler.separatorColor;
+  attr.separatorInset = self.styler.separatorInset;
+  attr.separatorLineHeight = self.styler.separatorLineHeight;
+  attr.shouldHideSeparators = self.styler.shouldHideSeparators;
+
+  // Set inlay and hidden state if necessary.
+  [self inlayAttributeIfNecessary:attr];
+  [self hideAttributeIfNecessary:attr];
+
+  return attr;
+}
+
+- (MDCCollectionViewLayoutAttributes *)updateSupplementaryViewAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // In vertical scrolling, supplementary views only respect their height and ignore their width
+  // value. The opposite is true for horizontal scrolling. Therefore we must manually set insets
+  // on both the backgroundView and contentView in order to match the insets of the collection
+  // view rows.
+  CGRect insetFrame = attr.frame;
+  UIEdgeInsets insets = [self insetsAtSectionIndex:attr.indexPath.section];
+  if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
+    insetFrame = CGRectInset(insetFrame, insets.left / 2 + insets.right / 2, 0);
+    if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
+      insetFrame.origin.y += insets.top;
+    } else if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+      insetFrame.origin.y -= insets.bottom;
+    }
+    attr.frame = insetFrame;
+  }
+  return attr;
+}
+
+- (UIEdgeInsets)insetsAtSectionIndex:(NSInteger)section {
+  // Determine insets based on cell style.
+  CGFloat inset = (CGFloat)floor(MDCCollectionViewCellStyleCardSectionInset);
+  UIEdgeInsets insets = UIEdgeInsetsZero;
+  NSInteger numberOfSections = self.collectionView.numberOfSections;
+  BOOL isTop = (section == 0);
+  BOOL isBottom = (section == numberOfSections - 1);
+  MDCCollectionViewCellStyle cellStyle = [self.styler cellStyleAtSectionIndex:section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  // Set left/right insets.
+  if (isCardStyle) {
+    insets.left = inset;
+    insets.right = inset;
+  }
+  // Set top/bottom insets.
+  if (isCardStyle || isGroupedStyle) {
+    insets.top = (CGFloat)floor((isTop) ? inset : inset / 2.0f);
+    insets.bottom = (CGFloat)floor((isBottom) ? inset : inset / 2.0f);
+  }
+  return insets;
+}
+
+- (MDCCollectionViewOrdinalPosition)ordinalPositionForListElementWithAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // Returns the ordinal position of cells and supplementary views within a list layout. This is
+  // used to determine the layout attributes applied to their styling.
+  MDCCollectionViewOrdinalPosition position = 0;
+  NSIndexPath *indexPath = attr.indexPath;
+  NSInteger numberOfItemsInSection = [self numberOfItemsInSection:indexPath.section];
+  BOOL isTop = NO;
+  BOOL isBottom = NO;
+  BOOL hasSectionHeader = [_headerSections containsIndex:indexPath.section];
+  BOOL hasSectionFooter = [_footerSections containsIndex:indexPath.section];
+  BOOL hasSectionItems = YES;
+
+  BOOL hidesHeaderBackground = NO;
+  if ([self.styler.delegate
+          respondsToSelector:@selector(collectionView:shouldHideHeaderBackgroundForSection:)]) {
+    hidesHeaderBackground = [self.styler.delegate collectionView:self.styler.collectionView
+                            shouldHideHeaderBackgroundForSection:indexPath.section];
+  }
+
+  BOOL hidesFooterBackground = NO;
+  if ([self.styler.delegate
+          respondsToSelector:@selector(collectionView:shouldHideFooterBackgroundForSection:)]) {
+    hidesFooterBackground = [self.styler.delegate collectionView:self.styler.collectionView
+                            shouldHideFooterBackgroundForSection:indexPath.section];
+  }
+
+  if (attr.representedElementCategory == UICollectionElementCategoryCell) {
+    isTop = (indexPath.item == 0) && (!hasSectionHeader || hidesHeaderBackground);
+    isBottom = (indexPath.item == numberOfItemsInSection - 1) &&
+               (!hasSectionFooter || hidesFooterBackground);
+  } else if (attr.representedElementCategory == UICollectionElementCategorySupplementaryView) {
+    NSString *kind = attr.representedElementKind;
+    BOOL isElementHeader = ([kind isEqualToString:UICollectionElementKindSectionHeader]);
+    BOOL isElementFooter = ([kind isEqualToString:UICollectionElementKindSectionFooter]);
+    isTop = (isElementFooter && !hasSectionItems && !hasSectionHeader) || isElementHeader;
+    isBottom = (isElementHeader && !hasSectionItems && !hasSectionFooter) || isElementFooter;
+  }
+
+  if (attr.editing || [self.styler isItemInlaidAtIndexPath:attr.indexPath]) {
+    isTop = YES;
+    isBottom = YES;
+  }
+
+  if (!isTop && !isBottom) {
+    position |= MDCCollectionViewOrdinalPositionVerticalCenter;
+  } else {
+    position |= isTop ? MDCCollectionViewOrdinalPositionVerticalTop : position;
+    position |= isBottom ? MDCCollectionViewOrdinalPositionVerticalBottom : position;
+  }
+  return position;
+}
+
+- (MDCCollectionViewOrdinalPosition)ordinalPositionForGridElementWithAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // Returns the ordinal position of cells and supplementary views within a grid layout. This is
+  // used to determine the layout attributes applied to their styling.
+  MDCCollectionViewOrdinalPosition position = 0;
+  NSIndexPath *indexPath = attr.indexPath;
+  NSInteger numberOfItemsInSection = [self numberOfItemsInSection:indexPath.section];
+  NSInteger gridColumnCount = self.styler.gridColumnCount;
+  NSInteger maxRowIndex = (NSInteger)(floor(numberOfItemsInSection / gridColumnCount) - 1);
+  NSInteger maxColumnIndex = gridColumnCount - 1;
+  NSInteger ordinalRow = (NSInteger)(floor(indexPath.item / gridColumnCount));
+  NSInteger ordinalColumn = (NSInteger)(floor(indexPath.item % gridColumnCount));
+
+  // Set vertical ordinal position.
+  if (ordinalRow > 0 && ordinalRow < maxRowIndex) {
+    position = position | MDCCollectionViewOrdinalPositionVerticalCenter;
+  } else {
+    position =
+        (ordinalRow == 0) ? position | MDCCollectionViewOrdinalPositionVerticalTop : position;
+    position = (ordinalRow == maxRowIndex)
+                   ? position | MDCCollectionViewOrdinalPositionVerticalBottom
+                   : position;
+  }
+
+  // Set horizontal ordinal position.
+  if (ordinalColumn > 0 && ordinalColumn < maxColumnIndex) {
+    position = position | MDCCollectionViewOrdinalPositionHorizontalCenter;
+  } else {
+    position =
+        (ordinalColumn == 0) ? position | MDCCollectionViewOrdinalPositionHorizontalLeft : position;
+    position = (ordinalColumn == maxColumnIndex)
+                   ? position | MDCCollectionViewOrdinalPositionHorizontalRight
+                   : position;
+  }
+  return position;
+}
+
+- (void)updateCellStateMaskWithAttribute:(MDCCollectionViewLayoutAttributes *)attr {
+  attr.shouldShowSelectorStateMask = NO;
+  attr.shouldShowReorderStateMask = NO;
+
+  // Determine proper state to show cell if editing.
+  if (attr.editing) {
+    if ([self.collectionView.dataSource
+            conformsToProtocol:@protocol(MDCCollectionViewEditingDelegate)]) {
+      id<MDCCollectionViewEditingDelegate> editingDelegate =
+          (id<MDCCollectionViewEditingDelegate>)self.collectionView.dataSource;
+
+      // Check if delegate can select during editing.
+      if ([editingDelegate respondsToSelector:@selector(collectionView:
+                                                  canSelectItemDuringEditingAtIndexPath:)]) {
+        attr.shouldShowSelectorStateMask = [editingDelegate collectionView:self.collectionView
+                                     canSelectItemDuringEditingAtIndexPath:attr.indexPath];
+      }
+
+      // Check if delegate can reorder.
+      if ([editingDelegate respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)]) {
+        attr.shouldShowReorderStateMask = [editingDelegate collectionView:self.collectionView
+                                                   canMoveItemAtIndexPath:attr.indexPath];
+      }
+    }
+  }
+}
+
+- (void)inlayAttributeIfNecessary:(MDCCollectionViewLayoutAttributes *)attr {
+  // Inlay this attribute if necessary.
+  CGFloat inset = MDCCollectionViewCellStyleCardSectionInset;
+  UIEdgeInsets inlayInsets = UIEdgeInsetsZero;
+  NSInteger item = attr.indexPath.item;
+  NSArray<NSIndexPath *> *inlaidIndexPaths = [self.styler indexPathsForInlaidItems];
+
+  // Update ordinal position for index paths adjacent to inlaid index path.
+  for (NSIndexPath *inlaidIndexPath in inlaidIndexPaths) {
+    if (inlaidIndexPath.section == attr.indexPath.section) {
+      NSInteger numberOfItemsInSection = [self numberOfItemsInSection:inlaidIndexPath.section];
+      if (attr.representedElementCategory == UICollectionElementCategoryCell) {
+        if (item == inlaidIndexPath.item) {
+          // Get previous and next index paths to the inlaid index path.
+          BOOL prevAttrIsInlaid = NO;
+          BOOL nextAttrIsInlaid = NO;
+          BOOL hasSectionHeader = [_headerSections containsIndex:inlaidIndexPath.section];
+          BOOL hasSectionFooter = [_footerSections containsIndex:inlaidIndexPath.section];
+
+          if (inlaidIndexPath.item > 0 || hasSectionHeader) {
+            NSIndexPath *prevIndexPath = [NSIndexPath indexPathForItem:(inlaidIndexPath.item - 1)
+                                                             inSection:inlaidIndexPath.section];
+            prevAttrIsInlaid = [self.styler isItemInlaidAtIndexPath:prevIndexPath];
+            inlayInsets.top = prevAttrIsInlaid ? inset / 2 : inset;
+          }
+
+          if (inlaidIndexPath.item < numberOfItemsInSection - 1 || hasSectionFooter) {
+            NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:(inlaidIndexPath.item + 1)
+                                                             inSection:inlaidIndexPath.section];
+            nextAttrIsInlaid = [self.styler isItemInlaidAtIndexPath:nextIndexPath];
+            inlayInsets.bottom = nextAttrIsInlaid ? inset / 2 : inset;
+          }
+
+          // Is attribute to be inlaid.
+          attr.frame = UIEdgeInsetsInsetRect(attr.frame, inlayInsets);
+          attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+        } else if (item == inlaidIndexPath.item - 1) {
+          // Is previous to inlaid attribute.
+          if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalTop) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+          } else if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalCenter) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalBottom;
+          }
+        } else if (item == inlaidIndexPath.item + 1) {
+          // Is next to inlaid attribute.
+          if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalCenter) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTop;
+          } else if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalBottom) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalBottom;
+          }
+        }
+
+      } else if (attr.representedElementCategory == UICollectionElementCategorySupplementaryView) {
+        // If header/footer attribute, update if adjacent to inlaid index path.
+        NSString *kind = attr.representedElementKind;
+        BOOL isElementHeader = ([kind isEqualToString:UICollectionElementKindSectionHeader]);
+        BOOL isElementFooter = ([kind isEqualToString:UICollectionElementKindSectionFooter]);
+        if (isElementHeader && inlaidIndexPath.item == 0) {
+          attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+        } else if (isElementFooter && inlaidIndexPath.item == numberOfItemsInSection - 1) {
+          attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+        }
+      }
+    }
+  }
+}
+
+- (void)hideAttributeIfNecessary:(MDCCollectionViewLayoutAttributes *)attr {
+  if (self.editor) {
+    // Hide the attribute if the editor is either currently handling a cell item or section swipe
+    // for dismissal, or is reordering a cell item.
+    BOOL isCell = attr.representedElementCategory == UICollectionElementCategoryCell;
+    if (attr.indexPath.section == self.editor.dismissingSection ||
+        ([attr.indexPath isEqual:self.editor.dismissingCellIndexPath] && isCell) ||
+        ([attr.indexPath isEqual:self.editor.reorderingCellIndexPath] && isCell)) {
+      attr.hidden = YES;
+    }
+  }
+}
+
+- (void)addInfoBarAttributesIfNecessary:
+        (NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  if (self.editor.isEditing && [attributes count] > 0) {
+    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
+
+    // Add header info bar if editing.
+    [attributes
+        addObject:[self layoutAttributesForSupplementaryViewOfKind:MDCCollectionInfoBarKindHeader
+                                                       atIndexPath:indexPath]];
+
+    // Add footer info bar if editing and item(s) are selected.
+    NSInteger selectedItemCount = [self.collectionView.indexPathsForSelectedItems count];
+    if (selectedItemCount > 0) {
+      [attributes
+          addObject:[self layoutAttributesForSupplementaryViewOfKind:MDCCollectionInfoBarKindFooter
+                                                         atIndexPath:indexPath]];
+    }
+  }
+}
+
+- (void)addDecorationViewIfNecessary:
+        (NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  // If necessary, adds a decoration view to a section drawn below its items. This will only happen
+  // for a grid layout when it is either A) grouped-style or B) card-style with zero padding. When
+  // this happens, the background for those items will not be drawn, and instead this decoration
+  // view will extend to the bounds of the sum of its respective section item frames. Shadowing and
+  // border will be applied to this decoration view as per the styler settings.
+  if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    NSMutableSet *sectionSet = [NSMutableSet set];
+    BOOL shouldShowGridBackground = NO;
+    NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *decorationAttributes =
+        [NSMutableArray array];
+    for (MDCCollectionViewLayoutAttributes *attr in attributes) {
+      NSInteger section = attr.indexPath.section;
+
+      // Only add one decoration view per section.
+      if (![sectionSet containsObject:@(section)]) {
+        NSIndexPath *decorationIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
+        MDCCollectionViewLayoutAttributes *decorationAttr =
+            (MDCCollectionViewLayoutAttributes *)[self
+                layoutAttributesForDecorationViewOfKind:kCollectionDecorationView
+                                            atIndexPath:decorationIndexPath];
+        shouldShowGridBackground = [self shouldShowGridBackgroundWithAttribute:decorationAttr];
+        decorationAttr.shouldShowGridBackground = shouldShowGridBackground;
+        decorationAttr.backgroundImage =
+            shouldShowGridBackground
+                ? [self.styler backgroundImageForCellLayoutAttributes:decorationAttr]
+                : nil;
+        [decorationAttributes addObject:decorationAttr];
+        [sectionSet addObject:@(section)];
+      }
+      if (shouldShowGridBackground) {
+        attr.backgroundImage = nil;
+      }
+    }
+    [attributes addObjectsFromArray:decorationAttributes];
+  }
+}
+
+- (BOOL)shouldShowGridBackgroundWithAttribute:(MDCCollectionViewLayoutAttributes *)attr {
+  // Determine whether to show grid background.
+  if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    if (self.styler.cellStyle == MDCCollectionViewCellStyleGrouped ||
+        (self.styler.cellStyle == MDCCollectionViewCellStyleCard && self.styler.gridPadding == 0)) {
+      return YES;
+    }
+  }
+  return NO;
+}
+
+- (NSInteger)numberOfItemsInSection:(NSInteger)section {
+  return [self.collectionView numberOfItemsInSection:section];
+}
+
+#pragma mark - Cell Appearance Animation
+
+- (CGRect)boundsForAppearanceAnimationWithInitialBounds:(CGRect)initialBounds {
+  // Increase initial bounds by 25% allowing offscreen attributes to be included in the
+  // appearance animation.
+  if (self.styler.shouldAnimateCellsOnAppearance && self.styler.willAnimateCellsOnAppearance) {
+    CGRect newBounds = initialBounds;
+    newBounds.size.height += (newBounds.size.height / 4);
+    return newBounds;
+  }
+  return initialBounds;
+}
+
+- (void)beginCellAppearanceAnimationIfNecessary:
+        (NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  // Here we want to assign a delay to each attribute such that the animation will fade-in from the
+  // top downwards in a staggered manner. However, the array of attributes we receive here are not
+  // in the correct order and must be sorted and re-ordered to properly assign these delays.
+  //
+  // First we will sort the array of attributes by index path to ensure proper ordering. Secondly
+  // we will manipulate the array to bring any headers before their first respective cell items.
+  //
+  // When completed, we will end up with an array of attributes in the form of
+  // header -> item -> footer ... repeated for each section. Now we can use this ordered array
+  // to assign delays based on their proper ordinal position from top down.
+  __block NSInteger attributeCount = attributes.count;
+  NSTimeInterval duration = self.styler.animateCellsOnAppearanceDuration;
+  if (self.styler.shouldAnimateCellsOnAppearance && attributeCount > 0) {
+    // First sort by index path.
+    NSArray<__kindof UICollectionViewLayoutAttributes *> *sortedByIndexPath = [attributes
+        sortedArrayUsingComparator:^NSComparisonResult(MDCCollectionViewLayoutAttributes *attr1,
+                                                       MDCCollectionViewLayoutAttributes *attr2) {
+          return [attr1.indexPath compare:attr2.indexPath];
+        }];
+
+    // Next create new array containing attributes in the form of header -> item -> footer.
+    NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *sortedAttributes =
+        [NSMutableArray array];
+    [sortedByIndexPath enumerateObjectsUsingBlock:^(MDCCollectionViewLayoutAttributes *attr,
+                                                    NSUInteger idx, BOOL *stop) {
+      if (sortedAttributes.count > 0) {
+        // Check if current attribute is a header and previous attribute is an item. If so,
+        // insert the current header attribute before the cell.
+        MDCCollectionViewLayoutAttributes *prevAttr =
+            [sortedAttributes objectAtIndex:sortedAttributes.count - 1];
+        BOOL prevAttrIsItem =
+            prevAttr.representedElementCategory == UICollectionElementCategoryCell;
+        BOOL attrIsHeader =
+            [attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader];
+        if (attrIsHeader && prevAttrIsItem) {
+          [sortedAttributes insertObject:attr atIndex:sortedAttributes.count - 1];
+          return;
+        }
+        if ([attr.representedElementKind isEqualToString:MDCCollectionInfoBarKindHeader] ||
+            [attr.representedElementKind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+          // Reduce the attributeCount here to reflect only attributes that can be animated.
+          attributeCount--;
+          return;
+        }
+      }
+      [sortedAttributes addObject:attr];
+    }];
+
+    // Now assign delays and add padding to frame Y coordinate which gets removed during animation.
+    [sortedAttributes enumerateObjectsUsingBlock:^(MDCCollectionViewLayoutAttributes *attr,
+                                                   NSUInteger idx, BOOL *stop) {
+      // If the element is an info bar header, then don't do anything.
+      attr.willAnimateCellsOnAppearance = self.styler.willAnimateCellsOnAppearance;
+      attr.animateCellsOnAppearanceDuration = self.styler.animateCellsOnAppearanceDuration;
+      attr.animateCellsOnAppearanceDelay =
+          (attributeCount > 0) ? ((CGFloat)idx / attributeCount) * duration : 0;
+
+      if (self.styler.willAnimateCellsOnAppearance) {
+        CGRect frame = attr.frame;
+        frame.origin.y += self.styler.animateCellsOnAppearancePadding;
+        attr.frame = frame;
+      }
+    }];
+
+    // Call asynchronously to allow the current layout cycle to complete before issuing animations.
+    if (self.styler.willAnimateCellsOnAppearance) {
+      dispatch_async(dispatch_get_main_queue(), ^{
+        [self.styler beginCellAppearanceAnimation];
+      });
+    }
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
new file mode 100644
index 0000000..b0f577a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
@@ -0,0 +1,265 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCCollectionViewStylingDelegate;
+@class MDCCollectionViewLayoutAttributes;
+
+/** The default section insets. Should be an even number to allow even division. */
+extern const CGFloat MDCCollectionViewCellStyleCardSectionInset;
+
+/** The styles in which the collectionView cells can be shown. */
+typedef NS_ENUM(NSUInteger, MDCCollectionViewCellStyle) {
+  /** Cells displayed full width without section padding. */
+  MDCCollectionViewCellStyleDefault,
+
+  /** Cells displayed full width with section padding. */
+  MDCCollectionViewCellStyleGrouped,
+
+  /** Cells displayed card style with sections padding. */
+  MDCCollectionViewCellStyleCard,
+};
+
+/** The layout types in which the collectionView cells can be shown. */
+typedef NS_ENUM(NSUInteger, MDCCollectionViewCellLayoutType) {
+  /** Cells displayed in list layout. */
+  MDCCollectionViewCellLayoutTypeList,
+
+  /** Cells displayed in grid layout. */
+  MDCCollectionViewCellLayoutTypeGrid,
+
+  /**
+   Cells displayed in custom defined layout. A new UICollectionViewLayout must be
+   provided and set on the collection view.
+   */
+  MDCCollectionViewCellLayoutTypeCustom
+};
+
+/**
+ The MDCCollectionViewStyling protocol defines the stylable properties for a Material collection
+ view.
+ */
+@protocol MDCCollectionViewStyling <NSObject>
+
+/** The associated collection view. */
+@property(nonatomic, readonly, weak, nullable) UICollectionView *collectionView;
+
+/** The delegate is sent messages when styles change. */
+@property(nonatomic, weak, nullable) id<MDCCollectionViewStylingDelegate> delegate;
+
+/** Indicates whether the collection view layout should be invalidated. */
+@property(nonatomic, assign) BOOL shouldInvalidateLayout;
+
+#pragma mark - Cell Styling
+
+/** The cell background color. Defaults to white color. */
+@property(nonatomic, strong, nonnull) UIColor *cellBackgroundColor;
+
+/**
+ The cell layout type. Defaults to MDCCollectionViewCellLayoutTypeList if not set. Not animated.
+ Defaults to MDCCollectionViewCellLayoutTypeList.
+ */
+@property(nonatomic, assign) MDCCollectionViewCellLayoutType cellLayoutType;
+
+/**
+ The grid column count. Requires cellLayoutType to be set to MDCCollectionViewCellLayoutTypeGrid.
+ Not animated.
+ */
+@property(nonatomic, assign) NSInteger gridColumnCount;
+
+/**
+ The grid padding property is used when the cellLayoutType is MDCCollectionViewCellLayoutTypeGrid
+ and the gridColumnCount is greater than or equal to 2. This value ensure that the left, center,
+ and right padding are equivalent. This prevents double padding at center. Not animated.
+ */
+@property(nonatomic, assign) CGFloat gridPadding;
+
+/** The cell style. Not animated. @c setCellStyle:animated: for animated layout type changes. */
+@property(nonatomic, assign) MDCCollectionViewCellStyle cellStyle;
+
+/**
+ Updates the cell style with/without animation.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)setCellStyle:(MDCCollectionViewCellStyle)cellStyle animated:(BOOL)animated;
+
+/**
+ The collection view cell style at the specified section index.
+
+ @param section The collection view section.
+ @return The cell style at specified section.
+ */
+- (MDCCollectionViewCellStyle)cellStyleAtSectionIndex:(NSInteger)section;
+
+/**
+ The collection view cell background image view (utilized to render the background color and
+ shadows) edge outsets as determined for a cell and its layout attributes.
+
+ @param attr The cell's layout attributes.
+ @return Edge outsets as detemined by cell style at this index.
+ */
+- (UIEdgeInsets)backgroundImageViewOutsetsForCellWithAttribute:
+        (nonnull MDCCollectionViewLayoutAttributes *)attr;
+
+/**
+ Returns an image for use with the given cell style and ordinal position within section.
+
+ The returned image is cached internally after the first request. Changing any of the display
+ properties will invalidate the cached images.
+
+ @param attr The cell's layout attributes.
+ @return Image as determined by cell style and section ordinal position.
+ */
+- (nullable UIImage *)backgroundImageForCellLayoutAttributes:
+        (nonnull MDCCollectionViewLayoutAttributes *)attr;
+
+#pragma mark - Cell Separator
+
+/** Separator color. Defaults to #E0E0E0. */
+@property(nonatomic, strong, nullable) UIColor *separatorColor;
+
+/** Separator inset. Defaults to UIEdgeInsetsZero. */
+@property(nonatomic) UIEdgeInsets separatorInset;
+
+/** Separator line height. Defaults to 1.0f */
+@property(nonatomic) CGFloat separatorLineHeight;
+
+/* Whether to hide the cell separators. Defaults to NO. */
+@property(nonatomic) BOOL shouldHideSeparators;
+
+#pragma mark - Item Inlaying
+
+/**
+ Whether inlaying a collection view item is allowed. When an item is inlaid, it will be given
+ padding at its edges to make it inset from other sibling items. A typical use case for inlaying
+ is when setting a collection view into editing mode, in which each cell gets inlaid so that they
+ can individually be selected/unselected/swiped for deletion.
+
+ If YES, call the -inlayItemAtIndexPath:animated method to inlay the item at the specified
+ index path. Remove the inlay by calling the -removeInlayAtIndexPath:animated: method.
+ Not animated. Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL allowsItemInlay;
+
+/** Whether inlaying multiple items is allowed. Not animated. Defaults to NO. */
+@property(nonatomic, assign) BOOL allowsMultipleItemInlays;
+
+/**
+ Returns an array of collection view index paths for items that have their respective frames
+ inlaid.
+
+ @return An array of index paths.
+ */
+- (nullable NSArray<NSIndexPath *> *)indexPathsForInlaidItems;
+
+/**
+ A Boolean value indicating if the collection view item at the specified index path has its
+ frame inlaid.
+
+ @param indexPath The collection view index path.
+ @return YES if the cells are Material styled cards. Otherwise No.
+ */
+- (BOOL)isItemInlaidAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Inlays the item at the specified index path.
+
+ Property allowsItemInlay must be set to YES, otherwise no-op.
+
+ @param indexPath The specified index path.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)applyInlayToItemAtIndexPath:(nonnull NSIndexPath *)indexPath animated:(BOOL)animated;
+
+/**
+ Removes the inlaid state of the item at the specified index path.
+
+ @param indexPath The specified index path.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)removeInlayFromItemAtIndexPath:(nonnull NSIndexPath *)indexPath animated:(BOOL)animated;
+
+/**
+ Inlays items at all available index paths.
+
+ Property allowsItemInlay must be set to YES, otherwise no-op.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)applyInlayToAllItemsAnimated:(BOOL)animated;
+
+/**
+ Removes the inlaid state of items at all available index paths.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)removeInlayFromAllItemsAnimated:(BOOL)animated;
+
+/**
+ Resets the internal storage array of all item index paths for inlaid items. When modifying
+ items in the collection view model, a call to this method will ensure that all inserted
+ and/or deleted index paths are reflected properly in the return array from the
+ method -indexPathsForInlaidItems. Calling this is not animated.
+ */
+- (void)resetIndexPathsForInlaidItems;
+
+#pragma mark - Cell Appearance Animation
+
+/**
+ Whether cells should animate on appearance. This property typically should be set in the
+ -viewDidLoad method of the controller. If YES, cells will animate the following properties:
+
+ A) Cell heights will begin expanded by the padding specified by animateCellsOnAppearancePadding.
+    It will then animate to original height.
+
+ B) Cell frame will begin with positive y-offset as specified by animateCellsOnAppearancePadding.
+    It will animate upwards to original y coordinate.
+
+ C) Cell contentView and separatorView will begin hidden by setting alpha to 0. It will then
+    animate with a fade-in transition in a staggered fashion from the top cell down to last
+    visible cell.
+ */
+@property(nonatomic, assign) BOOL shouldAnimateCellsOnAppearance;
+
+/** Whether cells should calculate their initial properties before animation on appearance. */
+@property(nonatomic, readonly, assign) BOOL willAnimateCellsOnAppearance;
+
+/*
+ The cell appearance animation padding. This value is ignored unless
+ shouldAnimateCellsOnAppearance is set to YES. Its value is set at initialization time by the
+ constant MDCCollectionViewAnimatedAppearancePadding.
+ */
+@property(nonatomic, readonly, assign) CGFloat animateCellsOnAppearancePadding;
+
+/*
+ The cell appearance animation duration. This value is ignored unless
+ shouldAnimateCellsOnAppearance is set to YES. Its value is set at initialization time by the
+ constant MDCCollectionViewAnimatedAppearanceDuration.
+ */
+@property(nonatomic, readonly, assign) NSTimeInterval animateCellsOnAppearanceDuration;
+
+/**
+ This method should only be called from MDCCollectionViewFlowLayout class once all visible
+ collection view attributes are available. By calling -updateLayoutAnimated within this method's
+ animation block, it will trigger the collection view to query both the item and supplementary
+ view sizing methods of the UICollectionViewDelegateFlowLayout protocol, resulting in an
+ animated resizing of the cells by the height specified in animateCellsOnAppearancePadding.
+ */
+- (void)beginCellAppearanceAnimation;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
new file mode 100644
index 0000000..620cde6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
@@ -0,0 +1,151 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCCollectionViewStyling.h"
+
+@class MDCInkTouchController;
+@class MDCInkView;
+
+/** A delegate protocol which allows setting collection view cell styles. */
+@protocol MDCCollectionViewStylingDelegate <NSObject>
+@optional
+
+#pragma mark - Styling
+
+/**
+ Asks the delegate for the cell height at the specified collection view index path. The style
+ controller will make padding/insets adjustments to this value as needed depending on the cell
+ style and editing mode.
+
+ @param collectionView The collection view.
+ @param indexPath The item's index path.
+ @return The cell height at the specified index path.
+ */
+- (CGFloat)collectionView:(nonnull UICollectionView *)collectionView
+    cellHeightAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate for the cell style at the specified collection view section index. All
+ remaining sections to have their cells styled per the styler @c cellStyle property.
+
+ @param collectionView The collection view.
+ @param section The collection view section.
+ @return The cell style to be used at the specified index.
+ */
+- (MDCCollectionViewCellStyle)collectionView:(nonnull UICollectionView *)collectionView
+                         cellStyleForSection:(NSInteger)section;
+
+/**
+ Asks the delegate for the cell background color at the specified collection view index path.
+
+ @param collectionView The collection view.
+ @param indexPath The item's index path.
+ @return The cell background color at the specified index path.
+ */
+- (nullable UIColor *)collectionView:(nonnull UICollectionView *)collectionView
+      cellBackgroundColorAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate whether the specified item should hide its background image/shadowing.
+
+ @param collectionView The collection view.
+ @param indexPath The item's index path.
+ @return If the item background should be hidden at the specified index path.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHideItemBackgroundAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate whether the specified header should hide its background image/shadowing.
+
+ @param collectionView The collection view.
+ @param section The collection view section.
+ @return If the header background should be hidden at the specified section.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHideHeaderBackgroundForSection:(NSInteger)section;
+
+/**
+ Asks the delegate whether the specified footer should hide its background image/shadowing.
+
+ @param collectionView The collection view.
+ @param section The collection view section.
+ @return If the footer background should be hidden at the specified section.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHideFooterBackgroundForSection:(NSInteger)section;
+
+#pragma mark - Item inlaying
+
+/**
+ Allows the receiver to receive notification that items at the specified index paths did
+ inlay their frame.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didApplyInlayToItemAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+/**
+ Allows the receiver to receive notification that items at the specified index paths did
+ remove the inlay of their frames.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didRemoveInlayFromItemAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+#pragma mark - Ink Touches
+
+/**
+ Asks the delegate whether the inkView for a specified index path should be hidden.
+
+ @param collectionView The collection view.
+ @param indexPath The collection view index path.
+ @return If the ink view should be hidden at the specified index path.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    hidesInkViewAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate for the ink color at the specified index path.
+
+ If nil, defaults to MDCInkView defaultInkColor.
+
+ @param collectionView The collection view.
+ @param indexPath The collection view index path.
+ @return The ink color at the specified index path.
+ */
+- (nullable UIColor *)collectionView:(nonnull UICollectionView *)collectionView
+                 inkColorAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Allows the receiver to set the ink view at the specified collection view index path.
+
+ @param collectionView The collection view.
+ @param inkTouchController The ink controller of the ink view.
+ @param indexPath The collection view index path.
+ @return The inkView to be used at the specified index path.
+ */
+- (nonnull MDCInkView *)collectionView:(nonnull UICollectionView *)collectionView
+                    inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+                    inkViewAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MaterialCollections.bundle/Resources/en.lproj/MaterialCollections.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MaterialCollections.bundle/Resources/en.lproj/MaterialCollections.strings
new file mode 100644
index 0000000..4e9cd34
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MaterialCollections.bundle/Resources/en.lproj/MaterialCollections.strings
@@ -0,0 +1,4 @@
+/* Label for a button indicating a collectionView row can be deleted. (40 chars.) */
+"DeleteButton" = "Delete";
+/* Label for info bar indicating available editing gestures for collectionView. (40 chars.) */
+"InfoBarGestureHint" = "Swipe an item to delete";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MaterialCollections.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MaterialCollections.h
new file mode 100644
index 0000000..2190414
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/MaterialCollections.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewController.h"
+#import "MDCCollectionViewEditing.h"
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MDCCollectionViewFlowLayout.h"
+#import "MDCCollectionViewStyling.h"
+#import "MDCCollectionViewStylingDelegate.h"
+#import "MaterialCollectionCells.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h
new file mode 100644
index 0000000..04b2e4d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The MDCCollectionGridBackgroundView class provides an implementation of UICollectionReusableView
+ that displays a background view under cells at each section of a collection view in grid layout.
+
+ This will only happen for a grid layout when it is either A) grouped-style or B) card-style with
+ zero padding. When this happens, the background for the section cells will not be drawn, and
+ instead this view will extend to the bounds of the sum of its respective section item frames.
+ */
+@interface MDCCollectionGridBackgroundView : UICollectionReusableView
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.m
new file mode 100644
index 0000000..9101e33
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.m
@@ -0,0 +1,56 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionGridBackgroundView.h"
+
+#import "MaterialCollectionLayoutAttributes.h"
+
+@implementation MDCCollectionGridBackgroundView {
+  UIImageView *_backgroundImageView;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionGridBackgroundViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionGridBackgroundViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionGridBackgroundViewInit {
+  _backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
+  _backgroundImageView.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+  [self addSubview:_backgroundImageView];
+}
+
+- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
+  [super applyLayoutAttributes:layoutAttributes];
+  NSAssert([layoutAttributes isKindOfClass:[MDCCollectionViewLayoutAttributes class]],
+           @"LayoutAttributes must be a subclass of MDCCollectionViewLayoutAttributes.");
+  MDCCollectionViewLayoutAttributes *attr = (MDCCollectionViewLayoutAttributes *)layoutAttributes;
+  _backgroundImageView.image = attr.backgroundImage;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h
new file mode 100644
index 0000000..3b079db
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h
@@ -0,0 +1,184 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCCollectionInfoBarView;
+
+/** The info bar supplementary view kind when shown in header. */
+extern NSString *_Nonnull const MDCCollectionInfoBarKindHeader;
+
+/** The info bar supplementary view kind when shown in footer. */
+extern NSString *_Nonnull const MDCCollectionInfoBarKindFooter;
+
+/** The animation duration for the info bar. */
+extern const CGFloat MDCCollectionInfoBarAnimationDuration;
+
+/** Height for the info bar when shown in header. */
+extern const CGFloat MDCCollectionInfoBarHeaderHeight;
+
+/** Height for the info bar when shown in footer. */
+extern const CGFloat MDCCollectionInfoBarFooterHeight;
+
+/** The available styles that the info bar can be shown within a collectionView. */
+typedef NS_ENUM(NSUInteger, MDCCollectionInfoBarViewStyle) {
+  MDCCollectionInfoBarViewStyleActionable,
+  MDCCollectionInfoBarViewStyleHUD
+};
+
+/** Delegate protocol for the MDCCollectionInfoBarView. */
+@protocol MDCCollectionInfoBarViewDelegate <NSObject>
+@required
+/**
+ Allows the receiver to update the info bar after it has been created.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ */
+- (void)updateControllerWithInfoBar:(nonnull MDCCollectionInfoBarView *)infoBar;
+
+@optional
+/**
+ Allows the receiver to get notifed when a tap gesture has been performed on the info bar.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ */
+- (void)didTapInfoBar:(nonnull MDCCollectionInfoBarView *)infoBar;
+
+/**
+ Allows the receiver to get notifed when an info bar will show.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition will be animated; otherwise, NO.
+ @param willAutoDismiss YES the info bar will be auto-dismissed after the time interval
+        set in @c autoDismissAfterDuration.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    willShowAnimated:(BOOL)animated
+     willAutoDismiss:(BOOL)willAutoDismiss;
+
+/**
+ Allows the receiver to get notifed after an info bar did show.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition was animated; otherwise, NO.
+ @param willAutoDismiss YES the info bar will be auto-dismissed after the time interval
+        set in @c autoDismissAfterDuration.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    didShowAnimated:(BOOL)animated
+    willAutoDismiss:(BOOL)willAutoDismiss;
+
+/**
+ Allows the receiver to get notifed when an info bar will dismiss.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition will be animated; otherwise, NO.
+ @param willAutoDismiss YES the info bar will be auto-dismissed after the time interval
+        set in @c autoDismissAfterDuration.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    willDismissAnimated:(BOOL)animated
+        willAutoDismiss:(BOOL)willAutoDismiss;
+
+/**
+ Allows the receiver to get notifed after an info bar has been dismissed.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition was animated; otherwise, NO.
+ @param didAutoDismiss YES the info bar was auto-dismissed.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    didDismissAnimated:(BOOL)animated
+        didAutoDismiss:(BOOL)didAutoDismiss;
+
+@end
+
+/**
+ The MDCCollectionInfoBarView class provides an implementation of
+ UICollectionReusableView that displays an animated view in either the header
+ or footer.
+ */
+@interface MDCCollectionInfoBarView : UICollectionReusableView
+
+/** A delegate through which the MDCCollectionInfoBarView may inform of updates. */
+@property(nonatomic, weak, nullable) id<MDCCollectionInfoBarViewDelegate> delegate;
+
+/** The background view containing the message label. This view is animatable on show/dismiss. */
+@property(nonatomic, readonly, strong, nullable) UIView *backgroundView;
+
+/** Whether the background view should be shown with a shadow. */
+@property(nonatomic, assign) BOOL shouldApplyBackgroundViewShadow;
+
+/**
+ The color assigned to the background view.
+
+ Defaults to #448AFF for header, and white for footer.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *tintColor;
+
+/**
+ The color assigned to the info bar message label.
+
+ Defaults to white for header, and #F44336 for footer.
+ */
+@property(nonatomic, strong, nullable) UIColor *titleColor;
+
+/** The info bar message label. */
+@property(nonatomic, readonly, strong, nullable) UILabel *titleLabel;
+
+/** The info bar message text. */
+@property(nonatomic, strong, nullable) NSString *message;
+
+/** The horizontal position of bar message. */
+@property(nonatomic, assign) NSTextAlignment textAlignment;
+
+/** Whether the background view can receive a tap gesture. */
+@property(nonatomic, assign) BOOL allowsTap;
+
+/** The optional style that the info bar can be shown. */
+@property(nonatomic, assign) MDCCollectionInfoBarViewStyle style;
+
+/**
+ The info bar supplementary view kind as set by the collectionView model
+ |collectionView:viewForSupplementaryElementOfKind:atIndexPath| method. Possible values
+ are MDCCollectionInfoBarKindHeader or MDCCollectionInfoBarKindFooter.
+ */
+@property(nonatomic, strong, nonnull) NSString *kind;
+
+/**
+ The desired duration after which the info bar will be automatically dismissed. If set to
+ 0, autoDismiss will be ignored.
+ */
+@property(nonatomic, assign) NSTimeInterval autoDismissAfterDuration;
+
+/** Whether the info bar is currently being shown. */
+@property(nonatomic, readonly, assign) BOOL isVisible;
+
+/**
+ Shows the info bar with/without animation.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)showAnimated:(BOOL)animated;
+
+/**
+ Dismisses the info bar with/without animation.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)dismissAnimated:(BOOL)animated;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.m
new file mode 100644
index 0000000..7d7c4ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.m
@@ -0,0 +1,254 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionInfoBarView.h"
+
+#import "MaterialShadowLayer.h"
+#import "MaterialTypography.h"
+
+NSString *const MDCCollectionInfoBarKindHeader = @"MDCCollectionInfoBarKindHeader";
+NSString *const MDCCollectionInfoBarKindFooter = @"MDCCollectionInfoBarKindFooter";
+
+const CGFloat MDCCollectionInfoBarAnimationDuration = 0.3f;
+const CGFloat MDCCollectionInfoBarHeaderHeight = 48.0f;
+const CGFloat MDCCollectionInfoBarFooterHeight = 48.0f;
+
+static const CGFloat MDCCollectionInfoBarLabelHorizontalPadding = 16.0f;
+
+// Colors derived from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t kCollectionInfoBarBlueColor = 0x448AFF;  // Blue A200
+static const uint32_t kCollectionInfoBarRedColor = 0xF44336;   // Red 500
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+@interface ShadowedView : UIView
+@end
+
+@implementation ShadowedView
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+@end
+
+@implementation MDCCollectionInfoBarView {
+  CGFloat _backgroundTransformY;
+  CALayer *_backgroundBorderLayer;
+  UITapGestureRecognizer *_tapGesture;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionInfoBarViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionInfoBarViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionInfoBarViewInit {
+  self.backgroundColor = [UIColor clearColor];
+  self.userInteractionEnabled = NO;
+  _backgroundView = [[ShadowedView alloc] initWithFrame:self.bounds];
+  _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  _backgroundView.hidden = YES;
+
+  _titleLabel = [[UILabel alloc]
+      initWithFrame:CGRectInset(self.bounds, MDCCollectionInfoBarLabelHorizontalPadding, 0)];
+  _titleLabel.backgroundColor = [UIColor clearColor];
+  _titleLabel.textAlignment = NSTextAlignmentCenter;
+  _titleLabel.font = [MDCTypography body1Font];
+  _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  [_backgroundView addSubview:_titleLabel];
+
+  [self addSubview:_backgroundView];
+
+  _tapGesture =
+      [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
+  [_backgroundView addGestureRecognizer:_tapGesture];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  if (_shouldApplyBackgroundViewShadow) {
+    [self setShouldApplyBackgroundViewShadow:_shouldApplyBackgroundViewShadow];
+  }
+}
+
+- (void)layoutSublayersOfLayer:(CALayer *)layer {
+  [super layoutSublayersOfLayer:layer];
+  // Set border layer frame.
+  _backgroundBorderLayer.frame = CGRectMake(-1, 0, CGRectGetWidth(self.backgroundView.bounds) + 2,
+                                            CGRectGetHeight(self.backgroundView.bounds) + 1);
+}
+
+- (void)setTintColor:(UIColor *)tintColor {
+  _tintColor = tintColor;
+  _backgroundView.backgroundColor = _tintColor;
+}
+
+- (void)setMessage:(NSString *)message {
+  _message = message;
+  _titleLabel.text = message;
+}
+
+- (void)setKind:(NSString *)kind {
+  _kind = kind;
+  if ([kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+    _backgroundTransformY = -MDCCollectionInfoBarHeaderHeight;
+  } else {
+    _backgroundTransformY = MDCCollectionInfoBarFooterHeight;
+  }
+  _backgroundView.transform = CGAffineTransformMakeTranslation(0, _backgroundTransformY);
+}
+
+- (void)setShouldApplyBackgroundViewShadow:(BOOL)shouldApplyBackgroundViewShadow {
+  _shouldApplyBackgroundViewShadow = shouldApplyBackgroundViewShadow;
+  MDCShadowLayer *shadowLayer = (MDCShadowLayer *)_backgroundView.layer;
+  shadowLayer.elevation = shouldApplyBackgroundViewShadow ? 1 : 0;
+}
+
+- (void)setTextAlignment:(NSTextAlignment)textAlignment {
+  _textAlignment = textAlignment;
+  _titleLabel.textAlignment = textAlignment;
+}
+
+- (void)setStyle:(MDCCollectionInfoBarViewStyle)style {
+  _style = style;
+  if (style == MDCCollectionInfoBarViewStyleHUD) {
+    self.allowsTap = NO;
+    self.shouldApplyBackgroundViewShadow = NO;
+    self.textAlignment = NSTextAlignmentLeft;
+    self.tintColor = ColorFromRGB(kCollectionInfoBarBlueColor);
+    self.titleLabel.textColor = [UIColor whiteColor];
+    self.autoDismissAfterDuration = 1.0f;
+    self.backgroundView.alpha = 0.9f;
+  } else if (style == MDCCollectionInfoBarViewStyleActionable) {
+    self.allowsTap = YES;
+    self.shouldApplyBackgroundViewShadow = YES;
+    self.textAlignment = NSTextAlignmentCenter;
+    self.tintColor = [UIColor whiteColor];
+    self.titleLabel.textColor = ColorFromRGB(kCollectionInfoBarRedColor);
+    self.autoDismissAfterDuration = 0.0f;
+    self.backgroundView.alpha = 1.0f;
+    self.isAccessibilityElement = YES;
+    self.accessibilityTraits = UIAccessibilityTraitButton;
+    self.accessibilityLabel = self.message;
+
+    // Adds border to be positioned during sublayer layout.
+    self.backgroundView.clipsToBounds = YES;
+    if (!_backgroundBorderLayer) {
+      _backgroundBorderLayer = [CALayer layer];
+      _backgroundBorderLayer.borderColor = [UIColor colorWithWhite:0 alpha:0.1f].CGColor;
+      _backgroundBorderLayer.borderWidth = 1.0f / [[UIScreen mainScreen] scale];
+      [self.backgroundView.layer addSublayer:_backgroundBorderLayer];
+    }
+  }
+}
+
+- (BOOL)isVisible {
+  return !_backgroundView.hidden;
+}
+
+- (void)showAnimated:(BOOL)animated {
+  _backgroundView.hidden = NO;
+  // Notify delegate.
+  if ([_delegate respondsToSelector:@selector(infoBar:willShowAnimated:willAutoDismiss:)]) {
+    [_delegate infoBar:self willShowAnimated:animated willAutoDismiss:[self shouldAutoDismiss]];
+  }
+
+  NSTimeInterval duration = (animated) ? MDCCollectionInfoBarAnimationDuration : 0.0f;
+  [UIView animateWithDuration:duration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseOut
+      animations:^{
+        _backgroundView.transform = CGAffineTransformIdentity;
+      }
+      completion:^(BOOL finished) {
+        self.userInteractionEnabled = _allowsTap;
+
+        // Notify delegate.
+        if ([_delegate respondsToSelector:@selector(infoBar:didShowAnimated:willAutoDismiss:)]) {
+          [_delegate infoBar:self
+              didShowAnimated:animated
+              willAutoDismiss:[self shouldAutoDismiss]];
+        }
+
+        [self autoDismissIfNecessaryWithAnimation:animated];
+      }];
+}
+
+- (void)dismissAnimated:(BOOL)animated {
+  // Notify delegate.
+  if ([_delegate respondsToSelector:@selector(infoBar:willDismissAnimated:willAutoDismiss:)]) {
+    [_delegate infoBar:self willDismissAnimated:animated willAutoDismiss:[self shouldAutoDismiss]];
+  }
+
+  NSTimeInterval duration = (animated) ? MDCCollectionInfoBarAnimationDuration : 0.0f;
+  [UIView animateWithDuration:duration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseIn
+      animations:^{
+        _backgroundView.transform = CGAffineTransformMakeTranslation(0, _backgroundTransformY);
+      }
+      completion:^(BOOL finished) {
+        self.userInteractionEnabled = NO;
+        _backgroundView.hidden = YES;
+
+        // Notify delegate.
+        if ([_delegate respondsToSelector:@selector(infoBar:didDismissAnimated:didAutoDismiss:)]) {
+          [_delegate infoBar:self
+              didDismissAnimated:animated
+                  didAutoDismiss:[self shouldAutoDismiss]];
+        }
+      }];
+}
+
+#pragma mark - Private
+
+- (void)handleTapGesture:(UITapGestureRecognizer *)recognizer {
+  if ([_delegate respondsToSelector:@selector(didTapInfoBar:)]) {
+    [_delegate didTapInfoBar:self];
+  }
+}
+
+- (BOOL)shouldAutoDismiss {
+  return (_autoDismissAfterDuration > 0);
+}
+
+- (void)autoDismissIfNecessaryWithAnimation:(BOOL)animation {
+  if ([self shouldAutoDismiss]) {
+    dispatch_time_t popTime =
+        dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoDismissAfterDuration * NSEC_PER_SEC));
+    dispatch_after(popTime, dispatch_get_main_queue(), ^{
+      [self dismissAnimated:animation];
+    });
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h
new file mode 100644
index 0000000..9390b5b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ Shorthand for returning a resource from MDCCollectionStringResources's singleton.
+ */
+#define MDCCollectionStringResources(sel) [[MDCCollectionStringResources sharedInstance] sel]
+
+/** String resources that are used for collection views. */
+@interface MDCCollectionStringResources : NSObject
+
+/** Returns the shared resources singleton instance. */
++ (nonnull instancetype)sharedInstance;
+
+/** Returns cell delete string. */
+- (nonnull NSString *)deleteButtonString;
+
+/** Returns cell gesture hint string. */
+- (nonnull NSString *)infoBarGestureHintString;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.m
new file mode 100644
index 0000000..9e269c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.m
@@ -0,0 +1,72 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionStringResources.h"
+
+#import "MaterialCollectionsStrings.h"
+#import "MaterialCollectionsStrings_table.h"
+
+// The Bundle for string resources.
+static NSString *const kBundleName = @"MaterialCollections.bundle";
+
+@implementation MDCCollectionStringResources
+
++ (instancetype)sharedInstance {
+  static MDCCollectionStringResources *sharedInstance;
+  @synchronized(self) {
+    if (sharedInstance == nil) {
+      sharedInstance = [[MDCCollectionStringResources alloc] init];
+    }
+  }
+  return sharedInstance;
+}
+
+- (NSString *)stringForId:(MaterialCollectionsStringId)stringID {
+  NSString *stringKey = kMaterialCollectionsStringTable[stringID];
+  NSBundle *bundle = [[self class] bundle];
+  NSString *tableName = [kBundleName stringByDeletingPathExtension];
+  return [bundle localizedStringForKey:stringKey value:nil table:tableName];
+}
+
+- (NSString *)deleteButtonString {
+  return [self stringForId:kStr_MaterialCollectionsDeleteButton];
+}
+
+- (NSString *)infoBarGestureHintString {
+  return [self stringForId:kStr_MaterialCollectionsInfoBarGestureHint];
+}
+
+#pragma mark - Resource bundle
+
++ (NSBundle *)bundle {
+  static NSBundle *bundle = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    bundle = [NSBundle bundleWithPath:[self bundlePathWithName:kBundleName]];
+  });
+
+  return bundle;
+}
+
++ (NSString *)bundlePathWithName:(NSString *)bundleName {
+  // In iOS 8+, we could be included by way of a dynamic framework, and our resource bundles may
+  // not be in the main .app bundle, but rather in a nested framework, so figure out where we live
+  // and use that as the search location.
+  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+  NSString *resourcePath = [(nil == bundle ? [NSBundle mainBundle] : bundle)resourcePath];
+  return [resourcePath stringByAppendingPathComponent:bundleName];
+}
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h
new file mode 100644
index 0000000..e020ef8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewEditing.h"
+
+/**
+ The MDCCollectionViewEditingManager class provides an implementation for a UICollectionView to
+ set its editing properties.
+ */
+@interface MDCCollectionViewEditor : NSObject <MDCCollectionViewEditing>
+
+/**
+ Initialize the controller with a collection view.
+
+ Designated initializer.
+
+ @param collectionView The controller's collection view.
+ */
+- (nonnull instancetype)initWithCollectionView:(nullable UICollectionView *)collectionView
+    NS_DESIGNATED_INITIALIZER;
+
+/** Use initWithCollectionView: instead. */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/** Use initWithCollectionView: instead. */
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.m
new file mode 100644
index 0000000..9a4a25e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.m
@@ -0,0 +1,819 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewEditor.h"
+
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MaterialShadowLayer.h"
+
+#import <tgmath.h>
+
+// Distance from center before we start fading the item.
+static const CGFloat kDismissalDistanceBeforeFading = 50.0f;
+
+// Minimum alpha for an item being dismissed.
+static const CGFloat kDismissalMinimumAlpha = 0.5f;
+
+// Final angle of the arc the item travels through during dismissal.
+static const CGFloat kDismissalArcAngle = (CGFloat)(M_PI / 6.0f);
+
+// The centroid for the item dismissal arc.
+static const CGFloat kDismissalArcYOffset = 400.0f;
+
+// Simple linear friction applied to swipe velocity.
+static const CGFloat kDismissalSwipeFriction = 0.05f;
+
+// Animation duration for dismissal / restore.
+static const NSTimeInterval kDismissalAnimationDuration = 0.3;
+static const NSTimeInterval kRestoreAnimationDuration = 0.2;
+
+// Distance from collection view bounds that reorder panning should trigger autoscroll.
+static const CGFloat kMDCAutoscrollPanningBuffer = 60.0f;
+
+// Distance collection view should offset during autoscroll.
+static const CGFloat kMDCAutoscrollPanningOffset = 10.0f;
+
+/** Autoscroll panning direction. */
+typedef NS_ENUM(NSInteger, MDCAutoscrollPanningDirection) {
+  kMDCAutoscrollPanningDirectionNone,
+  kMDCAutoscrollPanningDirectionUp,
+  kMDCAutoscrollPanningDirectionDown
+};
+
+/** A view that uses an MDCShadowLayer as its sublayer. */
+@interface ShadowedSnapshotView : UIView
+@end
+
+@implementation ShadowedSnapshotView
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+@end
+
+@interface MDCCollectionViewEditor () <UIGestureRecognizerDelegate>
+@end
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCCollectionViewEditor () <CAAnimationDelegate>
+@end
+#endif
+
+@implementation MDCCollectionViewEditor {
+  UILongPressGestureRecognizer *_longPressGestureRecognizer;
+  UIPanGestureRecognizer *_panGestureRecognizer;
+  CGPoint _selectedCellLocation;
+  CGPoint _initialCellLocation;
+  ShadowedSnapshotView *_cellSnapshot;
+  CADisplayLink *_autoscrollTimer;
+  MDCAutoscrollPanningDirection _autoscrollPanningDirection;
+}
+
+@synthesize collectionView = _collectionView;
+@synthesize delegate = _delegate;
+@synthesize reorderingCellIndexPath = _reorderingCellIndexPath;
+@synthesize dismissingCellIndexPath = _dismissingCellIndexPath;
+@synthesize dismissingSection = _dismissingSection;
+@synthesize editing = _editing;
+
+#pragma mark - Public
+
+- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
+  self = [super init];
+  if (self) {
+    _collectionView = collectionView;
+    _dismissingSection = NSNotFound;
+
+    // Setup gestures to handle collectionView editing.
+
+    SEL longPressSelector = @selector(handleLongPressGesture:);
+    _longPressGestureRecognizer =
+        [[UILongPressGestureRecognizer alloc] initWithTarget:self action:longPressSelector];
+    _longPressGestureRecognizer.delegate = self;
+    [_collectionView addGestureRecognizer:_longPressGestureRecognizer];
+
+    SEL panSelector = @selector(handlePanGesture:);
+    _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:panSelector];
+    _panGestureRecognizer.delegate = self;
+    [_collectionView addGestureRecognizer:_panGestureRecognizer];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  _longPressGestureRecognizer.delegate = nil;
+  _panGestureRecognizer.delegate = nil;
+
+  // Remove gesture recognizers to prevent duplicates when re-initializing this controller.
+  [_collectionView removeGestureRecognizer:_longPressGestureRecognizer];
+  [_collectionView removeGestureRecognizer:_panGestureRecognizer];
+}
+
+- (void)setEditing:(BOOL)editing {
+  [self setEditing:editing animated:NO];
+}
+
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
+  _editing = editing;
+  _collectionView.allowsMultipleSelection = editing;
+
+  // Clear any selected indexPaths.
+  for (NSIndexPath *indexPath in [_collectionView indexPathsForSelectedItems]) {
+    [_collectionView deselectItemAtIndexPath:indexPath animated:NO];
+  }
+
+  [CATransaction begin];
+  if (editing) {
+    // Notify delegate will begin editing.
+    if ([_delegate respondsToSelector:@selector(collectionViewWillBeginEditing:)]) {
+      [_delegate collectionViewWillBeginEditing:_collectionView];
+    }
+
+    [CATransaction setCompletionBlock:^{
+      // Notify delegate did begin editing.
+      if ([_delegate respondsToSelector:@selector(collectionViewDidBeginEditing:)]) {
+        [_delegate collectionViewDidBeginEditing:_collectionView];
+      }
+    }];
+
+  } else {
+    // Notify delegate will end editing.
+    if ([_delegate respondsToSelector:@selector(collectionViewWillEndEditing:)]) {
+      [_delegate collectionViewWillEndEditing:_collectionView];
+    }
+
+    [CATransaction setCompletionBlock:^{
+      // Notify delegate did end editing.
+      if ([_delegate respondsToSelector:@selector(collectionViewDidEndEditing:)]) {
+        [_delegate collectionViewDidEndEditing:_collectionView];
+      }
+    }];
+  }
+  [CATransaction commit];
+}
+
+#pragma mark - Private
+
+- (NSArray *)attributesAtSection:(NSInteger)section {
+  UICollectionViewLayout *layout = _collectionView.collectionViewLayout;
+  NSIndexPath *indexPath;
+  NSMutableArray *sectionAttributes = [NSMutableArray array];
+
+  // Get all item attributes at section.
+  NSInteger numberOfItemsInSection = [_collectionView numberOfItemsInSection:section];
+
+  for (NSInteger i = 0; i < numberOfItemsInSection; ++i) {
+    indexPath = [NSIndexPath indexPathForItem:i inSection:section];
+    UICollectionViewLayoutAttributes *attribute =
+        [layout layoutAttributesForItemAtIndexPath:indexPath];
+    [sectionAttributes addObject:attribute];
+  }
+
+  // Headers/footers require section but ignore item of index path, so set to zero.
+  indexPath = [NSIndexPath indexPathForItem:0 inSection:section];
+
+  // Get header attributes at section.
+  UICollectionViewLayoutAttributes *headerAttribute =
+      [layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
+                                             atIndexPath:indexPath];
+  [sectionAttributes addObject:headerAttribute];
+
+  // Get footer attributes at section.
+  UICollectionViewLayoutAttributes *footerAttribute =
+      [layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter
+                                             atIndexPath:indexPath];
+  [sectionAttributes addObject:footerAttribute];
+
+  return sectionAttributes;
+}
+
+- (NSInteger)swipedSectionAtLocation:(CGPoint)location {
+  // Returns section index being swiped for dismissal, or NSNotFound for an invalid swipes
+  // where location does not return an item or section header/footer.
+  CGRect contentFrame = _collectionView.frame;
+  contentFrame.size = _collectionView.contentSize;
+  NSArray *visibleAttributes =
+      [_collectionView.collectionViewLayout layoutAttributesForElementsInRect:contentFrame];
+  for (UICollectionViewLayoutAttributes *attribute in visibleAttributes) {
+    if (!CGRectIsNull(attribute.frame) && CGRectContainsPoint(attribute.frame, location)) {
+      return attribute.indexPath.section;
+    }
+  }
+  return NSNotFound;
+}
+
+#pragma mark - Snapshotting
+
+- (UIView *)snapshotWithIndexPath:(NSIndexPath *)indexPath {
+  // Here we will take a snapshot of the collectionView item.
+  if (_cellSnapshot) {
+    [_cellSnapshot removeFromSuperview];
+    _cellSnapshot = nil;
+  }
+
+  // Create snapshot.
+  UICollectionViewLayoutAttributes *attributes =
+      [_collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
+  _cellSnapshot = [[ShadowedSnapshotView alloc] initWithFrame:attributes.frame];
+  UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath];
+  [_cellSnapshot addSubview:[cell snapshotViewAfterScreenUpdates:NO]];
+
+  // Invalidate layout here to force attributes to now be hidden.
+  [_collectionView.collectionViewLayout invalidateLayout];
+  return _cellSnapshot;
+}
+
+- (UIView *)snapshotWithSection:(NSInteger)section {
+  // Here we will take a snapshot of the collectionView section items, header, and footer.
+  if (_cellSnapshot) {
+    [_cellSnapshot removeFromSuperview];
+    _cellSnapshot = nil;
+  }
+
+  // The snapshot frame encompasses all of the section items, header, and footer attribute frames.
+  NSArray *sectionAttributes = [self attributesAtSection:section];
+  CGRect snapshotFrame = CGRectNull;
+  for (UICollectionViewLayoutAttributes *attribute in sectionAttributes) {
+    if (!CGRectIsNull(attribute.frame) && !CGRectIsInfinite(attribute.frame)) {
+      snapshotFrame = CGRectUnion(snapshotFrame, attribute.frame);
+    }
+  }
+
+  // Create snapshot.
+  _cellSnapshot = [[ShadowedSnapshotView alloc] initWithFrame:snapshotFrame];
+  UIImageView *snapshotView =
+      [[UIImageView alloc] initWithImage:[self snapshotWithRect:snapshotFrame]];
+  [_cellSnapshot addSubview:snapshotView];
+
+  // Invalidate layout here to force attributes to now be hidden.
+  [_collectionView.collectionViewLayout invalidateLayout];
+  return _cellSnapshot;
+}
+
+- (UIImage *)snapshotWithRect:(CGRect)rect {
+  // Here we will take a snapshot of a rect within the collectionView.
+  UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
+  CGContextRef cx = UIGraphicsGetCurrentContext();
+  CGContextTranslateCTM(cx, -rect.origin.x, -rect.origin.y);
+
+  // Save original collection view properties.
+  id<UICollectionViewDelegate> savedDelegate = _collectionView.delegate;
+  _collectionView.delegate = nil;
+  CGPoint savedContentOffset = _collectionView.contentOffset;
+  BOOL savedClipsToBounds = _collectionView.clipsToBounds;
+  _collectionView.clipsToBounds = NO;
+
+  // Hide any scroll indicators.
+  BOOL showsHorizontalScrollIndicator = _collectionView.showsHorizontalScrollIndicator;
+  BOOL showsVerticalScrollIndicator = _collectionView.showsVerticalScrollIndicator;
+  _collectionView.showsHorizontalScrollIndicator = NO;
+  _collectionView.showsVerticalScrollIndicator = NO;
+
+  // Render snapshot.
+  [_collectionView.layer renderInContext:cx];
+  _collectionView.layer.rasterizationScale = [UIScreen mainScreen].scale;
+  _collectionView.layer.shouldRasterize = YES;
+  UIImage *screenshotImage = UIGraphicsGetImageFromCurrentImageContext();
+
+  // Reset collection view.
+  _collectionView.contentOffset = savedContentOffset;
+  _collectionView.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
+  _collectionView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
+  _collectionView.delegate = savedDelegate;
+  _collectionView.clipsToBounds = savedClipsToBounds;
+  _collectionView.layer.shouldRasterize = NO;
+
+  UIGraphicsEndImageContext();
+  return screenshotImage;
+}
+
+- (void)applyLayerShadowing:(CALayer *)layer {
+  MDCShadowLayer *shadowLayer = (MDCShadowLayer *)_cellSnapshot.layer;
+  shadowLayer.shadowMaskEnabled = NO;
+  shadowLayer.elevation = 3;
+}
+
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
+  if ([gestureRecognizer isEqual:_longPressGestureRecognizer]) {
+    // Only allow longpress if collectionView is editing.
+    return self.isEditing;
+
+  } else if ([gestureRecognizer isEqual:_panGestureRecognizer]) {
+    // Only allow panning if collectionView is editing or dismissing item/section.
+    BOOL allowsSwipeToDismissItem = NO;
+    if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissItem:)]) {
+      allowsSwipeToDismissItem = [_delegate collectionViewAllowsSwipeToDismissItem:_collectionView];
+    }
+
+    BOOL allowsSwipeToDismissSection = NO;
+    if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissSection:)]) {
+      allowsSwipeToDismissSection =
+          [_delegate collectionViewAllowsSwipeToDismissSection:_collectionView];
+    }
+    return (self.isEditing || allowsSwipeToDismissItem || allowsSwipeToDismissSection);
+  }
+  return YES;
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+    shouldRecognizeSimultaneouslyWithGestureRecognizer:
+        (UIGestureRecognizer *)otherGestureRecognizer {
+  return YES;
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+    shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
+  // Prevent panning to dismiss when scrolling.
+  return ([gestureRecognizer isEqual:_panGestureRecognizer] &&
+          [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]);
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+       shouldReceiveTouch:(UITouch *)touch {
+  if (self.isEditing) {
+    return YES;
+  } else {
+    return NO;
+  }
+}
+
+#pragma mark - LongPress Gesture Handling
+
+- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)recognizer {
+  switch (recognizer.state) {
+    case UIGestureRecognizerStateBegan: {
+      _initialCellLocation = [recognizer locationInView:_collectionView];
+      _selectedCellLocation = [recognizer locationInView:_collectionView];
+      _reorderingCellIndexPath = [_collectionView indexPathForItemAtPoint:_selectedCellLocation];
+
+      if ([_delegate respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] &&
+          ![_delegate collectionView:_collectionView
+              canMoveItemAtIndexPath:_reorderingCellIndexPath]) {
+        _reorderingCellIndexPath = nil;
+        return;
+      }
+
+      // Notify delegate dragging has began.
+      if ([_delegate
+              respondsToSelector:@selector(collectionView:willBeginDraggingItemAtIndexPath:)]) {
+        [_delegate collectionView:_collectionView
+            willBeginDraggingItemAtIndexPath:_reorderingCellIndexPath];
+      }
+
+      // Create cell snapshot with shadowing.
+      [_collectionView addSubview:[self snapshotWithIndexPath:_reorderingCellIndexPath]];
+      [self applyLayerShadowing:_cellSnapshot.layer];
+
+      // Disable scrolling.
+      [_collectionView setScrollEnabled:NO];
+      break;
+    }
+    case UIGestureRecognizerStateCancelled:
+    case UIGestureRecognizerStateEnded: {
+      // Stop autoscroll.
+      [self stopAutoscroll];
+      NSIndexPath *currentIndexPath = _reorderingCellIndexPath;
+      if (currentIndexPath) {
+        UICollectionViewLayoutAttributes *attributes = [_collectionView.collectionViewLayout
+            layoutAttributesForItemAtIndexPath:currentIndexPath];
+
+        void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+          // Notify delegate dragging has finished.
+          if ([_delegate
+                  respondsToSelector:@selector(collectionView:didEndDraggingItemAtIndexPath:)]) {
+            [_delegate collectionView:_collectionView
+                didEndDraggingItemAtIndexPath:_reorderingCellIndexPath];
+          }
+          [self restoreEditingItem];
+
+          // Re-enable scrolling.
+          [_collectionView setScrollEnabled:YES];
+        };
+
+        [UIView animateWithDuration:kDismissalAnimationDuration
+                              delay:0
+                            options:UIViewAnimationOptionBeginFromCurrentState
+                         animations:^{
+                           _cellSnapshot.frame = attributes.frame;
+                         }
+                         completion:completionBlock];
+      }
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+#pragma mark - Pan Gesture Handling
+
+- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {
+  if (_reorderingCellIndexPath) {
+    [self panToReorderWithRecognizer:recognizer];
+  } else {
+    [self panToDismissWithRecognizer:recognizer];
+  }
+}
+
+- (void)panToReorderWithRecognizer:(UIPanGestureRecognizer *)recognizer {
+  if (recognizer.state == UIGestureRecognizerStateChanged) {
+    // Transform snapshot position when panning.
+    _selectedCellLocation = [recognizer locationInView:_collectionView];
+    CGFloat change = _selectedCellLocation.y - _initialCellLocation.y;
+    CGAffineTransform transform = CGAffineTransformMakeTranslation(0, change);
+    _cellSnapshot.layer.transform = CATransform3DMakeAffineTransform(transform);
+
+    // Determine moved index paths.
+    NSIndexPath *newIndexPath = [_collectionView indexPathForItemAtPoint:_selectedCellLocation];
+    NSIndexPath *previousIndexPath = _reorderingCellIndexPath;
+    if ((newIndexPath == nil) || [newIndexPath isEqual:previousIndexPath]) {
+      return;
+    }
+
+    // Autoscroll if the cell is dragged out of the collectionView's bounds.
+    CGFloat buffer = kMDCAutoscrollPanningBuffer;
+    if (_selectedCellLocation.y < CGRectGetMinY(self.collectionView.bounds) + buffer) {
+      [self startAutoscroll];
+      _autoscrollPanningDirection = kMDCAutoscrollPanningDirectionUp;
+    } else if (_selectedCellLocation.y > (CGRectGetMaxY(self.collectionView.bounds) - buffer)) {
+      [self startAutoscroll];
+      _autoscrollPanningDirection = kMDCAutoscrollPanningDirectionDown;
+    } else {
+      [self stopAutoscroll];
+    }
+
+    // Check delegate for permission to move item.
+    if ([_delegate
+            respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:toIndexPath:)]) {
+      if ([_delegate collectionView:_collectionView
+              canMoveItemAtIndexPath:previousIndexPath
+                         toIndexPath:newIndexPath]) {
+        _reorderingCellIndexPath = newIndexPath;
+
+        // Notify delegate that item will move.
+        if ([_delegate respondsToSelector:@selector(collectionView:
+                                              willMoveItemAtIndexPath:
+                                                          toIndexPath:)]) {
+          [_delegate collectionView:_collectionView
+              willMoveItemAtIndexPath:previousIndexPath
+                          toIndexPath:newIndexPath];
+        }
+
+        // Notify delegate item did move.
+        if ([_delegate
+                respondsToSelector:@selector(collectionView:didMoveItemAtIndexPath:toIndexPath:)]) {
+          [_delegate collectionView:_collectionView
+              didMoveItemAtIndexPath:previousIndexPath
+                         toIndexPath:newIndexPath];
+        }
+      } else {
+        // Exit if delegate will not allow this indexPath to move.
+        return;
+      }
+    }
+  }
+}
+
+- (void)panToDismissWithRecognizer:(UIPanGestureRecognizer *)recognizer {
+  CGPoint translation = [recognizer translationInView:_collectionView];
+  CGPoint velocity = [recognizer velocityInView:_collectionView];
+  CGPoint location = [recognizer locationInView:_collectionView];
+
+  switch (recognizer.state) {
+    case UIGestureRecognizerStateBegan: {
+      if (fabs(velocity.y) > fabs(velocity.x)) {
+        // Exit if panning vertically.
+        return [self exitPanToDismissWithRecognizer:recognizer];
+      }
+
+      BOOL allowsSwipeToDismissSection = NO;
+      if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissSection:)]) {
+        allowsSwipeToDismissSection =
+            [_delegate collectionViewAllowsSwipeToDismissSection:_collectionView];
+      }
+
+      BOOL allowsSwipeToDismissItem = NO;
+      if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissItem:)]) {
+        allowsSwipeToDismissItem =
+            [_delegate collectionViewAllowsSwipeToDismissItem:_collectionView];
+      }
+
+      if (allowsSwipeToDismissSection && !self.isEditing) {
+        // Determine panned section to dismiss.
+        _dismissingSection = [self swipedSectionAtLocation:location];
+        if (_dismissingSection == NSNotFound) {
+          return [self exitPanToDismissWithRecognizer:recognizer];
+        }
+
+        // Check delegate for permission to swipe section.
+        if ([_delegate respondsToSelector:@selector(collectionView:canSwipeToDismissSection:)]) {
+          if ([_delegate collectionView:_collectionView
+                  canSwipeToDismissSection:_dismissingSection]) {
+            // Notify delegate.
+            if ([_delegate
+                    respondsToSelector:@selector(collectionView:willBeginSwipeToDismissSection:)]) {
+              [_delegate collectionView:_collectionView
+                  willBeginSwipeToDismissSection:_dismissingSection];
+            }
+          } else {
+            // Cannot swipe so exit.
+            return [self exitPanToDismissWithRecognizer:recognizer];
+          }
+        }
+
+        // Create section snapshot.
+        [_collectionView insertSubview:[self snapshotWithSection:_dismissingSection] atIndex:0];
+        break;
+
+      } else if (allowsSwipeToDismissItem) {
+        // Determine panned index path to dismiss.
+        _dismissingCellIndexPath = [_collectionView indexPathForItemAtPoint:location];
+        if (!_dismissingCellIndexPath) {
+          return [self exitPanToDismissWithRecognizer:recognizer];
+        }
+
+        // Check delegate for permission to swipe item.
+        if ([_delegate
+                respondsToSelector:@selector(collectionView:canSwipeToDismissItemAtIndexPath:)]) {
+          if ([_delegate collectionView:_collectionView
+                  canSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath]) {
+            // Notify delegate.
+            if ([_delegate respondsToSelector:@selector(collectionView:
+                                                  willBeginSwipeToDismissItemAtIndexPath:)]) {
+              [_delegate collectionView:_collectionView
+                  willBeginSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath];
+            }
+          } else {
+            // Cannot swipe so exit.
+            return [self exitPanToDismissWithRecognizer:recognizer];
+          }
+        }
+
+        // Create item snapshot.
+        [_collectionView insertSubview:[self snapshotWithIndexPath:_dismissingCellIndexPath]
+                               atIndex:0];
+        break;
+      }
+    }
+
+    case UIGestureRecognizerStateChanged: {
+      // Update the tracked item's position and alpha.
+      CGAffineTransform transform;
+      CGFloat alpha;
+      // The item is fully opaque until it pans at least @c kDismissalDistanceBeforeFading points.
+      CGFloat panDistance = (CGFloat)fabs(translation.x) - kDismissalDistanceBeforeFading;
+      if (panDistance > 0) {
+        transform = [self transformItemDismissalToTranslationX:translation.x];
+        alpha = [self dismissalAlphaForTranslationX:translation.x];
+      } else {
+        // Pan the item.
+        transform = CGAffineTransformMakeTranslation(translation.x, 0);
+        alpha = 1;
+      }
+      _cellSnapshot.layer.transform = CATransform3DMakeAffineTransform(transform);
+      _cellSnapshot.alpha = alpha;
+      break;
+    }
+
+    case UIGestureRecognizerStateEnded: {
+      // Check the final translation, including the final velocity, to determine
+      // if the item should be dismissed.
+      CGFloat momentumX = velocity.x * kDismissalSwipeFriction;
+      CGFloat translationX = translation.x + momentumX;
+
+      if (fabs(translationX) > [self distanceThresholdForDismissal]) {
+        // @c translationX is only guaranteed to be over the dismissal threshold;
+        // make sure the view animates all the way off the screen.
+        translationX = (CGFloat)copysign(
+            MAX(fabs(translationX), CGRectGetWidth(_collectionView.bounds)), translationX);
+        [self animateFinalItemDismissalToTranslationX:translationX];
+      } else {
+        [self restorePanningItemIfNecessaryWithMomentumX:momentumX];
+      }
+      break;
+    }
+    default: {
+      [self restorePanningItemIfNecessaryWithMomentumX:0];
+      break;
+    }
+  }
+}
+
+- (void)exitPanToDismissWithRecognizer:(UIPanGestureRecognizer *)recognizer {
+  // To exit, disable the recognizer immediately which forces it to drop out of the current
+  // loop and prevent any state updates. Then re-enable to allow future panning.
+  recognizer.enabled = NO;
+  recognizer.enabled = YES;
+}
+
+#pragma mark - Dismissal animation.
+
+- (CGAffineTransform)transformItemDismissalToTranslationX:(CGFloat)translationX {
+  // Returns a transform that can be applied to the snapshot during dismissal. The
+  // translation will pan along an arc facing downwards.
+  CGFloat panDistance = (CGFloat)fabs(translationX) - kDismissalDistanceBeforeFading;
+  CGFloat panRatio = panDistance / CGRectGetWidth(_collectionView.bounds);
+  CGFloat arcAngle = (translationX > 0 ? kDismissalArcAngle : -kDismissalArcAngle);
+
+  CGAffineTransform initialTranslation = CGAffineTransformMakeTranslation(0, -kDismissalArcYOffset);
+  CGAffineTransform rotation = CGAffineTransformMakeRotation(panRatio * arcAngle);
+
+  // Modify the X translation to take account of the rotation angle.
+  // This makes the item continue to track the finger as it follows the arc.
+  CGFloat correctedXTranslation = (CGFloat)(translationX * (1 - cos(kDismissalArcAngle) / 2));
+  if (translationX > 0) {
+    correctedXTranslation = MAX(kDismissalDistanceBeforeFading, correctedXTranslation);
+  } else {
+    correctedXTranslation = MIN(-kDismissalDistanceBeforeFading, correctedXTranslation);
+  }
+
+  // Reverse @c initialTranslation and add @c translation.x to ensure that
+  // we pan along with the arc.
+  CGAffineTransform reverseTranslation =
+      CGAffineTransformMakeTranslation(correctedXTranslation, kDismissalArcYOffset);
+
+  CGAffineTransform arcTransform = CGAffineTransformConcat(initialTranslation, rotation);
+  return CGAffineTransformConcat(arcTransform, reverseTranslation);
+}
+
+- (void)animateFinalItemDismissalToTranslationX:(CGFloat)translationX {
+  // Called at the end of a pan gesture that results in the item being dismissed.
+  // Animation that moves the dismissed item to the final location and fades it out.
+  CGAffineTransform transform = [self transformItemDismissalToTranslationX:translationX];
+
+  // Notify delegate of dismissed section.
+  if (_dismissingSection != NSNotFound) {
+    if ([_delegate respondsToSelector:@selector(collectionView:didEndSwipeToDismissSection:)]) {
+      [_delegate collectionView:_collectionView didEndSwipeToDismissSection:_dismissingSection];
+    }
+  }
+
+  // Notify delegate of dismissed item.
+  if (_dismissingCellIndexPath) {
+    if ([_delegate
+            respondsToSelector:@selector(collectionView:didEndSwipeToDismissItemAtIndexPath:)]) {
+      [_delegate collectionView:_collectionView
+          didEndSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath];
+    }
+  }
+
+  [UIView animateWithDuration:kDismissalAnimationDuration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseOut
+      animations:^{
+        _cellSnapshot.layer.transform = CATransform3DMakeAffineTransform(transform);
+        _cellSnapshot.alpha = 0;
+      }
+      completion:^(BOOL finished) {
+        [self restoreEditingItem];
+      }];
+}
+
+- (void)restorePanningItemIfNecessaryWithMomentumX:(CGFloat)momentumX {
+  // If we never had a snapshot, or the snapshot never moved, then skip straight to cleanup.
+  if (_cellSnapshot == nil || CGAffineTransformIsIdentity(_cellSnapshot.transform)) {
+    [self restoreEditingItem];
+    return;
+  }
+
+  CAAnimationGroup *allAnimations = [CAAnimationGroup animation];
+  allAnimations.duration = kRestoreAnimationDuration;
+
+  CATransform3D startTransform = CATransform3DMakeAffineTransform(_cellSnapshot.transform);
+  CATransform3D midTransform = CATransform3DTranslate(startTransform, momentumX, 0, 0);
+  CATransform3D endTransform = CATransform3DIdentity;
+
+  CAKeyframeAnimation *transformAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
+  transformAnimation.values = @[
+    [NSValue valueWithCATransform3D:startTransform], [NSValue valueWithCATransform3D:midTransform],
+    [NSValue valueWithCATransform3D:endTransform]
+  ];
+  transformAnimation.calculationMode = kCAAnimationCubicPaced;
+
+  CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+  opacityAnimation.fromValue = @(_cellSnapshot.alpha);
+  opacityAnimation.toValue = @1;
+
+  allAnimations.animations = @[ transformAnimation, opacityAnimation ];
+  allAnimations.delegate = self;
+  allAnimations.fillMode = kCAFillModeBackwards;
+  _cellSnapshot.layer.transform = CATransform3DIdentity;
+  _cellSnapshot.alpha = 1;
+  [_cellSnapshot.layer addAnimation:allAnimations forKey:nil];
+}
+
+- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)didFinish {
+  [self cancelPanningItem];
+}
+
+- (void)cancelPanningItem {
+  // Notify delegate of panned section cancellation.
+  if (_dismissingSection != NSNotFound) {
+    if ([_delegate respondsToSelector:@selector(collectionView:didCancelSwipeToDismissSection:)]) {
+      [_delegate collectionView:_collectionView didCancelSwipeToDismissSection:_dismissingSection];
+    }
+  }
+
+  // Notify delegate of panned index path cancellation.
+  if (_dismissingCellIndexPath) {
+    if ([_delegate
+            respondsToSelector:@selector(collectionView:didCancelSwipeToDismissItemAtIndexPath:)]) {
+      [_delegate collectionView:_collectionView
+          didCancelSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath];
+    }
+  }
+
+  [self restoreEditingItem];
+}
+
+- (void)restoreEditingItem {
+  // Remove snapshot and reset item.
+  [_cellSnapshot removeFromSuperview];
+  _cellSnapshot = nil;
+  _dismissingSection = NSNotFound;
+  _dismissingCellIndexPath = nil;
+  _reorderingCellIndexPath = nil;
+  [_collectionView.collectionViewLayout invalidateLayout];
+}
+
+// The distance an item must be panned before it is dismissed. Currently half of the bounds width.
+- (CGFloat)distanceThresholdForDismissal {
+  return _collectionView.bounds.size.width / 2;
+}
+
+- (CGFloat)dismissalAlphaForTranslationX:(CGFloat)translationX {
+  translationX = (CGFloat)fabs(translationX) - kDismissalDistanceBeforeFading;
+  CGFloat adjustedThreshold = [self distanceThresholdForDismissal] - kDismissalDistanceBeforeFading;
+  CGFloat dismissalPercentage = (CGFloat)MIN(1, fabs(translationX) / adjustedThreshold);
+  return kDismissalMinimumAlpha + (1 - kDismissalMinimumAlpha) * (1 - dismissalPercentage);
+}
+
+#pragma mark - Reordering Autoscroll
+
+- (void)startAutoscroll {
+  if (_autoscrollTimer) {
+    [self stopAutoscroll];
+  }
+  _autoscrollTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(autoscroll:)];
+  [_autoscrollTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
+}
+
+- (void)stopAutoscroll {
+  if (_autoscrollTimer) {
+    [_autoscrollTimer invalidate];
+    _autoscrollTimer = nil;
+    _autoscrollPanningDirection = kMDCAutoscrollPanningDirectionNone;
+  }
+}
+
+- (void)autoscroll:(CADisplayLink *)sender {
+  // Scrolls at each tick of CADisplayLink by setting scroll contentOffset. Animation is performed
+  // within UIView animation block rather than directly calling -setContentOffset:animated: method
+  // in order to prevent jerkiness in scrolling.
+  BOOL isPanningDown = _autoscrollPanningDirection == kMDCAutoscrollPanningDirectionDown;
+  CGFloat yOffset = kMDCAutoscrollPanningOffset * (isPanningDown ? 1 : -1);
+  CGFloat contentYOffset = self.collectionView.contentOffset.y;
+
+  // Quit early if scrolling past collection view bounds.
+  if ((!isPanningDown && contentYOffset <= 0) ||
+      (isPanningDown &&
+       contentYOffset >=
+           self.collectionView.contentSize.height - CGRectGetHeight(self.collectionView.bounds))) {
+    [self stopAutoscroll];
+    return;
+  }
+
+  // When autoscrolling, keep cell snapshot transform to longpress position.
+  CGAffineTransform snapshotTransform =
+      CATransform3DGetAffineTransform(_cellSnapshot.layer.transform);
+  snapshotTransform.ty += yOffset;
+
+  [UIView animateWithDuration:0.3
+                        delay:0
+                      options:UIViewAnimationOptionBeginFromCurrentState
+                   animations:^{
+                     self.collectionView.contentOffset =
+                         CGPointMake(0, MAX(0, contentYOffset + yOffset));
+
+                     // Transform snapshot position when panning.
+                     _cellSnapshot.layer.transform =
+                         CATransform3DMakeAffineTransform(snapshotTransform);
+                   }
+                   completion:nil];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h
new file mode 100644
index 0000000..6e899da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewStyling.h"
+
+/**
+ The MDCCollectionViewStyler class provides a default implementation for a UICollectionView to set
+ its style properties.
+ */
+@interface MDCCollectionViewStyler : NSObject <MDCCollectionViewStyling>
+
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Initializes and returns a newly allocated styler object with the specified collection view.
+
+ Designated initializer.
+
+ @param collectionView The controller's collection view.
+ */
+- (nonnull instancetype)initWithCollectionView:(nonnull UICollectionView *)collectionView
+    NS_DESIGNATED_INITIALIZER;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.m
new file mode 100644
index 0000000..fc8c9ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.m
@@ -0,0 +1,733 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewStyler.h"
+
+#import "MDCCollectionViewStylingDelegate.h"
+#import "MaterialCollectionLayoutAttributes.h"
+
+#import <tgmath.h>
+
+#define RGBCOLOR(r, g, b) \
+  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
+
+typedef NS_OPTIONS(NSUInteger, BackgroundCacheKey) {
+  BackgroundCacheKeyFlat = 0,
+  BackgroundCacheKeyTop = 1 << 0,
+  BackgroundCacheKeyBottom = 1 << 1,
+  BackgroundCacheKeyCard = 1 << 2,
+  BackgroundCacheKeyGrouped = 1 << 3,
+  BackgroundCacheKeyHighlighted = 1 << 4,
+  BackgroundCacheKeyMax = 1 << 5,
+};
+
+const CGFloat MDCCollectionViewCellStyleCardSectionInset = 8.0f;
+
+/** Cell content view insets for card-style cells */
+static const CGFloat kFourThirds = 4.0f / 3.0f;
+static const UIEdgeInsets kCollectionViewCellContentInsetsRetina3x = {kFourThirds, kFourThirds,
+                                                                      kFourThirds, kFourThirds};
+static const UIEdgeInsets kCollectionViewCellContentInsetsRetina = {1.5, 1.5, 1.5, 1.5};
+static const UIEdgeInsets kCollectionViewCellContentInsets = {1, 2, 1, 2};
+
+/** Default cell separator style settings */
+static const CGFloat kCollectionViewCellSeparatorDefaultHeightInPixels = 1.0f;
+
+/** Grid layout defaults */
+static const NSInteger kCollectionViewGridDefaultColumnCount = 2;
+static const CGFloat kCollectionViewGridDefaultPadding = 4.0f;
+
+/** The drawn cell background */
+static const CGSize kCellImageSize = {44, 44};
+static const CGFloat kCollectionViewCellDefaultBorderWidth = 1.0f;
+static const CGFloat kCollectionViewCellDefaultBorderRadius = 1.5f;
+static inline UIColor *kCollectionViewCellDefaultBorderColor() {
+  return [UIColor colorWithWhite:0 alpha:0.05f];
+}
+
+/** Cell shadowing */
+static const CGFloat kCollectionViewCellDefaultShadowWidth = 1.0f;
+static inline CGSize kCollectionViewCellDefaultShadowOffset() {
+  return CGSizeMake(0, 1);
+}
+static inline UIColor *kCollectionViewCellDefaultShadowColor() {
+  return [UIColor colorWithWhite:0 alpha:0.1f];
+}
+
+/** Animate cell on appearance settings */
+static const CGFloat kCollectionViewAnimatedAppearancePadding = 20.0f;
+static const NSTimeInterval kCollectionViewAnimatedAppearanceDelay = 0.1;
+static const NSTimeInterval kCollectionViewAnimatedAppearanceDuration = 0.3;
+
+/** Modifies only the right and bottom edges of a CGRect. */
+NS_INLINE CGRect RectContract(CGRect rect, CGFloat dx, CGFloat dy) {
+  return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width - dx, rect.size.height - dy);
+}
+
+/** Modifies only the top and left edges of a CGRect. */
+NS_INLINE CGRect RectShift(CGRect rect, CGFloat dx, CGFloat dy) {
+  return CGRectOffset(RectContract(rect, dx, dy), dx, dy);
+}
+
+@interface MDCCollectionViewStyler ()
+
+/**
+ A dictionary of NSPointerArray caches, keyed by UIColor, for cached cell background images
+ using that background color. Index into the NSPointerArray using the results of
+ backgroundCacheKeyForCardStyle:isGroupedStyle:isTop:isBottom:isHighlighted:
+ */
+@property(nonatomic, readonly) NSMutableDictionary *cellBackgroundCaches;
+
+/** An set of index paths for items that are inlaid. */
+@property(nonatomic, strong) NSMutableSet *inlaidIndexPathSet;
+
+@end
+
+@implementation MDCCollectionViewStyler
+
+@synthesize collectionView = _collectionView;
+@synthesize delegate = _delegate;
+@synthesize shouldInvalidateLayout = _shouldInvalidateLayout;
+@synthesize cellBackgroundColor = _cellBackgroundColor;
+@synthesize cellLayoutType = _cellLayoutType;
+@synthesize gridColumnCount = _gridColumnCount;
+@synthesize gridPadding = _gridPadding;
+@synthesize cellStyle = _cellStyle;
+@synthesize separatorColor = _separatorColor;
+@synthesize separatorInset = _separatorInset;
+@synthesize separatorLineHeight = _separatorLineHeight;
+@synthesize shouldHideSeparators = _shouldHideSeparators;
+@synthesize allowsItemInlay = _allowsItemInlay;
+@synthesize allowsMultipleItemInlays = _allowsMultipleItemInlays;
+@synthesize shouldAnimateCellsOnAppearance = _shouldAnimateCellsOnAppearance;
+@synthesize willAnimateCellsOnAppearance = _willAnimateCellsOnAppearance;
+@synthesize animateCellsOnAppearancePadding = _animateCellsOnAppearancePadding;
+@synthesize animateCellsOnAppearanceDuration = _animateCellsOnAppearanceDuration;
+
+- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
+  self = [super init];
+  if (self) {
+    _collectionView = collectionView;
+
+    // Cell default style properties.
+    _cellBackgroundColor = [UIColor whiteColor];
+    _cellStyle = MDCCollectionViewCellStyleDefault;
+    _collectionView.backgroundColor = RGBCOLOR(0xEE, 0xEE, 0xEE);
+    _inlaidIndexPathSet = [NSMutableSet set];
+
+    // Cell separator defaults.
+    _separatorColor = RGBCOLOR(224, 224, 224);
+    _separatorInset = UIEdgeInsetsZero;
+    _separatorLineHeight =
+        kCollectionViewCellSeparatorDefaultHeightInPixels / [[UIScreen mainScreen] scale];
+    _shouldHideSeparators = NO;
+
+    // Grid defaults.
+    _cellLayoutType = MDCCollectionViewCellLayoutTypeList;
+    _gridColumnCount = kCollectionViewGridDefaultColumnCount;
+    _gridPadding = kCollectionViewGridDefaultPadding;
+
+    // Animate cell on appearance settings.
+    _animateCellsOnAppearancePadding = kCollectionViewAnimatedAppearancePadding;
+    _animateCellsOnAppearanceDuration = kCollectionViewAnimatedAppearanceDuration;
+
+    // Caching.
+    _cellBackgroundCaches = [NSMutableDictionary dictionary];
+  }
+  return self;
+}
+
+- (BOOL)isEqual:(id)object {
+  // If shouldInvalidateLayout property is NO, prevent a collection view layout caused when
+  // layout attributes check here if they are equal.
+  return (self == object) && ![self shouldInvalidateLayoutForStyleChange];
+}
+
+#pragma mark - Cell Appearance Animation
+
+- (void)setShouldAnimateCellsOnAppearance:(BOOL)shouldAnimateCellsOnAppearance {
+  _shouldAnimateCellsOnAppearance = shouldAnimateCellsOnAppearance;
+  _willAnimateCellsOnAppearance = shouldAnimateCellsOnAppearance;
+}
+
+- (void)beginCellAppearanceAnimation {
+  if (_shouldAnimateCellsOnAppearance) {
+    _willAnimateCellsOnAppearance = NO;
+    [UIView animateWithDuration:_animateCellsOnAppearanceDuration
+        delay:kCollectionViewAnimatedAppearanceDelay
+        options:UIViewAnimationOptionCurveEaseInOut
+        animations:^{
+          [self updateLayoutAnimated:YES];
+        }
+        completion:^(BOOL finished) {
+          [self setShouldAnimateCellsOnAppearance:NO];
+        }];
+  }
+}
+
+#pragma mark - Caching
+
+- (BackgroundCacheKey)backgroundCacheKeyForCardStyle:(BOOL)isCardStyle
+                                      isGroupedStyle:(BOOL)isGroupedStyle
+                                               isTop:(BOOL)isTop
+                                            isBottom:(BOOL)isBottom
+                                       isHighlighted:(BOOL)isHighlighted {
+  if (!isCardStyle && !isGroupedStyle) {
+    return BackgroundCacheKeyFlat;
+  }
+  BackgroundCacheKey options = isTop ? BackgroundCacheKeyTop : 0;
+  options |= isBottom ? BackgroundCacheKeyBottom : 0;
+  options |= isCardStyle ? BackgroundCacheKeyCard : 0;
+  options |= isGroupedStyle ? BackgroundCacheKeyGrouped : 0;
+  options |= isHighlighted ? BackgroundCacheKeyHighlighted : 0;
+  NSAssert(isCardStyle != isGroupedStyle, @"Cannot be both card and grouped style");
+  return options;
+}
+
+- (NSPointerArray *)cellBackgroundCache {
+  NSPointerArray *cache = [NSPointerArray strongObjectsPointerArray];
+  cache.count = BackgroundCacheKeyMax;
+  return cache;
+}
+
+#pragma mark - Separators
+
+- (void)setSeparatorColor:(UIColor *)separatorColor {
+  if (_separatorColor == separatorColor) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _separatorColor = separatorColor;
+}
+
+- (void)setSeparatorInset:(UIEdgeInsets)separatorInset {
+  if (UIEdgeInsetsEqualToEdgeInsets(_separatorInset, separatorInset)) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _separatorInset = separatorInset;
+}
+
+- (void)setSeparatorLineHeight:(CGFloat)separatorLineHeight {
+  if (_separatorLineHeight == separatorLineHeight) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _separatorLineHeight = separatorLineHeight;
+}
+
+- (void)setShouldHideSeparators:(BOOL)shouldHideSeparators {
+  if (_shouldHideSeparators == shouldHideSeparators) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _shouldHideSeparators = shouldHideSeparators;
+}
+
+- (void)setCellStyle:(MDCCollectionViewCellStyle)cellStyle {
+  if (_cellStyle == cellStyle) {
+    return;
+  }
+  [_cellBackgroundCaches removeAllObjects];
+  [self invalidateLayoutForStyleChange];
+  _cellStyle = cellStyle;
+}
+
+#pragma mark - Public
+
+- (UIEdgeInsets)backgroundImageViewOutsetsForCellWithAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // Inset contentView to allow for shadowed borders in cards.
+  UIEdgeInsets insets = UIEdgeInsetsZero;
+
+  MDCCollectionViewCellStyle cellStyle = [self cellStyleAtSectionIndex:attr.indexPath.section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  BOOL isHighlighted = NO;
+
+  MDCCollectionViewOrdinalPosition position = attr.sectionOrdinalPosition;
+
+  if ([self drawShadowForCellWithIsCardStye:isCardStyle
+                               isGroupStyle:isGroupedStyle
+                              isHighlighted:isHighlighted]) {
+    CGFloat mainScreenScale = [[UIScreen mainScreen] scale];
+    if (mainScreenScale > (CGFloat)2.1) {
+      insets = kCollectionViewCellContentInsetsRetina3x;
+    } else if (mainScreenScale > (CGFloat)1.1) {
+      insets = kCollectionViewCellContentInsetsRetina;
+    } else {
+      insets = kCollectionViewCellContentInsets;
+    }
+
+    if (!isCardStyle) {
+      insets = UIEdgeInsetsMake(insets.top, 0, insets.bottom, 0);
+    }
+
+    switch (position) {
+      case MDCCollectionViewOrdinalPositionVerticalTop:
+        insets = UIEdgeInsetsMake(insets.top, insets.left, 0, insets.right);
+        break;
+      case MDCCollectionViewOrdinalPositionVerticalBottom:
+        insets = UIEdgeInsetsMake(0, insets.left, insets.bottom, insets.right);
+        break;
+      case MDCCollectionViewOrdinalPositionVerticalCenter:
+        insets = UIEdgeInsetsMake(0, insets.left, 0, insets.right);
+        break;
+      default:
+        break;
+    }
+  }
+
+  return insets;
+}
+
+- (void)setCellStyle:(MDCCollectionViewCellStyle)cellStyle animated:(BOOL)animated {
+  _cellStyle = cellStyle;
+  [self updateLayoutAnimated:animated];
+}
+
+- (MDCCollectionViewCellStyle)cellStyleAtSectionIndex:(NSInteger)section {
+  MDCCollectionViewCellStyle cellStyle = self.cellStyle;
+  if (self.delegate &&
+      [self.delegate respondsToSelector:@selector(collectionView:cellStyleForSection:)]) {
+    cellStyle = [self.delegate collectionView:_collectionView cellStyleForSection:section];
+  }
+  return cellStyle;
+}
+
+- (NSArray *)indexPathsForInlaidItems {
+  return [_inlaidIndexPathSet allObjects];
+}
+
+- (BOOL)isItemInlaidAtIndexPath:(NSIndexPath *)indexPath {
+  return [_inlaidIndexPathSet containsObject:indexPath];
+}
+
+- (void)applyInlayToItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated {
+  if (_allowsItemInlay) {
+    // If necessary, remove any previously inlaid items.
+    if (!_allowsMultipleItemInlays) {
+      for (NSIndexPath *inlaidIndexPath in [self indexPathsForInlaidItems]) {
+        [self removeInlayFromItemAtIndexPath:inlaidIndexPath animated:animated];
+      }
+    }
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      if ([self.delegate
+              respondsToSelector:@selector(collectionView:didApplyInlayToItemAtIndexPaths:)]) {
+        [self.delegate collectionView:_collectionView
+            didApplyInlayToItemAtIndexPaths:@[ indexPath ]];
+      }
+    };
+
+    // Inlay this item.
+    [_inlaidIndexPathSet addObject:indexPath];
+    [self updateLayoutAnimated:animated completion:completionBlock];
+  }
+}
+
+- (void)removeInlayFromItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated {
+  [_inlaidIndexPathSet removeObject:indexPath];
+
+  void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+    if ([self.delegate
+            respondsToSelector:@selector(collectionView:didRemoveInlayFromItemAtIndexPaths:)]) {
+      [self.delegate collectionView:_collectionView
+          didRemoveInlayFromItemAtIndexPaths:@[ indexPath ]];
+    }
+  };
+
+  [self updateLayoutAnimated:animated completion:completionBlock];
+}
+
+- (void)applyInlayToAllItemsAnimated:(BOOL)animated {
+  if (_allowsItemInlay && _allowsMultipleItemInlays) {
+    // Store all index paths.
+    [_inlaidIndexPathSet removeAllObjects];
+    NSInteger sections = [_collectionView numberOfSections];
+    for (NSInteger section = 0; section < sections; section++) {
+      for (NSInteger item = 0; item < [_collectionView numberOfItemsInSection:section]; item++) {
+        [_inlaidIndexPathSet addObject:[NSIndexPath indexPathForItem:item inSection:section]];
+      }
+    }
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      if ([self.delegate
+              respondsToSelector:@selector(collectionView:didApplyInlayToItemAtIndexPaths:)]) {
+        [self.delegate collectionView:_collectionView
+            didApplyInlayToItemAtIndexPaths:[_inlaidIndexPathSet allObjects]];
+      }
+    };
+
+    // Inlay all items.
+    [self updateLayoutAnimated:animated completion:completionBlock];
+  }
+}
+
+- (void)removeInlayFromAllItemsAnimated:(BOOL)animated {
+  NSArray *indexPaths = [_inlaidIndexPathSet allObjects];
+  [_inlaidIndexPathSet removeAllObjects];
+
+  void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+    if ([self.delegate
+            respondsToSelector:@selector(collectionView:didRemoveInlayFromItemAtIndexPaths:)]) {
+      [self.delegate collectionView:_collectionView didRemoveInlayFromItemAtIndexPaths:indexPaths];
+    }
+  };
+
+  [self updateLayoutAnimated:animated completion:completionBlock];
+}
+
+- (void)resetIndexPathsForInlaidItems {
+  [_inlaidIndexPathSet removeAllObjects];
+  [self applyInlayToAllItemsAnimated:NO];
+}
+
+- (void)updateLayoutAnimated:(BOOL)animated {
+  [self updateLayoutAnimated:animated completion:nil];
+}
+
+#pragma mark - Private
+
+- (void)updateLayoutAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion {
+  if (animated) {
+    // Invalidate current layout while allowing animation to new layout.
+    [UIView animateWithDuration:0
+        animations:^{
+          [_collectionView.collectionViewLayout invalidateLayout];
+        }
+        completion:^(BOOL finished) {
+          if (completion) {
+            completion(finished);
+          }
+        }];
+  } else {
+    _shouldInvalidateLayout = YES;
+
+    // Create new layout with existing layout properties.
+    NSData *data =
+        [NSKeyedArchiver archivedDataWithRootObject:_collectionView.collectionViewLayout];
+    UICollectionViewFlowLayout *newLayout = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+    [_collectionView setCollectionViewLayout:newLayout
+                                    animated:animated
+                                  completion:^(BOOL finished) {
+                                    if (completion) {
+                                      completion(finished);
+                                    }
+                                  }];
+  }
+}
+
+- (void)invalidateLayoutForStyleChange {
+  _shouldInvalidateLayout = YES;
+}
+
+- (BOOL)shouldInvalidateLayoutForStyleChange {
+  // Whether the collection view layout should be invalidated due to a style property that has
+  // changed value.
+  return _shouldInvalidateLayout;
+}
+
+#pragma mark - Cell Image Background
+
+- (BOOL)drawShadowForCellWithIsCardStye:(BOOL)isCardStyle
+                           isGroupStyle:(BOOL)isGroupStyle
+                          isHighlighted:(BOOL)isHighlighted {
+  return (isCardStyle || isGroupStyle) && kCollectionViewCellDefaultShadowWidth > 0 &&
+         !isHighlighted;
+}
+
+- (UIImage *)backgroundImageForCellLayoutAttributes:(MDCCollectionViewLayoutAttributes *)attr {
+  BOOL isSectionHeader =
+      [attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader];
+  BOOL isSectionFooter =
+      [attr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter];
+  BOOL isDecorationView =
+      attr.representedElementCategory == UICollectionElementCategoryDecorationView;
+  BOOL isTop = attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalTop;
+  BOOL isBottom = attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalBottom;
+
+  MDCCollectionViewCellStyle cellStyle = [self cellStyleAtSectionIndex:attr.indexPath.section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  BOOL isGridLayout = (_cellLayoutType == MDCCollectionViewCellLayoutTypeGrid);
+  if (!isCardStyle && !isGroupedStyle) {
+    // If not card or grouped style, revert @c isBottom to allow drawing separator at bottom.
+    isBottom = NO;
+  }
+  CGFloat borderRadius = (isCardStyle) ? kCollectionViewCellDefaultBorderRadius : 0.0f;
+
+  // Allowance for grid decoration view.
+  if (isGridLayout) {
+    if (!isDecorationView && attr.shouldShowGridBackground) {
+      return nil;
+    } else {
+      isTop = isBottom = YES;
+    }
+  }
+
+  // If no-background section header, return nil image.
+  BOOL hidesHeaderBackground = NO;
+  if ([_delegate
+          respondsToSelector:@selector(collectionView:shouldHideHeaderBackgroundForSection:)]) {
+    hidesHeaderBackground = [_delegate collectionView:_collectionView
+                 shouldHideHeaderBackgroundForSection:attr.indexPath.section];
+  }
+  if (hidesHeaderBackground && isSectionHeader) {
+    return nil;
+  }
+
+  // If no-background section footer, return nil image.
+  BOOL hidesFooterBackground = NO;
+  if ([_delegate
+          respondsToSelector:@selector(collectionView:shouldHideFooterBackgroundForSection:)]) {
+    hidesFooterBackground = [_delegate collectionView:_collectionView
+                 shouldHideFooterBackgroundForSection:attr.indexPath.section];
+  }
+  if (hidesFooterBackground && isSectionFooter) {
+    return nil;
+  }
+
+  // If no-background section item, return nil image.
+  BOOL hidesBackground = NO;
+  if ([_delegate
+          respondsToSelector:@selector(collectionView:shouldHideItemBackgroundAtIndexPath:)]) {
+    hidesBackground = [_delegate collectionView:_collectionView
+            shouldHideItemBackgroundAtIndexPath:attr.indexPath];
+  }
+  if (hidesBackground && !(isDecorationView || isSectionFooter || isSectionHeader)) {
+    return nil;
+  }
+
+  BOOL isHighlighted = NO;
+
+  BackgroundCacheKey backgroundCacheKey = [self backgroundCacheKeyForCardStyle:isCardStyle
+                                                                isGroupedStyle:isGroupedStyle
+                                                                         isTop:isTop
+                                                                      isBottom:isBottom
+                                                                 isHighlighted:isHighlighted];
+
+  if (backgroundCacheKey > BackgroundCacheKeyMax) {
+    NSAssert(NO, @"Invalid styler cell background cache key");
+    return nil;
+  }
+
+  // Get cell color.
+  UIColor *backgroundColor = _cellBackgroundColor;
+  if ([_delegate respondsToSelector:@selector(collectionView:cellBackgroundColorAtIndexPath:)]) {
+    backgroundColor =
+        [_delegate collectionView:_collectionView cellBackgroundColorAtIndexPath:attr.indexPath];
+  }
+
+  NSPointerArray *cellBackgroundCache = _cellBackgroundCaches[backgroundColor];
+  if (!cellBackgroundCache) {
+    cellBackgroundCache = [self cellBackgroundCache];
+    _cellBackgroundCaches[backgroundColor] = cellBackgroundCache;
+  } else if ([cellBackgroundCache pointerAtIndex:backgroundCacheKey]) {
+    return (__bridge UIImage *)[cellBackgroundCache pointerAtIndex:backgroundCacheKey];
+  }
+
+  CGRect imageRect = CGRectMake(0, 0, kCellImageSize.width, kCellImageSize.height);
+  UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0);
+
+  CGContextRef cx = UIGraphicsGetCurrentContext();
+
+  // Create a transparent background.
+  CGContextClearRect(cx, imageRect);
+
+  // Inner background color
+  CGContextSetFillColorWithColor(cx, backgroundColor.CGColor);
+
+  CGRect contentFrame = imageRect;
+
+  // Draw the shadow.
+  if ([self drawShadowForCellWithIsCardStye:isCardStyle
+                               isGroupStyle:isGroupedStyle
+                              isHighlighted:isHighlighted]) {
+    if (isCardStyle) {
+      contentFrame = CGRectInset(imageRect, kCollectionViewCellDefaultShadowWidth, 0);
+    }
+    if (isTop) {
+      contentFrame = RectShift(contentFrame, 0, kCollectionViewCellDefaultShadowWidth);
+    }
+    if (isBottom) {
+      contentFrame = RectContract(contentFrame, 0, kCollectionViewCellDefaultShadowWidth);
+    }
+
+    CGContextSaveGState(cx);
+    CGRect shadowFrame = contentFrame;
+
+    // We want the shadow to clip to the top and bottom edges of the image so that when two cells
+    // are next to each other their shadows line up perfectly.
+    if (!isTop) {
+      shadowFrame = RectShift(shadowFrame, 0, -kCollectionViewCellDefaultShadowWidth);
+    }
+    if (!isBottom) {
+      shadowFrame = RectContract(shadowFrame, 0, -kCollectionViewCellDefaultShadowWidth);
+    }
+
+    [self applyBackgroundPathToContext:cx
+                                  rect:shadowFrame
+                                 isTop:isTop
+                              isBottom:isBottom
+                                isCard:(isCardStyle || isGroupedStyle)
+                          borderRadius:borderRadius];
+    CGContextSetShadowWithColor(cx, kCollectionViewCellDefaultShadowOffset(),
+                                kCollectionViewCellDefaultShadowWidth,
+                                kCollectionViewCellDefaultShadowColor().CGColor);
+    CGContextDrawPath(cx, kCGPathFill);
+    CGContextRestoreGState(cx);
+  } else {
+    // Draw a flat cell background.
+    CGContextSaveGState(cx);
+    [self applyBackgroundPathToContext:cx
+                                  rect:contentFrame
+                                 isTop:isTop
+                              isBottom:isBottom
+                                isCard:(isCardStyle || isGroupedStyle)
+                          borderRadius:borderRadius];
+    CGContextFillPath(cx);
+    CGContextRestoreGState(cx);
+  }
+  // Draw border paths for cells. We want the cell border to overlap the shadow and the content.
+  if ((isCardStyle || isGroupedStyle) && !isHighlighted) {
+    CGFloat minPixelOffset = [self minPixelOffset];
+    CGRect borderFrame = CGRectInset(contentFrame, -minPixelOffset, -minPixelOffset);
+    CGContextSaveGState(cx);
+    CGContextSetLineWidth(cx, kCollectionViewCellDefaultBorderWidth);
+    CGContextSetStrokeColorWithColor(cx, kCollectionViewCellDefaultBorderColor().CGColor);
+    [self applyBorderPathToContext:cx
+                              rect:borderFrame
+                             isTop:isTop
+                          isBottom:isBottom
+                            isCard:isCardStyle
+                      borderRadius:borderRadius];
+    CGContextStrokePath(cx);
+    CGContextRestoreGState(cx);
+  }
+
+  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+  UIGraphicsEndImageContext();
+  UIImage *resizableImage = [self resizableImage:image];
+  [cellBackgroundCache replacePointerAtIndex:backgroundCacheKey
+                                 withPointer:(__bridge void *)(resizableImage)];
+  return resizableImage;
+}
+
+#pragma mark - Private Context Paths
+
+// We want to draw the borders and shadows on single retina-pixel boundaries if possible, but
+// we need to avoid doing this on non-retina devices because it'll look blurry.
+- (CGFloat)minPixelOffset {
+  return 1.0f / [[UIScreen mainScreen] scale];
+}
+
+- (UIImage *)resizableImage:(UIImage *)image {
+  // Returns a resizable version of this image with cap insets equal to center point.
+  CGFloat capWidth = (CGFloat)floor(image.size.width / 2);
+  CGFloat capHeight = (CGFloat)floor(image.size.height / 2);
+  UIEdgeInsets capInsets = UIEdgeInsetsMake(capHeight, capWidth, capHeight, capWidth);
+  return [image resizableImageWithCapInsets:capInsets];
+}
+
+- (void)applyBackgroundPathToContext:(CGContextRef)c
+                                rect:(CGRect)rect
+                               isTop:(BOOL)isTop
+                            isBottom:(BOOL)isBottom
+                              isCard:(BOOL)isCard
+                        borderRadius:(CGFloat)borderRadius {
+  // Draw background paths for cell.
+  CGFloat minPixelOffset = (isCard) ? [self minPixelOffset] : 0.0f;
+  CGFloat minX = CGRectGetMinX(rect) + minPixelOffset;
+  CGFloat midX = CGRectGetMidX(rect) + minPixelOffset;
+  CGFloat maxX = CGRectGetMaxX(rect) - minPixelOffset;
+  CGFloat minY = CGRectGetMinY(rect) - minPixelOffset;
+  CGFloat midY = CGRectGetMidY(rect) - minPixelOffset;
+  CGFloat maxY = CGRectGetMaxY(rect) + minPixelOffset;
+
+  CGContextBeginPath(c);
+
+  CGContextMoveToPoint(c, minX, midY);
+  if (isTop && isCard) {
+    CGContextAddArcToPoint(c, minX, minY + 1, midX, minY + 1, borderRadius);
+    CGContextAddArcToPoint(c, maxX, minY + 1, maxX, midY, borderRadius);
+  } else {
+    CGContextAddLineToPoint(c, minX, minY);
+    CGContextAddLineToPoint(c, maxX, minY);
+  }
+
+  CGContextAddLineToPoint(c, maxX, midY);
+
+  if (isBottom & isCard) {
+    CGContextAddArcToPoint(c, maxX, maxY - 1, midX, maxY - 1, borderRadius);
+    CGContextAddArcToPoint(c, minX, maxY - 1, minX, midY, borderRadius);
+  } else {
+    CGContextAddLineToPoint(c, maxX, maxY);
+    CGContextAddLineToPoint(c, minX, maxY);
+  }
+  CGContextAddLineToPoint(c, minX, midY);
+
+  CGContextClosePath(c);
+}
+
+- (void)applyBorderPathToContext:(CGContextRef)c
+                            rect:(CGRect)rect
+                           isTop:(BOOL)isTop
+                        isBottom:(BOOL)isBottom
+                          isCard:(BOOL)isCard
+                    borderRadius:(CGFloat)borderRadius {
+  // Draw border paths for cell.
+  CGFloat minPixelOffset = (isCard) ? [self minPixelOffset] : 0.0f;
+  CGFloat minX = CGRectGetMinX(rect) + minPixelOffset;
+  CGFloat midX = CGRectGetMidX(rect) + minPixelOffset;
+  CGFloat maxX = CGRectGetMaxX(rect) - minPixelOffset;
+  CGFloat minY = CGRectGetMinY(rect) - minPixelOffset;
+  CGFloat midY = CGRectGetMidY(rect) - minPixelOffset;
+  CGFloat maxY = CGRectGetMaxY(rect) + minPixelOffset;
+
+  CGContextBeginPath(c);
+
+  if (isTop && isBottom) {
+    CGContextMoveToPoint(c, minX, midY);
+    CGContextAddArcToPoint(c, minX, minY + 1, midX, minY + 1, borderRadius);
+    CGContextAddArcToPoint(c, maxX, minY + 1, maxX, midY, borderRadius);
+    CGContextAddLineToPoint(c, maxX, midY);
+    CGContextAddArcToPoint(c, maxX, maxY - 1, midX, maxY - 1, borderRadius);
+    CGContextAddArcToPoint(c, minX, maxY - 1, minX, midY, borderRadius);
+    CGContextAddLineToPoint(c, minX, midY);
+  } else if (isTop) {
+    CGContextMoveToPoint(c, minX, maxY);
+    CGContextAddLineToPoint(c, minX, midY);
+    CGContextAddArcToPoint(c, minX, minY + 1, midX, minY + 1, borderRadius);
+    CGContextAddArcToPoint(c, maxX, minY + 1, maxX, midY, borderRadius);
+    CGContextAddLineToPoint(c, maxX, maxY);
+  } else if (isBottom) {
+    CGContextMoveToPoint(c, maxX, minY);
+    CGContextAddLineToPoint(c, maxX, midY);
+    CGContextAddArcToPoint(c, maxX, maxY - 1, midX, maxY - 1, borderRadius);
+    CGContextAddArcToPoint(c, minX, maxY - 1, minX, midY, borderRadius);
+    CGContextAddLineToPoint(c, minX, minY);
+  } else {
+    CGContextMoveToPoint(c, minX, minY);
+    CGContextAddLineToPoint(c, minX, maxY);
+    CGContextMoveToPoint(c, maxX, minY);
+    CGContextAddLineToPoint(c, maxX, maxY);
+  }
+
+  CGContextClosePath(c);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h
new file mode 100644
index 0000000..58553ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+typedef enum {
+  kStr_MaterialCollectionsInfoBarGestureHint = 0,
+  kStr_MaterialCollectionsDeleteButton = 1,
+} MaterialCollectionsStringId;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h
new file mode 100644
index 0000000..41e4aa8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// A table of string keys to look-up localized strings in the bundle.
+// This table is to be indexed using the generated enum.
+
+static NSString *const kMaterialCollectionsStringTable[] = {
+    @"InfoBarGestureHint",  // Swipe an item to delete
+    @"DeleteButton",        // Delete
+};
+#define kNumMaterialCollectionsStrings 2
+#define kMaterialCollectionsStringsOffset 0
+#define kMaterialCollectionsStringsEnd 10000
+static NSString *const kMaterialCollectionsStringsTableName = @"MaterialCollections";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.h
new file mode 100644
index 0000000..ea8330a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.h
@@ -0,0 +1,145 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+@class MDCAlertAction;
+
+/**
+ MDCAlertController displays an alert message to the user, similar to UIAlertController.
+
+ https://material.google.com/components/dialogs.html
+
+ MDCAlertController requires iOS 8 or later.
+
+ MDCAlertController class is intended to be used as-is and does not support subclassing. The view
+ hierarchy for this class is private and must not be modified.
+ */
+@interface MDCAlertController : UIViewController
+
+/**
+ Convenience constructor to create and return a view controller for displaying an alert to the user.
+
+ After creating the alert controller, add actions to the controller by calling -addAction.
+
+ @note Most alerts don't need titles. Use only for high-risk situations.
+
+ @param title The title of the alert.
+ @param message Descriptive text that summarizes a decision in a sentence of two.
+ @return An initialized MDCAlertController object.
+ */
++ (nonnull instancetype)alertControllerWithTitle:(nullable NSString *)title
+                                         message:(nullable NSString *)message;
+
+/** Alert controllers must be created with alertControllerWithTitle:message: */
+- (nonnull instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
+                                 bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
+
+/** Alert controllers must be created with alertControllerWithTitle:message: */
+- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+
+/**
+ Adds an action to the alert dialog.
+
+ Actions are the possible reactions of the user to the presented alert. Actions are added as a
+ button at the bottom of the alert. Affirmative actions should be added before dismissive actions.
+ Action buttons will be laid out from right to left if possible or top to bottom depending on space.
+
+ Material spec recommends alerts should not have more than two actions.
+
+ @param action Will be added to the end of MDCAlertController.actions.
+ */
+- (void)addAction:(nonnull MDCAlertAction *)action;
+
+/**
+ The actions that the user can take in response to the alert.
+
+ The order of the actions in the array matches the order in which they were added to the alert.
+ */
+@property(nonatomic, nonnull, readonly) NSArray<MDCAlertAction *> *actions;
+
+// TODO(iangordon): Add support for preferredAction to match UIAlertController.
+// TODO(iangordon): Consider adding support for UITextFields to match UIAlertController.
+
+/**
+ High level description of the alert or decision being made.
+
+ Use title only for high-risk situations, such as the potential loss of connectivity. If used,
+ users should be able to understand the choices based on the title and button text alone.
+ */
+@property(nonatomic, nullable, copy) NSString *title;
+
+/** Descriptive text that summarizes a decision in a sentence of two. */
+@property(nonatomic, nullable, copy) NSString *message;
+
+/*
+ Indicates whether the alert contents should automatically update their font when the device’s
+ UIContentSizeCategory changes.
+
+ This property is modeled after the adjustsFontForContentSizeCategory property in the
+ UIConnectSizeCategoryAdjusting protocol added by Apple in iOS 10.0.
+
+ Default value is NO.
+ */
+@property(nonatomic, readwrite, setter=mdc_setAdjustsFontForContentSizeCategory:)
+    BOOL mdc_adjustsFontForContentSizeCategory UI_APPEARANCE_SELECTOR;
+
+/** MDCAlertController handles its own transitioning delegate. */
+- (void)setTransitioningDelegate:
+        (_Nullable id<UIViewControllerTransitioningDelegate>)transitioningDelegate NS_UNAVAILABLE;
+
+/** MDCAlertController.modalPresentationStyle is always UIModalPresentationCustom. */
+- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle NS_UNAVAILABLE;
+
+@end
+
+/**
+ MDCActionHandler is a block that will be invoked when the action is selected.
+ */
+typedef void (^MDCActionHandler)(MDCAlertAction *_Nonnull action);
+
+/**
+ MDCAlertAction is passed to an MDCAlertController to add a button to the alert dialog.
+ */
+@interface MDCAlertAction : NSObject <NSCopying>
+
+/**
+ Action alerts control the buttons that will be displayed on the bottom of an alert controller.
+
+ @param title The title of the button shown on the alert dialog.
+ @param handler A block to execute when the user selects the action.
+ @return An initialized MDCActionAlert object.
+ */
++ (nonnull instancetype)actionWithTitle:(nonnull NSString *)title
+                                handler:(__nullable MDCActionHandler)handler;
+
+/** Alert actions must be created with actionWithTitle:handler: */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Title of the button shown on the alert dialog.
+
+ Alert actions titles must be set in the actionWithTitle:handler: method.
+ */
+@property(nonatomic, nullable, readonly) NSString *title;
+
+// TODO(iangordon): Add support for enabled property to match UIAlertAction
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.m
new file mode 100644
index 0000000..d0dccf9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.m
@@ -0,0 +1,554 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAlertController.h"
+
+#import "MDCDialogTransitionController.h"
+#import "MaterialButtons.h"
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+@interface MDCAlertAction ()
+
+@property(nonatomic, nullable, copy) MDCActionHandler completionHandler;
+
+@end
+
+@implementation MDCAlertAction
+
++ (instancetype)actionWithTitle:(nonnull NSString *)title
+                        handler:(void (^__nullable)(MDCAlertAction *action))handler {
+  return [[MDCAlertAction alloc] initWithTitle:title handler:handler];
+}
+
+- (instancetype)initWithTitle:(nonnull NSString *)title
+                      handler:(void (^__nullable)(MDCAlertAction *action))handler {
+  self = [super init];
+  if (self) {
+    _title = [title copy];
+    _completionHandler = [handler copy];
+  }
+  return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+  MDCAlertAction *action = [[self class] actionWithTitle:self.title handler:self.completionHandler];
+
+  return action;
+}
+
+@end
+
+// https://material.google.com/components/dialogs.html#dialogs-specs
+static const UIEdgeInsets MDCDialogContentInsets = {24.0, 24.0, 24.0, 24.0};
+static const CGFloat MDCDialogContentVerticalPadding = 20.0;
+
+static const UIEdgeInsets MDCDialogActionsInsets = {8.0, 8.0, 8.0, 8.0};
+static const CGFloat MDCDialogActionsHorizontalPadding = 8.0;
+static const CGFloat MDCDialogActionsVerticalPadding = 8.0;
+static const CGFloat MDCDialogActionButtonHeight = 36.0;
+static const CGFloat MDCDialogActionButtonMinimumWidth = 48.0;
+
+static const CGFloat MDCDialogMessageOpacity = 0.38f;
+
+@interface MDCAlertController ()
+
+@property(nonatomic, nonnull, strong) NSMutableArray<UIButton *> *actionButtons;
+
+@property(nonatomic, strong) UIScrollView *contentScrollView;
+@property(nonatomic, strong) UIScrollView *actionsScrollView;
+
+@property(nonatomic, strong) UILabel *titleLabel;
+@property(nonatomic, strong) UILabel *messageLabel;
+
+@property(nonatomic, getter=isVerticalActionsLayout) BOOL verticalActionsLayout;
+
+@property(nonatomic, strong) MDCDialogTransitionController *transitionController;
+
+- (nonnull instancetype)initWithTitle:(nullable NSString *)title
+                              message:(nullable NSString *)message;
+
+@end
+
+@implementation MDCAlertController {
+  NSString *_alertTitle;
+  NSString *_message;
+
+  NSMutableArray<MDCAlertAction *> *_actions;
+
+  CGSize _previousLayoutSize;
+
+  BOOL _mdc_adjustsFontForContentSizeCategory;
+}
+
++ (instancetype)alertControllerWithTitle:(nullable NSString *)alertTitle
+                                 message:(nullable NSString *)message {
+  MDCAlertController *alertController =
+      [[MDCAlertController alloc] initWithTitle:alertTitle message:message];
+
+  return alertController;
+}
+
+- (nonnull instancetype)initWithTitle:(nullable NSString *)title
+                              message:(nullable NSString *)message {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _alertTitle = [title copy];
+    _message = [message copy];
+
+    _contentScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
+    _actionsScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
+
+    _actions = [[NSMutableArray alloc] init];
+    _actionButtons = [[NSMutableArray alloc] init];
+
+    _transitionController = [[MDCDialogTransitionController alloc] init];
+    super.transitioningDelegate = _transitionController;
+    super.modalPresentationStyle = UIModalPresentationCustom;
+  }
+  return self;
+}
+
+/* Disable setter. Always use internal transition controller */
+- (void)setTransitioningDelegate:(id<UIViewControllerTransitioningDelegate>)transitioningDelegate {
+  NSAssert(NO, @"MDCAlertController.transitioningDelegate cannot be changed.");
+  return;
+}
+
+/* Disable setter. Always use custom presentation style */
+- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
+  NSAssert(NO, @"MDCAlertController.modalPresentationStyle cannot be changed.");
+  return;
+}
+
+- (NSString *)title {
+  return _alertTitle;
+}
+
+- (void)setTitle:(NSString *)title {
+  _alertTitle = [title copy];
+  self.titleLabel.text = _alertTitle;
+
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  [self.view setNeedsLayout];
+}
+
+- (NSString *)message {
+  return _message;
+}
+
+- (void)setMessage:(NSString *)message {
+  _message = [message copy];
+  self.messageLabel.text = _message;
+
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  [self.view setNeedsLayout];
+}
+
+- (NSArray<MDCAlertAction *> *)actions {
+  return [_actions copy];
+}
+
+- (void)addAction:(MDCAlertAction *)action {
+  [_actions addObject:[action copy]];
+
+  MDCFlatButton *actionButton = [[MDCFlatButton alloc] initWithFrame:CGRectZero];
+  actionButton.mdc_adjustsFontForContentSizeCategory = self.mdc_adjustsFontForContentSizeCategory;
+  [actionButton setTitle:action.title forState:UIControlStateNormal];
+  // TODO(iangordon): Determine default text color values for Normal and Disabled
+  [actionButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
+  [actionButton sizeToFit];
+  CGRect buttonRect = actionButton.bounds;
+  buttonRect.size.height = MAX(buttonRect.size.height, MDCDialogActionButtonHeight);
+  buttonRect.size.width = MAX(buttonRect.size.width, MDCDialogActionButtonMinimumWidth);
+  actionButton.frame = buttonRect;
+  [actionButton addTarget:self
+                   action:@selector(actionButtonPressed:)
+         forControlEvents:UIControlEventTouchUpInside];
+  [self.actionsScrollView addSubview:actionButton];
+
+  [self.actionButtons addObject:actionButton];
+
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  [self.view setNeedsLayout];
+}
+
+- (BOOL)mdc_adjustsFontForContentSizeCategory {
+  return _mdc_adjustsFontForContentSizeCategory;
+}
+
+- (void)mdc_setAdjustsFontForContentSizeCategory:(BOOL)adjusts {
+  _mdc_adjustsFontForContentSizeCategory = adjusts;
+
+  // Update any action buttons to match the alert controller.
+  for (MDCButton *actionButton in self.actionButtons) {
+    actionButton.mdc_adjustsFontForContentSizeCategory = adjusts;
+  }
+
+  if (_mdc_adjustsFontForContentSizeCategory) {
+    [self updateFontsForDynamicType];
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(contentSizeCategoryDidChange:)
+                                                 name:UIContentSizeCategoryDidChangeNotification
+                                               object:nil];
+  } else {
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                    name:UIContentSizeCategoryDidChangeNotification
+                                                  object:nil];
+  }
+}
+
+// Handles UIContentSizeCategoryDidChangeNotifications
+- (void)contentSizeCategoryDidChange:(NSNotification *)notification {
+  [self updateFontsForDynamicType];
+}
+
+// Update the fonts used based on mdc_preferredFontForMaterialTextStyle and recalculate the
+// preferred content size.
+- (void)updateFontsForDynamicType {
+  self.titleLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleTitle];
+  self.messageLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleBody1];
+
+  // The action MDCButtons handle their own resizing
+
+  // Our presentation controller reacts to changes to preferredContentSize to determine our
+  // frame at the presented controller.
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+}
+
+- (void)actionButtonPressed:(id)sender {
+  NSInteger actionIndex = [self.actionButtons indexOfObject:sender];
+  MDCAlertAction *action = self.actions[actionIndex];
+
+  if (action.completionHandler) {
+    action.completionHandler(action);
+  }
+
+  [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.view.backgroundColor = [UIColor whiteColor];
+
+  self.contentScrollView.backgroundColor = [UIColor whiteColor];
+  [self.view addSubview:self.contentScrollView];
+
+  self.actionsScrollView.backgroundColor = [UIColor whiteColor];
+  [self.view addSubview:self.actionsScrollView];
+
+  self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  self.titleLabel.numberOfLines = 0;
+  self.titleLabel.textAlignment = NSTextAlignmentNatural;
+  if (self.mdc_adjustsFontForContentSizeCategory) {
+    self.titleLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleTitle];
+  } else {
+    self.titleLabel.font = [MDCTypography titleFont];
+  }
+  [self.contentScrollView addSubview:self.titleLabel];
+
+  self.messageLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  self.messageLabel.numberOfLines = 0;
+  self.messageLabel.textAlignment = NSTextAlignmentNatural;
+  if (self.mdc_adjustsFontForContentSizeCategory) {
+    self.messageLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleBody1];
+  } else {
+    self.messageLabel.font = [MDCTypography body1Font];
+  }
+  self.messageLabel.textColor = [UIColor colorWithWhite:0.0 alpha:MDCDialogMessageOpacity];
+  [self.contentScrollView addSubview:self.messageLabel];
+
+  self.titleLabel.text = self.title;
+  self.messageLabel.text = self.message;
+
+  CGSize idealSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  self.preferredContentSize = idealSize;
+  _previousLayoutSize = CGSizeZero;
+
+  [self.view setNeedsLayout];
+}
+
+- (void)viewWillLayoutSubviews {
+  [super viewWillLayoutSubviews];
+
+  const CGSize viewSize = self.view.bounds.size;
+
+  // Recalculate preferredSize, which is based on width available, if the viewSize has changed.
+  if (viewSize.width != _previousLayoutSize.width ||
+      viewSize.height != _previousLayoutSize.height) {
+    CGSize currentPreferredContentSize = self.preferredContentSize;
+    CGSize calculatedPreferredContentSize = [self calculatePreferredContentSizeForBounds:viewSize];
+
+    if (!CGSizeEqualToSize(currentPreferredContentSize, calculatedPreferredContentSize)) {
+      self.preferredContentSize = calculatedPreferredContentSize;
+    }
+
+    _previousLayoutSize = viewSize;
+  }
+
+  CGSize boundsSize = CGRectInfinite.size;
+  boundsSize.width = viewSize.width;
+
+  // Content
+  CGSize contentSize = [self calculateContentSizeThatFitsWidth:boundsSize.width];
+
+  CGRect contentRect = CGRectZero;
+  contentRect.size.width = viewSize.width;
+  contentRect.size.height = contentSize.height;
+
+  self.contentScrollView.contentSize = contentRect.size;
+
+  // Place Content in contentScrollView
+  boundsSize.width = boundsSize.width - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
+  CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
+  titleSize.width = boundsSize.width;
+  CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
+  messageSize.width = boundsSize.width;
+  boundsSize.width = boundsSize.width + MDCDialogContentInsets.left + MDCDialogContentInsets.right;
+
+  CGFloat contentInternalVerticalPadding = 0.0;
+  if (0.0 < titleSize.height && 0.0 < messageSize.height) {
+    contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
+  }
+
+  CGRect titleFrame = CGRectMake(MDCDialogContentInsets.left, MDCDialogContentInsets.top,
+                                 titleSize.width, titleSize.height);
+  CGRect messageFrame = CGRectMake(MDCDialogContentInsets.left,
+                                   CGRectGetMaxY(titleFrame) + contentInternalVerticalPadding,
+                                   messageSize.width, messageSize.height);
+
+  self.titleLabel.frame = titleFrame;
+  self.messageLabel.frame = messageFrame;
+
+  // Actions
+  CGSize actionSize = [self calculateActionsSizeThatFitsWidth:boundsSize.width];
+  const CGFloat horizontalActionHeight =
+      MDCDialogActionsInsets.top + MDCDialogActionButtonHeight + MDCDialogActionsInsets.bottom;
+  if (horizontalActionHeight < actionSize.height) {
+    self.verticalActionsLayout = YES;
+  } else {
+    self.verticalActionsLayout = NO;
+  }
+
+  CGRect actionsFrame = CGRectZero;
+  actionsFrame.size.width = self.view.bounds.size.width;
+  if (0 < [self.actions count]) {
+    actionsFrame.size.height = actionSize.height;
+  }
+  self.actionsScrollView.contentSize = actionsFrame.size;
+
+  // Place buttons in actionsScrollView
+  if (self.isVerticalActionsLayout) {
+    CGPoint buttonCenter;
+    buttonCenter.x = self.actionsScrollView.contentSize.width * 0.5f;
+    buttonCenter.y = self.actionsScrollView.contentSize.height - MDCDialogActionsInsets.bottom;
+    for (UIButton *button in self.actionButtons) {
+      CGRect buttonRect = button.frame;
+
+      buttonCenter.y -= buttonRect.size.height * 0.5;
+
+      button.center = buttonCenter;
+
+      if (button != [self.actionButtons lastObject]) {
+        buttonCenter.y -= buttonRect.size.height * 0.5;
+        buttonCenter.y -= MDCDialogActionsVerticalPadding;
+      }
+    }
+  } else {
+    CGPoint buttonOrigin = CGPointZero;
+    buttonOrigin.x = self.actionsScrollView.contentSize.width - MDCDialogActionsInsets.right;
+    buttonOrigin.y = MDCDialogActionsInsets.top;
+    for (UIButton *button in self.actionButtons) {
+      CGRect buttonRect = button.frame;
+
+      buttonOrigin.x -= buttonRect.size.width;
+      buttonRect.origin = buttonOrigin;
+
+      button.frame = buttonRect;
+
+      if (button != [self.actionButtons lastObject]) {
+        buttonOrigin.x -= MDCDialogActionsHorizontalPadding;
+      }
+    }
+    // Handle RTL
+    if (self.view.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      for (UIButton *button in self.actionButtons) {
+        CGRect buttonRect = button.frame;
+        CGRect flippedRect = MDCRectFlippedForRTL(buttonRect, CGRectGetWidth(self.view.bounds),
+                                                  UIUserInterfaceLayoutDirectionRightToLeft);
+        button.frame = flippedRect;
+      }
+    }
+  }
+
+  // Place scrollviews
+  CGRect contentScrollViewRect = CGRectZero;
+  contentScrollViewRect.size = self.contentScrollView.contentSize;
+
+  CGRect actionsScrollViewRect = CGRectZero;
+  actionsScrollViewRect.size = self.actionsScrollView.contentSize;
+
+  const CGFloat requestedHeight =
+      self.contentScrollView.contentSize.height + self.actionsScrollView.contentSize.height;
+  if (requestedHeight <= self.view.bounds.size.height) {
+    // Simple layout case : both content and actions fit on the screen at once
+    self.contentScrollView.frame = contentScrollViewRect;
+
+    actionsScrollViewRect.origin.y =
+        self.view.bounds.size.height - actionsScrollViewRect.size.height;
+    self.actionsScrollView.frame = actionsScrollViewRect;
+  } else {
+    // Complex layout case : Split the space between the two scrollviews
+    CGFloat maxActionsHeight = self.view.bounds.size.height * 0.5f;
+    actionsScrollViewRect.size.height = MIN(maxActionsHeight, actionsScrollViewRect.size.height);
+    actionsScrollViewRect.origin.y =
+        self.view.bounds.size.height - actionsScrollViewRect.size.height;
+    self.actionsScrollView.frame = actionsScrollViewRect;
+
+    contentScrollViewRect.size.height =
+        self.view.bounds.size.height - actionsScrollViewRect.size.height;
+    self.contentScrollView.frame = contentScrollViewRect;
+  }
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+
+  [coordinator animateAlongsideTransition:^(
+                   id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
+    // Reset preferredContentSize on viewWIllTransition to take advantage of additional width
+    self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+  }
+                               completion:nil];
+}
+
+#pragma mark - Internal
+
+// @param boundingWidth should not include any internal margins or padding
+- (CGSize)calculateContentSizeThatFitsWidth:(CGFloat)boundingWidth {
+  CGSize boundsSize = CGRectInfinite.size;
+  boundsSize.width = boundingWidth - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
+
+  CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
+  CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
+
+  CGFloat contentWidth = MAX(titleSize.width, messageSize.width);
+  contentWidth += MDCDialogContentInsets.left + MDCDialogContentInsets.right;
+
+  CGFloat contentInternalVerticalPadding = 0.0;
+  if (0.0 < titleSize.height && 0.0 < messageSize.height) {
+    contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
+  }
+  CGFloat contentHeight = titleSize.height + contentInternalVerticalPadding + messageSize.height;
+  contentHeight += MDCDialogContentInsets.top + MDCDialogContentInsets.bottom;
+
+  CGSize contentSize;
+  contentSize.width = (CGFloat)ceil(contentWidth);
+  contentSize.height = (CGFloat)ceil(contentHeight);
+
+  return contentSize;
+}
+
+// @param boundingWidth should not include any internal margins or padding
+- (CGSize)calculateActionsSizeThatFitsWidth:(CGFloat)boundingWidth {
+  CGSize boundsSize = CGRectInfinite.size;
+  boundsSize.width = boundingWidth;
+
+  CGSize horizontalSize = [self actionButtonsSizeInHorizontalLayout];
+  CGSize verticalSize = [self actionButtonsSizeInVericalLayout];
+
+  CGSize actionsSize;
+  if (boundsSize.width < horizontalSize.width) {
+    // Use VerticalLayout
+    actionsSize.width = MIN(verticalSize.width, boundsSize.width);
+    actionsSize.height = MIN(verticalSize.height, boundsSize.height);
+  } else {
+    // Use HorizontalLayout
+    actionsSize.width = MIN(horizontalSize.width, boundsSize.width);
+    actionsSize.height = MIN(horizontalSize.height, boundsSize.height);
+  }
+
+  actionsSize.width = (CGFloat)ceil(actionsSize.width);
+  actionsSize.height = (CGFloat)ceil(actionsSize.height);
+
+  return actionsSize;
+}
+
+// @param boundsSize should not include any internal margins or padding
+- (CGSize)calculatePreferredContentSizeForBounds:(CGSize)boundsSize {
+  // Content & Actions
+  CGSize contentSize = [self calculateContentSizeThatFitsWidth:boundsSize.width];
+  CGSize actionSize = [self calculateActionsSizeThatFitsWidth:boundsSize.width];
+
+  // Final Sizing
+  CGSize totalSize;
+  totalSize.width = MAX(contentSize.width, actionSize.width);
+  totalSize.height = contentSize.height + actionSize.height;
+
+  return totalSize;
+}
+
+- (CGSize)actionButtonsSizeInHorizontalLayout {
+  CGSize size = CGSizeZero;
+  if (0 < [self.actions count]) {
+    size.height =
+        MDCDialogActionsInsets.top + MDCDialogActionButtonHeight + MDCDialogActionsInsets.bottom;
+    size.width = MDCDialogActionsInsets.left + MDCDialogActionsInsets.right;
+    for (UIButton *button in self.actionButtons) {
+      size.width += CGRectGetWidth(button.bounds);
+      if (button != [self.actionButtons lastObject]) {
+        size.width += MDCDialogActionsHorizontalPadding;
+      }
+    }
+  }
+
+  return size;
+}
+
+- (CGSize)actionButtonsSizeInVericalLayout {
+  CGSize size = CGSizeZero;
+  if (0 < [self.actions count]) {
+    size.height = MDCDialogActionsInsets.top + MDCDialogActionsInsets.bottom;
+    size.width = MDCDialogActionsInsets.left + MDCDialogActionsInsets.right;
+    for (UIButton *button in self.actionButtons) {
+      size.height += CGRectGetHeight(button.bounds);
+      size.width = MAX(size.width, CGRectGetWidth(button.bounds));
+      if (button != [self.actionButtons lastObject]) {
+        size.height += MDCDialogActionsVerticalPadding;
+      }
+    }
+  }
+
+  return size;
+}
+
+#pragma mark - UIAccessibilityAction
+
+- (BOOL)accessibilityPerformEscape {
+  [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
+  return YES;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
new file mode 100644
index 0000000..628d0a2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
@@ -0,0 +1,71 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+/**
+ MDCDialogPresentationController will present a modal ViewController as a dialog according to the
+ Material spec.
+
+ https://material.google.com/components/dialogs.html
+
+ MDCDialogPresentationController should not be used to present full-screen dialogs.
+
+ The presented UIViewController will be asked for it's preferredContentSize to help determine
+ the best size for the dialog to be displayed.
+
+ This controller will manage the background dimming view and add a material-styled shadow underneath
+ the presented view.
+
+ This controller will respond to the display / dismissal of the keyboard and update the
+ presentedView's frame.
+ */
+@interface MDCDialogPresentationController : UIPresentationController
+
+/**
+ Should a tap on the dimmed background view dismiss the presented controller.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL dismissOnBackgroundTap;
+
+/**
+ Returns the size of the specified child view controller's content.
+
+ The size is initially based on container.preferredSize. Width is will have a minimum of 280 and a
+ maximum of the parentSize - 40 for the padding on the left and right size.
+
+ Height has no minimum.  Height has a maximum of the parentSize - height of any displayed
+ keyboards - 48 for the padding on the top and bottom.  If preferredSize.height is 0, height will
+ be set to the maximum.
+ */
+- (CGSize)sizeForChildContentContainer:(nonnull id<UIContentContainer>)container
+               withParentContainerSize:(CGSize)parentSize;
+
+/**
+ Returns the frame rectangle to assign to the presented view at the end of the animations.
+
+ The size of the frame is determined by sizeForChildContentContainer:withParentContainerSize:. The
+ presentedView is centered horizontally and verically in the available space.  The available space
+ is the size of the containerView subtracting any space taken up by the keyboard.
+ */
+- (CGRect)frameOfPresentedViewInContainerView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.m
new file mode 100644
index 0000000..5ad9103
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.m
@@ -0,0 +1,320 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCDialogPresentationController.h"
+
+#import "MaterialKeyboardWatcher.h"
+#import "private/MDCDialogShadowedView.h"
+
+static CGFloat MDCDialogMinimumWidth = 280.0f;
+// TODO: Spec indicates 40 side margins and 280 minimum width.
+// That is incompatible with a 320 wide device.
+// Side margins set to 20 until we have a resolution
+static UIEdgeInsets MDCDialogEdgeInsets = {24, 20, 24, 20};
+
+@interface MDCDialogPresentationController ()
+
+// View matching the container's bounds that dims the entire screen and catchs taps to dismiss.
+@property(nonatomic) UIView *dimmingView;
+
+// Tracking view that adds a shadow under the presented view. This view's frame should always match
+// the presented view's.
+@property(nonatomic) UIView *trackingView;
+
+@end
+
+@implementation MDCDialogPresentationController {
+  UITapGestureRecognizer *_dismissGestureRecognizer;
+}
+
+#pragma mark - UIPresentationController
+
+// dismissOnBackgroundTap wraps the enable property of our gesture recognizer to
+// avoid duplication.
+- (void)setDismissOnBackgroundTap:(BOOL)dismissOnBackgroundTap {
+  _dismissGestureRecognizer.enabled = dismissOnBackgroundTap;
+}
+
+- (BOOL)dismissOnBackgroundTap {
+  return _dismissGestureRecognizer.enabled;
+}
+
+- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController
+                       presentingViewController:(UIViewController *)presentingViewController {
+  self = [super initWithPresentedViewController:presentedViewController
+                       presentingViewController:presentingViewController];
+  if (self) {
+    _dimmingView = [[UIView alloc] initWithFrame:CGRectZero];
+    _dimmingView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.4f];
+    _dimmingView.alpha = 0.0f;
+    _dismissGestureRecognizer =
+        [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss:)];
+    [_dimmingView addGestureRecognizer:_dismissGestureRecognizer];
+
+    _trackingView = [[MDCDialogShadowedView alloc] init];
+
+    [self registerKeyboardNotifications];
+  }
+
+  return self;
+}
+
+- (void)dealloc {
+  [self unregisterKeyboardNotifications];
+}
+
+- (CGRect)frameOfPresentedViewInContainerView {
+  CGRect presentedViewFrame = CGRectZero;
+
+  CGRect containerBounds = self.containerView.bounds;
+  containerBounds.size.height -= [MDCKeyboardWatcher sharedKeyboardWatcher].keyboardOffset;
+
+  presentedViewFrame.size = [self sizeForChildContentContainer:self.presentedViewController
+                                       withParentContainerSize:containerBounds.size];
+
+  presentedViewFrame.origin.x = (containerBounds.size.width - presentedViewFrame.size.width) * 0.5f;
+  presentedViewFrame.origin.y =
+      (containerBounds.size.height - presentedViewFrame.size.height) * 0.5f;
+
+  presentedViewFrame.origin.x = (CGFloat)floor(presentedViewFrame.origin.x);
+  presentedViewFrame.origin.y = (CGFloat)floor(presentedViewFrame.origin.y);
+
+  return presentedViewFrame;
+}
+
+- (void)presentationTransitionWillBegin {
+  // TODO: Follow the Material spec description of Autonomous surface creation for both
+  // presentation and dismissal of the dialog.
+  // https://spec.googleplex.com/quantum/motion/choreography.html#choreography-creation
+
+  // Set the dimming view to the container's bounds and fully transparent.
+  self.dimmingView.frame = self.containerView.bounds;
+  self.dimmingView.alpha = 0.0f;
+  [self.containerView addSubview:self.dimmingView];
+
+  // Set the shadowing view to the same frame as the presented view.
+  CGRect presentedFrame = [self frameOfPresentedViewInContainerView];
+  self.trackingView.frame = presentedFrame;
+  self.trackingView.alpha = 0.0f;
+  [self.containerView addSubview:self.trackingView];
+
+  // Fade-in chrome views to be fully visible.
+  id<UIViewControllerTransitionCoordinator> transitionCoordinator =
+      [self.presentedViewController transitionCoordinator];
+  if (transitionCoordinator) {
+    [transitionCoordinator
+        animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+          self.dimmingView.alpha = 1.0f;
+          self.trackingView.alpha = 1.0f;
+        }
+                        completion:NULL];
+  } else {
+    self.dimmingView.alpha = 1.0f;
+    self.trackingView.alpha = 1.0f;
+  }
+}
+
+- (void)presentationTransitionDidEnd:(BOOL)completed {
+  if (completed) {
+    // Stop the presenting view from being tapped for voiceover while this view is up.
+    // Setting @c accessibilityViewIsModal on the presented view (or its parent) should be enough,
+    // but it's not.
+    // b/19519321
+    self.presentingViewController.view.accessibilityElementsHidden = YES;
+    self.presentedView.accessibilityViewIsModal = YES;
+    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, [self presentedView]);
+  } else {
+    // Transition was cancelled.
+    [self.dimmingView removeFromSuperview];
+    [self.trackingView removeFromSuperview];
+  }
+}
+
+- (void)dismissalTransitionWillBegin {
+  // Fade-out dimmingView and trackingView to be fully transparent.
+  id<UIViewControllerTransitionCoordinator> transitionCoordinator =
+      [self.presentedViewController transitionCoordinator];
+  if (transitionCoordinator != nil) {
+    [transitionCoordinator
+        animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+          self.dimmingView.alpha = 0.0f;
+          self.trackingView.alpha = 0.0f;
+        }
+                        completion:NULL];
+  } else {
+    self.dimmingView.alpha = 0.0f;
+    self.trackingView.alpha = 0.0f;
+  }
+}
+
+- (void)dismissalTransitionDidEnd:(BOOL)completed {
+  if (completed) {
+    [self.dimmingView removeFromSuperview];
+    [self.trackingView removeFromSuperview];
+
+    // Re-enable accessibilityElements on the presenting view controller.
+    self.presentingViewController.view.accessibilityElementsHidden = NO;
+  }
+
+  [super dismissalTransitionDidEnd:completed];
+}
+
+/**
+ Indicate that the presenting view controller's view should not be removed when the presentation
+ animations finish.
+
+ MDCDialogPresentationController does not cover the presenting view controller's content entirely
+ so we must return NO.
+ */
+- (BOOL)shouldRemovePresentersView {
+  return NO;
+}
+
+#pragma mark - UIContentContainer
+
+/**
+ Determines the size of the presented container's view based on available space and the preferred
+ content size of the container.
+ */
+- (CGSize)sizeForChildContentContainer:(id<UIContentContainer>)container
+               withParentContainerSize:(CGSize)parentSize {
+  if (CGSizeEqualToSize(parentSize, CGSizeZero)) {
+    return CGSizeZero;
+  }
+
+  CGSize maxChildSize;
+  maxChildSize.width = parentSize.width - MDCDialogEdgeInsets.left - MDCDialogEdgeInsets.right;
+  maxChildSize.height = parentSize.height - MDCDialogEdgeInsets.top - MDCDialogEdgeInsets.bottom;
+
+  CGSize targetSize = maxChildSize;
+
+  const CGSize preferredContentSize = container.preferredContentSize;
+  if (!CGSizeEqualToSize(preferredContentSize, CGSizeZero)) {
+    targetSize = preferredContentSize;
+
+    // If the targetSize.width is greater than 0.0 it must be at least MDCDialogMinimumWidth.
+    if (0.0f < targetSize.width && targetSize.width < MDCDialogMinimumWidth) {
+      targetSize.width = MDCDialogMinimumWidth;
+    }
+    // targetSize cannot exceed maxChildSize.
+    targetSize.width = MIN(targetSize.width, maxChildSize.width);
+    targetSize.height = MIN(targetSize.height, maxChildSize.height);
+  }
+
+  targetSize.width = (CGFloat)ceil(targetSize.width);
+  targetSize.height = (CGFloat)ceil(targetSize.height);
+
+  return targetSize;
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+
+  [coordinator
+      animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        self.dimmingView.frame = self.containerView.bounds;
+        CGRect presentedViewFrame = [self frameOfPresentedViewInContainerView];
+        self.presentedView.frame = presentedViewFrame;
+        self.trackingView.frame = presentedViewFrame;
+      }
+                      completion:NULL];
+}
+
+/**
+ If the container's preferred content size has changed and we are able to accommidate the new size,
+ update the frame of the presented view and the shadowing view.
+ */
+- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container {
+  [super preferredContentSizeDidChangeForChildContentContainer:container];
+
+  CGSize existingSize = self.presentedView.bounds.size;
+  CGSize newSize = [self sizeForChildContentContainer:container
+                              withParentContainerSize:self.containerView.bounds.size];
+
+  if (!CGSizeEqualToSize(existingSize, newSize)) {
+    CGRect presentedViewFrame = [self frameOfPresentedViewInContainerView];
+    self.presentedView.frame = presentedViewFrame;
+    self.trackingView.frame = presentedViewFrame;
+  }
+}
+
+#pragma mark - Internal
+
+- (void)dismiss:(UIGestureRecognizer *)gesture {
+  if (gesture.state == UIGestureRecognizerStateRecognized) {
+    [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
+  }
+}
+
+#pragma mark - Keyboard handling
+
+- (void)registerKeyboardNotifications {
+  [[NSNotificationCenter defaultCenter] addObserver:self
+                                           selector:@selector(keyboardWatcherHandler:)
+                                               name:MDCKeyboardWatcherKeyboardWillShowNotification
+                                             object:nil];
+
+  [[NSNotificationCenter defaultCenter] addObserver:self
+                                           selector:@selector(keyboardWatcherHandler:)
+                                               name:MDCKeyboardWatcherKeyboardWillHideNotification
+                                             object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(keyboardWatcherHandler:)
+             name:MDCKeyboardWatcherKeyboardWillChangeFrameNotification
+           object:nil];
+}
+
+- (void)unregisterKeyboardNotifications {
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:MDCKeyboardWatcherKeyboardWillShowNotification
+              object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:MDCKeyboardWatcherKeyboardWillHideNotification
+              object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:MDCKeyboardWatcherKeyboardWillChangeFrameNotification
+              object:nil];
+}
+
+#pragma mark - KeyboardWatcher Notifications
+
+- (void)keyboardWatcherHandler:(NSNotification *)aNotification {
+  NSTimeInterval animationDuration =
+      [MDCKeyboardWatcher animationDurationFromKeyboardNotification:aNotification];
+
+  UIViewAnimationOptions animationCurveOption =
+      [MDCKeyboardWatcher animationCurveOptionFromKeyboardNotification:aNotification];
+
+  [UIView animateWithDuration:animationDuration
+                        delay:0.0f
+                      options:animationCurveOption | UIViewAnimationOptionTransitionNone
+                   animations:^{
+                     CGRect presentedViewFrame = [self frameOfPresentedViewInContainerView];
+                     self.presentedView.frame = presentedViewFrame;
+                     self.trackingView.frame = presentedViewFrame;
+                   }
+                   completion:NULL];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
new file mode 100644
index 0000000..6353b5f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
@@ -0,0 +1,43 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+/**
+ MDCDialogTransitionController is be used to setup a custom transition and animationed presentation
+ and dismissal for material-styled alerts, simple dialogs and confirmation dialogs.
+
+ https://material.google.com/components/dialogs.html
+
+ This class provides a basic implementation of UIViewControllerAnimatedTransitioning and
+ UIViewControllerTransitioningDelegate.
+
+ In order to use a custom modal transition, the UIViewController to be presented must set two
+ properties. The UIViewControllers transitioningDelegate should be set to an instance of this class.
+ myDialogViewController.modalPresentationStyle = UIModalPresentationCustom;
+ myDialogViewController.transitioningDelegate = dialogTransitionController;
+
+ The presenting UIViewController then calls presentViewController:animated:completion:
+ [rootViewController presentViewController:myDialogViewController animated:YES completion:...];
+ */
+@interface MDCDialogTransitionController
+    : NSObject <UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate>
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.m
new file mode 100644
index 0000000..4735814
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.m
@@ -0,0 +1,112 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCDialogTransitionController.h"
+
+#import "MDCDialogPresentationController.h"
+
+@implementation MDCDialogTransitionController
+
+static const NSTimeInterval MDCDialogTransitionDuration = 0.5;
+
+#pragma mark - UIViewControllerAnimatedTransitioning
+
+- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
+  return MDCDialogTransitionDuration;
+}
+
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
+  // If a view in the transitionContext is nil, it likely hasn't been loaded by its ViewController
+  // yet.  Ask for it directly to initiate a loadView on the ViewController.
+  UIViewController *fromViewController =
+      [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
+  UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
+  if (fromView == nil) {
+    fromView = fromViewController.view;
+  }
+
+  UIViewController *toViewController =
+      [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
+  UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
+  if (toView == nil) {
+    toView = toViewController.view;
+  }
+
+  UIViewController *toPresentingViewController = toViewController.presentingViewController;
+  BOOL presenting = (toPresentingViewController == fromViewController) ? YES : NO;
+
+  UIViewController *animatingViewController = presenting ? toViewController : fromViewController;
+  UIView *animatingView = presenting ? toView : fromView;
+
+  UIView *containerView = transitionContext.containerView;
+
+  if (presenting) {
+    [containerView addSubview:toView];
+  }
+
+  CGFloat startingAlpha = presenting ? 0.0f : 1.0f;
+  CGFloat endingAlpha = presenting ? 1.0f : 0.0f;
+
+  animatingView.frame = [transitionContext finalFrameForViewController:animatingViewController];
+  animatingView.alpha = startingAlpha;
+
+  NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
+  UIViewAnimationOptions options =
+      UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState;
+
+  [UIView animateWithDuration:transitionDuration
+      delay:0.0
+      options:options
+      animations:^{
+        animatingView.alpha = endingAlpha;
+      }
+      completion:^(BOOL finished) {
+        // If we're dismissing, remove the presented view from the hierarchy
+        if (!presenting) {
+          [fromView removeFromSuperview];
+        }
+
+        // From ADC : UIViewControllerContextTransitioning
+        // When you do create transition animations, always call the
+        // completeTransition: from an appropriate completion block to let UIKit know
+        // when all of your animations have finished.
+        [transitionContext completeTransition:YES];
+      }];
+}
+
+#pragma mark - UIViewControllerTransitioningDelegate
+
+- (UIPresentationController *)
+    presentationControllerForPresentedViewController:(UIViewController *)presented
+                            presentingViewController:(UIViewController *)presenting
+                                sourceViewController:(UIViewController *)source {
+  return [[MDCDialogPresentationController alloc] initWithPresentedViewController:presented
+                                                         presentingViewController:presenting];
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)
+    animationControllerForPresentedController:(UIViewController *)presented
+                         presentingController:(UIViewController *)presenting
+                             sourceController:(UIViewController *)source {
+  return self;
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:
+        (UIViewController *)dismissed {
+  return self;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MaterialDialogs.h
new file mode 100644
index 0000000..5beed78
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/MaterialDialogs.h
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAlertController.h"
+#import "MDCDialogPresentationController.h"
+#import "MDCDialogTransitionController.h"
+#import "UIViewController+MaterialDialogs.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
new file mode 100644
index 0000000..2733b17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+@class MDCDialogPresentationController;
+
+/**
+ Material Dialog UIViewController Category
+ */
+@interface UIViewController (MaterialDialogs)
+
+/**
+ The Material dialog presentation controller that is managing the current view controller.
+
+ @return nil if the view controller is not managed by a Material dialog presentaiton controller.
+ */
+@property(nonatomic, readonly) MDCDialogPresentationController *mdc_dialogPresentationController;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.m
new file mode 100644
index 0000000..a12b3e9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.m
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIViewController+MaterialDialogs.h"
+
+#import "MDCDialogPresentationController.h"
+
+@implementation UIViewController (MaterialDialogs)
+
+- (MDCDialogPresentationController *)mdc_dialogPresentationController {
+  id presentationController = self.presentationController;
+  if ([presentationController isKindOfClass:[MDCDialogPresentationController class]]) {
+    return (MDCDialogPresentationController *)presentationController;
+  }
+
+  return nil;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h
new file mode 100644
index 0000000..2c0eff1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h
@@ -0,0 +1,21 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCDialogShadowedView : UIView
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.m
new file mode 100644
index 0000000..adf62f6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.m
@@ -0,0 +1,40 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCDialogShadowedView.h"
+
+#import "MDCShadowElevations.h"
+#import "MDCShadowLayer.h"
+
+@implementation MDCDialogShadowedView
+
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+
+- (MDCShadowLayer *)shadowLayer {
+  return (MDCShadowLayer *)self.layer;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    [[self shadowLayer] setElevation:MDCShadowElevationDialog];
+  }
+  return self;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
new file mode 100644
index 0000000..fcbfc82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
@@ -0,0 +1,125 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** The default alpha for the outer highlight circle. */
+extern const CGFloat kMDCFeatureHighlightOuterHighlightAlpha;
+
+/**
+ Completion block called when the feature highlight is dismissed either by calling |acceptFeature|
+ or |rejectFeature| on the feature highlight or the user accepts or rejects the highlight by tapping
+ somewhere on the highlight view.
+
+ @param accepted Whether the highlight was accepted or rejected
+ */
+typedef void (^MDCFeatureHighlightCompletion)(BOOL accepted);
+
+/**
+ MDCFeatureHighlightViewController highlights an element of a UI to introduce features or
+ functionality that a user hasn’t tried.
+
+ https://material.googleplex.com/growth-communications/feature-discovery.html
+
+ MDCFeatureHighlightViewController should be presented modally and dismissed using either
+ |acceptFeature| or |rejectFeature|.
+
+ While MDCFeatureHighlightViewController supports changing state while presented, it is not
+ recommended as the design spec does not specify any patterns for that behavior.
+
+ @note Due to a bug in the iOS simulator it is possible that the feature highlight will not render
+ correctly in the simulator. If you're encountering issues make sure to test on device.
+ */
+@interface MDCFeatureHighlightViewController : UIViewController
+
+/**
+ Initializes the controller.
+
+ @param highlightedView The highlight will be presented above the |center| of |highlightedView|
+ @param displayedView Added to the highlight view and centered at the |center| of |highlightedView|
+ @param completion The completion block called when the highlight is dismissed
+ */
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                    andShowView:(nonnull UIView *)displayedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion
+    NS_DESIGNATED_INITIALIZER;
+
+/**
+ Initializes the controller.
+
+ This is a convience method for |initWithHighlightedView:andShowView:| with a snapshot of
+ |highlightedView| sent as |displayedView|.
+
+ @param highlightedView The highlight will be presented above the |center| of |highlightedView|
+ */
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion;
+
+/**
+ Feature Highlight controllers must be created with either initWithHighlightedView: constructor.
+ */
+- (nonnull instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
+                                 bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Sets the text to be displayed as the header of the help text.
+
+ The header is displayed above the body text.
+ */
+@property(nonatomic, copy, nullable) NSString *titleText;
+
+/**
+ Sets the text to be displayed as the body of the help text.
+
+ The body is displayed below the header text. If you are only showing a single block of text without
+ any header/body distinction, prefer |titleText|.
+ */
+@property(nonatomic, copy, nullable) NSString *bodyText;
+
+/**
+ Sets the color to be used for the outer highlight. Defaults to blue with an alpha of
+ kMDCFeatureHighlightOuterHighlightAlpha.
+
+ Alpha should be set to kMDCFeatureHighlightOuterHighlightAlpha.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *outerHighlightColor;
+
+/**
+ Sets the color to be used for the inner highlight. Defaults to white.
+
+ Should be opaque.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *innerHighlightColor;
+
+/**
+ Dismisses the feature highlight using the 'accept' style dismissal animation and triggers the
+ completion block with accepted set to YES.
+
+ Identical to the user tapping on the inner highlight.
+ */
+- (void)acceptFeature;
+
+/**
+ Dismisses the feature highlight using the 'reject' style dismissal animation and triggers the
+ completion block with accepted set to NO.
+
+ Identical to the user tapping outside of the inner highlight.
+ */
+- (void)rejectFeature;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m
new file mode 100644
index 0000000..a6c822b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m
@@ -0,0 +1,195 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightViewController.h"
+
+#import "private/MDCFeatureHighlightAnimationController.h"
+#import "private/MDCFeatureHighlightView.h"
+
+const CGFloat kMDCFeatureHighlightOuterHighlightAlpha = 0.96f;
+
+static const CGFloat kMDCFeatureHighlightPulseAnimationInterval = 1.5f;
+
+@interface MDCFeatureHighlightViewController () <UIViewControllerTransitioningDelegate>
+@end
+
+@implementation MDCFeatureHighlightViewController {
+  MDCFeatureHighlightAnimationController *_animationController;
+  MDCFeatureHighlightCompletion _completion;
+  MDCFeatureHighlightView *_featureHighlightView;
+  NSTimer *_pulseTimer;
+  UIView *_displayedView;
+  UIView *_highlightedView;
+}
+
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                    andShowView:(nonnull UIView *)displayedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion {
+  if (self = [super initWithNibName:nil bundle:nil]) {
+    _highlightedView = highlightedView;
+    _displayedView = displayedView;
+    _completion = completion;
+    _animationController = [[MDCFeatureHighlightAnimationController alloc] init];
+    _animationController.presenting = YES;
+
+    [_highlightedView addObserver:self
+                       forKeyPath:@"frame"
+                          options:NSKeyValueObservingOptionNew
+                          context:nil];
+
+    super.transitioningDelegate = self;
+    super.modalPresentationStyle = UIModalPresentationCustom;
+  }
+  return self;
+}
+
+/* Disable setter. Always use internal transition controller */
+- (void)setTransitioningDelegate:(id<UIViewControllerTransitioningDelegate>)transitioningDelegate {
+  NSAssert(NO, @"MDCAlertController.transitioningDelegate cannot be changed.");
+  return;
+}
+
+/* Disable setter. Always use custom presentation style */
+- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
+  NSAssert(NO, @"MDCAlertController.modalPresentationStyle cannot be changed.");
+  return;
+}
+
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion {
+  return [self initWithHighlightedView:highlightedView
+                           andShowView:[highlightedView snapshotViewAfterScreenUpdates:YES]
+                            completion:completion];
+}
+
+- (void)dealloc {
+  [_pulseTimer invalidate];
+  [_highlightedView removeObserver:self forKeyPath:@"frame"];
+}
+
+- (void)loadView {
+  _featureHighlightView = [[MDCFeatureHighlightView alloc] initWithFrame:CGRectZero];
+  _featureHighlightView.displayedView = _displayedView;
+  _featureHighlightView.titleLabel.text = self.titleText;
+  _featureHighlightView.bodyLabel.text = self.bodyText;
+  _featureHighlightView.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+  _featureHighlightView.outerHighlightColor = self.outerHighlightColor;
+  _featureHighlightView.innerHighlightColor = self.innerHighlightColor;
+
+  __weak __typeof__(self) weakSelf = self;
+  _featureHighlightView.interactionBlock = ^(BOOL accepted) {
+    __typeof__(self) strongSelf = weakSelf;
+    [strongSelf dismiss:accepted];
+  };
+
+  self.view = _featureHighlightView;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+
+  CGPoint point = [_highlightedView.superview convertPoint:_highlightedView.center
+                                         toCoordinateSpace:_featureHighlightView];
+  _featureHighlightView.highlightPoint = point;
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+  [super viewDidAppear:animated];
+
+  _pulseTimer = [NSTimer scheduledTimerWithTimeInterval:kMDCFeatureHighlightPulseAnimationInterval
+                                                 target:_featureHighlightView
+                                               selector:@selector(animatePulse)
+                                               userInfo:NULL
+                                                repeats:YES];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+  [super viewWillDisappear:animated];
+
+  [_pulseTimer invalidate];
+}
+
+- (UIColor *)outerHighlightColor {
+  if (!_outerHighlightColor) {
+    return [[UIColor blueColor] colorWithAlphaComponent:kMDCFeatureHighlightOuterHighlightAlpha];
+  }
+  return _outerHighlightColor;
+}
+
+- (UIColor *)innerHighlightColor {
+  if (!_innerHighlightColor) {
+    return [UIColor whiteColor];
+  }
+  return _innerHighlightColor;
+}
+
+- (void)acceptFeature {
+  [self dismiss:YES];
+}
+
+- (void)rejectFeature {
+  [self dismiss:NO];
+}
+
+- (void)dismiss:(BOOL)accepted {
+  _animationController.presenting = NO;
+  if (accepted) {
+    _animationController.dismissStyle = MDCFeatureHighlightDismissAccepted;
+  } else {
+    _animationController.dismissStyle = MDCFeatureHighlightDismissRejected;
+  }
+  [self dismissViewControllerAnimated:YES
+                           completion:^() {
+                             if (self->_completion) {
+                               self->_completion(accepted);
+                             }
+                           }];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary<NSString *, id> *)change
+                       context:(void *)context {
+  if (object == _highlightedView && [keyPath isEqualToString:@"frame"]) {
+    CGPoint point = [_highlightedView.superview convertPoint:_highlightedView.center
+                                                      toView:_featureHighlightView];
+    _featureHighlightView.highlightPoint = point;
+    [_featureHighlightView layoutIfNeeded];
+  }
+}
+
+#pragma mark - UIViewControllerTransitioningDelegate
+
+- (id<UIViewControllerAnimatedTransitioning>)
+    animationControllerForPresentedController:(UIViewController *)presented
+                         presentingController:(UIViewController *)presenting
+                             sourceController:(UIViewController *)source {
+  if (presented == self) {
+    return _animationController;
+  }
+  return nil;
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:
+        (UIViewController *)dismissed {
+  if (dismissed == self) {
+    return _animationController;
+  }
+  return nil;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
new file mode 100644
index 0000000..61cd5d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightViewController.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h
new file mode 100644
index 0000000..7046b85
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+typedef enum : NSUInteger {
+  MDCFeatureHighlightDismissAccepted,
+  MDCFeatureHighlightDismissRejected,
+} MDCFeatureHighlightDismissStyle;
+
+@interface MDCFeatureHighlightAnimationController : NSObject <UIViewControllerAnimatedTransitioning>
+
+@property(nonatomic, assign) MDCFeatureHighlightDismissStyle dismissStyle;
+@property(nonatomic, assign, getter=isPresenting) BOOL presenting;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m
new file mode 100644
index 0000000..39fa989
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m
@@ -0,0 +1,91 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightAnimationController.h"
+
+#import "MDCFeatureHighlightView.h"
+
+const NSTimeInterval kMDCFeatureHighlightPresentationDuration = 0.35f;
+const NSTimeInterval kMDCFeatureHighlightDismissalDuration = 0.2f;
+
+@implementation MDCFeatureHighlightAnimationController
+
+- (NSTimeInterval)transitionDuration:
+        (nullable id<UIViewControllerContextTransitioning>)transitionContext {
+  if (self.presenting) {
+    return kMDCFeatureHighlightPresentationDuration;
+  } else {
+    return kMDCFeatureHighlightDismissalDuration;
+  }
+}
+
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
+  UIViewController *toViewController =
+      [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
+  UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
+  UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
+
+  MDCFeatureHighlightView *highlightView = nil;
+  if ([fromView isKindOfClass:[MDCFeatureHighlightView class]]) {
+    highlightView = (MDCFeatureHighlightView *)fromView;
+  } else if ([toView isKindOfClass:[MDCFeatureHighlightView class]]) {
+    highlightView = (MDCFeatureHighlightView *)toView;
+  }
+
+  if (self.presenting) {
+    [transitionContext.containerView addSubview:toView];
+    toView.frame = [transitionContext finalFrameForViewController:toViewController];
+  }
+
+  NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
+
+  [highlightView layoutIfNeeded];
+  if (self.presenting) {
+    [highlightView animateDiscover:transitionDuration];
+  } else {
+    switch (self.dismissStyle) {
+      case MDCFeatureHighlightDismissAccepted:
+        [highlightView animateAccepted:transitionDuration];
+        break;
+
+      case MDCFeatureHighlightDismissRejected:
+        [highlightView animateRejected:transitionDuration];
+        break;
+    }
+  }
+  [UIView animateWithDuration:transitionDuration
+      delay:0.0
+      options:UIViewAnimationOptionBeginFromCurrentState
+      animations:^{
+        // We have to perform an animation on highlightView in this block or else UIKit
+        // will not know we are performing an animation and will cancel our
+        // CAAnimations.
+        if (self.presenting) {
+          [highlightView layoutAppearing];
+        } else {
+          [highlightView layoutDisappearing];
+        }
+      }
+      completion:^(BOOL finished) {
+        // If we're dismissing, remove the highlight view from the hierarchy
+        if (!self.presenting) {
+          [fromView removeFromSuperview];
+        }
+        [transitionContext completeTransition:YES];
+      }];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h
new file mode 100644
index 0000000..ee6a603
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+
+@interface MDCFeatureHighlightLayer : CAShapeLayer
+
+@property(nonatomic, assign) CGPoint center;
+
+- (void)setCenter:(CGPoint)center radius:(CGFloat)radius animated:(BOOL)animated;
+
+- (void)setFillColor:(CGColorRef)fillColor animated:(BOOL)animated;
+
+- (void)animateRadiusOverKeyframes:(NSArray *)radii
+                          keyTimes:(NSArray *)keyTimes
+                            center:(CGPoint)center;
+
+- (void)animateFillColorOverKeyframes:(NSArray *)colors keyTimes:(NSArray *)keyTimes;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m
new file mode 100644
index 0000000..66e9f1c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m
@@ -0,0 +1,94 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightLayer.h"
+
+@implementation MDCFeatureHighlightLayer {
+  CGFloat _radius;
+}
+
+- (void)setCenter:(CGPoint)center {
+  _center = center;
+
+  CGRect circleRect = CGRectMake(center.x - _radius, center.y - _radius, _radius * 2, _radius * 2);
+  self.path = (__bridge CGPathRef _Nullable)
+      (CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL)));
+}
+
+- (void)setCenter:(CGPoint)center radius:(CGFloat)radius animated:(BOOL)animated {
+  _center = center;
+  _radius = radius;
+
+  CGRect circleRect = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
+  if (animated) {
+    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
+    animation.duration = [CATransaction animationDuration];
+    animation.timingFunction = [CATransaction animationTimingFunction];
+    if (self.path) {
+      animation.fromValue = (__bridge id)self.path;
+    } else {
+      animation.fromValue = CFBridgingRelease(
+          CGPathCreateWithEllipseInRect(CGRectMake(center.x, center.y, 0, 0), NULL));
+    }
+    self.path = (__bridge CGPathRef _Nullable)
+        CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL));
+    [self addAnimation:animation forKey:@"path"];
+  } else {
+    self.path = (__bridge CGPathRef _Nullable)
+        CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL));
+  }
+}
+
+- (void)setFillColor:(CGColorRef)fillColor animated:(BOOL)animated {
+  if (animated) {
+    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
+    animation.duration = [CATransaction animationDuration];
+    animation.timingFunction = [CATransaction animationTimingFunction];
+    animation.fromValue = (__bridge id)self.fillColor;
+    self.fillColor = fillColor;
+    [self addAnimation:animation forKey:@"fillColor"];
+  } else {
+    self.fillColor = fillColor;
+  }
+}
+
+- (void)animateRadiusOverKeyframes:(NSArray *)radii
+                          keyTimes:(NSArray *)keyTimes
+                            center:(CGPoint)center {
+  NSMutableArray *values = [NSMutableArray arrayWithCapacity:radii.count];
+  for (NSNumber *radius in radii) {
+    CGFloat r = radius.floatValue;
+    CGRect circleRect = CGRectMake(center.x - r, center.y - r, r * 2, r * 2);
+    [values addObject:CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL))];
+  }
+  CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
+  animation.duration = [CATransaction animationDuration];
+  animation.timingFunction = [CATransaction animationTimingFunction];
+  animation.values = values;
+  animation.keyTimes = keyTimes;
+  [self addAnimation:animation forKey:@"path"];
+}
+
+- (void)animateFillColorOverKeyframes:(NSArray *)colors keyTimes:(NSArray *)keyTimes {
+  CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"fillColor"];
+  animation.duration = [CATransaction animationDuration];
+  animation.timingFunction = [CATransaction animationTimingFunction];
+  animation.values = colors;
+  animation.keyTimes = keyTimes;
+  [self addAnimation:animation forKey:@"fillColor"];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h
new file mode 100644
index 0000000..8d3279a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h
@@ -0,0 +1,40 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+typedef void (^MDCFeatureHighlightInteractionBlock)(BOOL accepted);
+
+@interface MDCFeatureHighlightView : UIView
+
+@property(nonatomic, strong) UIColor *outerHighlightColor;
+@property(nonatomic, strong) UIColor *innerHighlightColor;
+
+@property(nonatomic, assign) CGPoint highlightPoint;
+@property(nonatomic, strong) UIView *displayedView;
+@property(nonatomic, strong) UILabel *titleLabel;
+@property(nonatomic, strong) UILabel *bodyLabel;
+@property(nonatomic, strong) MDCFeatureHighlightInteractionBlock interactionBlock;
+
+- (void)layoutAppearing;
+- (void)layoutDisappearing;
+
+- (void)animateDiscover:(NSTimeInterval)duration;
+- (void)animateAccepted:(NSTimeInterval)duration;
+- (void)animateRejected:(NSTimeInterval)duration;
+- (void)animatePulse;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.m
new file mode 100644
index 0000000..a6a95e7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.m
@@ -0,0 +1,344 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightView.h"
+
+#import "MDCFeatureHighlightLayer.h"
+#import "MDFTextAccessibility.h"
+#import "MaterialTypography.h"
+
+const CGFloat kMDCFeatureHighlightMinimumInnerRadius = 44.0f;
+const CGFloat kMDCFeatureHighlightInnerContentPadding = 10.0f;
+const CGFloat kMDCFeatureHighlightInnerPadding = 20.0f;
+const CGFloat kMDCFeatureHighlightTextPadding = 40.0f;
+const CGFloat kMDCFeatureHighlightTextMaxWidth = 300.0f;
+const CGFloat kMDCFeatureHighlightConcentricBound = 88.0f;
+const CGFloat kMDCFeatureHighlightNonconcentricOffset = 20.0f;
+const CGFloat kMDCFeatureHighlightMaxTextHeight = 1000.0f;
+const CGFloat kMDCFeatureHighlightTitleFontSize = 20.0f;
+
+// Animation consts
+const CGFloat kMDCFeatureHighlightInnerRadiusFactor = 1.1f;
+const CGFloat kMDCFeatureHighlightOuterRadiusFactor = 1.125f;
+const CGFloat kMDCFeatureHighlightPulseRadiusFactor = 2.0f;
+const CGFloat kMDCFeatureHighlightPulseStartAlpha = 0.54f;
+const CGFloat kMDCFeatureHighlightInnerRadiusBloomAmount =
+    (kMDCFeatureHighlightInnerRadiusFactor - 1) * kMDCFeatureHighlightMinimumInnerRadius;
+const CGFloat kMDCFeatureHighlightPulseRadiusBloomAmount =
+    (kMDCFeatureHighlightPulseRadiusFactor - 1) * kMDCFeatureHighlightMinimumInnerRadius;
+
+@implementation MDCFeatureHighlightView {
+  BOOL _forceConcentricLayout;
+  UIView *_highlightView;
+  CGPoint _highlightPoint;
+  CGPoint _highlightCenter;
+  CGFloat _innerRadius;
+  CGPoint _outerCenter;
+  CGFloat _outerRadius;
+  MDCFeatureHighlightLayer *_outerLayer;
+  MDCFeatureHighlightLayer *_pulseLayer;
+  MDCFeatureHighlightLayer *_innerLayer;
+  MDCFeatureHighlightLayer *_displayMaskLayer;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  if (self = [super initWithFrame:frame]) {
+    self.backgroundColor = [UIColor clearColor];
+
+    _outerLayer = [[MDCFeatureHighlightLayer alloc] init];
+    [self.layer addSublayer:_outerLayer];
+
+    _pulseLayer = [[MDCFeatureHighlightLayer alloc] init];
+    [self.layer addSublayer:_pulseLayer];
+
+    _innerLayer = [[MDCFeatureHighlightLayer alloc] init];
+    [self.layer addSublayer:_innerLayer];
+
+    _displayMaskLayer = [[MDCFeatureHighlightLayer alloc] init];
+    _displayMaskLayer.fillColor = [UIColor whiteColor].CGColor;
+
+    _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    _titleLabel.font =
+        [[MDCTypography fontLoader] regularFontOfSize:kMDCFeatureHighlightTitleFontSize];
+    _titleLabel.textAlignment = NSTextAlignmentNatural;
+    _titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+    _titleLabel.numberOfLines = 0;
+    [self addSubview:_titleLabel];
+
+    _bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    _bodyLabel.font = [MDCTypography subheadFont];
+    _bodyLabel.shadowColor = nil;
+    _bodyLabel.shadowOffset = CGSizeZero;
+    _bodyLabel.textAlignment = NSTextAlignmentNatural;
+    _bodyLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+    _bodyLabel.numberOfLines = 0;
+    [self addSubview:_bodyLabel];
+
+    UITapGestureRecognizer *tapRecognizer =
+        [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapView:)];
+    [self addGestureRecognizer:tapRecognizer];
+
+    self.outerHighlightColor = [UIColor blueColor];
+    self.innerHighlightColor = [UIColor whiteColor];
+
+    // We want the inner and outer highlights to animate from the same origin so we start them from
+    // a concentric position.
+    _forceConcentricLayout = YES;
+  }
+  return self;
+}
+
+- (void)layoutAppearing {
+  // TODO: Mask the labels during the presentation and dismissal animations.
+  _titleLabel.alpha = 1;
+  _bodyLabel.alpha = 1;
+}
+
+- (void)layoutDisappearing {
+  _titleLabel.alpha = 0;
+  _bodyLabel.alpha = 0;
+}
+
+- (void)setOuterHighlightColor:(UIColor *)outerHighlightColor {
+  _outerHighlightColor = outerHighlightColor;
+  _outerLayer.fillColor = _outerHighlightColor.CGColor;
+
+  MDFTextAccessibilityOptions options = MDFTextAccessibilityOptionsPreferLighter;
+  if ([MDFTextAccessibility isLargeForContrastRatios:_bodyLabel.font]) {
+    options |= MDFTextAccessibilityOptionsLargeFont;
+  }
+
+  UIColor *outerColor = [_outerHighlightColor colorWithAlphaComponent:1.0];
+  _bodyLabel.textColor =
+      [MDFTextAccessibility textColorOnBackgroundColor:outerColor
+                                       targetTextAlpha:[MDCTypography captionFontOpacity]
+                                               options:options];
+
+  options = MDFTextAccessibilityOptionsPreferLighter;
+  if ([MDFTextAccessibility isLargeForContrastRatios:_titleLabel.font]) {
+    options |= MDFTextAccessibilityOptionsLargeFont;
+  }
+  // Since MDFTextAccessibility can return either a dark value or light value color we want to
+  // guarantee that the title and body have the same value.
+  CGFloat titleAlpha = [MDFTextAccessibility minAlphaOfTextColor:_bodyLabel.textColor
+                                               onBackgroundColor:outerColor
+                                                         options:options];
+  titleAlpha = MAX([MDCTypography titleFontOpacity], titleAlpha);
+  _titleLabel.textColor = [_bodyLabel.textColor colorWithAlphaComponent:titleAlpha];
+}
+
+- (void)setInnerHighlightColor:(UIColor *)innerHighlightColor {
+  _innerHighlightColor = innerHighlightColor;
+
+  _pulseLayer.fillColor = _innerHighlightColor.CGColor;
+  _innerLayer.fillColor = _innerHighlightColor.CGColor;
+}
+
+- (void)setDisplayedView:(UIView *)displayedView {
+  CGSize displayedSize = displayedView.frame.size;
+  CGFloat viewRadius =
+      (CGFloat)sqrt(pow(displayedSize.width / 2, 2) + pow(displayedSize.height / 2, 2));
+  viewRadius += kMDCFeatureHighlightInnerContentPadding;
+  _innerRadius = MAX(viewRadius, kMDCFeatureHighlightMinimumInnerRadius);
+
+  _displayedView.layer.mask = nil;
+  [_displayedView removeFromSuperview];
+  _displayedView = displayedView;
+  [self addSubview:_displayedView];
+  _displayedView.layer.mask = _displayMaskLayer;
+}
+
+- (void)setHighlightPoint:(CGPoint)highlightPoint {
+  _highlightPoint = highlightPoint;
+
+  [self setNeedsLayout];
+  [self layoutIfNeeded];
+}
+
+- (void)animateDiscover:(NSTimeInterval)duration {
+  [_innerLayer setFillColor:[_innerHighlightColor colorWithAlphaComponent:0].CGColor];
+  [_outerLayer setFillColor:[_outerHighlightColor colorWithAlphaComponent:0].CGColor];
+
+  CGPoint displayMaskCenter =
+      CGPointMake(_displayedView.frame.size.width / 2, _displayedView.frame.size.height / 2);
+
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  [CATransaction setAnimationDuration:duration];
+  [_displayMaskLayer setCenter:displayMaskCenter radius:_innerRadius animated:YES];
+  [_innerLayer setFillColor:[_innerHighlightColor colorWithAlphaComponent:1].CGColor animated:YES];
+  [_innerLayer setCenter:_highlightPoint radius:_innerRadius animated:YES];
+  [_outerLayer setFillColor:_outerHighlightColor.CGColor animated:YES];
+  [_outerLayer setCenter:_highlightCenter radius:_outerRadius animated:YES];
+  [CATransaction commit];
+
+  _forceConcentricLayout = NO;
+}
+
+- (void)animatePulse {
+  NSArray *keyTimes = @[ @0, @0.5, @1 ];
+  id pulseColorStart =
+      (__bridge id)
+          [_innerHighlightColor colorWithAlphaComponent:kMDCFeatureHighlightPulseStartAlpha]
+              .CGColor;
+  id pulseColorEnd = (__bridge id)[_innerHighlightColor colorWithAlphaComponent:0].CGColor;
+  CGFloat radius = _innerRadius;
+
+  [CATransaction begin];
+  [CATransaction setAnimationDuration:1.0f];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  CGFloat innerBloomRadius = radius + kMDCFeatureHighlightInnerRadiusBloomAmount;
+  CGFloat pulseBloomRadius = radius + kMDCFeatureHighlightPulseRadiusBloomAmount;
+  NSArray *innerKeyframes = @[ @(radius), @(innerBloomRadius), @(radius) ];
+  [_innerLayer animateRadiusOverKeyframes:innerKeyframes keyTimes:keyTimes center:_highlightPoint];
+  NSArray *pulseKeyframes = @[ @(radius), @(radius), @(pulseBloomRadius) ];
+  [_pulseLayer animateRadiusOverKeyframes:pulseKeyframes keyTimes:keyTimes center:_highlightPoint];
+  [_pulseLayer animateFillColorOverKeyframes:@[ pulseColorStart, pulseColorStart, pulseColorEnd ]
+                                    keyTimes:keyTimes];
+  [CATransaction commit];
+}
+
+- (void)animateAccepted:(NSTimeInterval)duration {
+  CGPoint displayMaskCenter =
+      CGPointMake(_displayedView.frame.size.width / 2, _displayedView.frame.size.height / 2);
+
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  [CATransaction setAnimationDuration:duration];
+  [_displayMaskLayer setCenter:displayMaskCenter radius:0.0 animated:YES];
+  [_innerLayer setCenter:_highlightPoint radius:0 animated:YES];
+  [_outerLayer setFillColor:[_outerHighlightColor colorWithAlphaComponent:0].CGColor animated:YES];
+  [_outerLayer setCenter:_highlightCenter
+                  radius:kMDCFeatureHighlightOuterRadiusFactor * _outerRadius
+                animated:YES];
+  [CATransaction commit];
+
+  _forceConcentricLayout = YES;
+}
+
+- (void)animateRejected:(NSTimeInterval)duration {
+  CGPoint displayMaskCenter =
+      CGPointMake(_displayedView.frame.size.width / 2, _displayedView.frame.size.height / 2);
+
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  [CATransaction setAnimationDuration:duration];
+  [_displayMaskLayer setCenter:displayMaskCenter radius:0 animated:YES];
+  [_innerLayer setCenter:_highlightPoint radius:0 animated:YES];
+  [_outerLayer setFillColor:[_outerHighlightColor colorWithAlphaComponent:0].CGColor animated:YES];
+  [_outerLayer setCenter:_highlightPoint radius:0 animated:YES];
+  [CATransaction commit];
+
+  _forceConcentricLayout = NO;
+}
+
+- (void)layoutSubviews {
+  [_innerLayer removeAllAnimations];
+  [_outerLayer removeAllAnimations];
+  [_pulseLayer removeAllAnimations];
+
+  BOOL leftHalf = _highlightPoint.x < self.frame.size.width / 2;
+  BOOL topHalf = _highlightPoint.y < self.frame.size.height / 2;
+
+  CGFloat textWidth = MIN(self.frame.size.width - 2 * kMDCFeatureHighlightTextPadding,
+                          kMDCFeatureHighlightTextMaxWidth);
+  CGSize titleSize =
+      [_titleLabel sizeThatFits:CGSizeMake(textWidth, kMDCFeatureHighlightMaxTextHeight)];
+  CGSize detailSize =
+      [_bodyLabel sizeThatFits:CGSizeMake(textWidth, kMDCFeatureHighlightMaxTextHeight)];
+  titleSize.width = MAX(titleSize.width, detailSize.width);
+  detailSize.width = titleSize.width;
+
+  CGFloat textHeight = titleSize.height + detailSize.height;
+
+  if ((_highlightPoint.y <= kMDCFeatureHighlightConcentricBound) ||
+      (_highlightPoint.y >= self.frame.size.height - kMDCFeatureHighlightConcentricBound)) {
+    _highlightCenter = _highlightPoint;
+  } else {
+    if (topHalf) {
+      _highlightCenter.y = _highlightPoint.y + _innerRadius + textHeight / 2;
+    } else {
+      _highlightCenter.y = _highlightPoint.y - _innerRadius - textHeight / 2;
+    }
+    if (leftHalf) {
+      _highlightCenter.x = _highlightPoint.x + kMDCFeatureHighlightNonconcentricOffset;
+    } else {
+      _highlightCenter.x = _highlightPoint.x - kMDCFeatureHighlightNonconcentricOffset;
+    }
+  }
+
+  _displayedView.center = _highlightPoint;
+  _innerLayer.center = _highlightPoint;
+  _pulseLayer.center = _highlightPoint;
+
+  if (_forceConcentricLayout) {
+    _outerLayer.center = _highlightPoint;
+  } else {
+    _outerLayer.center = _highlightCenter;
+  }
+
+  CGFloat leftTextBound = kMDCFeatureHighlightTextPadding;
+  CGFloat rightTextBound = self.frame.size.width - MAX(titleSize.width, detailSize.width) -
+                           kMDCFeatureHighlightTextPadding;
+  CGPoint titlePos = CGPointMake(0, 0);
+  titlePos.x = MIN(MAX(_highlightCenter.x - textWidth / 2, leftTextBound), rightTextBound);
+  if (topHalf) {
+    titlePos.y = _highlightPoint.y + kMDCFeatureHighlightInnerPadding + _innerRadius;
+  } else {
+    titlePos.y = _highlightPoint.y - kMDCFeatureHighlightInnerPadding - _innerRadius - textHeight;
+  }
+
+  CGRect titleFrame = (CGRect){titlePos, titleSize};
+  _titleLabel.frame = titleFrame;
+
+  CGRect detailFrame = (CGRect){CGPointMake(titlePos.x, CGRectGetMaxY(titleFrame)), detailSize};
+  _bodyLabel.frame = detailFrame;
+
+  // Calculating the radius required for a circle centered at _highlightCenter that fully encircles
+  // both labels.
+  CGRect textFrames = CGRectUnion(_titleLabel.frame, _bodyLabel.frame);
+  CGFloat distX = ABS(CGRectGetMidX(textFrames) - _highlightCenter.x) + textFrames.size.width / 2;
+  CGFloat distY = ABS(CGRectGetMidY(textFrames) - _highlightCenter.y) + textFrames.size.height / 2;
+  CGFloat minTextRadius =
+      (CGFloat)(sqrt(pow(distX, 2) + pow(distY, 2)) + kMDCFeatureHighlightTextPadding);
+
+  // Calculating the radius required for a circle centered at _highlightCenter that fully encircles
+  // the inner highlight.
+  distX = ABS(_highlightCenter.x - _highlightPoint.x);
+  distY = ABS(_highlightCenter.y - _highlightPoint.y);
+  CGFloat minInnerHighlightRadius = (CGFloat)(sqrt(pow(distX, 2) + pow(distY, 2)) + _innerRadius +
+                                              kMDCFeatureHighlightInnerPadding);
+
+  // Use the larger of the two radii to ensure everything is encircled.
+  _outerRadius = MAX(minTextRadius, minInnerHighlightRadius);
+}
+
+- (void)didTapView:(UITapGestureRecognizer *)tapGestureRecognizer {
+  CGPoint pos = [tapGestureRecognizer locationInView:self];
+  CGFloat dist =
+      (float)(sqrt(pow(pos.x - _highlightPoint.x, 2) + pow(pos.y - _highlightPoint.y, 2)));
+  BOOL accepted = dist <= _innerRadius;
+
+  if (self.interactionBlock) {
+    self.interactionBlock(accepted);
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
new file mode 100644
index 0000000..38fa58c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
@@ -0,0 +1,44 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCFlexibleHeaderViewController;
+
+/**
+ The MDCFlexibleHeaderContainerViewController controller is a straightforward container of a
+ content view controller and a MDCFlexibleHeaderViewController.
+
+ This view controller may be used in situations where the content view controller can't have a
+ header injected into its view hierarchy. UIPageViewController is one such view controller.
+ */
+@interface MDCFlexibleHeaderContainerViewController : UIViewController
+
+- (nonnull instancetype)initWithContentViewController:
+        (nullable UIViewController *)contentViewController NS_DESIGNATED_INITIALIZER;
+
+/**
+ The header view controller that lives alongside the content view controller.
+
+ This view controller's view will be placed in front of the content view controller's view.
+ */
+@property(nonatomic, strong, nonnull, readonly)
+    MDCFlexibleHeaderViewController *headerViewController;
+
+/** The content view controller to be displayed behind the header. */
+@property(nonatomic, strong, nullable) UIViewController *contentViewController;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m
new file mode 100644
index 0000000..85577db
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m
@@ -0,0 +1,98 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderContainerViewController.h"
+
+#import "MDCFlexibleHeaderView.h"
+#import "MDCFlexibleHeaderViewController.h"
+
+@implementation MDCFlexibleHeaderContainerViewController
+
+- (instancetype)initWithContentViewController:(UIViewController *)contentViewController {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _headerViewController = [[MDCFlexibleHeaderViewController alloc] init];
+    [self addChildViewController:_headerViewController];
+
+    self.contentViewController = contentViewController;
+  }
+  return self;
+}
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+  return [self initWithContentViewController:nil];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  return [self initWithContentViewController:nil];
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  [self.view addSubview:self.contentViewController.view];
+  [self.contentViewController didMoveToParentViewController:self];
+
+  // Enforce the header's desire to fully cover the width of its parent view.
+  CGRect frame = self.view.frame;
+  frame.origin.x = 0;
+  frame.size.width = self.view.bounds.size.width;
+  self.headerViewController.view.frame = self.view.bounds;
+  [self.view addSubview:self.headerViewController.view];
+  [self.headerViewController didMoveToParentViewController:self];
+}
+
+- (void)viewWillLayoutSubviews {
+  [super viewWillLayoutSubviews];
+  [self.headerViewController updateTopLayoutGuide];
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _headerViewController.prefersStatusBarHidden;
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  return _headerViewController.preferredStatusBarStyle;
+}
+
+#pragma mark - Public
+
+- (void)setContentViewController:(UIViewController *)contentViewController {
+  if (_contentViewController == contentViewController) {
+    return;
+  }
+
+  // Teardown of the old controller
+
+  [_contentViewController willMoveToParentViewController:nil];
+  if ([_contentViewController isViewLoaded]) {
+    [_contentViewController.view removeFromSuperview];
+  }
+  [_contentViewController removeFromParentViewController];
+
+  // Setup of the new controller
+
+  _contentViewController = contentViewController;
+
+  [self addChildViewController:contentViewController];
+  if ([self isViewLoaded]) {
+    [self.view insertSubview:contentViewController.view
+                belowSubview:self.headerViewController.headerView];
+    [contentViewController didMoveToParentViewController:self];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
new file mode 100644
index 0000000..a0d180e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
@@ -0,0 +1,455 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+typedef void (^MDCFlexibleHeaderChangeContentInsetsBlock)(void);
+typedef void (^MDCFlexibleHeaderShadowIntensityChangeBlock)(CALayer *_Nonnull shadowLayer,
+                                                            CGFloat intensity);
+
+/**
+ The possible translation (shift) behaviors of a flexible header view.
+
+ Enabling shifting allows the header to enter the
+ @c MDCFlexibleHeaderScrollPhaseShifting scroll phase.
+ */
+typedef NS_ENUM(NSInteger, MDCFlexibleHeaderShiftBehavior) {
+
+  /** Header's y position never changes in reaction to scroll events. */
+  MDCFlexibleHeaderShiftBehaviorDisabled,
+
+  /** When fully-collapsed, the header translates vertically in reaction to scroll events. */
+  MDCFlexibleHeaderShiftBehaviorEnabled,
+
+  /**
+   When fully-collapsed, the header translates vertically in reaction to scroll events along with
+   the status bar.
+
+   If used with a vertically-paging scroll view, this behavior acts like
+   MDCFlexibleHeaderShiftBehaviorEnabled.
+   */
+  MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar,
+};
+
+/** The importance of content contained within the flexible header view. */
+typedef NS_ENUM(NSInteger, MDCFlexibleHeaderContentImportance) {
+
+  /**
+   Default behavior requires at most approximately a single swipe before the header re-appears.
+   */
+  MDCFlexibleHeaderContentImportanceDefault,
+
+  /**
+   Highly-important header content will re-appear faster than default importance.
+
+   Examples of important content:
+
+   - Search bar.
+   - Non-navigational actions.
+   */
+  MDCFlexibleHeaderContentImportanceHigh,
+};
+
+/** Mutually exclusive phases that the flexible header view can be in. */
+typedef NS_ENUM(NSInteger, MDCFlexibleHeaderScrollPhase) {
+
+  /**
+   The header is at its min height and shifting off/on screen.
+
+   frame.origin.y is changing.
+   */
+  MDCFlexibleHeaderScrollPhaseShifting,
+
+  /**
+   The header is changing its height within the min-max range.
+
+   frame.size.height is changing.
+   */
+  MDCFlexibleHeaderScrollPhaseCollapsing,
+
+  /**
+   The header is changing its height and is taller than its maximum height.
+
+   frame.size.height is changing.
+   */
+  MDCFlexibleHeaderScrollPhaseOverExtending,
+};
+
+@protocol MDCFlexibleHeaderViewDelegate;
+
+/**
+ MDCFlexibleHeaderView tracks the content offset of a scroll view and adjusts its size and
+ position according to a configurable set of behaviors.
+
+ ### UIScrollViewDelegate forwarding
+
+ This view relies on you informing it of certain UIScrollViewDelegate events as they happen. These
+ events are listed in the UIScrollViewDelegate events section.
+ */
+IB_DESIGNABLE
+@interface MDCFlexibleHeaderView : UIView
+
+#pragma mark Custom shadow
+
+/**
+ Custom shadow shown under flexible header content.
+ */
+@property(nonatomic, strong, nullable) CALayer *shadowLayer;
+
+/**
+ Sets a custom shadow layer and a block that should be executed when shadow intensity changes.
+ */
+- (void)setShadowLayer:(nonnull CALayer *)shadowLayer
+    intensityDidChangeBlock:(nonnull MDCFlexibleHeaderShadowIntensityChangeBlock)block;
+
+#pragma mark UIScrollViewDelegate events
+
+/**
+ Informs the receiver that the tracking scroll view's contentOffset has changed.
+
+ Must be called from the trackingScrollView delegate's UIScrollViewDelegate::scrollViewDidScroll:
+ implementor.
+ */
+- (void)trackingScrollViewDidScroll;
+
+/**
+ Informs the receiver that the tracking scroll view has finished dragging.
+
+ Must be called from the trackingScrollView delegate's
+ UIScrollViewDelegate::scrollViewDidEndDragging:willDecelerate: implementor.
+ */
+- (void)trackingScrollViewDidEndDraggingWillDecelerate:(BOOL)willDecelerate;
+
+/**
+ Informs the receiver that the tracking scroll view has finished decelerating.
+
+ Must be called from the trackingScrollView delegate's
+ UIScrollViewDelegate::scrollViewDidEndDecelerating: implementor.
+ */
+- (void)trackingScrollViewDidEndDecelerating;
+
+/**
+ Potentially modifies the target content offset in order to ensure that the header view is either
+ visible or hidden depending on its current position.
+
+ Must be called from the trackingScrollView delegate's
+ -scrollViewWillEndDragging:withVelocity:targetContentOffset: implementor.
+
+ If your scroll view is vertically paging then this method will do nothing. You should also
+ disable hidesStatusBarWhenCollapsed.
+
+ @return A Boolean value indicating whether the target content offset was modified.
+ */
+- (BOOL)trackingScrollViewWillEndDraggingWithVelocity:(CGPoint)velocity
+                                  targetContentOffset:(inout nonnull CGPoint *)targetContentOffset;
+
+#pragma mark Changing the tracking scroll view
+
+/**
+ Informs the receiver that the tracking scroll view might be about to change to a new tracking
+ scroll view.
+ */
+- (void)trackingScrollWillChangeToScrollView:(nullable UIScrollView *)scrollView;
+
+#pragma mark Shifting the tracking scroll view on-screen
+
+/** Asks the receiver to bring the header on-screen if it's currently off-screen. */
+- (void)shiftHeaderOnScreenAnimated:(BOOL)animated;
+
+/** Asks the receiver to take the header off-screen if it's currently on-screen. */
+- (void)shiftHeaderOffScreenAnimated:(BOOL)animated;
+
+#pragma mark UIKit Hooks
+
+// All of these UIKit hooks must be called from the view controller that owns this header view.
+// Failure to do so will result in undefined behavior of the flexible header view.
+
+/**
+ Returns a Boolean value indicating whether the status bar should be visible.
+
+ Must be called by the owning UIViewController's -prefersStatusBarHidden.
+ */
+@property(nonatomic, readonly) BOOL prefersStatusBarHidden;
+
+// Pre-iOS 8 Interface Orientation APIs
+
+/**
+ Informs the receiver that the interface orientation is about to change.
+
+ Must be called from UIViewController::willRotateToInterfaceOrientation:duration:.
+ */
+- (void)interfaceOrientationWillChange;
+
+/**
+ Informs the receiver that the interface orientation is in the process of changing.
+
+ Must be called from UIViewController::willAnimateRotationToInterfaceOrientation:duration:.
+ */
+- (void)interfaceOrientationIsChanging;
+
+/**
+ Informs the receiver that the interface orientation has changed.
+
+ Must be called from UIViewController::didRotateFromInterfaceOrientation:.
+ */
+- (void)interfaceOrientationDidChange;
+
+// iOS 8 Interface Orientation APIs
+
+/**
+ Informs the receiver that the owning view controller's size will change.
+
+ Must be called from UIViewController::viewWillTransitionToSize:withTransitionCoordinator: on apps
+ targeting iOS 8 and onward.
+ */
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator;
+
+#pragma mark Changing Content Insets
+
+/**
+ Must be called by a client that wishes to update the content insets of the tracking scroll view.
+
+ Not using this method can lead to undefined behavior due to the flexible header view assuming
+ that a certain amount of additional content insets have been provided to the tracking scroll
+ view.
+
+ The provided block will be executed after the flexible header has removed its modifications to
+ the tracking scroll view. Upon completion of the block, the flexible header will re-inject these
+ modifications into the new content insets and ensure that the content offset doesn't change due
+ to the new content insets.
+ */
+- (void)changeContentInsets:(nonnull MDCFlexibleHeaderChangeContentInsetsBlock)block;
+
+#pragma mark Forwarding Touch Events
+
+/**
+ Forwards any tap events made to the provided view on to the tracking scroll view.
+
+ Views will only forward their taps if they are a subview of this header view and are interactive.
+
+ Touch forwarding does not apply to subviews of the provided view.
+ */
+- (void)forwardTouchEventsForView:(nonnull UIView *)view;
+
+/** Stops forwarding tap events on the given view to the tracking scroll view. */
+- (void)stopForwardingTouchEventsForView:(nonnull UIView *)view;
+
+#pragma mark Scroll Phase
+
+/**
+ Returns the current scroll phase of the flexible header.
+
+ There are three mutually-exclusive scroll phases: shifting, collapsing, and over-extending.
+ Whichever phase the header view is in governs what scrollPhaseValue and scrollPhasePercentage
+ represent.
+
+ This and the related scrollPhase properties are only valid immediately after a call to
+ -trackingScrollViewDidScroll.
+ */
+@property(nonatomic, readonly) MDCFlexibleHeaderScrollPhase scrollPhase;
+
+/**
+ A value in screen points denoting the absolute position within the current scroll phase.
+
+ The range for each phase follows:
+
+ - Shifting:       [0, minimumHeight)
+ - Collapsing:     [minimumHeight, maximumHeight)
+ - Over-extending: [maximumHeight, +inf)
+ */
+@property(nonatomic, readonly) CGFloat scrollPhaseValue;
+
+/**
+ A normalized value denoting the position within the current scroll phase.
+
+ The meaning of the percentage for each phase follows:
+
+ - Shifting:       0 is unshifted, 1.0 is fully shifted off-screen
+ - Collapsing:     0 == minimumHeight, 1.0 == maximumHeight
+ - Over-extending: 1.0 height == maximumHeight, every additional 1.0 is one maximumHeight unit
+
+ Note that a single percentage does not necessarily have equal weight between the three phases, so
+ you should not use this value for any behavior that is active across any two phases; use
+ scrollPhaseValue instead.
+ */
+@property(nonatomic, readonly) CGFloat scrollPhasePercentage;
+
+#pragma mark Bounding Dimensions
+
+/**
+ The minimum height that this header can shrink to.
+
+ If you change the value of this property and the maximumHeight of the receiver is below the new
+ minimumHeight, maximumHeight will be adjusted to match the new minimum value.
+ */
+@property(nonatomic) CGFloat minimumHeight;
+
+/**
+ The maximum height that this header can expand to.
+
+ If you change the value of this property and the minimumHeight of the receiver is above the new
+ maximumHeight, minimumHeight will be adjusted to match the new maximumHeight.
+ */
+@property(nonatomic) CGFloat maximumHeight;
+
+#pragma mark Behaviors
+
+/** The behavior of the header in response to the user interacting with the tracking scroll view. */
+@property(nonatomic) MDCFlexibleHeaderShiftBehavior shiftBehavior;
+
+/**
+ If shiftBehavior is enabled, this property affects the manner in which the Header reappears when
+ pulling content down in the tracking scroll view.
+
+ Ignored if shiftBehavior == MDCFlexibleHeaderShiftBehaviorDisabled.
+
+ Default: MDCFlexibleHeaderContentImportanceDefault
+ */
+@property(nonatomic) MDCFlexibleHeaderContentImportance headerContentImportance;
+
+/**
+ Whether or not the header view is allowed to expand past its maximum height when the tracking
+ scroll view has been dragged past its top edge.
+
+ Default: YES
+ */
+@property(nonatomic) BOOL canOverExtend;
+
+/**
+ A hint stating whether or not the operating system's status bar frame can ever overlap the header's
+ frame.
+
+ This property is enabled by default with the expectation that the flexible header will primarily
+ be used in full-screen settings on the phone.
+
+ Disabling this property informs the flexible header that it should not concern itself with the
+ status bar in any manner. shiftBehavior .EnabledWithStatusBar will be treated simply as .Enabled
+ in this case.
+
+ Default: YES
+ */
+@property(nonatomic) BOOL statusBarHintCanOverlapHeader;
+
+@property(nonatomic) float visibleShadowOpacity;  ///< The visible shadow opacity. Default: 0.4
+
+#pragma mark Scroll View Tracking
+
+/**
+ The scroll view whose content offset affects the height/offset of the flexible header view.
+
+ The receiver will inject the maximum height of the header view into the top component of the
+ tracking scroll view's content insets. This ensures that there is enough space in the top insets
+ to fit the header. This should be taken into account when working with the tracking scroll view's
+ content insets.
+
+ Importantly, if you wish to make changes to the tracking scroll view's content insets after it
+ has been registered to a flexible header view, you must do so from within a -changeContentInsets:
+ invocation on the flexible header view.
+
+ The tracking scroll view is weakly held so that we don't unintentionally keep the scroll view
+ around any longer than it needs to be. Doing so could get into tricky situations where the view
+ controller didn't nil out the scroll view's delegate in dealloc and UIScrollView's non-weak
+ delegate points to a dead object.
+ */
+@property(nonatomic, weak, nullable) UIScrollView *trackingScrollView;
+
+/**
+ When enabled, the header view will prioritize shifting off-screen and collapsing over shifting
+ on-screen and expanding.
+
+ This should only be enabled when the user is scrubbing the tracking scroll view, i.e. they're
+ able to jump large distances using a scrubber control.
+ */
+@property(nonatomic) BOOL trackingScrollViewIsBeingScrubbed;
+
+/**
+ Whether or not the header is floating in front of an infinite stream of content.
+
+ Enabling this behavior will cause the header to always appear to be floating "in front of" the
+ content in Material space. This behavior should _only_ be enabled for content that has no top
+ edge, e.g. an infinite stream of vertical content.
+
+ Default: NO
+ */
+@property(nonatomic, getter=isInFrontOfInfiniteContent) BOOL inFrontOfInfiniteContent;
+
+/**
+ Whether or not the receiver is shared by many scroll views, such as in a tabbed interface with
+ many columns of content.
+
+ Default: NO
+ */
+@property(nonatomic) BOOL sharedWithManyScrollViews;
+
+#pragma mark Configuring Status Bar Behaviors
+
+/**
+ Whether this header view's content is translucent/transparent. Provides a hint to status bar
+ rendering, to correctly display contents scrolling under the status bar as it shifts on/off screen.
+
+ Default: NO
+ */
+@property(nonatomic) BOOL contentIsTranslucent;
+
+#pragma mark Header View Delegate
+
+/** The delegate for this header view. */
+@property(nonatomic, weak, nullable) id<MDCFlexibleHeaderViewDelegate> delegate;
+
+@end
+
+/**
+ The MDCFlexibleHeaderViewDelegate protocol allows a delegate to respond to changes in the header
+ view's state.
+
+ The delegate is typically the UIViewController that owns this flexible header view.
+ */
+@protocol MDCFlexibleHeaderViewDelegate <NSObject>
+@required
+
+/**
+ Informs the receiver that the flexible header view's preferred status bar visibility has changed.
+ */
+- (void)flexibleHeaderViewNeedsStatusBarAppearanceUpdate:
+        (nonnull MDCFlexibleHeaderView *)headerView;
+
+/**
+ Informs the receiver that the flexible header view's frame has changed.
+
+ The frame may change in response to scroll events of the tracking scroll view. The receiver
+ should use the MDCFlexibleHeaderView scrollPhase APIs to determine which phase the header's frame
+ is in.
+ */
+- (void)flexibleHeaderViewFrameDidChange:(nonnull MDCFlexibleHeaderView *)headerView;
+
+@end
+
+// clang-format off
+@interface MDCFlexibleHeaderView ()
+
+/** @see shiftBehavior */
+@property(nonatomic) MDCFlexibleHeaderShiftBehavior behavior
+__deprecated_msg("Use shiftBehavior instead.");
+
+#pragma mark Accessing the header's views
+
+/** Deprecated. Please register views directly to the flexible header. */
+@property(nonatomic, strong, nonnull) UIView *contentView
+__deprecated_msg("Please register views directly to the flexible header.");
+
+@end
+// clang-format on
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
new file mode 100644
index 0000000..7fa143e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
@@ -0,0 +1,1276 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderView.h"
+
+#import "private/MDCStatusBarShifter.h"
+
+#if TARGET_IPHONE_SIMULATOR
+float UIAnimationDragCoefficient(void);  // Private API for simulator animation speed
+#endif
+
+static const CGFloat kExpectedStatusBarHeight = 20;
+
+// The default maximum height for the header. Includes the status bar height.
+static const CGFloat kFlexibleHeaderDefaultHeight = 76;
+
+// The maximum default opacity of the shadow.
+static const float kDefaultVisibleShadowOpacity = 0.4f;
+
+// This length defines the moment at which the shadow will be fully visible as the header shifts
+// on-screen.
+static const CGFloat kShadowScaleLength = 8;
+
+// Duration of the UIKit animation that occurs when changing the tracking scroll view.
+static const NSTimeInterval kTrackingScrollViewDidChangeAnimationDuration = 0.2;
+
+// The epsilon used to determine when we've arrived at the destination while shifting the header
+// on/off-screen with the display link.
+static const float kShiftEpsilon = 0.1f;
+
+// The minimum delta y before we change the scroll direction.
+static const CGFloat kDeltaYSlop = 5;
+
+// Affects how fast the header shifts on/off-screen while animating. Bigger value = faster.
+static const CGFloat kAttachmentCoefficient = 12;
+
+// The amount the user needs to scroll back before the header starts shifting back on-screen.
+static const CGFloat kMaxAnchorLengthFullSwipe = 175;
+static const CGFloat kMaxAnchorLengthQuickSwipe = 25;
+
+// The minimum proportion of the header that will cause it to slide back on screen when the scroll
+// view finishes decelerating with the header partially shifted.
+static const CGFloat kMinimumVisibleProportion = 0.25;
+
+static inline MDCFlexibleHeaderShiftBehavior ShiftBehaviorForCurrentAppContext(
+    MDCFlexibleHeaderShiftBehavior intendedShiftBehavior) {
+  if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"] &&
+      intendedShiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar) {
+    return MDCFlexibleHeaderShiftBehaviorEnabled;
+  }
+  return intendedShiftBehavior;
+}
+
+static NSString *const MDCFlexibleHeaderMinimumHeightKey = @"MDCFlexibleHeaderMinimumHeightKey";
+static NSString *const MDCFlexibleHeaderMaximumHeightKey = @"MDCFlexibleHeaderMaximumHeightKey";
+static NSString *const MDCFlexibleHeaderShiftBehaviorKey = @"MDCFlexibleHeaderShiftBehaviorKey";
+static NSString *const MDCFlexibleHeaderContentImportanceKey =
+    @"MDCFlexibleHeaderContentImportanceKey";
+static NSString *const MDCFlexibleHeaderCanOverExtendKey = @"MDCFlexibleHeaderCanOverExtendKey";
+static NSString *const MDCFlexibleHeaderStatusBarCanOverlapKey =
+    @"MDCFlexibleHeaderStatusBarCanOverlapKey";
+static NSString *const MDCFlexibleHeaderVisibleShadowOpacityKey =
+    @"MDCFlexibleHeaderVisibleShadowOpacityKey";
+static NSString *const MDCFlexibleHeaderTrackingScrollViewKey =
+    @"MDCFlexibleHeaderTrackingScrollViewKey";
+static NSString *const MDCFlexibleHeaderInFrontOfInfiniteContentKey =
+    @"MDCFlexibleHeaderInFrontOfInfiniteContentKey";
+static NSString *const MDCFlexibleHeaderSharedWithManyScrollViewsKey =
+    @"MDCFlexibleHeaderSharedWithManyScrollViewsKey";
+static NSString *const MDCFlexibleHeaderContentIsTranslucentKey =
+    @"MDCFlexibleHeaderContentIsTranslucentKey";
+static NSString *const MDCFlexibleHeaderDelegateKey = @"MDCFlexibleHeaderDelegateKey";
+
+@interface MDCFlexibleHeaderView () <MDCStatusBarShifterDelegate>
+
+// The intensity strength of the shadow being displayed under the flexible header. Use this property
+// to check what the intensity of a custom shadow should be depending on a scroll position. Valid
+// values range from 0 to 1. Where 0 is no shadow is visible and 1 is the shadow is fully visible.
+@property(nonatomic, readonly) CGFloat shadowIntensity;
+
+@end
+
+// All injections into the content and scroll indicator insets are tracked here. It's super
+// important that we track what we added, rather than trying to cache the original values, because
+// we can't know if the insets have changed out from under us by another party.
+//
+// A separate info object is tracked for each scroll view tracked by the flexible header view.
+@interface MDCFlexibleHeaderScrollViewInfo : NSObject
+
+// The amount injected into contentInsets.top
+@property(nonatomic) CGFloat injectedTopContentInset;
+
+// Whether or not we've injected the top content inset
+@property(nonatomic) BOOL hasInjectedTopContentInset;
+
+// The amount injected into scrollIndicatorInsets.top
+@property(nonatomic) CGFloat injectedTopScrollIndicatorInset;
+
+@end
+
+@implementation MDCFlexibleHeaderView {
+  // We keep a weak reference to all forwarding views in case the client forgets to stop forwarding
+  // events for a view that's been removed from the header view. If we held a strong reference here
+  // then the removed view would never be deallocated.
+  NSHashTable *_forwardingViews;  // [UIView]
+
+  // A weak reference map of scroll views to info that have been tracked by this header view.
+  NSMapTable *_trackedScrollViews;  // {UIScrollView:MDCFlexibleHeaderScrollViewInfo}
+  MDCFlexibleHeaderScrollViewInfo *_trackingInfo;
+
+  // The ideal visibility state of the header. This may not match the present visibility if the user
+  // is interacting with the header or if we're presently animating it.
+  BOOL _wantsToBeHidden;
+
+  // Shift behavior state
+
+  // Prevents delta calculations on first update pass.
+  BOOL _shiftAccumulatorLastContentOffsetIsValid;
+  // When the header can slide off-screen, this tracks how off-screen the header is.
+  // Essentially: view's top edge = -_shiftAccumulator
+  CGFloat _shiftAccumulator;
+  CGPoint _shiftAccumulatorLastContentOffset;  // Stores our last delta'd content offset.
+  CGFloat _shiftAccumulatorDeltaY;
+  CADisplayLink *_shiftAccumulatorDisplayLink;
+
+  BOOL _interfaceOrientationIsChanging;
+  BOOL _contentInsetsAreChanging;
+  BOOL _isChangingStatusBarVisibility;
+
+  MDCStatusBarShifter *_statusBarShifter;
+
+  // Layers for header shadows.
+  CALayer *_defaultShadowLayer;
+  CALayer *_customShadowLayer;
+
+  // The block executed when shadow intensity changes.
+  MDCFlexibleHeaderShadowIntensityChangeBlock _shadowIntensityChangeBlock;
+
+#if DEBUG
+  // Keeps track of whether the client called ...WillEndDraggingWithVelocity:...
+  BOOL _didAdjustTargetContentOffset;
+#endif
+}
+
+// MDCFlexibleHeader properties
+@synthesize trackingScrollViewIsBeingScrubbed = _trackingScrollViewIsBeingScrubbed;
+@synthesize scrollPhase = _scrollPhase;
+@synthesize scrollPhaseValue = _scrollPhaseValue;
+@synthesize scrollPhasePercentage = _scrollPhasePercentage;
+
+// MDCFlexibleHeaderConfiguration properties
+@synthesize trackingScrollView = _trackingScrollView;
+@synthesize minimumHeight = _minimumHeight;
+@synthesize maximumHeight = _maximumHeight;
+@synthesize canOverExtend = _canOverExtend;
+@synthesize inFrontOfInfiniteContent = _inFrontOfInfiniteContent;
+@synthesize sharedWithManyScrollViews = _sharedWithManyScrollViews;
+@synthesize visibleShadowOpacity = _visibleShadowOpacity;
+
+#if DEBUG
+- (void)dealloc {
+  [_trackingScrollView.panGestureRecognizer removeTarget:self
+                                                  action:@selector(fhv_scrollViewDidPan:)];
+}
+#endif
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCFlexibleHeaderViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCFlexibleHeaderViewInit];
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderMinimumHeightKey]) {
+      _minimumHeight = (CGFloat)[aDecoder decodeDoubleForKey:MDCFlexibleHeaderMinimumHeightKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderMaximumHeightKey]) {
+      _maximumHeight = (CGFloat)[aDecoder decodeDoubleForKey:MDCFlexibleHeaderMaximumHeightKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderShiftBehaviorKey]) {
+      _shiftBehavior = [aDecoder decodeIntegerForKey:MDCFlexibleHeaderShiftBehaviorKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderContentImportanceKey]) {
+      _headerContentImportance =
+          [aDecoder decodeIntegerForKey:MDCFlexibleHeaderContentImportanceKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderCanOverExtendKey]) {
+      _canOverExtend = [aDecoder decodeBoolForKey:MDCFlexibleHeaderCanOverExtendKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderStatusBarCanOverlapKey]) {
+      _statusBarHintCanOverlapHeader =
+          [aDecoder decodeBoolForKey:MDCFlexibleHeaderStatusBarCanOverlapKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderVisibleShadowOpacityKey]) {
+      _visibleShadowOpacity = [aDecoder decodeFloatForKey:MDCFlexibleHeaderVisibleShadowOpacityKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderTrackingScrollViewKey]) {
+      _trackingScrollView = [aDecoder decodeObjectForKey:MDCFlexibleHeaderTrackingScrollViewKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderInFrontOfInfiniteContentKey]) {
+      _inFrontOfInfiniteContent =
+          [aDecoder decodeBoolForKey:MDCFlexibleHeaderInFrontOfInfiniteContentKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderSharedWithManyScrollViewsKey]) {
+      _sharedWithManyScrollViews =
+          [aDecoder decodeBoolForKey:MDCFlexibleHeaderSharedWithManyScrollViewsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderContentIsTranslucentKey]) {
+      _contentIsTranslucent = [aDecoder decodeBoolForKey:MDCFlexibleHeaderContentIsTranslucentKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderDelegateKey]) {
+      _delegate = [aDecoder decodeObjectForKey:MDCFlexibleHeaderDelegateKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+
+  [aCoder encodeDouble:self.minimumHeight forKey:MDCFlexibleHeaderMinimumHeightKey];
+  [aCoder encodeDouble:self.maximumHeight forKey:MDCFlexibleHeaderMaximumHeightKey];
+  [aCoder encodeInteger:self.shiftBehavior forKey:MDCFlexibleHeaderShiftBehaviorKey];
+  [aCoder encodeInteger:self.headerContentImportance forKey:MDCFlexibleHeaderContentImportanceKey];
+  [aCoder encodeBool:self.canOverExtend forKey:MDCFlexibleHeaderCanOverExtendKey];
+  [aCoder encodeBool:self.statusBarHintCanOverlapHeader
+              forKey:MDCFlexibleHeaderStatusBarCanOverlapKey];
+  [aCoder encodeFloat:self.visibleShadowOpacity forKey:MDCFlexibleHeaderVisibleShadowOpacityKey];
+  [aCoder encodeBool:self.inFrontOfInfiniteContent
+              forKey:MDCFlexibleHeaderInFrontOfInfiniteContentKey];
+  [aCoder encodeBool:self.sharedWithManyScrollViews
+              forKey:MDCFlexibleHeaderSharedWithManyScrollViewsKey];
+  [aCoder encodeBool:self.contentIsTranslucent forKey:MDCFlexibleHeaderContentIsTranslucentKey];
+  if (self.trackingScrollView) {
+    [aCoder encodeConditionalObject:self.trackingScrollView
+                             forKey:MDCFlexibleHeaderTrackingScrollViewKey];
+  }
+  if (self.delegate) {
+    [aCoder encodeConditionalObject:self.delegate forKey:MDCFlexibleHeaderDelegateKey];
+  }
+}
+
+- (void)commonMDCFlexibleHeaderViewInit {
+  _statusBarShifter = [[MDCStatusBarShifter alloc] init];
+  _statusBarShifter.delegate = self;
+  _statusBarShifter.enabled = [self fhv_shouldAllowShifting];
+
+  NSPointerFunctionsOptions options =
+      (NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality);
+  _forwardingViews = [NSHashTable hashTableWithOptions:options];
+
+  NSPointerFunctionsOptions keyOptions =
+      (NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality);
+  NSPointerFunctionsOptions valueOptions =
+      (NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality);
+  _trackedScrollViews = [NSMapTable mapTableWithKeyOptions:keyOptions valueOptions:valueOptions];
+
+  _headerContentImportance = MDCFlexibleHeaderContentImportanceDefault;
+  _statusBarHintCanOverlapHeader = YES;
+
+  _minimumHeight = kFlexibleHeaderDefaultHeight;
+  _maximumHeight = kFlexibleHeaderDefaultHeight;
+  _visibleShadowOpacity = kDefaultVisibleShadowOpacity;
+  _canOverExtend = YES;
+
+  _defaultShadowLayer = [CALayer layer];
+  _defaultShadowLayer.shadowColor = [[UIColor blackColor] CGColor];
+  _defaultShadowLayer.shadowOffset = CGSizeMake(0, 1.f);
+  _defaultShadowLayer.shadowRadius = 4.f;
+  _defaultShadowLayer.shadowOpacity = 0;
+  _defaultShadowLayer.hidden = YES;
+  [self.layer addSublayer:_defaultShadowLayer];
+
+  // Allow for custom shadows to be used.
+  _customShadowLayer = [CALayer layer];
+  _customShadowLayer.hidden = YES;
+  [self.layer addSublayer:_customShadowLayer];
+
+  _contentView = [[UIView alloc] initWithFrame:self.bounds];
+  _contentView.autoresizingMask =
+      (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+  [super addSubview:_contentView];
+
+  self.backgroundColor = [UIColor lightGrayColor];
+  _defaultShadowLayer.backgroundColor = self.backgroundColor.CGColor;
+
+  self.layer.shadowColor = [[UIColor blackColor] CGColor];
+  self.layer.shadowOffset = CGSizeMake(0, 1);
+  self.layer.shadowRadius = 4.f;
+  self.layer.shadowOpacity = 0;
+}
+
+- (void)setVisibleShadowOpacity:(float)visibleShadowOpacity {
+  _visibleShadowOpacity = visibleShadowOpacity;
+  [self fhv_accumulatorDidChange];
+}
+
+- (void)fhv_setShadowLayer:(CALayer *)shadowLayer
+    intensityDidChangeBlock:(MDCFlexibleHeaderShadowIntensityChangeBlock)block {
+  _shadowIntensityChangeBlock = block;
+
+  // If there is a custom shadow make sure the shadow on self.layer is not visible.
+  self.layer.shadowOpacity = 0;
+  CALayer *oldShadowLayer = _shadowLayer;
+  if (shadowLayer == _shadowLayer) {
+    return;
+  }
+  _shadowLayer = shadowLayer;
+  [oldShadowLayer removeFromSuperlayer];
+  if (shadowLayer) {
+    // When a custom shadow is being used hide the default shadow.
+    _defaultShadowLayer.hidden = YES;
+    _customShadowLayer.hidden = NO;
+    [_customShadowLayer addSublayer:_shadowLayer];
+  } else {
+    _defaultShadowLayer.hidden = NO;
+    _customShadowLayer.hidden = YES;
+    _shadowLayer = nil;
+  }
+}
+
+- (void)setShadowLayer:(CALayer *)shadowLayer {
+  [self fhv_setShadowLayer:shadowLayer intensityDidChangeBlock:nil];
+}
+
+- (void)setShadowLayer:(CALayer *)shadowLayer
+    intensityDidChangeBlock:(MDCFlexibleHeaderShadowIntensityChangeBlock)block {
+  [self fhv_setShadowLayer:shadowLayer intensityDidChangeBlock:block];
+}
+
+#pragma mark - UIView
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return CGSizeMake(size.width, _minimumHeight);
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self fhv_updateShadowPath];
+  BOOL disableActions = [CATransaction disableActions];
+  [CATransaction setDisableActions:YES];
+  _defaultShadowLayer.frame = self.bounds;
+  _customShadowLayer.frame = self.bounds;
+  _shadowLayer.frame = self.bounds;
+  [_defaultShadowLayer layoutIfNeeded];
+  [_customShadowLayer layoutIfNeeded];
+  [_shadowLayer layoutIfNeeded];
+  [CATransaction setDisableActions:disableActions];
+}
+
+- (void)willMoveToSuperview:(UIView *)newSuperview {
+  [super willMoveToSuperview:newSuperview];
+
+  if (newSuperview == self.trackingScrollView) {
+    self.transform = CGAffineTransformMakeTranslation(0, self.trackingScrollView.contentOffset.y);
+  }
+}
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+  UIView *hitView = [super hitTest:point withEvent:event];
+
+  // Forwards taps to the scroll view.
+  if (hitView == self || [_forwardingViews containsObject:hitView]) {
+    hitView = _trackingScrollView;
+  }
+
+  return hitView;
+}
+
+- (void)setFrame:(CGRect)frame {
+  [super setFrame:frame];
+
+  if (!_interfaceOrientationIsChanging) {
+    [self fhv_updateLayout];
+  }
+}
+
+#pragma mark - Private (fhv_ prefix)
+
+- (void)fhv_removeInsetsFromScrollView:(UIScrollView *)scrollView {
+  if (!scrollView) {
+    return;
+  }
+  if (_sharedWithManyScrollViews) {
+    return;  // Never remove our insets from scroll views while the header is being shared.
+  }
+
+  MDCFlexibleHeaderScrollViewInfo *info = [_trackedScrollViews objectForKey:scrollView];
+  if (!info) {
+    return;
+  }
+
+  UIEdgeInsets insets = scrollView.contentInset;
+  insets.top -= info.injectedTopContentInset;
+  info.injectedTopContentInset = 0;
+  info.hasInjectedTopContentInset = NO;
+  scrollView.contentInset = insets;
+
+  UIEdgeInsets scrollIndicatorInsets = _trackingScrollView.scrollIndicatorInsets;
+  scrollIndicatorInsets.top -= info.injectedTopScrollIndicatorInset;
+  info.injectedTopScrollIndicatorInset = 0;
+  _trackingScrollView.scrollIndicatorInsets = scrollIndicatorInsets;
+}
+
+- (MDCFlexibleHeaderScrollViewInfo *)fhv_addInsetsToScrollView:(UIScrollView *)scrollView {
+  if (!scrollView) {
+    return nil;
+  }
+
+  MDCFlexibleHeaderScrollViewInfo *info = [_trackedScrollViews objectForKey:scrollView];
+  if (!info) {
+    info = [[MDCFlexibleHeaderScrollViewInfo alloc] init];
+    [_trackedScrollViews setObject:info forKey:scrollView];
+    if (_trackingScrollView == scrollView) {
+      _trackingInfo = info;
+    }
+  }
+
+  if (!info.hasInjectedTopContentInset) {
+    UIEdgeInsets insets = scrollView.contentInset;
+    insets.top += _maximumHeight;
+    info.injectedTopContentInset = _maximumHeight;
+    info.hasInjectedTopContentInset = YES;
+    scrollView.contentInset = insets;
+  }
+
+  // The scroll indicator insets are updated by fhv_accumulatorDidChange and change dynamically with
+  // the header.
+  return info;
+}
+
+- (void)fhv_updateShadowPath {
+  UIBezierPath *path =
+      [UIBezierPath bezierPathWithRect:CGRectInset(self.bounds, -self.layer.shadowRadius, 0)];
+  self.layer.shadowPath = [path CGPath];
+}
+
+#pragma mark Typically-used values
+
+// Returns the contentOffset of the tracking scroll view bounded to the range of content offsets
+// that will affect the header.
+- (CGPoint)fhv_boundedContentOffset {
+  // We don't care about rubber banding beyond the bottom of the content.
+  return CGPointMake(_trackingScrollView.contentOffset.x,
+                     MIN(_trackingScrollView.contentOffset.y, [self fhv_contentOffsetMaxY]));
+}
+
+- (CGFloat)fhv_rawTopContentInset {
+  return _trackingScrollView.contentInset.top - _trackingInfo.injectedTopContentInset;
+}
+
+- (CGFloat)fhv_contentOffsetWithoutInjectedTopInset {
+  return _trackingScrollView.contentOffset.y + [self fhv_rawTopContentInset];
+}
+
+- (CGFloat)fhv_contentOffsetMaxY {
+  return _trackingScrollView.contentSize.height - _trackingScrollView.bounds.size.height;
+}
+
+// Returns a value indicating how much the header is overlapping the tracking scroll view's content.
+// > 0 overlapping the content
+// = 0 attached to top of content
+// < 0 the content is below the header
+- (CGFloat)fhv_projectedHeaderBottomEdge {
+  CGFloat offsetWithoutInset = [self fhv_contentOffsetWithoutInjectedTopInset];
+  CGRect projectedFrame = [self convertRect:self.bounds toView:self.trackingScrollView.superview];
+  CGFloat frameBottomEdge = CGRectGetMaxY(projectedFrame);
+  return frameBottomEdge + offsetWithoutInset;
+}
+
+- (CGFloat)fhv_accumulatorMax {
+  BOOL shouldCollapseToStatusBar = [self fhv_shouldCollapseToStatusBar];
+  return (shouldCollapseToStatusBar ? _minimumHeight - kExpectedStatusBarHeight : _minimumHeight);
+}
+
+#pragma mark Logical short forms
+
+- (BOOL)fhv_shouldAllowShifting {
+  return self.hidesStatusBarWhenCollapsed && self.statusBarHintCanOverlapHeader;
+}
+
+- (BOOL)fhv_shouldCollapseToStatusBar {
+  return !self.hidesStatusBarWhenCollapsed && self.statusBarHintCanOverlapHeader;
+}
+
+- (BOOL)fhv_canShiftOffscreen {
+  return ((_shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabled ||
+           _shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar) &&
+          !_trackingScrollView.pagingEnabled);
+}
+
+- (BOOL)fhv_isPartiallyShifted {
+  return ([self fhv_isDetachedFromTopOfContent] && _shiftAccumulator > 0 &&
+          _shiftAccumulator < [self fhv_accumulatorMax]);
+}
+
+// The flexible header is "in front of" the content.
+- (BOOL)fhv_isDetachedFromTopOfContent {
+  // Epsilon here is somewhat large in order to be visually-forgiving for sub-point situations.
+  return [self fhv_projectedHeaderBottomEdge] > (CGFloat)0.5;
+}
+
+- (BOOL)fhv_isOverExtendingBottom {
+  CGFloat bottomEdgeOfScrollView =
+      (_trackingScrollView.contentOffset.y + _trackingScrollView.bounds.size.height);
+  CGFloat bottomEdgeOfContent =
+      (_trackingScrollView.contentSize.height + _trackingScrollView.contentInset.bottom);
+  BOOL canOverExtendBottom =
+      (_trackingScrollView.contentSize.height > _trackingScrollView.bounds.size.height);
+  return (canOverExtendBottom && (bottomEdgeOfScrollView >= bottomEdgeOfContent));
+}
+
+#pragma mark Phase Calculation
+
+// Given the current frame, calculates the scroll phase, value, and percentage.
+- (void)fhv_recalculatePhase {
+  CGRect frame = self.frame;
+
+  if (frame.origin.y < 0) {
+    _scrollPhase = MDCFlexibleHeaderScrollPhaseShifting;
+    _scrollPhaseValue = frame.origin.y + _minimumHeight;
+    CGFloat adjustedHeight = _minimumHeight;
+    if ([self fhv_shouldCollapseToStatusBar]) {
+      adjustedHeight -= kExpectedStatusBarHeight;
+    }
+    if (adjustedHeight > 0) {
+      _scrollPhasePercentage = -frame.origin.y / adjustedHeight;
+    } else {
+      _scrollPhasePercentage = 0;
+    }
+
+    return;
+  }
+
+  _scrollPhaseValue = frame.size.height;
+
+  if (frame.size.height < _maximumHeight) {
+    _scrollPhase = MDCFlexibleHeaderScrollPhaseCollapsing;
+
+    CGFloat heightLength = _maximumHeight - _minimumHeight;
+    if (heightLength > 0) {
+      _scrollPhasePercentage = (frame.size.height - _minimumHeight) / heightLength;
+    } else {
+      _scrollPhasePercentage = 0;
+    }
+
+    return;
+  }
+
+  _scrollPhase = MDCFlexibleHeaderScrollPhaseOverExtending;
+  if (_maximumHeight > 0) {
+    _scrollPhasePercentage = 1 + (frame.size.height - _maximumHeight) / _maximumHeight;
+  } else {
+    _scrollPhasePercentage = 0;
+  }
+}
+
+#pragma mark Display Link
+
+// The display link is only active when the user is no longer interacting with the scroll view and
+// we'd like to shift the header either on- or off-screen.
+
+#if TARGET_IPHONE_SIMULATOR
+- (float)fhv_dragCoefficient {
+  if (&UIAnimationDragCoefficient) {
+    float coeff = UIAnimationDragCoefficient();
+    if (coeff > 1) {
+      return coeff;
+    }
+  }
+  return 1;
+}
+#endif
+
+- (void)fhv_startDisplayLink {
+  [self fhv_stopDisplayLink];
+
+  // NOTE: This may cause a retain cycle.
+  // cl/129917749
+  _shiftAccumulatorDisplayLink =
+      [CADisplayLink displayLinkWithTarget:self
+                                  selector:@selector(fhv_shiftAccumulatorDisplayLinkDidFire:)];
+  [_shiftAccumulatorDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+}
+
+- (void)fhv_stopDisplayLink {
+  [_shiftAccumulatorDisplayLink invalidate];
+  _shiftAccumulatorDisplayLink = nil;
+}
+
+- (void)fhv_shiftAccumulatorDisplayLinkDidFire:(CADisplayLink *)displayLink {
+  // Erase any scrollback that was injected into the accumulator by capping it back down.
+  _shiftAccumulator = MIN([self fhv_accumulatorMax], _shiftAccumulator);
+
+  CGFloat destination = _wantsToBeHidden ? [self fhv_accumulatorMax] : 0;
+  CGFloat distanceToDestination = destination - _shiftAccumulator;
+
+  NSTimeInterval duration = displayLink.duration;
+
+#if TARGET_IPHONE_SIMULATOR
+  duration /= [self fhv_dragCoefficient];
+#endif
+
+  // This is a simple "force" that's stronger the further we are from the destination.
+  _shiftAccumulator += kAttachmentCoefficient * distanceToDestination * duration;
+  _shiftAccumulator = MAX(0, MIN([self fhv_accumulatorMax], _shiftAccumulator));
+
+  [_statusBarShifter setOffset:_shiftAccumulator];
+
+  // Have we reached our destination?
+  if (fabs(destination - _shiftAccumulator) <= kShiftEpsilon) {
+    _shiftAccumulator = destination;
+
+    [self fhv_stopDisplayLink];
+  }
+
+  [self fhv_commitAccumulatorToFrame];
+}
+
+#pragma mark Shift Accumulator
+
+- (void)fhv_accumulatorDidChange {
+  if (!_trackingScrollView) {
+    // Set the shadow opacity directly.
+    self.layer.shadowOpacity = _visibleShadowOpacity;
+
+    return;
+  }
+
+  CGRect frame = self.frame;
+
+  CGFloat frameBottomEdge = [self fhv_projectedHeaderBottomEdge];
+  frameBottomEdge = MAX(0, MIN(kShadowScaleLength, frameBottomEdge));
+
+  CGFloat boundedAccumulator = MIN([self fhv_accumulatorMax], _shiftAccumulator);
+
+  CGFloat shadowIntensity;
+  if (self.hidesStatusBarWhenCollapsed) {
+    // Calculate the desired shadow strength for the offset & accumulator and then take the
+    // weakest strength.
+    CGFloat accumulator = MAX(0, MIN(kShadowScaleLength, _minimumHeight - boundedAccumulator));
+    if (self.isInFrontOfInfiniteContent) {
+      // When in front of infinite content we only care to hide the shadow when our header is
+      // off-screen.
+      shadowIntensity = MAX(0, MIN(1, accumulator / kShadowScaleLength));
+
+    } else {
+      // When over non-infinite content we also want to hide the shadow when we're anchored to the
+      // top of our content.
+      shadowIntensity = MAX(0, MIN(1, MIN(accumulator, frameBottomEdge) / kShadowScaleLength));
+    }
+
+  } else if (self.isInFrontOfInfiniteContent) {
+    shadowIntensity = 1;
+
+  } else {
+    // Adjust the opacity as the bottom edge of the header increasingly overlaps the contents
+    shadowIntensity = frameBottomEdge / kShadowScaleLength;
+  }
+  if (_defaultShadowLayer.hidden && _customShadowLayer.hidden) {
+    self.layer.shadowOpacity = (float)(_visibleShadowOpacity * shadowIntensity);
+  } else {
+    _defaultShadowLayer.shadowOpacity = (float)(_visibleShadowOpacity * shadowIntensity);
+  }
+  _shadowIntensity = shadowIntensity;
+  if (_shadowIntensityChangeBlock) {
+    _shadowIntensityChangeBlock(_shadowLayer, _shadowIntensity);
+  }
+
+  [_statusBarShifter setOffset:boundedAccumulator];
+
+  // Small performance improvement to not set the hidden property on every scroll tick.
+  BOOL isHidden = boundedAccumulator >= _minimumHeight;
+  if (isHidden != self.hidden) {
+    self.hidden = isHidden;
+  }
+
+  UIEdgeInsets scrollIndicatorInsets = _trackingScrollView.scrollIndicatorInsets;
+  scrollIndicatorInsets.top -= _trackingInfo.injectedTopScrollIndicatorInset;
+
+  _trackingInfo.injectedTopScrollIndicatorInset = frame.size.height - boundedAccumulator;
+  scrollIndicatorInsets.top += _trackingInfo.injectedTopScrollIndicatorInset;
+
+  _trackingScrollView.scrollIndicatorInsets = scrollIndicatorInsets;
+}
+
+#pragma mark Layout
+
+- (void)fhv_updateLayout {
+  if (!_trackingScrollView) {
+    return;
+  }
+
+  // We use the content offset to calculate the unclamped height of the frame.
+  CGFloat offsetWithoutInset = [self fhv_contentOffsetWithoutInjectedTopInset];
+  CGFloat headerHeight = -offsetWithoutInset;
+
+  if (_trackingScrollView.isTracking) {
+    [self fhv_stopDisplayLink];
+  }
+
+  if (_shiftAccumulatorLastContentOffsetIsValid) {
+    // We track the last direction for our target offset behavior.
+    CGFloat deltaY = [self fhv_boundedContentOffset].y - _shiftAccumulatorLastContentOffset.y;
+
+    if (_shiftAccumulatorDeltaY * deltaY < 0) {
+      // Direction has changed.
+      _shiftAccumulatorDeltaY = 0;
+    }
+    _shiftAccumulatorDeltaY += deltaY;
+
+    // Keeps track of the last direction the user moved their finger in.
+    if (_trackingScrollView.isTracking) {
+      if (_shiftAccumulatorDeltaY > kDeltaYSlop) {
+        _wantsToBeHidden = YES;
+      } else if (_shiftAccumulatorDeltaY < -kDeltaYSlop) {
+        _wantsToBeHidden = NO;
+      }
+    }
+
+    if (![self fhv_isOverExtendingBottom] && !_shiftAccumulatorDisplayLink) {
+      // When we're not allowed to shift offscreen, only allow the header to shift further
+      // on-screen in case it was previously off-screen due to a behavior change.
+      if (![self fhv_canShiftOffscreen]) {
+        deltaY = MIN(0, deltaY);
+      }
+
+      // When scrubbing we only allow the header to shrink and shift off-screen.
+      if (self.trackingScrollViewIsBeingScrubbed) {
+        deltaY = MAX(0, deltaY);
+      }
+
+      // Check if our delta y will cause us to cross the boundary from shrinking to shifting and,
+      // if so, cap the deltaY to only the overshoot, otherwise the header will overshift.
+
+      // headerHeight and deltaY are in inverted coordinate spaces, so when we do
+      // headerHeight + deltaY we're calculating where the headerHeight was _before_ this update.
+
+      CGFloat previousHeaderHeight = headerHeight + deltaY;
+
+      // Overshoot coming in
+      if (headerHeight < _minimumHeight && previousHeaderHeight > _minimumHeight) {
+        deltaY = _minimumHeight - headerHeight;
+
+        // Overshoot going out
+      } else if (headerHeight > _minimumHeight && previousHeaderHeight < _minimumHeight) {
+        deltaY = (headerHeight + deltaY) - _minimumHeight;
+      }
+
+      // Calculate the upper bound of the accumulator based on what phase we're in.
+
+      CGFloat upperBound;
+
+      if (headerHeight < 0) {  // Header is shifting while detached from content.
+        upperBound = [self fhv_accumulatorMax] + [self fhv_anchorLength];
+
+      } else if (headerHeight < _minimumHeight) {  // Header is shifting while attached to content.
+        upperBound = [self fhv_accumulatorMax];
+
+      } else {  // Header is not shifting.
+        upperBound = 0;
+      }
+
+      // Ensure that we don't lose any deltaY by first capping the accumulator within its valid
+      // range.
+      _shiftAccumulator = MIN(upperBound, _shiftAccumulator);
+
+      // Accumulate the deltaY.
+      _shiftAccumulator = MAX(0, MIN(upperBound, _shiftAccumulator + deltaY));
+    }
+  }
+
+  CGRect bounds = self.bounds;
+
+  if (_canOverExtend) {
+    bounds.size.height = MAX(_minimumHeight, headerHeight);
+
+  } else {
+    bounds.size.height = MAX(_minimumHeight, MIN(_maximumHeight, headerHeight));
+  }
+
+  self.bounds = bounds;
+
+  [self fhv_commitAccumulatorToFrame];
+
+  _shiftAccumulatorLastContentOffset = [self fhv_boundedContentOffset];
+  _shiftAccumulatorLastContentOffsetIsValid = YES;
+}
+
+- (CGFloat)fhv_anchorLength {
+  switch (_headerContentImportance) {
+    case MDCFlexibleHeaderContentImportanceDefault:
+      return kMaxAnchorLengthFullSwipe;
+
+    case MDCFlexibleHeaderContentImportanceHigh:
+      return kMaxAnchorLengthQuickSwipe;
+  }
+}
+
+// Commit the current shiftOffscreenAccumulator value to the view's position.
+- (void)fhv_commitAccumulatorToFrame {
+  CGPoint position = self.center;
+  // Offset the frame.
+  position.y = -MIN([self fhv_accumulatorMax], _shiftAccumulator);
+  position.y += self.bounds.size.height / 2;
+
+  self.center = position;
+
+  [self fhv_accumulatorDidChange];
+  [self fhv_recalculatePhase];
+
+  [_statusBarShifter setOffset:_shiftAccumulator];
+
+  [self.delegate flexibleHeaderViewFrameDidChange:self];
+}
+
+- (void)fhv_contentOffsetDidChange {
+#if DEBUG
+  _didAdjustTargetContentOffset = NO;
+#endif
+
+  // We generally expect the tracking scroll view to be a sibling to the flexible header, but there
+  // are cases where this assumption is always incorrect.
+  //
+  // Notably, UITableViewController's .view _is_ the tableView, so there is no way to add a flexible
+  // header other than as a subview to the scroll view. This is the most common case to which the
+  // following logic has been written.
+  if (self.superview == self.trackingScrollView) {
+    self.transform = CGAffineTransformMakeTranslation(0, self.trackingScrollView.contentOffset.y);
+
+    if (self.superview.subviews.lastObject != self) {
+      [self.superview bringSubviewToFront:self];
+    }
+  }
+
+  // While the interface orientation is rotating we don't respond to any adjustments to the content
+  // offset.
+  if (_interfaceOrientationIsChanging || _contentInsetsAreChanging ||
+      _isChangingStatusBarVisibility) {
+    return;
+  }
+
+  [self fhv_updateLayout];
+}
+
+#pragma mark Gestures
+
+// TODO(#1254): Re-enable sanity check assert on viewDidPan
+// This function is a temporary inclusion to stop an assert from triggering on iOS 10.3b until
+// we determine the cause. Remove once #1254 is closed.
+#if DEBUG
+static BOOL isRunningiOS10_3OrAbove() {
+  static dispatch_once_t onceToken;
+  static BOOL isRunningiOS10_3OrAbove;
+  dispatch_once(&onceToken, ^{
+    NSProcessInfo *info = [NSProcessInfo processInfo];
+    if ([info respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
+      isRunningiOS10_3OrAbove = [info isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){
+                                                                          .majorVersion = 10,
+                                                                          .minorVersion = 3,
+                                                                          .patchVersion = 0,
+                                                                      }];
+    }
+  });
+  return isRunningiOS10_3OrAbove;
+}
+#endif
+
+#if DEBUG
+- (void)fhv_scrollViewDidPan:(UIPanGestureRecognizer *)pan {
+  if (pan.state == UIGestureRecognizerStateEnded && [self fhv_canShiftOffscreen]) {
+    // You _must_ implement the target content offset method in your UIScrollViewDelegate.
+    // Not implementing the target content offset method can allow the status bar to get into an
+    // indeterminate state and may cause your app to be rejected.
+
+    // TODO(#1254): Re-enable sanity check assert on viewDidPan
+    // To re-enable, remove isRunningiOS10_3OrAbove() function and always assert.
+    if (!isRunningiOS10_3OrAbove()) {
+      NSAssert(_didAdjustTargetContentOffset, @"%@ isn't invoking %@'s %@.",
+               NSStringFromClass([_trackingScrollView class]), NSStringFromClass([self class]),
+               NSStringFromSelector(
+                   @selector(trackingScrollViewWillEndDraggingWithVelocity:targetContentOffset:)));
+    }
+  }
+}
+#endif
+
+#pragma mark - MDCStatusBarShifterDelegate
+
+- (void)statusBarShifterNeedsStatusBarAppearanceUpdate:(MDCStatusBarShifter *)statusBarShifter {
+  // UINavigationController reacts to status bar visibility changes by adjusting the content offset.
+  // To counteract this sort of behavior, we forcefully stash the content offset and restore it
+  // after updating the status bar appearance.
+  _isChangingStatusBarVisibility = YES;
+  CGPoint stashedContentOffset = _trackingScrollView.contentOffset;
+  [self.delegate flexibleHeaderViewNeedsStatusBarAppearanceUpdate:self];
+  [UIView performWithoutAnimation:^{
+    _trackingScrollView.contentOffset = stashedContentOffset;
+  }];
+  _isChangingStatusBarVisibility = NO;
+}
+
+- (void)statusBarShifter:(MDCStatusBarShifter *)statusBarShifter
+    wantsSnapshotViewAdded:(UIView *)view {
+  [self addSubview:view];
+}
+
+#pragma mark - Public
+
+- (void)setTrackingScrollView:(UIScrollView *)trackingScrollView {
+  if (_trackingScrollView == trackingScrollView) {
+    return;
+  }
+
+#if DEBUG
+  [_trackingScrollView.panGestureRecognizer removeTarget:self
+                                                  action:@selector(fhv_scrollViewDidPan:)];
+  [trackingScrollView.panGestureRecognizer addTarget:self action:@selector(fhv_scrollViewDidPan:)];
+
+#if 0   // TODO(featherless):
+        // https://github.com/material-components/material-components-ios/issues/214
+  // Verify existence of a delegate.
+  NSAssert(!trackingScrollView || trackingScrollView.delegate,
+           @"The provided tracking scroll view %@ has no delegate. Without a delegate, %@ will not"
+           @" be able to react to scroll events and may perform incorrectly."
+           @" This assertion will only fire in debug builds.",
+           NSStringFromClass([trackingScrollView class]),
+           NSStringFromClass([self class]));
+#endif  // #if 0
+#endif  // #if DEBUG
+
+  // If this header is shared by many scroll views then we leave the insets when switching the
+  // tracking scroll view.
+  [self fhv_removeInsetsFromScrollView:_trackingScrollView];
+
+  BOOL wasTrackingScrollView = _trackingScrollView != nil;
+
+  _trackingScrollView = trackingScrollView;
+
+  _shiftAccumulatorLastContentOffsetIsValid = NO;
+  _shiftAccumulatorLastContentOffset = _trackingScrollView.contentOffset;
+  _shiftAccumulatorDeltaY = 0;
+
+  _trackingInfo = [_trackedScrollViews objectForKey:_trackingScrollView];
+  if (!_sharedWithManyScrollViews || !_trackingInfo) {
+    [self fhv_addInsetsToScrollView:_trackingScrollView];
+  }
+  void (^animate)() = ^{
+    [self fhv_updateLayout];
+  };
+  void (^completion)(BOOL) = ^(BOOL finished) {
+    if (!finished) {
+      return;
+    }
+
+    // When the tracking scroll view is cleared we need a shadow update.
+    if (!_trackingScrollView) {
+      [self fhv_accumulatorDidChange];
+    }
+  };
+  if (wasTrackingScrollView) {
+    [UIView animateWithDuration:kTrackingScrollViewDidChangeAnimationDuration
+                     animations:animate
+                     completion:completion];
+  } else {
+    animate();
+    completion(YES);
+  }
+}
+
+- (void)trackingScrollViewDidScroll {
+  [self fhv_contentOffsetDidChange];
+}
+
+- (void)trackingScrollViewDidEndDraggingWillDecelerate:(BOOL)willDecelerate {
+  if (![self fhv_canShiftOffscreen]) {
+    _wantsToBeHidden = NO;
+  }
+  if (!willDecelerate && [self fhv_isPartiallyShifted]) {
+    [self fhv_startDisplayLink];
+  }
+}
+
+- (void)trackingScrollViewDidEndDecelerating {
+  if ([self fhv_isPartiallyShifted]) {
+    _wantsToBeHidden =
+        (_shiftAccumulator >= (1 - kMinimumVisibleProportion) * [self fhv_accumulatorMax]);
+    [self fhv_startDisplayLink];
+  }
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _statusBarShifter.prefersStatusBarHidden;
+}
+
+- (BOOL)hidesStatusBarWhenCollapsed {
+  return (_shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar &&
+          !_trackingScrollView.pagingEnabled);
+}
+
+- (void)setstatusBarHintCanOverlapHeader:(BOOL)statusBarHintCanOverlapHeader {
+  if (_statusBarHintCanOverlapHeader == statusBarHintCanOverlapHeader) {
+    return;
+  }
+  _statusBarHintCanOverlapHeader = statusBarHintCanOverlapHeader;
+
+  _statusBarShifter.enabled = [self fhv_shouldAllowShifting];
+
+  [self fhv_startDisplayLink];
+}
+
+- (void)setShiftBehavior:(MDCFlexibleHeaderShiftBehavior)shiftBehavior {
+  shiftBehavior = ShiftBehaviorForCurrentAppContext(shiftBehavior);
+  if (_shiftBehavior == shiftBehavior) {
+    return;
+  }
+  BOOL needsShiftOnScreen = (_shiftBehavior != MDCFlexibleHeaderShiftBehaviorDisabled &&
+                             shiftBehavior == MDCFlexibleHeaderShiftBehaviorDisabled);
+  _shiftBehavior = shiftBehavior;
+
+  _statusBarShifter.enabled = [self fhv_shouldAllowShifting];
+
+  if (needsShiftOnScreen) {
+    _wantsToBeHidden = NO;
+    [self fhv_startDisplayLink];
+  }
+}
+
+- (void)setBehavior:(MDCFlexibleHeaderShiftBehavior)behavior {
+  self.shiftBehavior = behavior;
+}
+
+- (MDCFlexibleHeaderShiftBehavior)behavior {
+  return self.shiftBehavior;
+}
+
+- (void)changeContentInsets:(MDCFlexibleHeaderChangeContentInsetsBlock)block {
+  if (!block) {
+    return;
+  }
+  _contentInsetsAreChanging = YES;
+  UIEdgeInsets previousInsets = _trackingScrollView.contentInset;
+  block();
+  CGFloat delta = _trackingScrollView.contentInset.top - previousInsets.top;
+  CGPoint contentOffset = _trackingScrollView.contentOffset;
+  contentOffset.y -= delta;  // Keeps the scroll view offset from jumping.
+  _trackingScrollView.contentOffset = contentOffset;
+  _contentInsetsAreChanging = NO;
+}
+
+- (void)interfaceOrientationWillChange {
+  NSAssert(!_interfaceOrientationIsChanging, @"Call to %@::%@ not matched by a call to %@.",
+           NSStringFromClass([self class]), NSStringFromSelector(_cmd),
+           NSStringFromSelector(@selector(interfaceOrientationDidChange)));
+
+  _interfaceOrientationIsChanging = YES;
+
+  [_statusBarShifter interfaceOrientationWillChange];
+}
+
+- (void)interfaceOrientationIsChanging {
+  NSAssert(_interfaceOrientationIsChanging, @"Call to %@::%@ not matched by a call to %@.",
+           NSStringFromClass([self class]), NSStringFromSelector(_cmd),
+           NSStringFromSelector(@selector(interfaceOrientationWillChange)));
+}
+
+- (void)interfaceOrientationDidChange {
+  NSAssert(_interfaceOrientationIsChanging, @"Call to %@::%@ not matched by a call to %@.",
+           NSStringFromClass([self class]), NSStringFromSelector(_cmd),
+           NSStringFromSelector(@selector(interfaceOrientationWillChange)));
+
+  _interfaceOrientationIsChanging = NO;
+
+  // Ignore any content offset delta that occured as a result of any orientation change.
+  _shiftAccumulatorLastContentOffset = [self fhv_boundedContentOffset];
+
+  [self fhv_updateLayout];
+
+  [_statusBarShifter interfaceOrientationDidChange];
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [self interfaceOrientationWillChange];
+  [coordinator
+      animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        [self interfaceOrientationIsChanging];
+      }
+      completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        [self interfaceOrientationDidChange];
+      }];
+}
+
+- (void)forwardTouchEventsForView:(UIView *)view {
+  [_forwardingViews addObject:view];
+}
+
+- (void)stopForwardingTouchEventsForView:(UIView *)view {
+  [_forwardingViews removeObject:view];
+}
+
+- (void)setMinimumHeight:(CGFloat)minimumHeight {
+  if (_minimumHeight == minimumHeight) {
+    return;
+  }
+
+  _minimumHeight = minimumHeight;
+
+  if (_minimumHeight > _maximumHeight) {
+    [self setMaximumHeight:_minimumHeight];
+  } else {
+    [self fhv_updateLayout];
+  }
+}
+
+- (void)setMaximumHeight:(CGFloat)maximumHeight {
+  if (_maximumHeight == maximumHeight) {
+    return;
+  }
+
+  CGPoint originalOffset = _trackingScrollView.contentOffset;
+
+  [self fhv_removeInsetsFromScrollView:_trackingScrollView];
+
+  _maximumHeight = maximumHeight;
+
+  CGPoint stashedOffset = _trackingScrollView.contentOffset;
+  [self fhv_addInsetsToScrollView:_trackingScrollView];
+
+  // Only restore the content offset if UIScrollView didn't decide to update the content offset for
+  // us. Notably, it seems to automatically adjust the content offset in the first runloop in which
+  // the scroll view's been created, but not in any further runloops.
+  if (CGPointEqualToPoint(stashedOffset, _trackingScrollView.contentOffset)) {
+    originalOffset.y = MAX(originalOffset.y, -_trackingScrollView.contentInset.top);
+    _trackingScrollView.contentOffset = originalOffset;
+  }
+
+  if (_maximumHeight < _minimumHeight) {
+    [self setMinimumHeight:_maximumHeight];
+  } else {
+    [self fhv_updateLayout];
+  }
+}
+
+- (void)setInFrontOfInfiniteContent:(BOOL)inFrontOfInfiniteContent {
+  if (_inFrontOfInfiniteContent == inFrontOfInfiniteContent) {
+    return;
+  }
+  _inFrontOfInfiniteContent = inFrontOfInfiniteContent;
+
+  [self fhv_updateLayout];
+}
+
+- (BOOL)trackingScrollViewWillEndDraggingWithVelocity:(CGPoint)velocity
+                                  targetContentOffset:(inout CGPoint *)targetContentOffset {
+#if DEBUG
+  _didAdjustTargetContentOffset = YES;
+#endif
+
+  if ([self fhv_canShiftOffscreen]) {
+    CGPoint target = *targetContentOffset;
+
+    CGFloat offsetTargetY = target.y + [self fhv_rawTopContentInset];
+    CGFloat flexHeight = -offsetTargetY;
+
+    if ([self fhv_canShiftOffscreen] && (0 < flexHeight && flexHeight < _minimumHeight)) {
+      // Don't allow the header to be partially visible.
+      if (_wantsToBeHidden) {
+        target.y = -[self fhv_rawTopContentInset];
+      } else {
+        target.y = -_minimumHeight - [self fhv_rawTopContentInset];
+      }
+      *targetContentOffset = target;
+      return YES;
+    }
+  }
+
+  return NO;
+}
+
+- (void)trackingScrollWillChangeToScrollView:(UIScrollView *)scrollView {
+  MDCFlexibleHeaderScrollViewInfo *info = [_trackedScrollViews objectForKey:scrollView];
+  if (!info) {
+    info = [self fhv_addInsetsToScrollView:scrollView];
+
+    CGPoint offset = scrollView.contentOffset;
+    offset.y -= info.injectedTopContentInset;
+    scrollView.contentOffset = offset;
+  }
+
+  if (_shiftAccumulator >= [self fhv_accumulatorMax]) {
+    // We're shifted off-screen, make sure that this scroll view isn't expecting to show the header.
+
+    CGPoint offset = scrollView.contentOffset;
+    CGFloat rawTopInset = scrollView.contentInset.top - info.injectedTopContentInset;
+    if (offset.y < -rawTopInset) {
+      offset.y = -rawTopInset;
+      scrollView.contentOffset = offset;
+    }
+
+  } else if (self.trackingScrollView.contentOffset.y != scrollView.contentOffset.y &&
+             self.trackingScrollView.contentOffset.y <= 0 && scrollView.contentOffset.y <= 0) {
+    // Our content is expanding the header in both columns, let's match up the content offsets so
+    // that the header's height won't change.
+    CGPoint offset = scrollView.contentOffset;
+    offset.y = self.trackingScrollView.contentOffset.y;
+    scrollView.contentOffset = offset;
+  }
+}
+
+- (void)shiftHeaderOnScreenAnimated:(BOOL)animated {
+  _wantsToBeHidden = NO;
+
+  if (animated) {
+    [self fhv_startDisplayLink];
+  } else {
+    // Remove any offscreen accumulation.
+    _shiftAccumulator = 0;
+    [self fhv_commitAccumulatorToFrame];
+  }
+}
+
+- (void)shiftHeaderOffScreenAnimated:(BOOL)animated {
+  _wantsToBeHidden = YES;
+
+  if (animated) {
+    [self fhv_startDisplayLink];
+  } else {
+    // Add offscreen accumulation equal to this header view's size.
+    _shiftAccumulator = self.fhv_accumulatorMax;
+    [self fhv_commitAccumulatorToFrame];
+  }
+}
+
+- (void)setContentIsTranslucent:(BOOL)contentIsTranslucent {
+  _contentIsTranslucent = contentIsTranslucent;
+
+  // Translucent content means that the status bar shifter should not use snapshotting. Otherwise,
+  // stale visual content under the status bar region may be snapshotted.
+  _statusBarShifter.snapshottingEnabled = !contentIsTranslucent;
+}
+
+@end
+
+@implementation MDCFlexibleHeaderScrollViewInfo
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
new file mode 100644
index 0000000..c8f3fde
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
@@ -0,0 +1,92 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCFlexibleHeaderView;
+@protocol MDCFlexibleHeaderViewLayoutDelegate;
+
+/**
+ The MDCFlexibleHeaderViewController controller is a simple UIViewController-oriented interface
+ for the flexible header view.
+
+ Note that for this view controller, self.view == self.headerView. This is because this view
+ controller is not meant to take up the full screen. Rather, it should be added as a child view
+ controller within another view controller.
+
+ ### UIScrollViewDelegate
+
+ Instances of this view controller implement the UIScrollViewDelegate methods that must be
+ forwarded to the flexible header view, so if you do not need to process the scroll view events
+ yourself you can set the header view controller instance as your scroll view delegate.
+
+ scrollView.delegate = headerViewController;
+ */
+@interface MDCFlexibleHeaderViewController
+    : UIViewController <UIScrollViewDelegate, UITableViewDelegate>
+
+/** The flexible header view instance that this controller manages. */
+@property(nonatomic, strong, nonnull, readonly) MDCFlexibleHeaderView *headerView;
+
+/** The layout delegate will be notified of any changes to the flexible header view's frame. */
+@property(nonatomic, weak, nullable) id<MDCFlexibleHeaderViewLayoutDelegate> layoutDelegate;
+
+#pragma mark UIViewController methods
+
+/**
+ Returns a Boolean indicating whether the status bar should be hidden or not.
+
+ Must be called by the parent view controller's -prefersStatusBarHidden implementation.
+ */
+- (BOOL)prefersStatusBarHidden;
+
+/**
+ Calculates the status bar style based on the header view's background color.
+
+ Light background colors use the default black status bar and dark background colors use the light
+ status bar. If the header view's background color is not fully-opaque, then this returns
+ UIStatusBarStyleDefault.
+ */
+- (UIStatusBarStyle)preferredStatusBarStyle;
+
+/**
+ Updates the topLayoutGuide to the correct position of a view controller paired with an instance of
+ MDCFlexibleHeaderViewController.
+
+ This method must be called in the |viewWillLayoutSubviews| method of view controller.
+ */
+- (void)updateTopLayoutGuide;
+
+@end
+
+/**
+ An object may conform to this protocol in order to receive layout change events caused by a
+ MDCFlexibleHeaderView.
+ */
+@protocol MDCFlexibleHeaderViewLayoutDelegate <NSObject>
+@required
+
+/**
+ Informs the receiver that the flexible header view's frame has changed.
+
+ The receiver should use the MDCFlexibleHeader scrollPhase APIs in order to react to the frame
+ changes.
+ */
+- (void)flexibleHeaderViewController:
+            (nonnull MDCFlexibleHeaderViewController *)flexibleHeaderViewController
+    flexibleHeaderViewFrameDidChange:(nonnull MDCFlexibleHeaderView *)flexibleHeaderView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m
new file mode 100644
index 0000000..cd2a237
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m
@@ -0,0 +1,250 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderViewController.h"
+
+#import "MDCFlexibleHeaderContainerViewController.h"
+#import "MDCFlexibleHeaderView.h"
+#import "MDFTextAccessibility.h"
+
+static inline BOOL ShouldUseLightStatusBarOnBackgroundColor(UIColor *color) {
+  if (CGColorGetAlpha(color.CGColor) < 1) {
+    return NO;
+  }
+
+  // We assume that the light iOS status text is white and not big enough to be considered "large"
+  // text according to the W3CAG 2.0 spec.
+  return [MDFTextAccessibility textColor:[UIColor whiteColor]
+                 passesOnBackgroundColor:color
+                                 options:MDFTextAccessibilityOptionsNone];
+}
+
+static NSString *const MDCFlexibleHeaderViewControllerHeaderViewKey =
+    @"MDCFlexibleHeaderViewControllerHeaderViewKey";
+static NSString *const MDCFlexibleHeaderViewControllerLayoutDelegateKey =
+    @"MDCFlexibleHeaderViewControllerLayoutDelegateKey";
+
+@interface MDCFlexibleHeaderViewController () <MDCFlexibleHeaderViewDelegate>
+
+/**
+ The current height offset of the flexible header controller with the addition of the current status
+ bar state at any given time.
+
+ This property is used to determine the bottom point of the |flexibleHeaderView| within the window.
+ */
+@property(nonatomic) CGFloat flexibleHeaderViewControllerHeightOffset;
+
+/**
+ The NSLayoutConstraint attached to the flexible header view controller's parentViewController's
+ topLayoutGuide.
+*/
+@property(nonatomic, weak) id topLayoutGuideTopConstraint;
+
+@end
+
+@implementation MDCFlexibleHeaderViewController
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+  if (self) {
+    [self commonMDCFlexibleHeaderViewControllerInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderViewControllerHeaderViewKey]) {
+      _headerView = [aDecoder decodeObjectForKey:MDCFlexibleHeaderViewControllerHeaderViewKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderViewControllerLayoutDelegateKey]) {
+      _layoutDelegate =
+          [aDecoder decodeObjectForKey:MDCFlexibleHeaderViewControllerLayoutDelegateKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeObject:self.headerView forKey:MDCFlexibleHeaderViewControllerHeaderViewKey];
+  [aCoder encodeConditionalObject:self.layoutDelegate
+                           forKey:MDCFlexibleHeaderViewControllerLayoutDelegateKey];
+}
+
+- (void)commonMDCFlexibleHeaderViewControllerInit {
+  MDCFlexibleHeaderView *headerView =
+      [[MDCFlexibleHeaderView alloc] initWithFrame:[UIScreen mainScreen].bounds];
+  headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  headerView.delegate = self;
+  _headerView = headerView;
+}
+
+- (void)loadView {
+  self.view = self.headerView;
+}
+
+- (void)willMoveToParentViewController:(UIViewController *)parent {
+  [super willMoveToParentViewController:parent];
+
+  parent.automaticallyAdjustsScrollViewInsets = NO;
+}
+
+- (void)didMoveToParentViewController:(UIViewController *)parent {
+  [super didMoveToParentViewController:parent];
+
+  // The header depends on the tracking scroll view to know how tall it should be.
+  // If there is no tracking scroll view then we have to poke the header into sizing itself.
+  if (!_headerView.trackingScrollView) {
+    [_headerView sizeToFit];
+  } else {
+    [_headerView trackingScrollViewDidScroll];
+  }
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+
+  for (NSLayoutConstraint *constraint in self.parentViewController.view.constraints) {
+    // Because topLayoutGuide is a readonly property on a viewController we must manipulate
+    // the present one via the NSLayoutConstraint attached to it. Thus we keep reference to it.
+    if (constraint.firstItem == self.parentViewController.topLayoutGuide &&
+        constraint.secondItem == nil) {
+      self.topLayoutGuideTopConstraint = constraint;
+    }
+  }
+
+  // On moving to parentViewController, we calculate the height
+  self.flexibleHeaderViewControllerHeightOffset = [self headerViewControllerHeight];
+
+#if DEBUG
+  NSAssert(![self.parentViewController.parentViewController
+               isKindOfClass:[MDCFlexibleHeaderContainerViewController class]],
+           @"An instance of %@ has been injected into a view controller (%@) that is already"
+           @" wrapped by an instance of %@ - this is not allowed and will cause double headers to"
+           @" appear. Choose to either wrap or inject your view controller (preferring injection"
+           @" where possible).",
+           NSStringFromClass([self class]), NSStringFromClass([self.parentViewController class]),
+           NSStringFromClass([MDCFlexibleHeaderContainerViewController class]));
+#endif
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  return (ShouldUseLightStatusBarOnBackgroundColor(_headerView.backgroundColor)
+              ? UIStatusBarStyleLightContent
+              : UIStatusBarStyleDefault);
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _headerView.prefersStatusBarHidden;
+}
+
+// Only include this logic when supporting pre-iOS 8 devices.
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
+                                duration:(NSTimeInterval)duration {
+  [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
+
+  // Check if we're on iOS 8 and above and the new method will be called.
+  if (![UIViewController instancesRespondToSelector:@selector(viewWillTransitionToSize:
+                                                             withTransitionCoordinator:)]) {
+    [_headerView interfaceOrientationWillChange];
+  }
+}
+
+- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
+                                         duration:(NSTimeInterval)duration {
+  [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
+
+  // Check if we're on iOS 8 and above and the new method will be called.
+  if (![UIViewController instancesRespondToSelector:@selector(viewWillTransitionToSize:
+                                                             withTransitionCoordinator:)]) {
+    [_headerView interfaceOrientationIsChanging];
+  }
+}
+
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+  [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
+
+  // Check if we're on iOS 8 and above and the new method will be called.
+  if (![UIViewController instancesRespondToSelector:@selector(viewWillTransitionToSize:
+                                                             withTransitionCoordinator:)]) {
+    [_headerView interfaceOrientationDidChange];
+  }
+}
+#endif  // #if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewDidScroll];
+  }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewDidEndDecelerating];
+  }
+}
+
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewDidEndDraggingWillDecelerate:decelerate];
+  }
+}
+
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
+                     withVelocity:(CGPoint)velocity
+              targetContentOffset:(inout CGPoint *)targetContentOffset {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewWillEndDraggingWithVelocity:velocity
+                                           targetContentOffset:targetContentOffset];
+  }
+}
+
+- (void)updateTopLayoutGuide {
+  [self.topLayoutGuideTopConstraint setConstant:self.flexibleHeaderViewControllerHeightOffset];
+}
+
+- (CGFloat)headerViewControllerHeight {
+  CGFloat height =
+      MAX(_headerView.frame.origin.y + _headerView.frame.size.height,
+          _headerView.shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar ? 0 : 20);
+  return height;
+}
+
+#pragma mark MDCFlexibleHeaderViewDelegate
+
+- (void)flexibleHeaderViewNeedsStatusBarAppearanceUpdate:(MDCFlexibleHeaderView *)headerView {
+  [self setNeedsStatusBarAppearanceUpdate];
+}
+
+- (void)flexibleHeaderViewFrameDidChange:(MDCFlexibleHeaderView *)headerView {
+  // Whenever the flexibleHeaderView's frame changes, we update the value of the height offset
+  self.flexibleHeaderViewControllerHeightOffset = [self headerViewControllerHeight];
+
+  // We must change the constant of the constraint attached to our parentViewController's
+  // topLayoutGuide to trigger the re-layout of its subviews
+  [self.topLayoutGuideTopConstraint setConstant:self.flexibleHeaderViewControllerHeightOffset];
+
+  [self.layoutDelegate flexibleHeaderViewController:self
+                   flexibleHeaderViewFrameDidChange:headerView];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
new file mode 100644
index 0000000..f8c3ca7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderContainerViewController.h"
+#import "MDCFlexibleHeaderView.h"
+#import "MDCFlexibleHeaderViewController.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h
new file mode 100644
index 0000000..964040e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h
@@ -0,0 +1,109 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCStatusBarShifterDelegate;
+
+/**
+ The status bar shifter is responsible for the management of the status bar's offset as a header
+ view is shifting off-screen.
+
+ This class is not intended to be subclassed.
+ */
+@interface MDCStatusBarShifter : NSObject
+
+#pragma mark Shifting the status bar
+
+/**
+ Provides the status bar shifter with the current desired y offset of the status bar.
+
+ A value of 0 means the status bar is unshifted. Values > 0 shift the status bar by that amount
+ off-screen. Negative values are treated as zero.
+ */
+- (void)setOffset:(CGFloat)offset;
+
+#pragma mark Configuring behavior
+
+/**
+ Whether or not the status bar shifter is enabled.
+
+ If the status bar shifter is disabled midway through shifting the status bar then the shifter
+ will move the status bar to a reasonable location.
+ */
+@property(nonatomic, getter=isEnabled) BOOL enabled;
+
+/**
+ A Boolean value indicating whether this class should use snapshotting when rendering the status
+ bar shift.
+
+ Defaults to YES.
+ */
+@property(nonatomic, getter=isSnapshottingEnabled) BOOL snapshottingEnabled;
+
+#pragma mark Responding to state changes
+
+@property(nonatomic, weak) id<MDCStatusBarShifterDelegate> delegate;
+
+#pragma mark Introspection
+
+/**
+ A Boolean value indicating whether the receiver is able to shift the status bar.
+
+ There are certain scenarios where the status bar shifter won't try to adjust the frame of the
+ status bar. For example, if the status bar is showing the tap-to-return-to-call effect. In these
+ cases this method returns NO.
+ */
+- (BOOL)canUpdateStatusBarFrame;
+
+#pragma mark UIViewController events
+
+/**
+ A Boolean value indicating whether the true status bar should be hidden.
+
+ The implementor of MDCStatusBarShifterDelegate should use this to inform UIKit of the expected
+ status bar visibility via UIViewController::prefersStatusBarHidden.
+ */
+- (BOOL)prefersStatusBarHidden;
+
+/** Must be called when the owning UIViewController's interface orientation is about to change. */
+- (void)interfaceOrientationWillChange;
+
+/** Must be called when the owning UIViewController's interface orientation has changed. */
+- (void)interfaceOrientationDidChange;
+
+@end
+
+/**
+ The MDCStatusBarShifterDelegate protocol allows a delegate to react to changes in the status bar
+ shifter's state.
+ */
+@protocol MDCStatusBarShifterDelegate <NSObject>
+@required
+
+/** Informs the receiver that the preferred status bar visibility has changed. */
+- (void)statusBarShifterNeedsStatusBarAppearanceUpdate:(MDCStatusBarShifter *)statusBarShifter;
+
+/**
+ Informs the receiver that a snapshot view would like to be added to a view hierarchy.
+
+ The receiver is expected to add `view` as a subview. The superview should be shifting off-screen,
+ which will cause the snapshot view to shift off-screen as well.
+ */
+- (void)statusBarShifter:(MDCStatusBarShifter *)statusBarShifter
+    wantsSnapshotViewAdded:(UIView *)view;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.m
new file mode 100644
index 0000000..2383755
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.m
@@ -0,0 +1,263 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCStatusBarShifter.h"
+
+#import "UIApplication+AppExtensions.h"
+
+static CGFloat kStatusBarExpectedHeight = 20;
+static NSTimeInterval kStatusBarBecomesInvalidAnimationDuration = 0.2;
+
+// If the time changes then we need to invalidate the status bar.
+// This value is the minimum amount of time we'll wait before invalidating the status bar even
+// after the time has changed in an effort to minimize flickering.
+static NSTimeInterval kMinimumNumberOfSecondsToWaitFor = 3;
+
+// Simple state machine for the shifter:
+//          IsReal => IsSnapshot
+//      IsSnapshot => IsReal, InvalidSnapshot
+// InvalidSnapshot => IsReal
+//
+// In other words, once a snapshot becomes invalid it must go through the real state before it can
+// become a snapshot again.
+//
+// The bulk of this state machine is represented in attemptSnapshotState:
+
+typedef NS_ENUM(NSInteger, MDCStatusBarShifterState) {
+  MDCStatusBarShifterStateRealStatusBar,
+  MDCStatusBarShifterStateIsSnapshot,
+  MDCStatusBarShifterStateInvalidSnapshot,
+};
+
+@implementation MDCStatusBarShifter {
+  UIView *_statusBarReplicaView;
+
+  // ivars that can invalidate the status bar
+  CGRect _originalStatusBarFrame;
+  NSTimeInterval _replicaViewTimestamp;
+  NSTimeInterval _secondsRemainingInMinute;
+  NSTimer *_replicaInvalidatorTimer;
+
+  // While our snapshot is invalid we have slightly different status bar visibility.
+  BOOL _prefersStatusBarHiddenWhileInvalid;
+
+  BOOL _prefersStatusBarHidden;
+  MDCStatusBarShifterState _snapshotState;
+}
+
+- (void)dealloc {
+  [_replicaInvalidatorTimer invalidate];
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _enabled = YES;
+    _snapshottingEnabled = YES;
+  }
+  return self;
+}
+
+#pragma mark - Private
+
+// Moves to the invalid state with a status bar animation.
+- (void)invalidateSnapshot {
+  [UIView animateWithDuration:kStatusBarBecomesInvalidAnimationDuration
+                   animations:^{
+                     [self attemptSnapshotState:MDCStatusBarShifterStateInvalidSnapshot];
+                   }];
+}
+
+// Conditions in which the status bar should be invalidated.
+- (BOOL)shouldInvalidateSnapshot {
+  // Frames don't match up
+  if (!CGRectEqualToRect(_statusBarReplicaView.frame, _originalStatusBarFrame)) {
+    return YES;
+  }
+
+  // The time has changed
+  if (([NSDate timeIntervalSinceReferenceDate] - _replicaViewTimestamp) >
+      _secondsRemainingInMinute) {
+    return YES;
+  }
+
+  return NO;
+}
+
+// May not necessarily end in the given state.
+- (void)attemptSnapshotState:(MDCStatusBarShifterState)snapshotState {
+  if (_snapshotState == snapshotState) {
+    // It's likely too good to be true that we're able to stay in the snapshot state, so let's see
+    // if we can invalidate the snapshot in any way.
+    if (_snapshotState == MDCStatusBarShifterStateIsSnapshot && [self shouldInvalidateSnapshot]) {
+      // Frame has become invalid - kill the snapshot.
+      [self invalidateSnapshot];
+    }
+    return;
+  }
+
+  // Don't allow changing from invalid to snapshot without going through "real" first.
+  if (_snapshotState == MDCStatusBarShifterStateInvalidSnapshot &&
+      snapshotState == MDCStatusBarShifterStateIsSnapshot) {
+    return;
+  }
+
+  // Can't go from real => invalid
+  if (_snapshotState == MDCStatusBarShifterStateRealStatusBar &&
+      snapshotState == MDCStatusBarShifterStateInvalidSnapshot) {
+    return;
+  }
+
+  // While disabled, can't leave the real status bar state.
+  if (!_enabled && _snapshotState == MDCStatusBarShifterStateRealStatusBar) {
+    return;
+  }
+
+  // If snapshotting is disabled, then can't go from real => snapshot, but must jump to invalid
+  // state.
+  if (!_snapshottingEnabled && _snapshotState == MDCStatusBarShifterStateRealStatusBar &&
+      snapshotState == MDCStatusBarShifterStateIsSnapshot) {
+    snapshotState = MDCStatusBarShifterStateInvalidSnapshot;
+  }
+
+  [_replicaInvalidatorTimer invalidate];
+
+  _snapshotState = snapshotState;
+
+  // React to changing the state
+  switch (_snapshotState) {
+    case MDCStatusBarShifterStateRealStatusBar: {
+      // Now showing the real status bar. Remove the replica.
+      [_statusBarReplicaView removeFromSuperview];
+      _statusBarReplicaView = nil;
+      self.prefersStatusBarHidden = NO;
+      break;
+    }
+    case MDCStatusBarShifterStateInvalidSnapshot: {
+      // Snapshot is now invalid, show the real status bar.
+      [_statusBarReplicaView removeFromSuperview];
+      _statusBarReplicaView = nil;
+      self.prefersStatusBarHidden = _prefersStatusBarHiddenWhileInvalid;
+      break;
+    }
+    case MDCStatusBarShifterStateIsSnapshot: {
+      // Take a snapshot of the status bar.
+      UIView *snapshotView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
+      UIView *clippingView = [[UIView alloc] init];
+      clippingView.frame =
+          CGRectMake(0, 0, snapshotView.frame.size.width, kStatusBarExpectedHeight);
+      clippingView.autoresizingMask =
+          (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin);
+      clippingView.clipsToBounds = YES;
+      [clippingView addSubview:snapshotView];
+      [self.delegate statusBarShifter:self wantsSnapshotViewAdded:clippingView];
+
+      _statusBarReplicaView = clippingView;
+      _originalStatusBarFrame = clippingView.frame;
+      _replicaViewTimestamp = [NSDate timeIntervalSinceReferenceDate];
+
+      NSCalendar *calendar = [NSCalendar currentCalendar];
+      NSDateComponents *components =
+          [calendar components:NSCalendarUnitSecond fromDate:[NSDate date]];
+      _secondsRemainingInMinute =
+          MAX(kMinimumNumberOfSecondsToWaitFor, (NSTimeInterval)(60 - components.second));
+
+      _replicaInvalidatorTimer = [NSTimer timerWithTimeInterval:_secondsRemainingInMinute
+                                                         target:self
+                                                       selector:@selector(invalidateSnapshot)
+                                                       userInfo:nil
+                                                        repeats:NO];
+      [[NSRunLoop currentRunLoop] addTimer:_replicaInvalidatorTimer forMode:NSRunLoopCommonModes];
+
+      self.prefersStatusBarHidden = YES;
+      break;
+    }
+  }
+}
+
+- (void)setPrefersStatusBarHidden:(BOOL)prefersStatusBarHidden {
+  if (_prefersStatusBarHidden == prefersStatusBarHidden) {
+    return;
+  }
+
+  _prefersStatusBarHidden = prefersStatusBarHidden;
+
+  [self.delegate statusBarShifterNeedsStatusBarAppearanceUpdate:self];
+}
+
+#pragma mark - Public
+
+- (void)setOffset:(CGFloat)offset {
+  if (![self canUpdateStatusBarFrame]) {
+    return;
+  }
+
+  // Bound the status bar range to [0...kStatusBarExpectedHeight].
+  CGFloat statusOffsetY = MIN(kStatusBarExpectedHeight, offset);
+
+  // Adjust the frame of the status bar.
+  if (statusOffsetY > 0) {
+    _prefersStatusBarHiddenWhileInvalid = statusOffsetY >= kStatusBarExpectedHeight;
+
+    if (_snapshotState == MDCStatusBarShifterStateInvalidSnapshot) {
+      // If we're in an invalid state then we have to manage the visibility directly.
+      [UIView animateWithDuration:kStatusBarBecomesInvalidAnimationDuration
+                       animations:^{
+                         self.prefersStatusBarHidden = _prefersStatusBarHiddenWhileInvalid;
+                       }];
+
+    } else {
+      [self attemptSnapshotState:MDCStatusBarShifterStateIsSnapshot];
+    }
+  } else {
+    [self attemptSnapshotState:MDCStatusBarShifterStateRealStatusBar];
+  }
+}
+
+- (void)setEnabled:(BOOL)enabled {
+  if (_enabled == enabled) {
+    return;
+  }
+  _enabled = enabled;
+
+  if (!_enabled) {
+    [UIView animateWithDuration:kStatusBarBecomesInvalidAnimationDuration
+                     animations:^{
+                       [self attemptSnapshotState:MDCStatusBarShifterStateRealStatusBar];
+                     }];
+  }
+}
+
+- (BOOL)canUpdateStatusBarFrame {
+  CGRect statusBarFrame = [[UIApplication mdc_safeSharedApplication] statusBarFrame];
+  CGFloat statusBarHeight = MIN(statusBarFrame.size.width, statusBarFrame.size.height);
+  return ((statusBarHeight == kStatusBarExpectedHeight) || _statusBarReplicaView ||
+          _snapshotState == MDCStatusBarShifterStateInvalidSnapshot);
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _prefersStatusBarHidden;
+}
+
+- (void)interfaceOrientationWillChange {
+  _statusBarReplicaView.hidden = YES;
+}
+
+- (void)interfaceOrientationDidChange {
+  _statusBarReplicaView.hidden = NO;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
new file mode 100644
index 0000000..e749c70
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
@@ -0,0 +1,54 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The MDCHeaderStackView class lays out a vertical stack of two views.
+
+ Both bars provided to this view must implement sizeThatFits and return their best-fit
+ dimensions.
+
+ # Layout Behavior
+
+ The layout behavior of the two bars is as follows:
+
+ topBar: top aligned, expands to fill all available vertical space not taken up by the bottomBar.
+ bottomBar: bottom aligned.
+
+ If no bottomBar is provided, top bar consumes the entire bounds of the stack view.
+
+ When resized, the top bar will shrink until it reaches its sizeThatFits dimensions.
+ If there is a bottom bar, then at this point the top bar will begin sliding off the top.
+ If there is no bottom bar, then at this point the top bar will stay put.
+
+ At no point in time will either the top or bottom bar shrink below their sizeThatFits height.
+
+ # sizeThatFits Behavior
+
+ sizeThatFits returns the fitted height for bottom bar if available, otherwise it returns the
+ fitted height for topBar. The width will be whatever width was provided.
+ */
+IB_DESIGNABLE
+@interface MDCHeaderStackView : UIView
+
+/** The top bar. Top aligned and vertically expands. */
+@property(nonatomic, strong, nullable) UIView *topBar;
+
+/** The bottom bar. Bottom aligned. */
+@property(nonatomic, strong, nullable) UIView *bottomBar;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.m
new file mode 100644
index 0000000..23cc13a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.m
@@ -0,0 +1,112 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCHeaderStackView.h"
+
+static NSString *const MDCHeaderStackViewTopBarKey = @"MDCHeaderStackViewTopBarKey";
+static NSString *const MDCHeaderStackViewBottomBarKey = @"MDCHeaderStackViewBottomBarKey";
+
+@implementation MDCHeaderStackView
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCHeaderStackViewTopBarKey]) {
+      _topBar = [aDecoder decodeObjectForKey:MDCHeaderStackViewTopBarKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCHeaderStackViewBottomBarKey]) {
+      _bottomBar = [aDecoder decodeObjectForKey:MDCHeaderStackViewBottomBarKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  if (self.topBar) {
+    [aCoder encodeObject:self.topBar forKey:MDCHeaderStackViewTopBarKey];
+  }
+  if (self.bottomBar) {
+    [aCoder encodeObject:self.bottomBar forKey:MDCHeaderStackViewBottomBarKey];
+  }
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  if (_bottomBar) {
+    size.height = [_bottomBar sizeThatFits:size].height;
+  } else {
+    size.height = [_topBar sizeThatFits:size].height;
+  }
+  return size;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  CGSize boundsSize = self.bounds.size;
+
+  CGSize topBarSize = [_topBar sizeThatFits:boundsSize];
+  CGSize bottomBarSize = [_bottomBar sizeThatFits:boundsSize];
+
+  CGFloat remainingHeight = boundsSize.height - topBarSize.height - bottomBarSize.height;
+
+  CGRect topBarFrame = CGRectMake(0, 0, topBarSize.width, topBarSize.height);
+  CGRect bottomBarFrame = CGRectMake(0, 0, bottomBarSize.width, bottomBarSize.height);
+
+  if (remainingHeight > 0) {
+    // Expand the top bar to fill the remaining height.
+    topBarFrame.size.height += remainingHeight;
+
+  } else if (remainingHeight < 0) {
+    // Negative value causes the top bar to slide up and away.
+    topBarFrame.origin.y += remainingHeight;
+  }
+  bottomBarFrame.origin.y = CGRectGetMaxY(topBarFrame);
+
+  _topBar.frame = topBarFrame;
+  _bottomBar.frame = bottomBarFrame;
+}
+
+#pragma mark - Public
+
+- (void)setTopBar:(UIView *)topBar {
+  if (_topBar == topBar) {
+    return;
+  }
+
+  [_topBar removeFromSuperview];
+
+  _topBar = topBar;
+
+  [self addSubview:_topBar];
+  [self setNeedsLayout];
+}
+
+- (void)setBottomBar:(UIView *)bottomBar {
+  if (_bottomBar == bottomBar) {
+    return;
+  }
+
+  [_bottomBar removeFromSuperview];
+
+  _bottomBar = bottomBar;
+
+  [self addSubview:_bottomBar];
+  [self setNeedsLayout];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
new file mode 100644
index 0000000..ee74066
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCHeaderStackView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
new file mode 100644
index 0000000..93c0c19
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
@@ -0,0 +1,61 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Custom gesture recognizer to observe the various ink response states.
+
+ MDCInkGestureRecognizer is a continuous recognizer that tracks single touches and optionally
+ fails if the touch moves outside the recongizer's view. Multiple touches will cause the
+ recognizer to transition to the UIGestureRecognizerStateCancelled state.
+ */
+@interface MDCInkGestureRecognizer : UIGestureRecognizer
+
+/**
+ Set the distance that causes the recognizer to cancel.
+ */
+@property(nonatomic, assign) CGFloat dragCancelDistance;
+
+/**
+ Set when dragging outside of the view causes the gesture recognizer to cancel.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL cancelOnDragOut;
+
+/**
+ Bounds inside of which the recognizer will recognize ink gestures, relative to self.view.frame.
+
+ If set to CGRectNull (the default), then the recognizer will use self.view.bounds as the target
+ bounds.
+
+ If cancelOnDragOut is YES and the user's touch moves beyond the target bounds inflated by
+ dragCancelDistance then the gesture is cancelled.
+ */
+@property(nonatomic) CGRect targetBounds;
+
+/**
+ Returns the point where the ink starts spreading from.
+
+ @param view View which the point is relative to.
+ */
+- (CGPoint)touchStartLocationInView:(UIView *)view;
+
+/** Returns YES if the touch's current location is still within the target bounds. */
+- (BOOL)isTouchWithinTargetBounds;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.m
new file mode 100644
index 0000000..cb51392
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.m
@@ -0,0 +1,96 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkGestureRecognizer.h"
+
+#import <UIKit/UIGestureRecognizerSubclass.h>
+
+static const CGFloat kInkGestureDefaultDragCancelDistance = 20;
+
+@implementation MDCInkGestureRecognizer {
+  CGPoint _touchStartLocation;
+  CGPoint _touchCurrentLocation;
+  BOOL _cancelOnDragOut;
+}
+
+- (instancetype)initWithTarget:(id)target action:(SEL)action {
+  self = [super initWithTarget:target action:action];
+  if (self) {
+    _cancelOnDragOut = YES;
+    _dragCancelDistance = kInkGestureDefaultDragCancelDistance;
+    _targetBounds = CGRectNull;
+    self.cancelsTouchesInView = NO;
+    self.delaysTouchesEnded = NO;
+  }
+  return self;
+}
+
+- (CGPoint)touchStartLocationInView:(UIView *)view {
+  return [view convertPoint:_touchStartLocation fromView:nil];
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesBegan:touches withEvent:event];
+  if ([touches count] == 1) {
+    self.state = UIGestureRecognizerStateBegan;
+    _touchStartLocation = [[touches anyObject] locationInView:nil];
+    _touchCurrentLocation = _touchStartLocation;
+  } else {
+    self.state = UIGestureRecognizerStateCancelled;
+  }
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesMoved:touches withEvent:event];
+  if (self.state == UIGestureRecognizerStateFailed) {
+    return;
+  }
+
+  _touchCurrentLocation = [[touches anyObject] locationInView:nil];
+
+  // Cancel the gesture if it is too far away.
+  if (_cancelOnDragOut && ![self isTouchWithinTargetBounds]) {
+    self.state = UIGestureRecognizerStateCancelled;
+  } else {
+    self.state = UIGestureRecognizerStateChanged;
+  }
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesEnded:touches withEvent:event];
+  self.state = UIGestureRecognizerStateEnded;
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesCancelled:touches withEvent:event];
+  self.state = UIGestureRecognizerStateCancelled;
+}
+
+- (BOOL)isTouchWithinTargetBounds {
+  CGRect targetBounds = [self effectiveTargetBounds];
+  CGRect boundsInWindowCoord = [self.view convertRect:targetBounds toView:nil];
+  boundsInWindowCoord =
+      CGRectInset(boundsInWindowCoord, -_dragCancelDistance, -_dragCancelDistance);
+  return CGRectContainsPoint(boundsInWindowCoord, _touchCurrentLocation);
+}
+
+#pragma mark - Private methods
+
+- (CGRect)effectiveTargetBounds {
+  return CGRectEqualToRect(_targetBounds, CGRectNull) ? self.view.bounds : _targetBounds;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.h
new file mode 100644
index 0000000..100935f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.h
@@ -0,0 +1,186 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCInkGestureRecognizer.h"
+
+@class MDCInkTouchController;
+@class MDCInkView;
+@protocol MDCInkTouchControllerDelegate;
+
+/**
+ MDCInkTouchController associates a MDCInkView with a UIGestureRecognizer to control the spread of
+ the ink.
+
+ Subclasses should avoid overriding the UIGestureRecognizerDelegate gestureRecognizerShouldBegin:
+ and gestureRecognizer:shouldReceiveTouch: methods to avoid breaking
+ MDCInkTouchControllerDelegate.
+
+ **NOTE:** The controller does not keep a strong reference to the view to which it is attaching an
+ ink view.
+ It is expected that the view will keep a strong reference to its own ink controller, or that the
+ view controller controlling the view will keep a strong reference to that view's ink controller.
+ */
+@interface MDCInkTouchController : NSObject <UIGestureRecognizerDelegate>
+
+/** Weak reference to the view that responds to touch events. */
+@property(nonatomic, weak, readonly, nullable) UIView *view;
+
+/**
+ The ink view for clients who do not create their own ink views via the delegate.
+ */
+@property(nonatomic, strong, readonly, nonnull) MDCInkView *defaultInkView;
+
+/** Delegate to extend the behavior of the touch control. */
+@property(nonatomic, weak, nullable) id<MDCInkTouchControllerDelegate> delegate;
+
+/** If YES, the gesture recognizer should delay the start of ink spread. Default is NO. */
+@property(nonatomic, assign) BOOL delaysInkSpread;
+
+/** The distance that causes the recognizer to cancel. Defaults to 20pt. */
+@property(nonatomic, assign) CGFloat dragCancelDistance;
+
+/**
+ Whether dragging outside of the view causes the gesture recognizer to cancel.
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL cancelsOnDragOut;
+
+/**
+ Bounds inside of which the recognizer will recognize ink gestures, relative to self.view.frame.
+
+ If set to CGRectNull (the default), then the recognizer will use self.view.bounds as the target
+ bounds.
+
+ If cancelsOnDragOut is YES and the user's touch moves beyond the target bounds inflated by
+ dragCancelDistance then the gesture is cancelled.
+ */
+@property(nonatomic) CGRect targetBounds;
+
+/** Gesture recognizer used to bind touch events to ink. */
+@property(nonatomic, strong, readonly, nonnull) MDCInkGestureRecognizer *gestureRecognizer;
+
+/** Unavailable, please use initWithView: instead. */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Initializes the controller.
+
+ @param view View that responds to touch events for ink.
+ */
+- (nonnull instancetype)initWithView:(nonnull UIView *)view NS_DESIGNATED_INITIALIZER;
+
+/**
+ When called the @c defaultInkView is added to the @c view.
+
+ This method is a no-op when the delegate conforms to @c inkTouchController:inkViewAtTouchLocation:
+ because this is how a client specifies a custom ink view.
+
+ If you want to specify a specific z-index order for your inkView please conform to
+ @c inkTouchController:insertInkView:intoView: and do so there.
+ */
+- (void)addInkView;
+
+/**
+ Cancels all touch processing and dissipates the ink.
+
+ This is useful if your application needs to remove the ink on scrolling, when preparing a view
+ for reuse, etc.
+ */
+- (void)cancelInkTouchProcessing;
+
+/**
+ Returns the ink view at a particular touch location.
+
+ If the delegate responds to @c inkTouchController:inkViewAtLocation: then this method queries it.
+ Otherwise, if @c addInkView has been called and @c location is in the bounds of
+ @c self.defaultView, then that view is returned. If none of these conditions are met, @c nil is
+ returned.
+
+ @param location The query location in the coordinates of @c self.view.
+ @return The ink view at the touch location, or nil.
+*/
+- (MDCInkView *_Nullable)inkViewAtTouchLocation:(CGPoint)location;
+
+@end
+
+/** Delegate methods for MDCInkTouchController. */
+@protocol MDCInkTouchControllerDelegate <NSObject>
+@optional
+
+/**
+ Inserts the ink view into the given view.
+
+ If this method is not implemented, the ink view is added as a subview of the view when the
+ controller's addInkView method is called. Delegates can choose to insert the ink view below the
+ contents as a background view. When inkTouchController:inkViewAtTouchLocation is implemented
+ this method will not be invoked.
+
+ @param inkTouchController The ink touch controller.
+ @param inkView The ink view.
+ @param view The view to add the ink view to.
+ */
+- (void)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+             insertInkView:(nonnull UIView *)inkView
+                  intoView:(nonnull UIView *)view;
+
+/**
+ Returns the ink view to use for a touch located at location in inkTouchController.view.
+
+ If the delegate implements this method, the controller will not create an ink view of its own and
+ inkTouchController:insertInkView:intoView: will not be called. This method allows the delegate
+ to control the creation and reuse of ink views.
+
+ @param inkTouchController The ink touch controller.
+ @param location The touch location in the coords of @c inkTouchController.view.
+ @return An ink view to use at the touch location.
+ */
+- (nullable MDCInkView *)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+                     inkViewAtTouchLocation:(CGPoint)location;
+
+/**
+ Controls whether the ink touch controller should be processing touches.
+
+ The touch controller will query this method to determine if it should start or continue to
+ process touches controlling the ink. Returning NO at the start of a gesture will prevent any ink
+ from being displayed, and returning NO in the middle of a gesture will cancel that gesture and
+ evaporate the ink.
+
+ If not implemented then YES is assumed.
+
+ @param inkTouchController The ink touch controller.
+ @param location The touch location relative to the inkTouchController view.
+ @return YES if the controller should process touches at @c location.
+
+ @see cancelInkTouchProcessing
+ */
+- (BOOL)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+    shouldProcessInkTouchesAtTouchLocation:(CGPoint)location;
+
+/**
+ Notifies the receiver that the ink touch controller did process an ink view at the
+ touch location.
+
+ @param inkTouchController The ink touch controller.
+ @param inkView The ink view.
+ @param location The touch location relative to the inkTouchController superView.
+ */
+- (void)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+         didProcessInkView:(nonnull MDCInkView *)inkView
+           atTouchLocation:(CGPoint)location;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.m
new file mode 100644
index 0000000..66f5315
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.m
@@ -0,0 +1,232 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkTouchController.h"
+
+#import "MDCInkView.h"
+
+static const NSTimeInterval kInkTouchDelayInterval = 0.1;
+
+@interface MDCInkTouchController ()
+@property(nonatomic, strong) MDCInkView *addedInkView;
+@property(nonatomic, strong) MDCInkView *defaultInkView;
+@property(nonatomic, assign) BOOL shouldRespondToTouch;
+@property(nonatomic, assign) CGPoint previousLocation;
+@end
+
+@protocol MDCInkTouchControllerLegacyDelegate <NSObject>
+@optional
+
+/**
+ This protocol is private and declares an old method signature that will be removed once legacy code
+ has been migrated to the new delegate protocol.
+ */
+- (BOOL)shouldInkTouchControllerProcessInkTouches:
+        (nonnull MDCInkTouchController *)inkTouchController
+    __deprecated_msg("shouldInkTouchControllerProcessInkTouches has been replaced with "
+                     "inkTouchController:shouldProcessInkTouchesAtTouchLocation.");
+
+@end
+
+@implementation MDCInkTouchController
+
+- (CGFloat)dragCancelDistance {
+  return _gestureRecognizer.dragCancelDistance;
+}
+
+- (void)setDragCancelDistance:(CGFloat)dragCancelDistance {
+  _gestureRecognizer.dragCancelDistance = dragCancelDistance;
+}
+
+- (BOOL)cancelsOnDragOut {
+  return _gestureRecognizer.cancelOnDragOut;
+}
+
+- (void)setCancelsOnDragOut:(BOOL)cancelsOnDragOut {
+  _gestureRecognizer.cancelOnDragOut = cancelsOnDragOut;
+}
+
+- (CGRect)targetBounds {
+  return _gestureRecognizer.targetBounds;
+}
+
+- (void)setTargetBounds:(CGRect)targetBounds {
+  _gestureRecognizer.targetBounds = targetBounds;
+}
+
+- (instancetype)initWithView:(UIView *)view {
+  self = [super init];
+  if (self) {
+    _gestureRecognizer =
+        [[MDCInkGestureRecognizer alloc] initWithTarget:self action:@selector(handleInkGesture:)];
+    _gestureRecognizer.delegate = self;
+
+    _view = view;
+    [_view addGestureRecognizer:_gestureRecognizer];
+
+    _defaultInkView = [[MDCInkView alloc] initWithFrame:view.bounds];
+    _defaultInkView.inkColor = _defaultInkView.defaultInkColor;
+    _defaultInkView.autoresizingMask =
+        UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [_view removeGestureRecognizer:_gestureRecognizer];
+  _gestureRecognizer.delegate = nil;
+}
+
+- (void)addInkView {
+  if (![_delegate respondsToSelector:@selector(inkTouchController:inkViewAtTouchLocation:)]) {
+    _addedInkView = _defaultInkView;
+
+    if ([_delegate respondsToSelector:@selector(inkTouchController:insertInkView:intoView:)]) {
+      [_delegate inkTouchController:self insertInkView:_addedInkView intoView:_view];
+    } else {
+      [_view addSubview:_addedInkView];
+    }
+  }
+}
+
+- (void)cancelInkTouchProcessing {
+  [_addedInkView cancelAllAnimationsAnimated:YES];
+}
+
+- (MDCInkView *_Nullable)inkViewAtTouchLocation:(CGPoint)location {
+  MDCInkView *inkView;
+  if ([_delegate respondsToSelector:@selector(inkTouchController:inkViewAtTouchLocation:)]) {
+    inkView = [_delegate inkTouchController:self inkViewAtTouchLocation:location];
+  } else {
+    CGPoint locationInInkCoords = [self.view convertPoint:location toView:_addedInkView];
+    if ([_addedInkView pointInside:locationInInkCoords withEvent:nil]) {
+      inkView = _addedInkView;
+    }
+  }
+  return inkView;
+}
+
+- (void)handleInkGesture:(MDCInkGestureRecognizer *)recognizer {
+  CGPoint touchLocation = [recognizer locationInView:_view];
+
+  switch (recognizer.state) {
+    case UIGestureRecognizerStateBegan: {
+      if ([_delegate respondsToSelector:@selector(inkTouchController:inkViewAtTouchLocation:)]) {
+        _addedInkView = [_delegate inkTouchController:self inkViewAtTouchLocation:touchLocation];
+        if (!_addedInkView) {
+          return [self cancelInkGestureWithRecognizer:recognizer];
+        }
+        NSAssert([_addedInkView isDescendantOfView:_view],
+                 @"Ink view %@ returned by inkTouchController:inkViewAtTouchLocation: must be a "
+                  "subview of base view %@",
+                 _addedInkView, _view);
+        recognizer.targetBounds = [_addedInkView convertRect:_addedInkView.bounds toView:_view];
+      }
+
+      _shouldRespondToTouch = YES;
+      dispatch_time_t delayTime =
+          dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC * kInkTouchDelayInterval));
+      dispatch_after(_delaysInkSpread ? delayTime : 0, dispatch_get_main_queue(), ^(void) {
+        [self touchBeganAtPoint:[recognizer locationInView:_addedInkView]
+                  touchLocation:touchLocation];
+      });
+      break;
+    }
+    case UIGestureRecognizerStatePossible:  // Ignored
+      break;
+    case UIGestureRecognizerStateChanged: {
+      // Due to changes on iPhone 6s, possibly due to the force touch,
+      // @c UIGestureRecognizerStateChanged constantly fires. However, we do not want to cancel the
+      // ink unless the users moves.
+      if (_shouldRespondToTouch && !CGPointEqualToPoint(touchLocation, _previousLocation)) {
+        _shouldRespondToTouch = NO;
+      }
+      break;
+    }
+    case UIGestureRecognizerStateCancelled:
+      [_addedInkView cancelAllAnimationsAnimated:YES];
+      _shouldRespondToTouch = NO;
+      break;
+    case UIGestureRecognizerStateRecognized:
+      [_addedInkView startTouchEndedAnimationAtPoint:touchLocation completion:nil];
+      _shouldRespondToTouch = NO;
+      break;
+    case UIGestureRecognizerStateFailed:
+      [_addedInkView cancelAllAnimationsAnimated:YES];
+      _shouldRespondToTouch = NO;
+      break;
+  }
+
+  if (_shouldRespondToTouch) {
+    _previousLocation = touchLocation;
+  } else {
+    _previousLocation = CGPointZero;
+  }
+}
+
+- (void)cancelInkGestureWithRecognizer:(MDCInkGestureRecognizer *)recognizer {
+  // To exit, disable the recognizer immediately which forces it to drop out of the current
+  // loop and prevent any state updates. Then re-enable to allow future gesture recognition.
+  recognizer.enabled = NO;
+  recognizer.enabled = YES;
+}
+
+- (void)touchBeganAtPoint:(CGPoint)point touchLocation:(CGPoint)touchLocation {
+  if (_shouldRespondToTouch) {
+    [_addedInkView startTouchBeganAnimationAtPoint:point completion:nil];
+    if ([_delegate
+            respondsToSelector:@selector(inkTouchController:didProcessInkView:atTouchLocation:)]) {
+      [_delegate inkTouchController:self
+                  didProcessInkView:_addedInkView
+                    atTouchLocation:touchLocation];
+    }
+    _shouldRespondToTouch = NO;
+  }
+}
+
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)other {
+  // Subclasses can override this to prioritize another recognizer.
+  return YES;
+}
+
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
+  if ([_delegate respondsToSelector:@selector(inkTouchController:
+                                        shouldProcessInkTouchesAtTouchLocation:)]) {
+    CGPoint touchLocation = [gestureRecognizer locationInView:_view];
+    return [_delegate inkTouchController:self shouldProcessInkTouchesAtTouchLocation:touchLocation];
+  } else if ([_delegate respondsToSelector:@selector(shouldInkTouchControllerProcessInkTouches:)]) {
+    // Please use inkTouchController:shouldProcessInkTouchesAtTouchLocation. The delegate call below
+    // is deprecated and only provided for legacy support.
+    id<MDCInkTouchControllerLegacyDelegate> legacyDelegate =
+        (id<MDCInkTouchControllerLegacyDelegate>)_delegate;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    return [legacyDelegate shouldInkTouchControllerProcessInkTouches:self];
+#pragma clang diagnostic pop
+  }
+  return YES;
+}
+
+#pragma mark - Deprecations
+
+- (MDCInkView *)inkView {
+  return _defaultInkView;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkView.h
new file mode 100644
index 0000000..6bb87fa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkView.h
@@ -0,0 +1,111 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Completion block signature for all ink animations. */
+typedef void (^MDCInkCompletionBlock)();
+
+/** Ink styles. */
+typedef NS_ENUM(NSInteger, MDCInkStyle) {
+  MDCInkStyleBounded,  /** Ink is clipped to the view's bounds. */
+  MDCInkStyleUnbounded /** Ink is not clipped to the view's bounds. */
+};
+
+/**
+ A UIView that draws and animates the Material Design ink effect for touch interactions.
+
+ There are two kinds of ink:
+
+ Bounded ink: Ink that spreads from a point and is contained in the bounds of a UI element such as a
+ button. The ink is visually clipped to the bounds of the UI element. Bounded ink is the most
+ commonly-used ink in the system. Examples include basic Material buttons, list menu items, and tile
+ grids.
+
+ Unbounded ink: Ink that spreads out from a point "on top" of other UI elements. It typically
+ reaches a maximum circle radius and then fades, unclipped by other UI elements. Typically used
+ when interacting with small UI elements such as navigation bar icons or slider "thumb" controls.
+ Examples include overflow menus, icon toggle buttons, and phone dialer keys.
+
+ Note that the two kinds of ink are designed to have different animation parameters, that is,
+ bounded ink isn't just clipped unbounded ink. Whether the ink is bounded or not depends on the kind
+ of UI element the user is interacting with.
+ */
+@interface MDCInkView : UIView
+
+/**
+ The style of ink for this view. Defaults to MDCInkStyleBounded.
+
+ Changes only affect subsequent animations, not animations in progress.
+ */
+@property(nonatomic, assign) MDCInkStyle inkStyle;
+
+/** The foreground color of the ink. The default value is defaultInkColor. */
+@property(nonatomic, strong, null_resettable) UIColor *inkColor;
+
+/** Default color used for ink if no color is specified. */
+@property(nonatomic, strong, readonly, nonnull) UIColor *defaultInkColor;
+
+/**
+ Maximum radius of the ink. If the radius <= 0 then half the length of the diagonal of self.bounds
+ is used. This value is ignored if @c inkStyle is set to |MDCInkStyleBounded|.
+ */
+@property(nonatomic, assign) CGFloat maxRippleRadius;
+
+/**
+ Use a custom center for the ink splash. If YES, then customInkCenter is used, otherwise the
+ center of self.bounds is used. Default is NO.
+ */
+@property(nonatomic, assign) BOOL usesCustomInkCenter;
+
+/**
+ Custom center for the ink splash in the view’s coordinate system.
+
+ Ignored if usesCustomInkCenter is not set.
+ */
+@property(nonatomic, assign) CGPoint customInkCenter;
+
+/**
+ Start the first part of the "press and release" animation at a particular point.
+
+ The "press and release" animation begins by fading in the ink ripple when this method is called.
+
+ @param point The user interaction position in the view’s coordinate system.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)startTouchBeganAnimationAtPoint:(CGPoint)point
+                             completion:(nullable MDCInkCompletionBlock)completionBlock;
+
+/**
+ Start the second part of the "press and release" animation at a particular point.
+
+ The "press and release" animation ends by completing the ink ripple expansion while fading out when
+ this method is called.
+
+ @param point The user interaction position in the view’s coordinate system.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)startTouchEndedAnimationAtPoint:(CGPoint)point
+                             completion:(nullable MDCInkCompletionBlock)completionBlock;
+
+/**
+ Cancel all animations.
+
+ @param animated If false, remove the animations immediately.
+ */
+- (void)cancelAllAnimationsAnimated:(BOOL)animated;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkView.m
new file mode 100644
index 0000000..01989c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MDCInkView.m
@@ -0,0 +1,125 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkView.h"
+
+#import "private/MDCInkLayer.h"
+
+@interface MDCInkView ()
+@property(nonatomic, readonly) MDCInkLayer *inkLayer;
+@end
+
+@implementation MDCInkView
+
++ (Class)layerClass {
+  return [MDCInkLayer class];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCInkViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCInkViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCInkViewInit {
+  self.userInteractionEnabled = NO;
+  self.backgroundColor = [UIColor clearColor];
+  self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+  self.inkColor = self.defaultInkColor;
+}
+
+- (void)setInkStyle:(MDCInkStyle)inkStyle {
+  _inkStyle = inkStyle;
+  switch (inkStyle) {
+    case MDCInkStyleBounded:
+      self.inkLayer.masksToBounds = YES;
+      self.inkLayer.bounded = YES;
+      break;
+    case MDCInkStyleUnbounded:
+      self.inkLayer.masksToBounds = NO;
+      self.inkLayer.bounded = NO;
+      break;
+  }
+}
+
+- (void)setInkColor:(UIColor *)inkColor {
+  if (inkColor == nil) {
+    return;
+  }
+  self.inkLayer.inkColor = inkColor;
+}
+
+- (UIColor *)inkColor {
+  return self.inkLayer.inkColor;
+}
+
+- (CGFloat)maxRippleRadius {
+  return self.inkLayer.maxRippleRadius;
+}
+
+- (void)setMaxRippleRadius:(CGFloat)radius {
+  self.inkLayer.maxRippleRadius = radius;
+}
+
+- (BOOL)usesCustomInkCenter {
+  return self.inkLayer.useCustomInkCenter;
+}
+
+- (void)setUsesCustomInkCenter:(BOOL)usesCustomInkCenter {
+  self.inkLayer.useCustomInkCenter = usesCustomInkCenter;
+}
+
+- (CGPoint)customInkCenter {
+  return self.inkLayer.customInkCenter;
+}
+
+- (void)setCustomInkCenter:(CGPoint)customInkCenter {
+  self.inkLayer.customInkCenter = customInkCenter;
+}
+
+- (MDCInkLayer *)inkLayer {
+  return (MDCInkLayer *)self.layer;
+}
+
+- (void)startTouchBeganAnimationAtPoint:(CGPoint)point
+                             completion:(MDCInkCompletionBlock)completionBlock {
+  [self.inkLayer spreadFromPoint:point completion:completionBlock];
+}
+
+- (void)startTouchEndedAnimationAtPoint:(CGPoint)point
+                             completion:(MDCInkCompletionBlock)completionBlock {
+  [self.inkLayer evaporateWithCompletion:completionBlock];
+}
+
+- (void)cancelAllAnimationsAnimated:(BOOL)animated {
+  [self.inkLayer resetAllInk:animated];
+}
+
+- (UIColor *)defaultInkColor {
+  return [[UIColor alloc] initWithWhite:0 alpha:0.06f];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MaterialInk.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MaterialInk.h
new file mode 100644
index 0000000..c73b152
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/MaterialInk.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkGestureRecognizer.h"
+#import "MDCInkTouchController.h"
+#import "MDCInkView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.h
new file mode 100644
index 0000000..a22b14d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.h
@@ -0,0 +1,104 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIKit.h>
+
+/**
+ A Core Animation layer that draws and animates the ink effect.
+
+ Exact behaviour of the ink splash is defined in this sandbox demo: http://go/qinkdemo.
+
+ Quick summary of how the ink ripple works:
+
+ 1. On touch down, blast initiates from the touch point.
+ 2. On touch down hold, it continues to spread, but will gravitate to the center point
+    of the view.
+ 3. On touch up, the ink ripple will lose energy, opacity will start to decrease.
+ */
+@interface MDCInkLayer : CALayer
+
+/** Clips the ripple to the bounds of the layer. */
+@property(nonatomic, assign, getter=isBounded) BOOL bounded;
+
+/** Maximum radius of the ink. No maximum if radius is 0 or less. This value is ignored if
+ @c bounded is set to |YES|.*/
+@property(nonatomic, assign) CGFloat maxRippleRadius;
+
+/** Set the foreground color of the ink. */
+@property(nonatomic, strong) UIColor *inkColor;
+
+/** Spread duration. */
+@property(nonatomic, readonly, assign) NSTimeInterval spreadDuration;
+
+/** Evaporate duration */
+@property(nonatomic, readonly, assign) NSTimeInterval evaporateDuration;
+
+/**
+ Set to YES if the ink layer should be using a custom center.
+ */
+@property(nonatomic, assign) BOOL useCustomInkCenter;
+
+/**
+ Center point which ink gravitates towards.
+
+ Ignored if useCustomInkCenter is not set.
+ */
+@property(nonatomic, assign) CGPoint customInkCenter;
+
+/**
+ Whether linear expansion should be used for the ink, rather than a Quantum curve. Useful for
+ ink which needs to fill the bounds of its view completely and leave those bounds at full speed.
+ */
+@property(nonatomic, assign) BOOL userLinearExpansion;
+
+/**
+ Reset any ink applied to the layer.
+
+ @param animated Enables the ink ripple fade out animation.
+ */
+- (void)resetAllInk:(BOOL)animated;
+
+/**
+ Spreads the ink over the whole view.
+
+ Can be called multiple times which will result in multiple ink ripples.
+
+ @param completionBlock Block called after the completion of the animation.
+ @param point Point at which the ink spreads from.
+ */
+- (void)spreadFromPoint:(CGPoint)point completion:(void (^)())completionBlock;
+
+/**
+ Dissipate ink blast, should be called on touch up.
+
+ If there are multiple ripples at once, the oldest ripple will be evaporated.
+
+ @param completionBlock Block called after the completion of the evaporation.
+ */
+- (void)evaporateWithCompletion:(void (^)())completionBlock;
+
+/**
+ Dissipates the ink blast, but condenses to a point. Used for touch exit or cancel.
+
+ If there are mulitple ripples, the oldest ripple will be evaporated.
+
+ @param point Evaporate the ink towards the point.
+ @param completionBlock Block called after the completion of the evaporation.
+ */
+- (void)evaporateToPoint:(CGPoint)point completion:(void (^)())completionBlock;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.m
new file mode 100644
index 0000000..9d18b4b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.m
@@ -0,0 +1,596 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkLayer.h"
+
+#import <UIKit/UIKit.h>
+
+static inline CGPoint MDCInkLayerInterpolatePoint(CGPoint start,
+                                                  CGPoint end,
+                                                  CGFloat offsetPercent) {
+  CGPoint centerOffsetPoint = CGPointMake(start.x + (end.x - start.x) * offsetPercent,
+                                          start.y + (end.y - start.y) * offsetPercent);
+  return centerOffsetPoint;
+}
+
+static inline CGFloat MDCInkLayerRadiusBounds(CGFloat maxRippleRadius,
+                                              CGFloat inkLayerRectHypotenuse,
+                                              BOOL bounded) {
+  if (maxRippleRadius > 0) {
+#ifdef MDC_BOUNDED_INK_IGNORES_MAX_RIPPLE_RADIUS
+    if (!bounded) {
+      return maxRippleRadius;
+    } else {
+      static dispatch_once_t onceToken;
+      dispatch_once(&onceToken, ^{
+        NSLog(@"Implementation of MDCInkView with |MDCInkStyle| MDCInkStyleBounded and "
+              @"maxRippleRadius has changed.\n\n"
+              @"MDCInkStyleBounded ignores maxRippleRadius. "
+              @"Please use |MDCInkStyle| MDCInkStyleUnbounded to continue using maxRippleRadius. "
+              @"For implementation questions, please email shepj@google.com");
+      });
+      return inkLayerRectHypotenuse;
+    }
+#else
+    return maxRippleRadius;
+#endif
+  } else {
+    return inkLayerRectHypotenuse;
+  }
+}
+
+static inline CGFloat MDCInkLayerRandom() {
+  const uint32_t max_value = 10000;
+  return (CGFloat)arc4random_uniform(max_value + 1) / max_value;
+}
+
+static inline CGPoint MDCInkLayerRectGetCenter(CGRect rect) {
+  return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
+}
+
+static inline CGFloat MDCInkLayerRectHypotenuse(CGRect rect) {
+  return (CGFloat)hypot(CGRectGetWidth(rect), CGRectGetHeight(rect));
+}
+
+static NSString *const kInkLayerOpacity = @"opacity";
+static NSString *const kInkLayerPosition = @"position";
+static NSString *const kInkLayerScale = @"transform.scale";
+
+// State tracking for ink.
+typedef NS_ENUM(NSInteger, MDCInkRippleState) {
+  kInkRippleNone,
+  kInkRippleSpreading,
+  kInkRippleComplete,
+  kInkRippleCancelled,
+};
+
+@protocol MDCInkLayerRippleDelegate <NSObject>
+
+@optional
+
+- (void)animationDidStop:(CAAnimation *)anim
+              shapeLayer:(CAShapeLayer *)shapeLayer
+                finished:(BOOL)finished;
+
+@end
+
+@interface MDCInkLayerRipple : CAShapeLayer
+
+@property(nonatomic, assign, getter=isAnimationCleared) BOOL animationCleared;
+@property(nonatomic, weak) id<MDCInkLayerRippleDelegate> animationDelegate;
+@property(nonatomic, assign) BOOL bounded;
+@property(nonatomic, weak) CALayer *inkLayer;
+@property(nonatomic, assign) CGFloat radius;
+@property(nonatomic, assign) CGPoint point;
+@property(nonatomic, assign) CGRect targetFrame;
+@property(nonatomic, assign) MDCInkRippleState rippleState;
+@property(nonatomic, strong) UIColor *color;
+
+@end
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCInkLayerRipple () <CAAnimationDelegate>
+@end
+#endif
+
+@implementation MDCInkLayerRipple
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _rippleState = kInkRippleNone;
+    _animationCleared = YES;
+  }
+  return self;
+}
+
+- (void)setupRipple {
+  self.fillColor = self.color.CGColor;
+  CGFloat dim = self.radius * 2.f;
+  self.frame = CGRectMake(0, 0, dim, dim);
+  UIBezierPath *ripplePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, dim, dim)];
+  self.path = ripplePath.CGPath;
+}
+
+- (void)enter {
+  _rippleState = kInkRippleSpreading;
+  [_inkLayer addSublayer:self];
+  _animationCleared = NO;
+}
+
+- (void)exit {
+  if (_rippleState != kInkRippleCancelled) {
+    _rippleState = kInkRippleComplete;
+  }
+}
+
+- (CAKeyframeAnimation *)opacityAnimWithValues:(NSArray<NSNumber *> *)values
+                                         times:(NSArray<NSNumber *> *)times {
+  CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:kInkLayerOpacity];
+  anim.fillMode = kCAFillModeForwards;
+  anim.keyTimes = times;
+  anim.removedOnCompletion = NO;
+  anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+  anim.values = values;
+  return anim;
+}
+
+- (CAKeyframeAnimation *)positionAnimWithPath:(CGPathRef)path
+                                     duration:(CGFloat)duration
+                               timingFunction:(CAMediaTimingFunction *)timingFunction {
+  CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:kInkLayerPosition];
+  anim.duration = duration;
+  anim.fillMode = kCAFillModeForwards;
+  anim.path = path;
+  anim.removedOnCompletion = NO;
+  anim.timingFunction = timingFunction;
+  return anim;
+}
+
+- (CAKeyframeAnimation *)scaleAnimWithValues:(NSArray<NSNumber *> *)values
+                                       times:(NSArray<NSNumber *> *)times {
+  CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:kInkLayerScale];
+  anim.fillMode = kCAFillModeForwards;
+  anim.keyTimes = times;
+  anim.removedOnCompletion = NO;
+  anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+  anim.values = values;
+  return anim;
+}
+
+- (CAMediaTimingFunction *)logDecelerateEasing {
+  // This bezier curve is an approximation of a log curve.
+  return [[CAMediaTimingFunction alloc] initWithControlPoints:0.157f:0.72f:0.386f:0.987f];
+}
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)finished {
+  if (!self.isAnimationCleared) {
+    [self removeFromSuperlayer];
+    [self.animationDelegate animationDidStop:anim shapeLayer:self finished:finished];
+  }
+}
+
+@end
+
+static CGFloat const kInkLayerForegroundBoundedOpacityExitDuration = 0.4f;
+static CGFloat const kInkLayerForegroundBoundedPositionExitDuration = 0.3f;
+static CGFloat const kInkLayerForegroundBoundedRadiusExitDuration = 0.8f;
+static CGFloat const kInkLayerForegroundRadiusGrowthMultiplier = 350.f;
+static CGFloat const kInkLayerForegroundUnboundedEnterDelay = 0.08f;
+static CGFloat const kInkLayerForegroundUnboundedOpacityEnterDuration = 0.12f;
+static CGFloat const kInkLayerForegroundWaveTouchDownAcceleration = 1024.f;
+static CGFloat const kInkLayerForegroundWaveTouchUpAcceleration = 3400.f;
+static NSString *const kInkLayerForegroundOpacityAnim = @"foregroundOpacityAnim";
+static NSString *const kInkLayerForegroundPositionAnim = @"foregroundPositionAnim";
+static NSString *const kInkLayerForegroundScaleAnim = @"foregroundScaleAnim";
+
+@interface MDCInkLayerForegroundRipple : MDCInkLayerRipple
+
+@property(nonatomic, assign) BOOL useCustomInkCenter;
+@property(nonatomic, assign) CGPoint customInkCenter;
+@property(nonatomic, strong) CAKeyframeAnimation *foregroundOpacityAnim;
+@property(nonatomic, strong) CAKeyframeAnimation *foregroundPositionAnim;
+@property(nonatomic, strong) CAKeyframeAnimation *foregroundScaleAnim;
+
+@end
+
+@implementation MDCInkLayerForegroundRipple
+
+- (void)setupRipple {
+  CGFloat random = MDCInkLayerRandom();
+  self.radius = (CGFloat)(0.9f + random * 0.1f) * kInkLayerForegroundRadiusGrowthMultiplier;
+  [super setupRipple];
+}
+
+- (void)enterWithCompletion:(void (^)())completionBlock {
+  [super enter];
+
+  if (self.bounded) {
+    _foregroundOpacityAnim = [self opacityAnimWithValues:@[ @0 ] times:@[ @0 ]];
+    _foregroundScaleAnim = [self scaleAnimWithValues:@[ @0 ] times:@[ @0 ]];
+  } else {
+    _foregroundOpacityAnim = [self opacityAnimWithValues:@[ @0, @1 ] times:@[ @0, @1 ]];
+    _foregroundOpacityAnim.duration = kInkLayerForegroundUnboundedOpacityEnterDuration;
+
+    CGFloat duration = (CGFloat)sqrt(self.radius / kInkLayerForegroundWaveTouchDownAcceleration);
+    _foregroundScaleAnim =
+        [self scaleAnimWithValues:@[ @0, @1 ]
+                            times:@[ @(kInkLayerForegroundUnboundedEnterDelay), @1 ]];
+    _foregroundScaleAnim.duration = duration;
+
+    CGFloat xOffset = self.targetFrame.origin.x - self.inkLayer.frame.origin.x;
+    CGFloat yOffset = self.targetFrame.origin.y - self.inkLayer.frame.origin.y;
+
+    UIBezierPath *movePath = [UIBezierPath bezierPath];
+    CGPoint startPoint = CGPointMake(self.point.x + xOffset, self.point.y + yOffset);
+    CGPoint endPoint = MDCInkLayerRectGetCenter(self.targetFrame);
+    if (self.useCustomInkCenter) {
+      endPoint = self.customInkCenter;
+    }
+    endPoint = CGPointMake(endPoint.x + xOffset, endPoint.y + yOffset);
+    [movePath moveToPoint:startPoint];
+    [movePath addLineToPoint:endPoint];
+
+    CAMediaTimingFunction *linearTimingFunction =
+        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+    _foregroundPositionAnim = [self positionAnimWithPath:movePath.CGPath
+                                                duration:duration
+                                          timingFunction:linearTimingFunction];
+    _foregroundPositionAnim.keyTimes = @[ @(kInkLayerForegroundUnboundedEnterDelay), @1 ];
+    [self addAnimation:_foregroundPositionAnim forKey:kInkLayerForegroundPositionAnim];
+  }
+
+  [CATransaction begin];
+  if (completionBlock) {
+    __weak MDCInkLayerForegroundRipple *weakSelf = self;
+    [CATransaction setCompletionBlock:^{
+      MDCInkLayerForegroundRipple *strongSelf = weakSelf;
+      if (strongSelf.rippleState != kInkRippleCancelled) {
+        completionBlock();
+      }
+    }];
+  }
+  [self addAnimation:_foregroundOpacityAnim forKey:kInkLayerForegroundOpacityAnim];
+  [self addAnimation:_foregroundScaleAnim forKey:kInkLayerForegroundScaleAnim];
+  [CATransaction commit];
+}
+
+- (void)exit:(BOOL)animated {
+  self.rippleState = kInkRippleCancelled;
+  [self exit:animated completion:nil];
+}
+
+- (void)exit:(BOOL)animated completion:(void (^)())completionBlock {
+  [super exit];
+
+  if (!animated) {
+    [self removeAllAnimations];
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    self.opacity = 0;
+    [CATransaction commit];
+    return;
+  }
+
+  if (self.bounded) {
+    _foregroundOpacityAnim.values = @[ @1, @0 ];
+    _foregroundOpacityAnim.duration = kInkLayerForegroundBoundedOpacityExitDuration;
+
+    // Bounded ripples move slightly towards the center of the tap target. Unbounded ripples
+    // move to the center of the tap target.
+
+    CGFloat xOffset = self.targetFrame.origin.x - self.inkLayer.frame.origin.x;
+    CGFloat yOffset = self.targetFrame.origin.y - self.inkLayer.frame.origin.y;
+
+    CGPoint startPoint = CGPointMake(self.point.x + xOffset, self.point.y + yOffset);
+    CGPoint endPoint = MDCInkLayerRectGetCenter(self.targetFrame);
+    if (self.useCustomInkCenter) {
+      endPoint = self.customInkCenter;
+    }
+    endPoint = CGPointMake(endPoint.x + xOffset, endPoint.y + yOffset);
+    CGPoint centerOffsetPoint = MDCInkLayerInterpolatePoint(startPoint, endPoint, 0.3f);
+    UIBezierPath *movePath = [UIBezierPath bezierPath];
+    [movePath moveToPoint:startPoint];
+    [movePath addLineToPoint:centerOffsetPoint];
+
+    _foregroundPositionAnim =
+        [self positionAnimWithPath:movePath.CGPath
+                          duration:kInkLayerForegroundBoundedPositionExitDuration
+                    timingFunction:[self logDecelerateEasing]];
+    _foregroundScaleAnim.values = @[ @0, @1 ];
+    _foregroundScaleAnim.keyTimes = @[ @0, @1 ];
+    _foregroundScaleAnim.duration = kInkLayerForegroundBoundedRadiusExitDuration;
+  } else {
+    NSNumber *opacityVal = [self.presentationLayer valueForKeyPath:kInkLayerOpacity];
+    if (!opacityVal) {
+      opacityVal = [NSNumber numberWithFloat:0];
+    }
+    CGFloat adjustedDuration = kInkLayerForegroundBoundedPositionExitDuration;
+    CGFloat normOpacityVal = opacityVal.floatValue;
+    CGFloat opacityDuration = normOpacityVal / 3.f;
+    _foregroundOpacityAnim.values = @[ opacityVal, @0 ];
+    _foregroundOpacityAnim.duration = opacityDuration + adjustedDuration;
+
+    NSNumber *scaleVal = [self.presentationLayer valueForKeyPath:kInkLayerScale];
+    if (!scaleVal) {
+      scaleVal = [NSNumber numberWithFloat:0];
+    }
+    CGFloat unboundedDuration = (CGFloat)sqrt(((1.f - scaleVal.floatValue) * self.radius) /
+                                              (kInkLayerForegroundWaveTouchDownAcceleration +
+                                               kInkLayerForegroundWaveTouchUpAcceleration));
+    _foregroundPositionAnim.duration = unboundedDuration + adjustedDuration;
+    _foregroundScaleAnim.values = @[ scaleVal, @1 ];
+    _foregroundScaleAnim.duration = unboundedDuration + adjustedDuration;
+  }
+
+  _foregroundOpacityAnim.keyTimes = @[ @0, @1 ];
+  if (_foregroundOpacityAnim.duration < _foregroundScaleAnim.duration) {
+    _foregroundScaleAnim.delegate = self;
+  } else {
+    _foregroundOpacityAnim.delegate = self;
+  }
+
+  _foregroundOpacityAnim.timingFunction =
+      [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+  _foregroundPositionAnim.timingFunction = [self logDecelerateEasing];
+  _foregroundScaleAnim.timingFunction = [self logDecelerateEasing];
+
+  [CATransaction begin];
+  if (completionBlock) {
+    __weak MDCInkLayerForegroundRipple *weakSelf = self;
+    [CATransaction setCompletionBlock:^{
+      MDCInkLayerForegroundRipple *strongSelf = weakSelf;
+      if (strongSelf.rippleState != kInkRippleCancelled) {
+        completionBlock();
+      }
+    }];
+  }
+  [self addAnimation:_foregroundOpacityAnim forKey:kInkLayerForegroundOpacityAnim];
+  [self addAnimation:_foregroundPositionAnim forKey:kInkLayerForegroundPositionAnim];
+  [self addAnimation:_foregroundScaleAnim forKey:kInkLayerForegroundScaleAnim];
+  [CATransaction commit];
+}
+
+- (void)removeAllAnimations {
+  [super removeAllAnimations];
+  _foregroundOpacityAnim = nil;
+  _foregroundPositionAnim = nil;
+  _foregroundScaleAnim = nil;
+  self.animationCleared = YES;
+}
+
+@end
+
+static CGFloat const kInkLayerBackgroundOpacityEnterDuration = 0.6f;
+static CGFloat const kInkLayerBackgroundBaseOpacityExitDuration = 0.48f;
+static CGFloat const kInkLayerBackgroundFastEnterDuration = 0.12f;
+static NSString *const kInkLayerBackgroundOpacityAnim = @"backgroundOpacityAnim";
+
+@interface MDCInkLayerBackgroundRipple : MDCInkLayerRipple
+
+@property(nonatomic, strong) CAKeyframeAnimation *backgroundOpacityAnim;
+
+@end
+
+@implementation MDCInkLayerBackgroundRipple
+
+- (void)enter {
+  [super enter];
+  _backgroundOpacityAnim = [self opacityAnimWithValues:@[ @0, @1 ] times:@[ @0, @1 ]];
+  _backgroundOpacityAnim.duration = kInkLayerBackgroundOpacityEnterDuration;
+  [self addAnimation:_backgroundOpacityAnim forKey:kInkLayerBackgroundOpacityAnim];
+}
+
+- (void)exit:(BOOL)animated {
+  [super exit];
+
+  if (!animated) {
+    [self removeAllAnimations];
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    self.opacity = 0;
+    [CATransaction commit];
+    return;
+  }
+
+  NSNumber *opacityVal = [self.presentationLayer valueForKeyPath:kInkLayerOpacity];
+  if (!opacityVal) {
+    opacityVal = [NSNumber numberWithFloat:0];
+  }
+  CGFloat duration = kInkLayerBackgroundBaseOpacityExitDuration;
+  if (self.bounded) {
+    // The end (tap release) animation should continue at the opacity level of the start animation.
+    CGFloat enterDuration = (1 - opacityVal.floatValue / 1) * kInkLayerBackgroundFastEnterDuration;
+    duration += enterDuration;
+    _backgroundOpacityAnim = [self opacityAnimWithValues:@[ opacityVal, @1, @0 ]
+                                                   times:@[ @0, @(enterDuration / duration), @1 ]];
+  } else {
+    _backgroundOpacityAnim = [self opacityAnimWithValues:@[ opacityVal, @0 ] times:@[ @0, @1 ]];
+  }
+  _backgroundOpacityAnim.duration = duration;
+  _backgroundOpacityAnim.delegate = self;
+  [self addAnimation:_backgroundOpacityAnim forKey:kInkLayerBackgroundOpacityAnim];
+}
+
+- (void)removeAllAnimations {
+  [super removeAllAnimations];
+  _backgroundOpacityAnim = nil;
+  self.animationCleared = YES;
+}
+
+@end
+
+@interface MDCInkLayer () <MDCInkLayerRippleDelegate>
+
+/**
+ Reset the bottom-most ink applied to the layer with a completion handler to be called on completion
+ if applicable.
+
+ @param animated Enables the ink ripple fade out animation.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)resetBottomInk:(BOOL)animated completion:(void (^)())completionBlock;
+
+/**
+ Reset the bottom-most ink applied to the layer with a completion handler to be called on completion
+ if applicable.
+
+ @param animated Enables the ink ripple fade out animation.
+ @param point Evaporate the ink towards the point.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)resetBottomInk:(BOOL)animated toPoint:(CGPoint)point completion:(void (^)())completionBlock;
+
+@property(nonatomic, strong) CAShapeLayer *compositeRipple;
+@property(nonatomic, strong) NSMutableArray<MDCInkLayerForegroundRipple *> *foregroundRipples;
+@property(nonatomic, strong) NSMutableArray<MDCInkLayerBackgroundRipple *> *backgroundRipples;
+
+@end
+
+@implementation MDCInkLayer
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    self.masksToBounds = YES;
+    _bounded = YES;
+    _compositeRipple = [CAShapeLayer layer];
+    _foregroundRipples = [NSMutableArray array];
+    _backgroundRipples = [NSMutableArray array];
+    [self addSublayer:_compositeRipple];
+  }
+  return self;
+}
+
+- (void)layoutSublayers {
+  [super layoutSublayers];
+  _compositeRipple.frame = self.frame;
+  CGFloat radius = MDCInkLayerRadiusBounds(_maxRippleRadius,
+                                           MDCInkLayerRectHypotenuse(self.bounds) / 2.f, _bounded);
+
+  CGRect rippleFrame =
+      CGRectMake(-(radius * 2.f - self.bounds.size.width) / 2.f,
+                 -(radius * 2.f - self.bounds.size.height) / 2.f, radius * 2.f, radius * 2.f);
+  _compositeRipple.frame = rippleFrame;
+  CGRect rippleBounds = CGRectMake(0, 0, radius * 2.f, radius * 2.f);
+  CAShapeLayer *rippleMaskLayer = [CAShapeLayer layer];
+  UIBezierPath *ripplePath = [UIBezierPath bezierPathWithOvalInRect:rippleBounds];
+  rippleMaskLayer.path = ripplePath.CGPath;
+  _compositeRipple.mask = rippleMaskLayer;
+}
+
+- (void)resetAllInk:(BOOL)animated {
+  if (self.foregroundRipples.count > 0) {
+    [self.foregroundRipples makeObjectsPerformSelector:@selector(exit:)];
+  }
+  if (self.backgroundRipples.count > 0) {
+    [self.backgroundRipples makeObjectsPerformSelector:@selector(exit:)];
+  }
+}
+
+- (void)resetBottomInk:(BOOL)animated completion:(void (^)())completionBlock {
+  if (self.foregroundRipples.count > 0) {
+    [[self.foregroundRipples objectAtIndex:(self.foregroundRipples.count - 1)]
+              exit:animated
+        completion:completionBlock];
+  }
+  if (self.backgroundRipples.count > 0) {
+    [[self.backgroundRipples objectAtIndex:(self.backgroundRipples.count - 1)] exit:animated];
+  }
+}
+
+- (void)resetBottomInk:(BOOL)animated
+               toPoint:(CGPoint)point
+            completion:(void (^)())completionBlock {
+  if (self.foregroundRipples.count > 0) {
+    MDCInkLayerForegroundRipple *foregroundRipple =
+        [self.foregroundRipples objectAtIndex:(self.foregroundRipples.count - 1)];
+    foregroundRipple.point = point;
+    [foregroundRipple exit:animated completion:completionBlock];
+  }
+  if (self.backgroundRipples.count > 0) {
+    [[self.backgroundRipples objectAtIndex:(self.backgroundRipples.count - 1)] exit:animated];
+  }
+}
+
+#pragma mark - Properties
+
+- (void)spreadFromPoint:(CGPoint)point completion:(void (^)())completionBlock {
+  // Create a mask layer before drawing the ink using the superlayer's shadowPath
+  // if it exists. This helps the FAB when it is not rectangular.
+  if (self.masksToBounds && self.superlayer.shadowPath) {
+    CAShapeLayer *mask = [CAShapeLayer layer];
+    mask.path = self.superlayer.shadowPath;
+    mask.fillColor = [UIColor whiteColor].CGColor;
+    self.mask = mask;
+  } else {
+    self.mask = nil;
+  }
+
+  CGFloat radius = MDCInkLayerRadiusBounds(_maxRippleRadius,
+                                           MDCInkLayerRectHypotenuse(self.bounds) / 2.f, _bounded);
+
+  MDCInkLayerBackgroundRipple *backgroundRipple = [[MDCInkLayerBackgroundRipple alloc] init];
+  backgroundRipple.inkLayer = _compositeRipple;
+  backgroundRipple.targetFrame = self.bounds;
+  backgroundRipple.point = point;
+  backgroundRipple.color = self.inkColor;
+  backgroundRipple.radius = radius;
+  backgroundRipple.bounded = self.bounded;
+  backgroundRipple.animationDelegate = self;
+  [backgroundRipple setupRipple];
+
+  MDCInkLayerForegroundRipple *foregroundRipple = [[MDCInkLayerForegroundRipple alloc] init];
+  foregroundRipple.inkLayer = _compositeRipple;
+  foregroundRipple.targetFrame = self.bounds;
+  foregroundRipple.point = point;
+  foregroundRipple.color = self.inkColor;
+  foregroundRipple.radius = radius;
+  foregroundRipple.bounded = self.bounded;
+  foregroundRipple.animationDelegate = self;
+  foregroundRipple.useCustomInkCenter = self.useCustomInkCenter;
+  foregroundRipple.customInkCenter = self.customInkCenter;
+  [foregroundRipple setupRipple];
+
+  [backgroundRipple enter];
+  [self.backgroundRipples addObject:backgroundRipple];
+  [foregroundRipple enterWithCompletion:completionBlock];
+  [self.foregroundRipples addObject:foregroundRipple];
+}
+
+- (void)evaporateWithCompletion:(void (^)())completionBlock {
+  [self resetBottomInk:YES completion:completionBlock];
+}
+
+- (void)evaporateToPoint:(CGPoint)point completion:(void (^)())completionBlock {
+  [self resetBottomInk:YES toPoint:point completion:completionBlock];
+}
+
+#pragma mark - MDCInkLayerRippleDelegate
+
+- (void)animationDidStop:(CAAnimation *)anim
+              shapeLayer:(CAShapeLayer *)shapeLayer
+                finished:(BOOL)finished {
+  [shapeLayer removeAllAnimations];
+
+  if ([shapeLayer isMemberOfClass:[MDCInkLayerForegroundRipple class]]) {
+    [self.foregroundRipples removeObject:(MDCInkLayerForegroundRipple *)shapeLayer];
+  } else if ([shapeLayer isMemberOfClass:[MDCInkLayerBackgroundRipple class]]) {
+    [self.backgroundRipples removeObject:(MDCInkLayerBackgroundRipple *)shapeLayer];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
new file mode 100644
index 0000000..a3e07da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
@@ -0,0 +1,194 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCButtonBarDelegate;
+
+/** Specifies the title alignment of the |MDCNavigationBar|. */
+typedef NS_ENUM(NSInteger, MDCNavigationBarTitleAlignment) {
+  /** Aligns the title to the center of the NavigationBar. */
+  MDCNavigationBarTitleAlignmentCenter,
+  /** Aligns the title to the left/leading of the NavigationBar. */
+  MDCNavigationBarTitleAlignmentLeading
+};
+
+/**
+ This protocol defines all of the properties on UINavigationItem that can be listened to by
+ MDCNavigationBar.
+ */
+@protocol MDCUINavigationItemObservables <NSObject>
+@required
+
+@property(nonatomic, copy, nullable) NSString *title;
+@property(nonatomic, strong, nullable) UIView *titleView;
+@property(nonatomic) BOOL hidesBackButton;
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leftBarButtonItems;
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *rightBarButtonItems;
+@property(nonatomic) BOOL leftItemsSupplementBackButton;
+@property(nonatomic, strong, nullable) UIBarButtonItem *leftBarButtonItem;
+@property(nonatomic, strong, nullable) UIBarButtonItem *rightBarButtonItem;
+
+@end
+
+@class MDCNavigationBar;
+
+/**
+  The MDCNavigationBarTextColorAccessibilityMutator class creates an external object with which to
+  work on an instance of a Material Navigation Bar to activate and ensure accessibility on its title
+  and buttons.
+
+  ### Dependencies
+
+  Material NavigationBarTextColorAccessibilityMutator depends on the Navigation Bar material
+  component and MDFTextAccessibility Framework.
+  */
+
+@interface MDCNavigationBarTextColorAccessibilityMutator : NSObject
+
+/**
+ Initializes and returns a newly created accessibility mutator
+ */
+- (nonnull instancetype)init;
+
+/**
+  Mutates title text color and navigation items' tint colors based on background color of
+  navigation bar.
+  */
+- (void)mutate:(nonnull MDCNavigationBar *)navBar;
+
+@end
+
+/**
+ The MDCNavigationBar class is a view consisting of a leading and trailing button bar, title label,
+ and an optional title view.
+
+ This view is not designed to have subviews added to it except via through its declared properties
+ (e.g. titleView).
+ */
+IB_DESIGNABLE
+@interface MDCNavigationBar : UIView
+
+#pragma mark Behavior
+
+/* Title displayed in the bar if titleView is unset. */
+@property(nonatomic, copy, nullable) NSString *title;
+
+/**
+ The title view layout differs from the traditional behavior of UINavigationBar.
+
+ Due to MDCNavigationBar being able to expand vertically, the titleView's height is updated to match
+ any changes in the MDCNavigationBar's height.
+
+ You may wish to create a container view that is able to manage subview layout if your situation
+ requires it.
+ */
+@property(nonatomic, strong, nullable) UIView *titleView;
+
+/**
+ Display attributes for the titleView's title text.
+
+ Setting this property will render an NSAttributedString with the assigned attributes across the
+ entire text.
+ */
+@property(nonatomic, copy, nullable)
+    NSDictionary<NSString *, id> *titleTextAttributes UI_APPEARANCE_SELECTOR;
+
+/** The back button to be displayed, if any. */
+@property(nonatomic, strong, nullable) UIBarButtonItem *backItem;
+
+/*  If YES, this navigation bar will hide the back button. */
+@property(nonatomic) BOOL hidesBackButton;
+
+/* Use these properties to set multiple items in a navigation bar.
+ The single properties (leadingBarButtonItem and trailingBarButtonItem) refer to the first item in
+ the respective array of items.
+
+ NOTE: You'll achieve the best results if you use either the singular properties or the plural
+ properties consistently and don't try to mix them.
+
+   leadingBarButtonItems are placed in the navigation bar from the leading edge to the trailing edge
+ with the first item in the list at the leading outside edge and leading aligned.
+   trailingBarButtonItems are placed from the trailing edge to the leading edge with the first item
+ in the list at the trailing outside edge and trailing aligned.
+ */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leadingBarButtonItems;
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *trailingBarButtonItems;
+
+/* By default, the leadingItemsSupplementBackButton property is NO. In this case, the back button is
+ not drawn and the leading item or items replace it. If you would like the leading items to appear
+ in addition to the back button (as opposed to instead of it) set leadingItemsSupplementBackButton
+ to YES.
+ */
+@property(nonatomic) BOOL leadingItemsSupplementBackButton;
+
+/*
+ Use these when you want to display a custom leading or trailing item in this navigation bar.
+ A custom leading item replaces the regular back button unless you set
+ leadingItemsSupplementBackButton to YES.
+ */
+@property(nonatomic, strong, nullable) UIBarButtonItem *leadingBarButtonItem;
+@property(nonatomic, strong, nullable) UIBarButtonItem *trailingBarButtonItem;
+
+/**
+ The horizontal text alignment of the navigation bar title. Defaults to
+ MDCNavigationBarTitleAlignmentLeading.
+ */
+@property(nonatomic) MDCNavigationBarTitleAlignment titleAlignment;
+
+#pragma mark Observing UINavigationItem instances
+
+/**
+ Begin observing changes to the provided navigation item.
+
+ Only one navigation item instance can be observed at a time. Observing a second navigation item
+ will stop observation of the first navigation item.
+
+ Once execution returns from this method the receiver's state will match that of the newly-observed
+ navigation item.
+
+ The observed navigation item is strongly held.
+ */
+- (void)observeNavigationItem:(nonnull UINavigationItem *)navigationItem;
+
+/**
+ Stop observing changes to the previously-observed navigation item.
+
+ Does nothing if no navigation item is being observed.
+ */
+- (void)unobserveNavigationItem;
+
+#pragma mark UINavigationItem interface matching
+
+/* Equivalent to leadingBarButtonItems. */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leftBarButtonItems;
+
+/* Equivalent to trailingBarButtonItems. */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *rightBarButtonItems;
+
+/* Equivalent to leadingBarButtonItem. */
+@property(nonatomic, strong, nullable) UIBarButtonItem *leftBarButtonItem;
+
+/* Equivalent to trailingBarButtonItem. */
+@property(nonatomic, strong, nullable) UIBarButtonItem *rightBarButtonItem;
+
+/* Equivalent to leadingItemsSupplementBackButton. */
+@property(nonatomic) BOOL leftItemsSupplementBackButton;
+
+/** The text alignment of the navigation bar title. Defaults to NSTextAlignmentLeft. */
+@property(nonatomic) NSTextAlignment textAlignment __deprecated_msg("Use titleAlignment instead.");
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.m
new file mode 100644
index 0000000..c40c3f1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.m
@@ -0,0 +1,722 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCNavigationBar.h"
+
+#import "MDFTextAccessibility.h"
+#import "MaterialButtonBar.h"
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+#import <objc/runtime.h>
+
+static inline CGFloat Ceil(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return ceil(value);
+#else
+  return ceilf(value);
+#endif
+}
+
+static inline CGFloat Floor(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return floor(value);
+#else
+  return floorf(value);
+#endif
+}
+
+static const CGFloat kNavigationBarDefaultHeight = 56;
+static const CGFloat kNavigationBarPadDefaultHeight = 64;
+static const UIEdgeInsets kTextInsets = {16, 16, 16, 16};
+static const UIEdgeInsets kTextPadInsets = {20, 16, 20, 16};
+
+// KVO contexts
+static char *const kKVOContextMDCNavigationBar = "kKVOContextMDCNavigationBar";
+
+static NSArray<NSString *> *MDCNavigationBarNavigationItemKVOPaths(void) {
+  static dispatch_once_t onceToken;
+  static NSArray<NSString *> *forwardingKeyPaths = nil;
+  dispatch_once(&onceToken, ^{
+    NSMutableArray<NSString *> *keyPaths = [NSMutableArray array];
+
+    Protocol *headerProtocol = @protocol(MDCUINavigationItemObservables);
+    unsigned int count = 0;
+    objc_property_t *propertyList = protocol_copyPropertyList(headerProtocol, &count);
+    if (propertyList) {
+      for (unsigned int ix = 0; ix < count; ++ix) {
+        [keyPaths addObject:[NSString stringWithFormat:@"%s", property_getName(propertyList[ix])]];
+      }
+      free(propertyList);
+    }
+
+    // Ensure that the plural bar button item key paths are listened to last, otherwise the
+    // non-plural variant will cause the extra bar button items to be lost. Fun!
+    NSArray<NSString *> *orderedKeyPaths = @[
+      NSStringFromSelector(@selector(leftBarButtonItems)),
+      NSStringFromSelector(@selector(rightBarButtonItems))
+    ];
+    [keyPaths removeObjectsInArray:orderedKeyPaths];
+    [keyPaths addObjectsFromArray:orderedKeyPaths];
+
+    forwardingKeyPaths = keyPaths;
+  });
+  return forwardingKeyPaths;
+}
+
+static NSString *const MDCNavigationBarTitleKey = @"MDCNavigationBarTitleKey";
+static NSString *const MDCNavigationBarTitleViewKey = @"MDCNavigationBarTitleViewKey";
+static NSString *const MDCNavigationBarTitleTextAttributesKey =
+    @"MDCNavigationBarTitleTextAttributesKey";
+static NSString *const MDCNavigationBarBackItemKey = @"MDCNavigationBarBackItemKey";
+static NSString *const MDCNavigationBarHidesBackButtonKey = @"MDCNavigationBarHidesBackButtonKey";
+static NSString *const MDCNavigationBarLeadingBarItemsKey = @"MDCNavigationBarLeadingBarItemsKey";
+static NSString *const MDCNavigationBarTrailingBarItemsKey = @"MDCNavigationBarTrailingBarItemsKey";
+static NSString *const MDCNavigationBarLeadingButtonSupplementsBackButtonKey =
+    @"MDCNavigationBarLeadingButtonSupplementsBackButtonKey";
+static NSString *const MDCNavigationBarTitleAlignmentKey = @"MDCNavigationBarTitleAlignmentKey";
+
+@implementation MDCNavigationBarTextColorAccessibilityMutator
+
+- (nonnull instancetype)init {
+  self = [super init];
+  return self;
+}
+
+- (void)mutate:(MDCNavigationBar *)navBar {
+  // Determine what is the appropriate background color
+  UIColor *backgroundColor = navBar.backgroundColor;
+  if (!backgroundColor) {
+    return;
+  }
+
+  // Update title label color based on navigationBar backgroundColor
+  NSMutableDictionary *textAttr =
+      [NSMutableDictionary dictionaryWithDictionary:[navBar titleTextAttributes]];
+  UIColor *textColor =
+      [MDFTextAccessibility textColorOnBackgroundColor:backgroundColor
+                                       targetTextAlpha:1.0
+                                                  font:[textAttr objectForKey:NSFontAttributeName]];
+  [textAttr setObject:textColor forKey:NSForegroundColorAttributeName];
+  [navBar setTitleTextAttributes:textAttr];
+
+  // Update button's tint color based on navigationBar backgroundColor
+  navBar.tintColor = textColor;
+}
+
+@end
+
+/**
+ Indiana Jones style placeholder view for UINavigationBar. Ownership of UIBarButtonItem.customView
+ and UINavigationItem.titleView are normally transferred to UINavigationController but we plan to
+ steal them away. In order to avoid crashing during KVO updates, we steal the view away and
+ replace it with a sandbag view.
+ */
+@interface MDCNavigationBarSandbagView : UIView
+@end
+
+@implementation MDCNavigationBarSandbagView
+@end
+
+@interface MDCNavigationBar (PrivateAPIs)
+
+- (UILabel *)titleLabel;
+- (MDCButtonBar *)leadingButtonBar;
+- (MDCButtonBar *)trailingButtonBar;
+
+@end
+
+@implementation MDCNavigationBar {
+  id _observedNavigationItemLock;
+  UINavigationItem *_observedNavigationItem;
+
+  UILabel *_titleLabel;
+
+  MDCButtonBar *_leadingButtonBar;
+  MDCButtonBar *_trailingButtonBar;
+
+  __weak UIViewController *_watchingViewController;
+}
+
+@synthesize leadingBarButtonItems = _leadingBarButtonItems;
+@synthesize trailingBarButtonItems = _trailingBarButtonItems;
+@synthesize hidesBackButton = _hidesBackButton;
+@synthesize leadingItemsSupplementBackButton = _leadingItemsSupplementBackButton;
+@synthesize titleView = _titleView;
+
+- (void)dealloc {
+  [self setObservedNavigationItem:nil];
+}
+
+- (void)commonMDCNavigationBarInit {
+  _observedNavigationItemLock = [[NSObject alloc] init];
+
+  _titleLabel = [[UILabel alloc] init];
+  _titleLabel.font = [MDCTypography titleFont];
+  _titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader;
+  _titleLabel.textAlignment = NSTextAlignmentCenter;
+  _leadingButtonBar = [[MDCButtonBar alloc] init];
+  _leadingButtonBar.layoutPosition = MDCButtonBarLayoutPositionLeading;
+  _trailingButtonBar = [[MDCButtonBar alloc] init];
+  _trailingButtonBar.layoutPosition = MDCButtonBarLayoutPositionTrailing;
+
+  [self addSubview:_titleLabel];
+  [self addSubview:_leadingButtonBar];
+  [self addSubview:_trailingButtonBar];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCNavigationBarInit];
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleKey]) {
+      self.title = [aDecoder decodeObjectForKey:MDCNavigationBarTitleKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleViewKey]) {
+      self.titleView = [aDecoder decodeObjectForKey:MDCNavigationBarTitleViewKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleTextAttributesKey]) {
+      self.titleTextAttributes =
+          [aDecoder decodeObjectForKey:MDCNavigationBarTitleTextAttributesKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarBackItemKey]) {
+      self.backItem = [aDecoder decodeObjectForKey:MDCNavigationBarBackItemKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarHidesBackButtonKey]) {
+      self.hidesBackButton = [aDecoder decodeBoolForKey:MDCNavigationBarHidesBackButtonKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarLeadingBarItemsKey]) {
+      self.leadingBarButtonItems = [aDecoder decodeObjectForKey:MDCNavigationBarLeadingBarItemsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTrailingBarItemsKey]) {
+      self.trailingBarButtonItems =
+          [aDecoder decodeObjectForKey:MDCNavigationBarTrailingBarItemsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarLeadingButtonSupplementsBackButtonKey]) {
+      self.leadingItemsSupplementBackButton =
+          [aDecoder decodeBoolForKey:MDCNavigationBarLeadingButtonSupplementsBackButtonKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleAlignmentKey]) {
+      self.titleAlignment = [aDecoder decodeIntegerForKey:MDCNavigationBarTitleAlignmentKey];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCNavigationBarInit];
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+
+  if (self.title) {
+    [aCoder encodeObject:self.title forKey:MDCNavigationBarTitleKey];
+  }
+
+  if (self.titleView) {
+    [aCoder encodeObject:self.titleView forKey:MDCNavigationBarTitleViewKey];
+  }
+
+  if (self.titleTextAttributes) {
+    [aCoder encodeObject:self.titleTextAttributes forKey:MDCNavigationBarTitleTextAttributesKey];
+  }
+
+  if (self.backItem) {
+    [aCoder encodeObject:self.backItem forKey:MDCNavigationBarBackItemKey];
+  }
+
+  [aCoder encodeBool:self.hidesBackButton forKey:MDCNavigationBarHidesBackButtonKey];
+
+  if (self.leadingBarButtonItems && self.leadingBarButtonItems.count > 0) {
+    [aCoder encodeObject:self.leadingBarButtonItems forKey:MDCNavigationBarLeadingBarItemsKey];
+  }
+
+  if (self.trailingBarButtonItems && self.trailingBarButtonItems.count > 0) {
+    [aCoder encodeObject:self.trailingBarButtonItems forKey:MDCNavigationBarTrailingBarItemsKey];
+  }
+
+  [aCoder encodeBool:self.leadingItemsSupplementBackButton
+              forKey:MDCNavigationBarLeadingButtonSupplementsBackButtonKey];
+  [aCoder encodeInteger:self.titleAlignment forKey:MDCNavigationBarTitleAlignmentKey];
+}
+
+#pragma mark Accessibility
+
+- (NSArray<__kindof UIView *> *)accessibilityElements {
+  return @[ _leadingButtonBar, self.titleView ?: _titleLabel, _trailingButtonBar ];
+}
+
+- (BOOL)isAccessibilityElement {
+  return NO;
+}
+
+- (NSInteger)accessibilityElementCount {
+  return self.accessibilityElements.count;
+}
+
+- (id)accessibilityElementAtIndex:(NSInteger)index {
+  return self.accessibilityElements[index];
+}
+
+- (NSInteger)indexOfAccessibilityElement:(id)element {
+  return [self.accessibilityElements indexOfObject:element];
+}
+
+#pragma mark UIView Overrides
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  CGSize leadingButtonBarSize = [_leadingButtonBar sizeThatFits:self.bounds.size];
+  CGRect leadingButtonBarFrame =
+      CGRectMake(0, self.bounds.origin.y, leadingButtonBarSize.width, leadingButtonBarSize.height);
+  _leadingButtonBar.frame = MDCRectFlippedForRTL(leadingButtonBarFrame, self.bounds.size.width,
+                                                 self.mdc_effectiveUserInterfaceLayoutDirection);
+
+  CGSize trailingButtonBarSize = [_trailingButtonBar sizeThatFits:self.bounds.size];
+  CGRect trailingButtonBarFrame =
+      CGRectMake(self.bounds.size.width - trailingButtonBarSize.width, self.bounds.origin.y,
+                 trailingButtonBarSize.width, trailingButtonBarSize.height);
+  _trailingButtonBar.frame = MDCRectFlippedForRTL(trailingButtonBarFrame, self.bounds.size.width,
+                                                  self.mdc_effectiveUserInterfaceLayoutDirection);
+
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+  UIEdgeInsets textInsets = isPad ? kTextPadInsets : kTextInsets;
+
+  CGRect textFrame = UIEdgeInsetsInsetRect(self.bounds, textInsets);
+  textFrame.origin.x += _leadingButtonBar.frame.size.width;
+  textFrame.size.width -= _leadingButtonBar.frame.size.width + _trailingButtonBar.frame.size.width;
+
+  NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
+  paraStyle.lineBreakMode = _titleLabel.lineBreakMode;
+
+  NSDictionary<NSString *, id> *attributes =
+      @{NSFontAttributeName : _titleLabel.font, NSParagraphStyleAttributeName : paraStyle};
+
+  CGSize titleSize = [_titleLabel.text boundingRectWithSize:textFrame.size
+                                                    options:NSStringDrawingTruncatesLastVisibleLine
+                                                 attributes:attributes
+                                                    context:NULL]
+                         .size;
+  titleSize.width = Ceil(titleSize.width);
+  titleSize.height = Ceil(titleSize.height);
+  CGRect titleFrame = CGRectMake(textFrame.origin.x, 0, titleSize.width, titleSize.height);
+  titleFrame = MDCRectFlippedForRTL(titleFrame, self.bounds.size.width,
+                                    self.mdc_effectiveUserInterfaceLayoutDirection);
+  UIControlContentVerticalAlignment titleVerticalAlignment = UIControlContentVerticalAlignmentTop;
+  CGRect alignedFrame = [self mdc_frameAlignedVertically:titleFrame
+                                            withinBounds:textFrame
+                                               alignment:titleVerticalAlignment];
+  _titleLabel.frame =
+      [self mdc_frameAlignedHorizontally:alignedFrame alignment:self.titleAlignment];
+  self.titleView.frame = textFrame;
+
+  // Button and title label alignment
+
+  CGFloat titleTextRectHeight =
+      [_titleLabel textRectForBounds:_titleLabel.bounds limitedToNumberOfLines:0].size.height;
+
+  if (_titleLabel.hidden || titleTextRectHeight <= 0) {
+    _leadingButtonBar.buttonTitleBaseline = 0;
+    _trailingButtonBar.buttonTitleBaseline = 0;
+  } else {
+    // Assumes that the title is center-aligned vertically.
+    CGFloat titleTextOriginY = (_titleLabel.frame.size.height - titleTextRectHeight) / 2;
+    CGFloat titleTextHeight = titleTextOriginY + titleTextRectHeight + _titleLabel.font.descender;
+    CGFloat titleBaseline = _titleLabel.frame.origin.y + titleTextHeight;
+    _leadingButtonBar.buttonTitleBaseline = titleBaseline;
+    _trailingButtonBar.buttonTitleBaseline = titleBaseline;
+  }
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  CGSize intrinsicContentSize = [self intrinsicContentSize];
+  return CGSizeMake(size.width, intrinsicContentSize.height);
+}
+
+- (CGSize)intrinsicContentSize {
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+  CGFloat height = (isPad ? kNavigationBarPadDefaultHeight : kNavigationBarDefaultHeight);
+  return CGSizeMake(UIViewNoIntrinsicMetric, height);
+}
+
+- (MDCNavigationBarTitleAlignment)titleAlignment {
+  return [MDCNavigationBar titleAlignmentFromTextAlignment:_titleLabel.textAlignment];
+}
+
+- (void)setTitleAlignment:(MDCNavigationBarTitleAlignment)titleAlignment {
+  _titleLabel.textAlignment = [MDCNavigationBar textAlignmentFromTitleAlignment:titleAlignment];
+  [self setNeedsLayout];
+}
+
+#pragma mark Private
+
++ (NSTextAlignment)textAlignmentFromTitleAlignment:(MDCNavigationBarTitleAlignment)titleAlignment {
+  switch (titleAlignment) {
+    case MDCNavigationBarTitleAlignmentCenter:
+      return NSTextAlignmentCenter;
+      break;
+    default:
+      NSAssert(NO, @"titleAlignment not understood: %li", (long)titleAlignment);
+    // Intentional fall through logic
+    case MDCNavigationBarTitleAlignmentLeading:
+      return NSTextAlignmentNatural;
+      break;
+  }
+}
+
++ (MDCNavigationBarTitleAlignment)titleAlignmentFromTextAlignment:(NSTextAlignment)textAlignment {
+  switch (textAlignment) {
+    default:
+      NSAssert(NO, @"textAlignment not supported: %li", (long)textAlignment);
+    // Intentional fall through logic
+    case NSTextAlignmentNatural:
+    case NSTextAlignmentLeft:
+      return MDCNavigationBarTitleAlignmentLeading;
+      break;
+    case NSTextAlignmentCenter:
+      return MDCNavigationBarTitleAlignmentCenter;
+      break;
+  }
+}
+
+- (UILabel *)titleLabel {
+  return _titleLabel;
+}
+
+- (MDCButtonBar *)leadingButtonBar {
+  return _leadingButtonBar;
+}
+
+- (MDCButtonBar *)trailingButtonBar {
+  return _trailingButtonBar;
+}
+
+#pragma mark KVO
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context {
+  if (context == kKVOContextMDCNavigationBar) {
+    void (^mainThreadWork)(void) = ^{
+      @synchronized(self->_observedNavigationItemLock) {
+        if (object != _observedNavigationItem) {
+          return;
+        }
+
+        [self setValue:[object valueForKey:keyPath] forKey:keyPath];
+      }
+    };
+
+    // Ensure that UIKit modifications occur on the main thread.
+    if ([NSThread isMainThread]) {
+      mainThreadWork();
+    } else {
+      [[NSOperationQueue mainQueue] addOperationWithBlock:mainThreadWork];
+    }
+
+  } else {
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+  }
+}
+
+#pragma mark Layout
+
+- (CGRect)mdc_frameAlignedVertically:(CGRect)frame
+                        withinBounds:(CGRect)bounds
+                           alignment:(UIControlContentVerticalAlignment)alignment {
+  switch (alignment) {
+    case UIControlContentVerticalAlignmentBottom:
+      return CGRectMake(frame.origin.x, CGRectGetMaxY(bounds) - frame.size.height, frame.size.width,
+                        frame.size.height);
+
+    case UIControlContentVerticalAlignmentCenter: {
+      CGFloat centeredY = Floor((bounds.size.height - frame.size.height) / 2) + bounds.origin.y;
+      return CGRectMake(frame.origin.x, centeredY, frame.size.width, frame.size.height);
+    }
+
+    case UIControlContentVerticalAlignmentTop: {
+      return CGRectMake(frame.origin.x, bounds.origin.y, frame.size.width, frame.size.height);
+    }
+
+    case UIControlContentVerticalAlignmentFill: {
+      return bounds;
+    }
+  }
+}
+
+- (CGRect)mdc_frameAlignedHorizontally:(CGRect)frame
+                             alignment:(MDCNavigationBarTitleAlignment)alignment {
+  switch (alignment) {
+    case MDCNavigationBarTitleAlignmentCenter:
+      return CGRectMake(CGRectGetMaxX(self.bounds) / 2 - frame.size.width / 2, frame.origin.y,
+                        frame.size.width, frame.size.height);
+
+    case MDCNavigationBarTitleAlignmentLeading:
+      return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+  }
+}
+
+- (NSArray<UIBarButtonItem *> *)mdc_buttonItemsForLeadingBar {
+  if (!self.leadingItemsSupplementBackButton && self.leadingBarButtonItems.count > 0) {
+    return self.leadingBarButtonItems;
+  }
+
+  NSMutableArray<UIBarButtonItem *> *buttonItems = [NSMutableArray array];
+  if (self.backItem && !self.hidesBackButton) {
+    [buttonItems addObject:self.backItem];
+  }
+  [buttonItems addObjectsFromArray:self.leadingBarButtonItems];
+  return buttonItems;
+}
+
+#pragma mark Colors
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  // Tint color should only modify interactive elements
+  _leadingButtonBar.tintColor = self.tintColor;
+  _trailingButtonBar.tintColor = self.tintColor;
+}
+
+#pragma mark Public
+
+- (void)setTitle:(NSString *)title {
+  // |self.titleTextAttributes| can only be set if |title| is set
+  if (self.titleTextAttributes && title.length > 0) {
+    _titleLabel.attributedText =
+        [[NSAttributedString alloc] initWithString:title attributes:_titleTextAttributes];
+  } else {
+    _titleLabel.text = title;
+  }
+  [self setNeedsLayout];
+}
+
+- (NSString *)title {
+  return _titleLabel.text;
+}
+
+- (void)setTitleView:(UIView *)titleView {
+  if (self.titleView == titleView) {
+    return;
+  }
+  // Ignore sandbag KVO events
+  if ([_observedNavigationItem.titleView isKindOfClass:[MDCNavigationBarSandbagView class]]) {
+    return;
+  }
+  [self.titleView removeFromSuperview];
+  _titleView = titleView;
+  [self addSubview:_titleView];
+
+  _titleLabel.hidden = _titleView != nil;
+
+  [self setNeedsLayout];
+
+  // Swap in the sandbag (so that UINavigationController won't steal our view)
+  if (titleView) {
+    _observedNavigationItem.titleView = [[MDCNavigationBarSandbagView alloc] init];
+  } else if (_observedNavigationItem.titleView) {
+    _observedNavigationItem.titleView = nil;
+  }
+}
+
+- (void)setTitleTextAttributes:(NSDictionary<NSString *, id> *)titleTextAttributes {
+  // If title dictionary is equivalent, no need to make changes
+  if ([_titleTextAttributes isEqualToDictionary:titleTextAttributes]) {
+    return;
+  }
+
+  // Copy attributes dictionary
+  _titleTextAttributes = [titleTextAttributes copy];
+  if (_titleLabel) {
+    // |_titleTextAttributes| can only be set if |self.title| is set
+    if (_titleTextAttributes && self.title.length > 0) {
+      // Set label text as newly created attributed string with attributes if non-nil
+      _titleLabel.attributedText =
+          [[NSAttributedString alloc] initWithString:self.title attributes:_titleTextAttributes];
+    } else {
+      // Otherwise set titleLabel text property
+      _titleLabel.text = self.title;
+    }
+    [self setNeedsLayout];
+  }
+}
+
+- (void)setLeadingBarButtonItems:(NSArray<UIBarButtonItem *> *)leadingBarButtonItems {
+  _leadingBarButtonItems = [leadingBarButtonItems copy];
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setTrailingBarButtonItems:(NSArray<UIBarButtonItem *> *)trailingBarButtonItems {
+  _trailingBarButtonItems = [trailingBarButtonItems copy];
+  _trailingButtonBar.items = _trailingBarButtonItems;
+  [self setNeedsLayout];
+}
+
+- (void)setLeadingBarButtonItem:(UIBarButtonItem *)leadingBarButtonItem {
+  self.leadingBarButtonItems = leadingBarButtonItem ? @[ leadingBarButtonItem ] : nil;
+}
+
+- (UIBarButtonItem *)leadingBarButtonItem {
+  return [self.leadingBarButtonItems firstObject];
+}
+
+- (void)setTrailingBarButtonItem:(UIBarButtonItem *)trailingBarButtonItem {
+  self.trailingBarButtonItems = trailingBarButtonItem ? @[ trailingBarButtonItem ] : nil;
+}
+
+- (UIBarButtonItem *)trailingBarButtonItem {
+  return [self.trailingBarButtonItems firstObject];
+}
+
+- (void)setBackBarButtonItem:(UIBarButtonItem *)backBarButtonItem {
+  self.backItem = backBarButtonItem;
+}
+
+- (UIBarButtonItem *)backBarButtonItem {
+  return self.backItem;
+}
+
+- (void)setBackItem:(UIBarButtonItem *)backItem {
+  if (_backItem == backItem) {
+    return;
+  }
+  _backItem = backItem;
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setHidesBackButton:(BOOL)hidesBackButton {
+  if (_hidesBackButton == hidesBackButton) {
+    return;
+  }
+  _hidesBackButton = hidesBackButton;
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setLeadingItemsSupplementBackButton:(BOOL)leadingItemsSupplementBackButton {
+  if (_leadingItemsSupplementBackButton == leadingItemsSupplementBackButton) {
+    return;
+  }
+  _leadingItemsSupplementBackButton = leadingItemsSupplementBackButton;
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setObservedNavigationItem:(UINavigationItem *)navigationItem {
+  @synchronized(_observedNavigationItemLock) {
+    if (navigationItem == _observedNavigationItem) {
+      return;
+    }
+
+    NSArray<NSString *> *keyPaths = MDCNavigationBarNavigationItemKVOPaths();
+    for (NSString *keyPath in keyPaths) {
+      [_observedNavigationItem removeObserver:self
+                                   forKeyPath:keyPath
+                                      context:kKVOContextMDCNavigationBar];
+    }
+
+    _observedNavigationItem = navigationItem;
+
+    NSKeyValueObservingOptions options =
+        (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial);
+    for (NSString *keyPath in keyPaths) {
+      [_observedNavigationItem addObserver:self
+                                forKeyPath:keyPath
+                                   options:options
+                                   context:kKVOContextMDCNavigationBar];
+    }
+  }
+}
+
+- (void)observeNavigationItem:(UINavigationItem *)navigationItem {
+  [self setObservedNavigationItem:navigationItem];
+}
+
+- (void)unobserveNavigationItem {
+  [self setObservedNavigationItem:nil];
+}
+
+#pragma mark UINavigationItem interface matching
+
+- (NSArray<UIBarButtonItem *> *)leftBarButtonItems {
+  return self.leadingBarButtonItems;
+}
+
+- (void)setLeftBarButtonItems:(NSArray<UIBarButtonItem *> *)leftBarButtonItems {
+  self.leadingBarButtonItems = leftBarButtonItems;
+}
+
+- (NSArray<UIBarButtonItem *> *)rightBarButtonItems {
+  return self.trailingBarButtonItems;
+}
+
+- (void)setRightBarButtonItems:(NSArray<UIBarButtonItem *> *)rightBarButtonItems {
+  self.trailingBarButtonItems = rightBarButtonItems;
+}
+
+- (UIBarButtonItem *)leftBarButtonItem {
+  return self.leadingBarButtonItem;
+}
+
+- (void)setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem {
+  self.leadingBarButtonItem = leftBarButtonItem;
+}
+
+- (UIBarButtonItem *)rightBarButtonItem {
+  return self.trailingBarButtonItem;
+}
+
+- (void)setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem {
+  self.trailingBarButtonItem = rightBarButtonItem;
+}
+
+- (BOOL)leftItemsSupplementBackButton {
+  return self.leadingItemsSupplementBackButton;
+}
+
+- (void)setLeftItemsSupplementBackButton:(BOOL)leftItemsSupplementBackButton {
+  self.leadingItemsSupplementBackButton = leftItemsSupplementBackButton;
+}
+
+#pragma mark deprecated
+
+- (void)setTextAlignment:(NSTextAlignment)textAlignment {
+  [self setTitleAlignment:[MDCNavigationBar titleAlignmentFromTextAlignment:textAlignment]];
+}
+
+- (NSTextAlignment)textAlignment {
+  return [MDCNavigationBar textAlignmentFromTitleAlignment:self.titleAlignment];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
new file mode 100644
index 0000000..f116c9d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCNavigationBar.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
new file mode 100644
index 0000000..23b988c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
@@ -0,0 +1,48 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Subclasses UIWindow to allow overlays to cover all content.
+
+ Overlays will be the full size of the screen, or when multitasking use all available screen space,
+ and will be rotated as appropriate based on device orientation. For performance, owners of overlay
+ views should set the @c hidden property to YES when the overlay is not in use.
+ */
+@interface MDCOverlayWindow : UIWindow
+
+/**
+ Notifies the window that the given overlay view should be shown.
+
+ Overlay owners must call this method to ensure that the overlay is actually displayed over the
+ window's primary content.
+
+ @param overlay The overlay being displayed.
+ @param level The UIWindowLevel to display the overlay on.
+ */
+- (void)activateOverlay:(UIView *)overlay withLevel:(UIWindowLevel)level;
+
+/**
+ Notifies the window that the given overlay is no longer active.
+
+ Overlay owners should still hide their overlay before calling this method.
+
+ @param overlay The overlay being displayed.
+ */
+- (void)deactivateOverlay:(UIView *)overlay;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.m
new file mode 100644
index 0000000..ef88d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.m
@@ -0,0 +1,282 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayWindow.h"
+
+#import <objc/runtime.h>
+
+#import "UIApplication+AppExtensions.h"
+
+/**
+ A container view for overlay views.
+
+ Used by MDCOverlayWindow, overlay views are added to the overlay window container when
+ @c activateOverlay is called and removed from the overlay window when @c deactivateOverlay is
+ called.
+ */
+@interface MDCOverlayWindowContainerView : UIView
+@end
+
+@interface MDCOverlayWindow ()
+
+@property(nonatomic, strong) NSMutableArray *overlays;
+@property(nonatomic, strong) MDCOverlayWindowContainerView *overlayView;
+
+// Forward declaration so that MDCOverlayWindowContainerView can call this method.
+- (void)noteOverlayRemoved:(UIView *)overlay;
+
+@end
+
+@implementation MDCOverlayWindowContainerView
+
+- (void)willRemoveSubview:(UIView *)subview {
+  [super willRemoveSubview:subview];
+
+  MDCOverlayWindow *window = (MDCOverlayWindow *)self.window;
+  [window noteOverlayRemoved:subview];
+}
+
+// Only allow a tap if it explicitly hit one of the overlays. Otherwise, behave as if this view
+// doesn't exist at all.
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+  UIView *hitView = [super hitTest:point withEvent:event];
+  return hitView == self ? nil : hitView;
+}
+
+@end
+
+@implementation MDCOverlayWindow
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    [self commonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonInit];
+  }
+  return self;
+}
+
+- (void)commonInit {
+  self.backgroundColor = [UIColor clearColor];
+
+  _overlays = [[NSMutableArray alloc] init];
+
+  _overlayView = [[MDCOverlayWindowContainerView alloc] initWithFrame:self.bounds];
+  _overlayView.autoresizingMask =
+      (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+  _overlayView.backgroundColor = [UIColor clearColor];
+  [self addSubview:_overlayView];
+
+  NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+  [nc addObserver:self
+         selector:@selector(handleRotationNotification:)
+             name:UIApplicationWillChangeStatusBarOrientationNotification
+           object:nil];
+
+  // Set a sane initial position.
+  [self updateOverlayViewForOrientation:[[UIApplication mdc_safeSharedApplication]
+                                            statusBarOrientation]];
+
+  // Set a sane hidden state.
+  [self updateOverlayHiddenState];
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark - Rotation
+
+- (void)updateOverlayViewForOrientation:(UIInterfaceOrientation)orientation {
+  // On iOS 8, the window orientation is corrected logically after transforms, so there is
+  // no need to apply this transform correction like we do for iOS 7 and below.
+  BOOL hasFixedCoordinateSpace = NO;
+  UIScreen *screen = [UIScreen mainScreen];
+  hasFixedCoordinateSpace = [screen respondsToSelector:@selector(fixedCoordinateSpace)];
+
+  if (!hasFixedCoordinateSpace) {
+    CGAffineTransform transform = CGAffineTransformIdentity;
+    BOOL swapBounds = NO;
+
+    switch (orientation) {
+      case UIInterfaceOrientationLandscapeLeft:
+        transform = CGAffineTransformMakeRotation((CGFloat)-M_PI_2);
+        swapBounds = YES;
+        break;
+      case UIInterfaceOrientationLandscapeRight:
+        transform = CGAffineTransformMakeRotation((CGFloat)M_PI_2);
+        swapBounds = YES;
+        break;
+      case UIInterfaceOrientationPortraitUpsideDown:
+        transform = CGAffineTransformMakeRotation((CGFloat)M_PI);
+        break;
+      case UIInterfaceOrientationPortrait:
+      default:
+        break;
+    }
+
+    CGRect bounds = self.bounds;
+
+    if (swapBounds) {
+      bounds = CGRectMake(0, 0, bounds.size.height, bounds.size.width);
+    }
+    self.overlayView.bounds = bounds;
+    self.overlayView.transform = transform;
+    [self.overlayView layoutIfNeeded];
+  }
+}
+
+// This method is called within an animation block, so we simply need to update the overlay view.
+- (void)handleRotationNotification:(NSNotification *)notification {
+  UIInterfaceOrientation orientation =
+      [notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
+  [self updateOverlayViewForOrientation:orientation];
+}
+
+#pragma mark - Window positioning
+
+// Regardless of what was added to this window, ensure that the overlay view is on top.
+- (void)didAddSubview:(UIView *)subview {
+  [super didAddSubview:subview];
+
+  [self bringSubviewToFront:self.overlayView];
+}
+
+#pragma mark - Overlay Activation
+
+- (void)updateOverlayHiddenState {
+  BOOL hasOverlays = [self.overlays count] > 0;
+  self.overlayView.hidden = !hasOverlays;
+  [self updateAccessibilityIsModal];
+}
+
+- (void)updateAccessibilityIsModal {
+  BOOL containsModal = NO;
+  for (UIView *overlay in self.overlays) {
+    if (overlay.accessibilityViewIsModal) {
+      containsModal = YES;
+      break;
+    }
+  }
+  self.overlayView.accessibilityViewIsModal = containsModal;
+}
+
+- (void)noteOverlayRemoved:(UIView *)overlay {
+  if (!overlay) {
+    return;
+  }
+
+  // If the overlay argument wasn't managed by us, don't do anything when it goes away.
+  if (![self.overlays containsObject:overlay]) {
+    return;
+  }
+
+  // Clean up the level information stored on the view.
+  [self removeLevelForOverlay:overlay];
+
+  // Stop tracking the overlay view.
+  [self.overlays removeObject:overlay];
+
+  // Show or hide ourself as needed.
+  [self updateOverlayHiddenState];
+}
+
+- (void)activateOverlay:(UIView *)overlay withLevel:(UIWindowLevel)level {
+  if (!overlay) {
+    return;
+  }
+
+  // Make sure the that the overlay is out of the view hierarchy, even our own (if this is a
+  // re-activation with a new level). If @c overlay is already in the overlay view, then this call
+  // will take care of cleaning up @c self.overlays, by way of @c noteOverlayRemoved:.
+  [overlay removeFromSuperview];
+
+  // Default to adding the overlay at the very end (on top) of all the other overlays. We'll check
+  // the existing overlays to see if this one needs to go in before.
+  __block NSUInteger insertionIndex = self.overlays.count;
+
+  // Because @c self.overlays is already sorted by level, we can pick the first index which has a
+  // level larger than @c level.
+  [self.overlays enumerateObjectsUsingBlock:^(UIView *existing, NSUInteger idx, BOOL *stop) {
+    UIWindowLevel existingLevel = [self windowLevelForOverlay:existing];
+    if (level < existingLevel) {
+      insertionIndex = idx;
+      *stop = YES;
+    }
+  }];
+
+  // Make sure that the overlay is as large as the overlay container view before adding it.
+  overlay.bounds = self.overlayView.bounds;
+  overlay.center = CGPointMake(CGRectGetMidX(overlay.bounds), CGRectGetMidY(overlay.bounds));
+  overlay.translatesAutoresizingMaskIntoConstraints = YES;
+  overlay.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
+  [self setLevel:level forOverlay:overlay];
+  [self.overlayView insertSubview:overlay atIndex:insertionIndex];
+  [self.overlays insertObject:overlay atIndex:insertionIndex];
+
+  [self updateOverlayHiddenState];
+}
+
+- (void)deactivateOverlay:(UIView *)overlay {
+  if (!overlay) {
+    return;
+  }
+
+  // If the overlay wasn't managed by us, don't do anything to deactivate it.
+  if (![self.overlays containsObject:overlay]) {
+    return;
+  }
+
+  // If @c overlay is already in the overlay view, then this call will take care of cleaning up
+  // @c self.overlays by way of @c noteOverlayRemoved:.
+  [overlay removeFromSuperview];
+}
+
+#pragma mark - Level Storage
+
+static char kLevelKey;
+
+- (UIWindowLevel)windowLevelForOverlay:(UIView *)overlay {
+  NSNumber *levelObject = objc_getAssociatedObject(self, &kLevelKey);
+  return [levelObject floatValue];
+}
+
+- (void)setLevel:(UIWindowLevel)level forOverlay:(UIView *)overlay {
+  NSNumber *levelObject = @(level);
+  objc_setAssociatedObject(overlay, &kLevelKey, levelObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (void)removeLevelForOverlay:(UIView *)overlay {
+  objc_setAssociatedObject(overlay, &kLevelKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
new file mode 100644
index 0000000..75d2373
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayWindow.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.h
new file mode 100644
index 0000000..723772c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.h
@@ -0,0 +1,129 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ A Material page control.
+
+ This control is designed to be a drop-in replacement for UIPageControl, but adhering to the
+ Material Design specifications for animation and layout.
+
+ The UIControlEventValueChanged control event is sent when the user changes the current page.
+
+ ### UIScrollViewDelegate
+
+ In order for the Page Control to respond correctly to scroll events set the scrollView.delegate to
+ your pageControl:
+
+   scrollView.delegate = pageControl;
+
+ or forward the UIScrollViewDelegate methods:
+
+   @c scrollViewDidScroll:
+   @c scrollViewDidEndDecelerating:
+   @c scrollViewDidEndScrollingAnimation:
+
+ */
+@interface MDCPageControl : UIControl <UIScrollViewDelegate>
+
+#pragma mark Managing the page
+
+/**
+ The number of page indicators in the control.
+
+ Negative values are clamped to 0.
+
+ The default value is 0.
+ */
+@property(nonatomic) NSInteger numberOfPages;
+
+/**
+ The current page indicator of the control.
+
+ See setCurrentPage:animated: for animated version.
+
+ Values outside the possible range are clamped within [0, numberOfPages-1].
+
+ The default value is 0.
+ */
+@property(nonatomic) NSInteger currentPage;
+
+/**
+ Sets the current page indicator of the control.
+
+ @param currentPage Index of the desired page indicator. Values outside the possible range are
+                    clamped within [0, numberOfPages-1].
+ @param animated    YES the change will be animated; otherwise, NO.
+ */
+- (void)setCurrentPage:(NSInteger)currentPage animated:(BOOL)animated;
+
+/**
+ A Boolean value that controls whether the page control is hidden when there is only one page.
+
+ The default value is NO.
+ */
+@property(nonatomic) BOOL hidesForSinglePage;
+
+#pragma mark Configuring the page colors
+
+/** The color of the non-current page indicators. */
+@property(nonatomic, strong, nullable) UIColor *pageIndicatorTintColor UI_APPEARANCE_SELECTOR;
+
+/** The color of the current page indicator. */
+@property(nonatomic, strong, nullable)
+    UIColor *currentPageIndicatorTintColor UI_APPEARANCE_SELECTOR;
+
+#pragma mark Configuring the page behavior
+
+/**
+ A Boolean value that controls when the current page is displayed.
+
+ If enabled, user interactions that cause the current page to change will not be visually
+ reflected until -updateCurrentPageDisplay is called.
+
+ The default value is NO.
+ */
+@property(nonatomic) BOOL defersCurrentPageDisplay;
+
+/**
+ Updates the page indicator to the current page.
+
+ This method is ignored if defersCurrentPageDisplay is NO.
+ */
+- (void)updateCurrentPageDisplay;
+
+#pragma mark Resizing the control
+
+/**
+ Returns the size required to accommodate the given number of pages.
+
+ @param pageCount The number of pages for which an estimated size should be returned.
+ */
+- (CGSize)sizeForNumberOfPages:(NSInteger)pageCount;
+
+#pragma mark UIScrollView interface
+
+/** The owner must call this to inform the control that scrolling has occurred. */
+- (void)scrollViewDidScroll:(nonnull UIScrollView *)scrollView;
+
+/** The owner must call this when the scrollView has ended its deleration. */
+- (void)scrollViewDidEndDecelerating:(nonnull UIScrollView *)scrollView;
+
+/** The owner must call this when the scrollView has ended its scrolling animation. */
+- (void)scrollViewDidEndScrollingAnimation:(nonnull UIScrollView *)scrollView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.m
new file mode 100644
index 0000000..193101e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.m
@@ -0,0 +1,520 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControl.h"
+
+#import "private/MDCPageControlIndicator.h"
+#import "private/MDCPageControlTrackLayer.h"
+#import "private/MaterialPageControlStrings.h"
+#import "private/MaterialPageControlStrings_table.h"
+
+#import <tgmath.h>
+
+// The Bundle for string resources.
+static NSString *const kMaterialPageControlBundle = @"MaterialPageControl.bundle";
+
+// The keypath for the content offset of a scrollview.
+static NSString *const kMaterialPageControlScrollViewContentOffset = @"bounds.origin";
+
+// Matches native UIPageControl minimum height.
+static const CGFloat kPageControlMinimumHeight = 37.0f;
+
+// Matches native UIPageControl indicator radius.
+static const CGFloat kPageControlIndicatorRadius = 3.5f;
+
+// Matches native UIPageControl indicator spacing margin.
+static const CGFloat kPageControlIndicatorMargin = kPageControlIndicatorRadius * 2.5;
+
+// Delay for revealing indicators staggered towards current page indicator.
+static const NSTimeInterval kPageControlIndicatorShowDelay = 0.04f;
+
+// Default indicator opacity.
+static const CGFloat kPageControlIndicatorDefaultOpacity = 0.5f;
+
+// Default white level for current page indicator color.
+static const CGFloat kPageControlCurrentPageIndicatorWhiteColor = 0.38f;
+
+// Default white level for page indicator color.
+static const CGFloat kPageControlPageIndicatorWhiteColor = 0.62f;
+
+// Normalize to [0,1] range.
+static inline CGFloat normalizeValue(CGFloat value, CGFloat minRange, CGFloat maxRange) {
+  CGFloat diff = maxRange - minRange;
+  return (diff > 0) ? ((value - minRange) / diff) : 0;
+}
+
+@implementation MDCPageControl {
+  UIView *_containerView;
+  NSMutableArray<MDCPageControlIndicator *> *_indicators;
+  NSMutableArray<NSValue *> *_indicatorPositions;
+  MDCPageControlIndicator *_animatedIndicator;
+  MDCPageControlTrackLayer *_trackLayer;
+  CGFloat _trackLength;
+  BOOL _isDeferredScrolling;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCPageControlInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCPageControlInit];
+  }
+  return self;
+}
+
+- (void)commonMDCPageControlInit {
+  CGFloat radius = kPageControlIndicatorRadius;
+  CGFloat topEdge = (CGFloat)(floor(CGRectGetHeight(self.bounds) - (radius * 2)) / 2);
+  CGRect containerFrame = CGRectMake(0, topEdge, CGRectGetWidth(self.bounds), radius * 2);
+  _containerView = [[UIView alloc] initWithFrame:containerFrame];
+
+  _trackLayer = [[MDCPageControlTrackLayer alloc] initWithRadius:radius];
+  [_containerView.layer addSublayer:_trackLayer];
+  _containerView.autoresizingMask =
+      UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
+      UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
+  [self addSubview:_containerView];
+
+  // Defaults.
+  _currentPage = 0;
+  _currentPageIndicatorTintColor =
+      [UIColor colorWithWhite:kPageControlCurrentPageIndicatorWhiteColor alpha:1];
+  _pageIndicatorTintColor = [UIColor colorWithWhite:kPageControlPageIndicatorWhiteColor alpha:1];
+
+  UITapGestureRecognizer *tapGestureRecognizer =
+      [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
+  [self addGestureRecognizer:tapGestureRecognizer];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  if (_hidesForSinglePage && [_indicators count] == 1) {
+    self.hidden = YES;
+    return;
+  }
+  self.hidden = NO;
+  for (MDCPageControlIndicator *indicator in _indicators) {
+    NSInteger indicatorIndex = [_indicators indexOfObject:indicator];
+    if (indicatorIndex == _currentPage) {
+      indicator.hidden = YES;
+    }
+    indicator.color = _pageIndicatorTintColor;
+  }
+  _animatedIndicator.color = _currentPageIndicatorTintColor;
+  _trackLayer.trackColor = _pageIndicatorTintColor;
+
+  // TODO(cjcox): Add back in RTL once we get the view category ready.
+  // This view must be mirrored by flipping instead of relayout, because we want to mirror
+  // the view itself, not its subviews.
+  //  if ([self class] == [MDCPageControl class]) {
+  //    [self mdc_flipViewForRTL];
+  //  }
+}
+
+- (void)setNumberOfPages:(NSInteger)numberOfPages {
+  _numberOfPages = MAX(0, numberOfPages);
+  _currentPage = MAX(0, MIN(_numberOfPages - 1, _currentPage));
+  [self resetControl];
+}
+
+- (void)setCurrentPage:(NSInteger)currentPage {
+  [self setCurrentPage:currentPage animated:NO];
+}
+
+- (void)setCurrentPage:(NSInteger)currentPage animated:(BOOL)animated {
+  [self setCurrentPage:currentPage animated:animated duration:0];
+}
+- (void)setCurrentPage:(NSInteger)currentPage
+              animated:(BOOL)animated
+              duration:(NSTimeInterval)duration {
+  currentPage = MAX(0, MIN(_numberOfPages - 1, currentPage));
+  NSInteger previousPage = _currentPage;
+  BOOL shouldReverse = (previousPage > currentPage);
+  _currentPage = currentPage;
+
+  if (animated) {
+    // Draw and extend track.
+    CGPoint startPoint = [_indicatorPositions[previousPage] CGPointValue];
+    CGPoint endPoint = [_indicatorPositions[currentPage] CGPointValue];
+    if (shouldReverse) {
+      startPoint = [_indicatorPositions[currentPage] CGPointValue];
+      endPoint = [_indicatorPositions[previousPage] CGPointValue];
+    }
+
+    // Remove track and reveal hidden indicators staggered towards current page indicator. Reveal
+    // indicators in reverse if scrolling to left.
+    void (^completionBlock)() = ^{
+      // We are using the delay to increase the time between the end of the extension of the track
+      // ahead of the dots movement and the contraction of the track under the dot at the
+      // destination.
+      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)),
+                     dispatch_get_main_queue(), ^{
+                       [_trackLayer removeTrackTowardsPoint:shouldReverse ? startPoint : endPoint
+                                                 completion:^{
+                                                   // Once track is removed, reveal indicators once
+                                                   // more to ensure
+                                                   // no hidden indicators remain.
+                                                   [self revealIndicatorsReversed:shouldReverse];
+                                                 }];
+                       [self revealIndicatorsReversed:shouldReverse];
+                     });
+    };
+
+    [_trackLayer drawAndExtendTrackFromStartPoint:startPoint
+                                       toEndPoint:endPoint
+                                       completion:completionBlock];
+  } else {
+    // If not animated, simply move indicator to new position and reset track.
+    CGPoint point = [_indicatorPositions[currentPage] CGPointValue];
+    [_animatedIndicator updateIndicatorTransformX:point.x - kPageControlIndicatorRadius];
+    [_trackLayer resetAtPoint:point];
+
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    [_indicators[previousPage] setHidden:NO];
+    [CATransaction commit];
+  }
+}
+
+- (void)setHidesForSinglePage:(BOOL)hidesForSinglePage {
+  _hidesForSinglePage = hidesForSinglePage;
+  [self setNeedsLayout];
+}
+
+- (CGSize)sizeForNumberOfPages:(NSInteger)pageCount {
+  CGFloat radius = kPageControlIndicatorRadius;
+  CGFloat margin = kPageControlIndicatorMargin;
+  CGFloat width = pageCount * ((radius * 2) + margin) - margin;
+  CGFloat height = MAX(kPageControlMinimumHeight, radius * 2);
+  return CGSizeMake(width, height);
+}
+
+- (BOOL)isPageIndexValid:(NSInteger)nextPage {
+  // Returns YES if next page is within bounds of page control. Otherwise NO.
+  return (nextPage >= 0 && nextPage < _numberOfPages);
+}
+
+#pragma mark - UIView(UIViewGeometry)
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return [self sizeForNumberOfPages:_numberOfPages];
+}
+
+#pragma mark - Colors
+
+- (void)setPageIndicatorTintColor:(UIColor *)pageIndicatorTintColor {
+  _pageIndicatorTintColor = pageIndicatorTintColor;
+  [self setNeedsLayout];
+}
+
+- (void)setCurrentPageIndicatorTintColor:(UIColor *)currentPageIndicatorTintColor {
+  _currentPageIndicatorTintColor = currentPageIndicatorTintColor;
+  [self setNeedsLayout];
+}
+
+#pragma mark - Scrolling
+
+- (NSInteger)scrolledPageNumber:(UIScrollView *)scrollView {
+  // Returns paged index of scrollView.
+  NSInteger unboundedPageNumber = lround(scrollView.contentOffset.x / scrollView.frame.size.width);
+  return MAX(0, MIN(_numberOfPages - 1, unboundedPageNumber));
+}
+
+- (CGFloat)scrolledPercentage:(UIScrollView *)scrollView {
+  // Returns scrolled percentage of scrollView from 0 to 1. If the scrollView has bounced past
+  // the edge of its content, it will return either a negative value or value above 1.
+  return normalizeValue(scrollView.contentOffset.x, 0,
+                        scrollView.contentSize.width - scrollView.frame.size.width);
+}
+
+#pragma mark - UIScrollViewDelegate Observers
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+  CGFloat scrolledPercentage = [self scrolledPercentage:scrollView];
+
+  // Detect if we are getting called from an animation block
+  if ([scrollView.layer.animationKeys containsObject:kMaterialPageControlScrollViewContentOffset]) {
+    CAAnimation *animation =
+        [scrollView.layer animationForKey:kMaterialPageControlScrollViewContentOffset];
+
+    // If the animation block has a delay it translates to the beginTime of the CAAnimation. We need
+    // to ensure that we delay our animation of the page control to keep in sync with the animation
+    // of the scrollView.contentOffset.
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animation.beginTime * NSEC_PER_SEC)),
+                   dispatch_get_main_queue(), ^{
+                     NSInteger currentPage = [self scrolledPageNumber:scrollView];
+                     [self setCurrentPage:currentPage animated:YES duration:animation.duration];
+
+                     CGFloat transformX = scrolledPercentage * _trackLength;
+                     [_animatedIndicator updateIndicatorTransformX:transformX
+                                                          animated:YES
+                                                          duration:animation.duration
+                                               mediaTimingFunction:animation.timingFunction];
+                   });
+
+  } else if (scrolledPercentage >= 0 && scrolledPercentage <= 1) {
+    // Update active indicator position.
+    CGFloat transformX = scrolledPercentage * _trackLength;
+    if (!_isDeferredScrolling) {
+      [_animatedIndicator updateIndicatorTransformX:transformX];
+    }
+
+    // Determine endpoints for drawing track depending on direction scrolled.
+    NSInteger scrolledPageNumber = [self scrolledPageNumber:scrollView];
+    CGPoint startPoint = [_indicatorPositions[scrolledPageNumber] CGPointValue];
+    CGPoint endPoint = startPoint;
+    CGFloat radius = kPageControlIndicatorRadius;
+    if (transformX > startPoint.x - radius) {
+      endPoint = [_indicatorPositions[scrolledPageNumber + 1] CGPointValue];
+    } else if (transformX < startPoint.x - radius) {
+      startPoint = [_indicatorPositions[scrolledPageNumber - 1] CGPointValue];
+    }
+
+    if (scrollView.isDragging) {
+      // Draw or extend track.
+      if (_trackLayer.isTrackHidden) {
+        [_trackLayer drawTrackFromStartPoint:startPoint toEndPoint:endPoint];
+      } else {
+        [_trackLayer extendTrackFromStartPoint:startPoint toEndPoint:endPoint];
+      }
+    }
+
+    // Hide indicators to be shown with animated reveal once track is removed.
+    if (!_isDeferredScrolling) {
+      [_indicators[scrolledPageNumber] setHidden:YES];
+    }
+  }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+  // Remove track towards current active indicator position.
+  NSInteger scrolledPageNumber = [self scrolledPageNumber:scrollView];
+  CGPoint point = [_indicatorPositions[scrolledPageNumber] CGPointValue];
+  BOOL shouldReverse = (_currentPage > scrolledPageNumber);
+  BOOL sendAction = (_currentPage != scrolledPageNumber);
+  _currentPage = scrolledPageNumber;
+
+  [_trackLayer removeTrackTowardsPoint:point
+                            completion:^{
+                              // Animate hidden indicators once more when completed to ensure all
+                              // indicators
+                              // have been revealed.
+                              [self revealIndicatorsReversed:shouldReverse];
+                            }];
+
+  // Animate hidden indicators staggered towards current page indicator. Show indicators
+  // in reverse if scrolling to left.
+  [self revealIndicatorsReversed:shouldReverse];
+
+  // Send notification if new scrolled page.
+  if (sendAction) {
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
+  _isDeferredScrolling = NO;
+  NSInteger scrolledPageNumber = [self scrolledPageNumber:scrollView];
+  BOOL shouldReverse = (_currentPage > scrolledPageNumber);
+  _currentPage = scrolledPageNumber;
+  [self revealIndicatorsReversed:shouldReverse];
+}
+
+#pragma mark - Indicators
+
+- (void)revealIndicatorsReversed:(BOOL)reversed {
+  // Animate hidden indicators staggered with delay.
+  NSArray<MDCPageControlIndicator *> *indicators =
+      reversed ? [[_indicators reverseObjectEnumerator] allObjects] : _indicators;
+  NSInteger count = 0;
+  for (MDCPageControlIndicator *indicator in indicators) {
+    // Determine if this is the current page indicator.
+    NSInteger indicatorIndex = [indicators indexOfObject:indicator];
+    if (reversed) {
+      indicatorIndex = [indicators count] - 1 - indicatorIndex;
+    }
+    BOOL isCurrentPageIndicator = indicatorIndex == _currentPage;
+
+    // Reveal indicators if hidden and not current page indicator.
+    if (indicator.isHidden && !isCurrentPageIndicator) {
+      dispatch_time_t popTime = dispatch_time(
+          DISPATCH_TIME_NOW, (int64_t)(kPageControlIndicatorShowDelay * count * NSEC_PER_SEC));
+      dispatch_after(popTime, dispatch_get_main_queue(), ^{
+        [indicator revealIndicator];
+      });
+      count++;
+    }
+  }
+}
+
+#pragma mark - UIGestureRecognizer
+
+- (void)handleTapGesture:(UITapGestureRecognizer *)gesture {
+  CGPoint touchPoint = [gesture locationInView:self];
+  BOOL willDecrement = touchPoint.x < CGRectGetMidX(self.bounds);
+  NSInteger nextPage;
+  if (willDecrement) {
+    nextPage = _currentPage - 1;
+  } else {
+    nextPage = _currentPage + 1;
+  }
+
+  // Quit if scrolling past bounds.
+  if ([self isPageIndexValid:nextPage]) {
+    if (_defersCurrentPageDisplay) {
+      _isDeferredScrolling = YES;
+      _currentPage = nextPage;
+    } else {
+      [self setCurrentPage:nextPage animated:YES];
+    }
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+- (void)updateCurrentPageDisplay {
+  // If _defersCurrentPageDisplay = YES, then update control only when this method is called.
+  if (_defersCurrentPageDisplay && [self isPageIndexValid:_currentPage]) {
+    [self setCurrentPage:_currentPage];
+
+    // Reset hidden state of indicators.
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    for (int i = 0; i < _numberOfPages; i++) {
+      MDCPageControlIndicator *indicator = _indicators[i];
+      indicator.hidden = (i == _currentPage) ? YES : NO;
+    }
+    [CATransaction commit];
+  }
+}
+
+#pragma mark - Accessibility
+
+- (BOOL)isAccessibilityElement {
+  return YES;
+}
+
+- (NSString *)accessibilityLabel {
+  return
+      [[self class] pageControlAccessibilityLabelWithPage:_currentPage + 1 ofPages:_numberOfPages];
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  return UIAccessibilityTraitAdjustable;
+}
+
+- (void)accessibilityIncrement {
+  // Quit if scrolling past bounds.
+  NSInteger nextPage = _currentPage + 1;
+  if ([self isPageIndexValid:nextPage]) {
+    [self setCurrentPage:nextPage animated:YES];
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    [self accessibilityLabel]);
+  }
+}
+
+- (void)accessibilityDecrement {
+  // Quit if scrolling past bounds.
+  NSInteger nextPage = _currentPage - 1;
+  if ([self isPageIndexValid:nextPage]) {
+    [self setCurrentPage:nextPage animated:YES];
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    [self accessibilityLabel]);
+  }
+}
+
+#pragma mark - Private
+
+- (void)resetControl {
+  // Clear indicators.
+  for (CALayer *layer in [_containerView.layer.sublayers copy]) {
+    if (layer != _trackLayer) {
+      [layer removeFromSuperlayer];
+    }
+  }
+  _indicators = [NSMutableArray arrayWithCapacity:_numberOfPages];
+  _indicatorPositions = [NSMutableArray arrayWithCapacity:_numberOfPages];
+
+  // Create indicators.
+  CGFloat radius = kPageControlIndicatorRadius;
+  CGFloat margin = kPageControlIndicatorMargin;
+  for (int i = 0; i < _numberOfPages; i++) {
+    CGFloat offsetX = i * (margin + (radius * 2));
+    CGFloat offsetY = radius;
+    CGPoint center = CGPointMake(offsetX + radius, offsetY);
+    MDCPageControlIndicator *indicator =
+        [[MDCPageControlIndicator alloc] initWithCenter:center radius:radius];
+    indicator.opacity = kPageControlIndicatorDefaultOpacity;
+    [_containerView.layer addSublayer:indicator];
+    [_indicators addObject:indicator];
+    [_indicatorPositions addObject:[NSValue valueWithCGPoint:indicator.position]];
+  }
+
+  // Resize container view to keep indicators centered.
+  CGFloat frameWidth = _containerView.frame.size.width;
+  CGSize controlSize = [self sizeForNumberOfPages:_numberOfPages];
+  _containerView.frame = CGRectInset(_containerView.frame, (frameWidth - controlSize.width) / 2, 0);
+  _trackLength = CGRectGetWidth(_containerView.frame) - (radius * 2);
+
+  // Add animated indicator that will travel freely across the container. Its transform will be
+  // updated by calling its -updateIndicatorTransformX method.
+  CGPoint center = CGPointMake(radius, radius);
+  _animatedIndicator = [[MDCPageControlIndicator alloc] initWithCenter:center radius:radius];
+  [_containerView.layer addSublayer:_animatedIndicator];
+
+  [self setNeedsLayout];
+}
+
+#pragma mark - Strings
+
++ (NSString *)pageControlAccessibilityLabelWithPage:(NSInteger)currentPage
+                                            ofPages:(NSInteger)ofPages {
+  NSString *key = kMaterialPageControlStringTable[kStr_MaterialPageControlAccessibilityLabel];
+  NSString *localizedString = NSLocalizedStringFromTableInBundle(
+      key, kMaterialPageControlStringsTableName, [self bundle], @"page {number} of {total number}");
+  return [NSString localizedStringWithFormat:localizedString, currentPage, ofPages];
+}
+
+#pragma mark - Resource bundle
+
++ (NSBundle *)bundle {
+  static NSBundle *bundle = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    bundle = [NSBundle bundleWithPath:[self bundlePathWithName:kMaterialPageControlBundle]];
+  });
+
+  return bundle;
+}
+
++ (NSString *)bundlePathWithName:(NSString *)bundleName {
+  // In iOS 8+, we could be included by way of a dynamic framework, and our resource bundles may
+  // not be in the main .app bundle, but rather in a nested framework, so figure out where we live
+  // and use that as the search location.
+  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+  NSString *resourcePath = [(nil == bundle ? [NSBundle mainBundle] : bundle)resourcePath];
+  return [resourcePath stringByAppendingPathComponent:bundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.bundle/Resources/en.lproj/MaterialPageControl.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.bundle/Resources/en.lproj/MaterialPageControl.strings
new file mode 100644
index 0000000..973bb5b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.bundle/Resources/en.lproj/MaterialPageControl.strings
@@ -0,0 +1,2 @@
+/* Accessibility label for page control. Example: "page 1 of 4". */
+"MaterialPageControlAccessibilityLabel" = "page %1$zd of %2$zd";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.h
new file mode 100644
index 0000000..b488b9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControl.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h
new file mode 100644
index 0000000..54660df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h
@@ -0,0 +1,61 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIKit.h>
+
+/**
+ This shape layer provides a circular indicator denoting a page in a page control.
+
+ @internal
+ */
+@interface MDCPageControlIndicator : CAShapeLayer
+
+/** The color of the indicator. */
+@property(nonatomic, strong) UIColor *color;
+
+/**
+ Default initializer.
+
+ @param center The layer position for this indicator.
+ @param radius The radius of this indicator circle.
+ */
+- (instancetype)initWithCenter:(CGPoint)center radius:(CGFloat)radius NS_DESIGNATED_INITIALIZER;
+
+/** Reveals the indicator by scaling from zero to full size while fading in. */
+- (void)revealIndicator;
+
+/**
+ Updates the indicator transform.x property along the track by the designated percentage.
+
+ @param transformX The transform.x value.
+ */
+- (void)updateIndicatorTransformX:(CGFloat)transformX;
+
+/**
+ Updates the indicator transform.x property along the track by the designated percentage.
+
+ @param transformX The transform.x value.
+ @param animated The whether to animate the change.
+ @param duration The duration of the animation.
+ @param timingFunction The timing function to use when animating the value.
+ */
+- (void)updateIndicatorTransformX:(CGFloat)transformX
+                         animated:(BOOL)animated
+                         duration:(NSTimeInterval)duration
+              mediaTimingFunction:(CAMediaTimingFunction *)timingFunction;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.m
new file mode 100644
index 0000000..79cba9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.m
@@ -0,0 +1,104 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControlIndicator.h"
+
+static const NSTimeInterval kPageControlIndicatorAnimationDuration = 0.3;
+static NSString *const kPageControlIndicatorAnimationKey = @"fadeInScaleUp";
+
+@implementation MDCPageControlIndicator {
+  BOOL _isAnimating;
+}
+
+- (instancetype)initWithCenter:(CGPoint)center radius:(CGFloat)radius {
+  self = [super init];
+  if (self) {
+    self.frame = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
+    self.path = [self circlePathWithRadius:radius];
+    self.zPosition = 1;
+  }
+  return self;
+}
+
+- (void)setColor:(UIColor *)color {
+  // Override here to disable implicit layer animation.
+  _color = color;
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  CGColorRef cgColor = _color.CGColor;
+  self.fillColor = cgColor;
+  [super setOpacity:(float)CGColorGetAlpha(cgColor)];
+  [CATransaction commit];
+}
+
+- (void)setOpacity:(float)opacity {
+  // Override here to disable implicit layer animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  [super setOpacity:opacity];
+  [CATransaction commit];
+}
+
+- (void)revealIndicator {
+  // Scale indicator from zero to full size while fading in.
+  CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+  scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.0, 0.0, 0.0)];
+  scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
+
+  CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+  fadeAnimation.fromValue = @(0);
+  fadeAnimation.toValue = @(self.opacity);
+
+  CAAnimationGroup *group = [CAAnimationGroup animation];
+  group.duration = kPageControlIndicatorAnimationDuration;
+  group.fillMode = kCAFillModeForwards;
+  group.removedOnCompletion = YES;
+  group.animations = @[ scaleAnimation, fadeAnimation ];
+  [self addAnimation:group forKey:kPageControlIndicatorAnimationKey];
+
+  // Default value.
+  self.hidden = NO;
+}
+
+- (void)updateIndicatorTransformX:(CGFloat)transformX
+                         animated:(BOOL)animated
+                         duration:(NSTimeInterval)duration
+              mediaTimingFunction:(CAMediaTimingFunction *)timingFunction {
+  [CATransaction begin];
+  [CATransaction setDisableActions:!animated];
+  [CATransaction setAnimationDuration:duration];
+  [CATransaction setAnimationTimingFunction:timingFunction];
+  self.transform = CATransform3DMakeTranslation(transformX, 0, 0);
+  [CATransaction commit];
+}
+
+- (void)updateIndicatorTransformX:(CGFloat)transformX {
+  // Disable animation of this transform.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  self.transform = CATransform3DMakeTranslation(transformX, 0, 0);
+  [CATransaction commit];
+}
+
+#pragma mark - Private
+
+- (CGPathRef)circlePathWithRadius:(CGFloat)radius {
+  return [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, radius * 2, radius * 2)
+                                    cornerRadius:radius]
+      .CGPath;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h
new file mode 100644
index 0000000..ddddcc7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h
@@ -0,0 +1,87 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIKit.h>
+
+/**
+ This shape layer provides a rounded rectangular track on which a page indicator can travel
+ between subsequent indicators. The track animates on appearance, removal, and when its
+ end points are updated.
+
+ @internal
+ */
+@interface MDCPageControlTrackLayer : CAShapeLayer
+
+/** The color of the indicator track. */
+@property(nonatomic, strong) UIColor *trackColor;
+
+/** A Boolean value indicating whether the track is hidden. */
+@property(nonatomic, readonly, getter=isTrackHidden) BOOL trackHidden;
+
+/**
+ Default initializer.
+
+ @param radius The radius of this indicator and track edges.
+ */
+- (instancetype)initWithRadius:(CGFloat)radius NS_DESIGNATED_INITIALIZER;
+
+/**
+ Draws a track with animation from the startpoint to endpoint.
+
+ @param startPoint The start point of the track.
+ @param endPoint The end point of the track.
+ */
+- (void)drawTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint;
+
+/**
+ Extends the visible track with animation to encompass the startpoint and endpoint.
+
+ @param startPoint The start point of the track.
+ @param endPoint The end point of the track.
+ */
+- (void)extendTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint;
+
+/**
+ Draws a track and extends it with animation to encompass the startpoint and endpoint. This
+ method should be called when an immediate track needs to be drawn and extended without
+ waiting for the draw animation. A typical use case is when called programmatically as
+ opposed to user gesture driven.
+
+ @param startPoint The start point of the track.
+ @param endPoint The end point of the track.
+ @param completion A block to execute when the presentation is finished.
+ */
+- (void)drawAndExtendTrackFromStartPoint:(CGPoint)startPoint
+                              toEndPoint:(CGPoint)endPoint
+                              completion:(void (^)())completion;
+
+/**
+ Removes the track with animation towards the designated point.
+
+ @param point The point the track should animate towards.
+ @param completion A block to execute when the presentation is finished.
+ */
+- (void)removeTrackTowardsPoint:(CGPoint)point completion:(void (^)())completion;
+
+/**
+ Resets the track with animation to the designated point.
+
+ @param point The point the track should be set to.
+ */
+- (void)resetAtPoint:(CGPoint)point;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.m
new file mode 100644
index 0000000..ae195c9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.m
@@ -0,0 +1,286 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControlTrackLayer.h"
+
+static const NSTimeInterval kPageControlAnimationDuration = 0.2;
+static const NSInteger kPageControlKeyframeCount = 2;
+static NSString *const kPageControlAnimationKeyDraw = @"drawTrack";
+
+@implementation MDCPageControlTrackLayer {
+  CGFloat _radius;
+  CGPoint _startPoint, _endPoint, _midPoint;
+  BOOL _isAnimating;
+}
+
+- (instancetype)initWithRadius:(CGFloat)radius {
+  self = [super init];
+  if (self) {
+    _trackHidden = YES;
+    _radius = radius;
+    self.cornerRadius = radius;
+  }
+  return self;
+}
+
+- (void)setTrackColor:(UIColor *)trackColor {
+  _trackColor = trackColor;
+  self.fillColor = trackColor.CGColor;
+  self.backgroundColor = trackColor.CGColor;
+}
+
+#pragma mark - Draw/Extend Track
+
+- (void)drawTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint {
+  if (_isAnimating || !_trackHidden || [self isPointZero:startPoint] ||
+      [self isPointZero:endPoint]) {
+    return;
+  }
+
+  // First reset track frame.
+  [self resetTrackFrame];
+
+  _isAnimating = YES;
+  _startPoint = startPoint;
+  _endPoint = endPoint;
+  _midPoint = [self midPointFromPoint:startPoint toPoint:endPoint];
+  [self resetHidden:NO];
+
+  [CATransaction begin];
+  [CATransaction setCompletionBlock:^{
+    // After drawn, remove animation and update track frame.
+    [self removeAnimationForKey:kPageControlAnimationKeyDraw];
+    [self updateTrackFrameWithAnimation:NO completion:nil];
+    _trackHidden = NO;
+    _isAnimating = NO;
+  }];
+
+  // Get animation keyframes.
+  NSMutableArray<UIBezierPath *> *values = [NSMutableArray array];
+  for (NSInteger i = 0; i < kPageControlKeyframeCount; i++) {
+    [values addObject:(id)[self pathAtKeyframe:i]];
+  }
+
+  // Add animation path.
+  CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
+  animation.duration = kPageControlAnimationDuration;
+  animation.removedOnCompletion = NO;
+  animation.fillMode = kCAFillModeForwards;
+  animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
+  animation.values = values;
+  [self addAnimation:animation forKey:kPageControlAnimationKeyDraw];
+  [CATransaction commit];
+}
+
+- (void)extendTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint {
+  if (_trackHidden || [self isPointZero:startPoint] || [self isPointZero:endPoint]) {
+    return;
+  }
+
+  // Extend track to encompass minimum startPoint and maximum endPoint.
+  _startPoint = (startPoint.x < _startPoint.x) ? startPoint : _startPoint;
+  _endPoint = (endPoint.x > _endPoint.x) ? endPoint : _endPoint;
+  [self updateTrackFrameWithAnimation:YES completion:nil];
+}
+
+- (void)drawAndExtendTrackFromStartPoint:(CGPoint)startPoint
+                              toEndPoint:(CGPoint)endPoint
+                              completion:(void (^)())completion {
+  _trackHidden = NO;
+  if ([self isPointZero:_startPoint]) {
+    // If no previous start point, first set frame without animation.
+    _startPoint = startPoint;
+    _endPoint = endPoint;
+    [self updateTrackFrameWithAnimation:NO
+                             completion:^{
+                               [self updateTrackFrameWithAnimation:YES
+                                                        completion:^{
+                                                          if (completion) {
+                                                            completion();
+                                                          }
+                                                        }];
+                             }];
+  } else {
+    // Previous startPoint exists, therefore animate to new start and end points.
+    _startPoint = startPoint;
+    _endPoint = endPoint;
+    [self updateTrackFrameWithAnimation:YES
+                             completion:^{
+                               if (completion) {
+                                 completion();
+                               }
+                             }];
+  }
+}
+
+- (void)updateTrackFrameWithAnimation:(BOOL)animated completion:(void (^)())completion {
+  // Set track frame without implicit animation.
+  [self resetHidden:NO];
+  [CATransaction begin];
+  [CATransaction setDisableActions:!animated];
+  [CATransaction setCompletionBlock:^{
+    if (completion) {
+      completion();
+    }
+  }];
+  self.frame = CGRectMake(_startPoint.x - _radius, _startPoint.y - _radius,
+                          _endPoint.x - _startPoint.x + (_radius * 2), _radius * 2);
+  [CATransaction commit];
+}
+
+- (void)resetTrackFrame {
+  // Reset track frame without implicit animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  self.frame = CGRectZero;
+  [CATransaction commit];
+}
+
+- (void)resetHidden:(BOOL)hidden {
+  // Reset hidden without implicit animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  self.hidden = hidden;
+  [CATransaction commit];
+}
+
+#pragma mark - Remove Track
+
+- (void)removeTrackTowardsPoint:(CGPoint)point completion:(void (^)())completion {
+  // Animate the track removal towards a single point.
+  _startPoint = point;
+  _endPoint = point;
+  [self updateTrackFrameWithAnimation:YES
+                           completion:^{
+                             [self reset];
+                             if (completion) {
+                               completion();
+                             }
+                           }];
+}
+
+- (void)resetAtPoint:(CGPoint)point {
+  // Resets the track at single point without animation.
+  _startPoint = point;
+  _endPoint = point;
+  [self updateTrackFrameWithAnimation:NO
+                           completion:^{
+                             [self reset];
+                           }];
+}
+
+- (void)reset {
+  // Reset track frame without implicit animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  [self removeAllAnimations];
+  _isAnimating = NO;
+  _trackHidden = YES;
+  [self resetHidden:YES];
+  [CATransaction commit];
+}
+
+#pragma mark - Private
+
+- (CGPoint)midPointFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
+  // Returns midpoint between two points.
+  return CGPointMake((fromPoint.x + toPoint.x) / 2, (fromPoint.y + toPoint.y) / 2);
+}
+
+- (CGPathRef)pathAtKeyframe:(NSInteger)keyframe {
+  // Generates bezier path keyframes that can be animated forward and in reverse.
+  CGFloat r = _radius;
+  CGFloat d = _radius * 2;
+  UIBezierPath *bezierPath = UIBezierPath.bezierPath;
+
+  if (keyframe == 0) {
+    // Create circles at start and end points.
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_startPoint];
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_endPoint];
+
+    // Create an arc from top of startpoint circle to midpoint.
+    [bezierPath
+        moveToPoint:[self pointOnCircleWithRadius:r angleInDegrees:300.0f origin:_startPoint]];
+    [bezierPath addQuadCurveToPoint:_midPoint controlPoint:CGPointMake(_midPoint.x - r / 2, r)];
+
+    // Create an arc from midpoint to top of endpoint circle.
+    [bezierPath
+        addQuadCurveToPoint:[self pointOnCircleWithRadius:r angleInDegrees:240.0f origin:_endPoint]
+               controlPoint:CGPointMake(_midPoint.x + r / 2, r)];
+
+    // Create a line from top of endpoint circle to bottom of endpoint circle.
+    [bezierPath
+        addLineToPoint:[self pointOnCircleWithRadius:r angleInDegrees:120.0f origin:_endPoint]];
+
+    // Create an arc from bottom of endpoint circle to midpoint.
+    [bezierPath addQuadCurveToPoint:_midPoint controlPoint:CGPointMake(_midPoint.x + r / 2, r)];
+
+    // Create an arc from midpoint to bottom of startpoint circle.
+    [bezierPath
+        addQuadCurveToPoint:[self pointOnCircleWithRadius:r angleInDegrees:60.0f origin:_startPoint]
+               controlPoint:CGPointMake(_midPoint.x - r / 2, r)];
+
+    // Create line from bottom of startpoint circle to top of startpoint circle.
+    [bezierPath
+        addLineToPoint:[self pointOnCircleWithRadius:r angleInDegrees:300.0f origin:_startPoint]];
+
+    // Close path.
+    [bezierPath closePath];
+
+  } else if (keyframe == 1) {
+    // Creates rectangular path from startpoint to endpoint with rounded ends.
+    // Requires same number of paths as previous keyframe to animate properly.
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_startPoint];
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_endPoint];
+    [bezierPath moveToPoint:CGPointMake(_startPoint.x, 0)];
+    [bezierPath addLineToPoint:CGPointMake(_midPoint.x, 0)];
+    [bezierPath addLineToPoint:CGPointMake(_endPoint.x, 0)];
+    [bezierPath addLineToPoint:CGPointMake(_endPoint.x, d)];
+    [bezierPath addLineToPoint:CGPointMake(_midPoint.x, d)];
+    [bezierPath addLineToPoint:CGPointMake(_startPoint.x, d)];
+    [bezierPath closePath];
+  }
+  return bezierPath.CGPath;
+}
+
+- (void)addRoundedEndpontToBezierPath:(UIBezierPath *)bezierPath atPoint:(CGPoint)point {
+  // Creates a closed circle at designated point.
+  [bezierPath moveToPoint:CGPointMake(point.x, _radius * 2)];
+  [bezierPath addArcWithCenter:point
+                        radius:_radius
+                    startAngle:0
+                      endAngle:[self degreesToRadians:360]
+                     clockwise:YES];
+}
+
+- (CGPoint)pointOnCircleWithRadius:(CGFloat)radius
+                    angleInDegrees:(CGFloat)angleInDegrees
+                            origin:(CGPoint)origin {
+  // Returns a point along a circles edge at given angle.
+  CGFloat locationX = (CGFloat)(radius * cos([self degreesToRadians:angleInDegrees])) + origin.x;
+  CGFloat locationY = (CGFloat)(radius * sin([self degreesToRadians:angleInDegrees])) + origin.y;
+  return CGPointMake(locationX, locationY);
+}
+
+- (CGFloat)degreesToRadians:(CGFloat)degrees {
+  return degrees * (CGFloat)M_PI / 180.0f;
+}
+
+- (BOOL)isPointZero:(CGPoint)point {
+  return CGPointEqualToPoint(point, CGPointZero);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h
new file mode 100644
index 0000000..0c54d17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h
@@ -0,0 +1,24 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// GENERATED CODE: DO NOT EDIT BY HAND
+// GENERATED FROM:
+// ./PageControl/GoogleKitPageControl.bundle/Resources/en.lproj/GoogleKitPageControl.strings
+// GENERATED BY: //depot/google3/googlemac/iPhone/Shared/Tools/generate_string_tables.py
+
+typedef enum {
+  kStr_MaterialPageControlAccessibilityLabel = 0,
+} MaterialPageControlStringId;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h
new file mode 100644
index 0000000..2314001
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h
@@ -0,0 +1,31 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// GENERATED CODE: DO NOT EDIT BY HAND
+// GENERATED FROM:
+// ./PageControl/GoogleKitPageControl.bundle/Resources/en.lproj/GoogleKitPageControl.strings
+// GENERATED BY: //depot/google3/googlemac/iPhone/Shared/Tools/generate_string_tables.py
+
+// A table of string keys to look-up localized strings in the bundle.
+// This table is to be indexed using the generated enum.
+
+static NSString *const kMaterialPageControlStringTable[] = {
+    @"MaterialPageControlAccessibilityLabel",  // page %1$zd of %2$zd
+};
+#define kNumMaterialPageControlStrings 1
+#define kMaterialControlStringsOffset 0
+#define kMaterialPageControlStringsEnd 10000
+static NSString *const kMaterialPageControlStringsTableName = @"MaterialPageControl";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.h
new file mode 100644
index 0000000..78507dc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.h
@@ -0,0 +1,212 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** The name of the tint 50 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint50Name;
+
+/** The name of the tint 100 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint100Name;
+
+/** The name of the tint 200 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint200Name;
+
+/** The name of the tint 300 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint300Name;
+
+/** The name of the tint 400 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint400Name;
+
+/** The name of the tint 500 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint500Name;
+
+/** The name of the tint 600 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint600Name;
+
+/** The name of the tint 700 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint700Name;
+
+/** The name of the tint 800 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint800Name;
+
+/** The name of the tint 900 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint900Name;
+
+/** The name of the accent 100 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent100Name;
+
+/** The name of the accent 200 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent200Name;
+
+/** The name of the accent 400 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent400Name;
+
+/** The name of the accent 700 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent700Name;
+
+/**
+ A palette of Material colors.
+
+ Material palettes have a set of named tint colors and an optional set of named accent colors. This
+ class provides access to the pre-defined set of Material palettes. MDCPalette objects are
+ immutable; it is safe to use them from multiple threads in your app.
+
+ @see https://www.google.com/design/spec/style/color.html#color-color-palette
+ */
+@interface MDCPalette : NSObject
+
+/** The red palette. */
++ (nonnull MDCPalette *)redPalette;
+
+/** The pink palette. */
++ (nonnull MDCPalette *)pinkPalette;
+
+/** The purple palette. */
++ (nonnull MDCPalette *)purplePalette;
+
+/** The deep purple palette. */
++ (nonnull MDCPalette *)deepPurplePalette;
+
+/** The indigo palette. */
++ (nonnull MDCPalette *)indigoPalette;
+
+/** The blue palette. */
++ (nonnull MDCPalette *)bluePalette;
+
+/** The light blue palette. */
++ (nonnull MDCPalette *)lightBluePalette;
+
+/** The cyan palette. */
++ (nonnull MDCPalette *)cyanPalette;
+
+/** The teal palette. */
++ (nonnull MDCPalette *)tealPalette;
+
+/** The green palette. */
++ (nonnull MDCPalette *)greenPalette;
+
+/** The light green palette. */
++ (nonnull MDCPalette *)lightGreenPalette;
+
+/** The lime palette. */
++ (nonnull MDCPalette *)limePalette;
+
+/** The yellow palette. */
++ (nonnull MDCPalette *)yellowPalette;
+
+/** The amber palette. */
++ (nonnull MDCPalette *)amberPalette;
+
+/** The orange palette. */
++ (nonnull MDCPalette *)orangePalette;
+
+/** The deep orange palette. */
++ (nonnull MDCPalette *)deepOrangePalette;
+
+/** The brown palette (no accents). */
++ (nonnull MDCPalette *)brownPalette;
+
+/** The grey palette (no accents). */
++ (nonnull MDCPalette *)greyPalette;
+
+/** The blue grey palette (no accents). */
++ (nonnull MDCPalette *)blueGreyPalette;
+
+/**
+ Returns a palette generated from a single target 500 tint color.
+
+ TODO(ajsecord): Document the algorithm used to generate the palette.
+
+ @param target500Color The target "500" color in the palette.
+ @return A palette generated with a 500 color matching the target color.
+ */
++ (nonnull instancetype)paletteGeneratedFromColor:(nonnull UIColor *)target500Color;
+
+/**
+ Returns a palette with a custom set of tints and accents.
+
+ The tints dictionary must have values for each key matching MDCPaletteTint.*Name. The accents
+ dictionary, if specified, may have entries for each key matching MDCPaletteAccent.*Name. Missing
+ accent values will cause an assert in debug mode and will return +[UIColor clearColor] in release
+ mode when the corresponding property is acccessed.
+
+ @param tints A dictionary mapping MDCPaletteTint.*Name keys to UIColors.
+ @param accents An optional dictionary mapping MDCPaletteAccent.*Name keys to UIColors.
+ @return An palette containing the custom colors.
+ */
++ (nonnull instancetype)paletteWithTints:(nonnull NSDictionary<const NSString *, UIColor *> *)tints
+                                 accents:
+                                     (nullable NSDictionary<const NSString *, UIColor *> *)accents;
+
+/**
+ Returns an initialized palette object with a custom set of tints and accents.
+
+ The tints dictionary must have values for each key matching MDCPaletteTint.*Name. The accents
+ dictionary, if specified, may have entries for each key matching MDCPaletteAccent.*Name. Missing
+ accent values will cause an assert in debug mode and will return +[UIColor clearColor] in release
+ mode when the corresponding property is acccessed.
+
+ @param tints A dictionary mapping MDCPaletteTint.*Name keys to UIColors.
+ @param accents An optional dictionary mapping MDCPaletteAccent.*Name keys to UIColors.
+ @return An initialized MDCPalette object containing the custom colors.
+ */
+- (nonnull instancetype)initWithTints:(nonnull NSDictionary<const NSString *, UIColor *> *)tints
+                              accents:(nullable NSDictionary<const NSString *, UIColor *> *)accents;
+
+/** The 50 tint color, the lightest tint of the palette. */
+@property(nonatomic, nonnull, readonly) UIColor *tint50;
+
+/** The 100 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint100;
+
+/** The 200 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint200;
+
+/** The 300 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint300;
+
+/** The 400 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint400;
+
+/** The 500 tint color, the representative tint of the palette. */
+@property(nonatomic, nonnull, readonly) UIColor *tint500;
+
+/** The 600 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint600;
+
+/** The 700 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint700;
+
+/** The 800 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint800;
+
+/** The 900 tint color, the darkest tint of the palette. */
+@property(nonatomic, nonnull, readonly) UIColor *tint900;
+
+/** The A100 accent color, the lightest accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent100;
+
+/** The A200 accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent200;
+
+/** The A400 accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent400;
+
+/** The A700 accent color, the darkest accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent700;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.m
new file mode 100644
index 0000000..4a713fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.m
@@ -0,0 +1,654 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPalettes.h"
+#import "private/MDCPaletteExpansions.h"
+#import "private/MDCPaletteNames.h"
+
+const NSString *MDCPaletteTint50Name = MDC_PALETTE_TINT_50_INTERNAL_NAME;
+const NSString *MDCPaletteTint100Name = MDC_PALETTE_TINT_100_INTERNAL_NAME;
+const NSString *MDCPaletteTint200Name = MDC_PALETTE_TINT_200_INTERNAL_NAME;
+const NSString *MDCPaletteTint300Name = MDC_PALETTE_TINT_300_INTERNAL_NAME;
+const NSString *MDCPaletteTint400Name = MDC_PALETTE_TINT_400_INTERNAL_NAME;
+const NSString *MDCPaletteTint500Name = MDC_PALETTE_TINT_500_INTERNAL_NAME;
+const NSString *MDCPaletteTint600Name = MDC_PALETTE_TINT_600_INTERNAL_NAME;
+const NSString *MDCPaletteTint700Name = MDC_PALETTE_TINT_700_INTERNAL_NAME;
+const NSString *MDCPaletteTint800Name = MDC_PALETTE_TINT_800_INTERNAL_NAME;
+const NSString *MDCPaletteTint900Name = MDC_PALETTE_TINT_900_INTERNAL_NAME;
+const NSString *MDCPaletteAccent100Name = MDC_PALETTE_ACCENT_100_INTERNAL_NAME;
+const NSString *MDCPaletteAccent200Name = MDC_PALETTE_ACCENT_200_INTERNAL_NAME;
+const NSString *MDCPaletteAccent400Name = MDC_PALETTE_ACCENT_400_INTERNAL_NAME;
+const NSString *MDCPaletteAccent700Name = MDC_PALETTE_ACCENT_700_INTERNAL_NAME;
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+@interface MDCPalette () {
+  NSDictionary<const NSString *, UIColor *> *_tints;
+  NSDictionary<const NSString *, UIColor *> *_accents;
+}
+
+@end
+
+@implementation MDCPalette
+
++ (MDCPalette *)redPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFEBEE),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFCDD2),
+      MDCPaletteTint200Name : ColorFromRGB(0xEF9A9A),
+      MDCPaletteTint300Name : ColorFromRGB(0xE57373),
+      MDCPaletteTint400Name : ColorFromRGB(0xEF5350),
+      MDCPaletteTint500Name : ColorFromRGB(0xF44336),
+      MDCPaletteTint600Name : ColorFromRGB(0xE53935),
+      MDCPaletteTint700Name : ColorFromRGB(0xD32F2F),
+      MDCPaletteTint800Name : ColorFromRGB(0xC62828),
+      MDCPaletteTint900Name : ColorFromRGB(0xB71C1C)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFF8A80),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFF5252),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFF1744),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xD50000)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)pinkPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFCE4EC),
+      MDCPaletteTint100Name : ColorFromRGB(0xF8BBD0),
+      MDCPaletteTint200Name : ColorFromRGB(0xF48FB1),
+      MDCPaletteTint300Name : ColorFromRGB(0xF06292),
+      MDCPaletteTint400Name : ColorFromRGB(0xEC407A),
+      MDCPaletteTint500Name : ColorFromRGB(0xE91E63),
+      MDCPaletteTint600Name : ColorFromRGB(0xD81B60),
+      MDCPaletteTint700Name : ColorFromRGB(0xC2185B),
+      MDCPaletteTint800Name : ColorFromRGB(0xAD1457),
+      MDCPaletteTint900Name : ColorFromRGB(0x880E4F)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFF80AB),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFF4081),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xF50057),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xC51162)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)purplePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xF3E5F5),
+      MDCPaletteTint100Name : ColorFromRGB(0xE1BEE7),
+      MDCPaletteTint200Name : ColorFromRGB(0xCE93D8),
+      MDCPaletteTint300Name : ColorFromRGB(0xBA68C8),
+      MDCPaletteTint400Name : ColorFromRGB(0xAB47BC),
+      MDCPaletteTint500Name : ColorFromRGB(0x9C27B0),
+      MDCPaletteTint600Name : ColorFromRGB(0x8E24AA),
+      MDCPaletteTint700Name : ColorFromRGB(0x7B1FA2),
+      MDCPaletteTint800Name : ColorFromRGB(0x6A1B9A),
+      MDCPaletteTint900Name : ColorFromRGB(0x4A148C)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xEA80FC),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xE040FB),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xD500F9),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xAA00FF)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)deepPurplePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xEDE7F6),
+      MDCPaletteTint100Name : ColorFromRGB(0xD1C4E9),
+      MDCPaletteTint200Name : ColorFromRGB(0xB39DDB),
+      MDCPaletteTint300Name : ColorFromRGB(0x9575CD),
+      MDCPaletteTint400Name : ColorFromRGB(0x7E57C2),
+      MDCPaletteTint500Name : ColorFromRGB(0x673AB7),
+      MDCPaletteTint600Name : ColorFromRGB(0x5E35B1),
+      MDCPaletteTint700Name : ColorFromRGB(0x512DA8),
+      MDCPaletteTint800Name : ColorFromRGB(0x4527A0),
+      MDCPaletteTint900Name : ColorFromRGB(0x311B92)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xB388FF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x7C4DFF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x651FFF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x6200EA)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)indigoPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE8EAF6),
+      MDCPaletteTint100Name : ColorFromRGB(0xC5CAE9),
+      MDCPaletteTint200Name : ColorFromRGB(0x9FA8DA),
+      MDCPaletteTint300Name : ColorFromRGB(0x7986CB),
+      MDCPaletteTint400Name : ColorFromRGB(0x5C6BC0),
+      MDCPaletteTint500Name : ColorFromRGB(0x3F51B5),
+      MDCPaletteTint600Name : ColorFromRGB(0x3949AB),
+      MDCPaletteTint700Name : ColorFromRGB(0x303F9F),
+      MDCPaletteTint800Name : ColorFromRGB(0x283593),
+      MDCPaletteTint900Name : ColorFromRGB(0x1A237E)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x8C9EFF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x536DFE),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x3D5AFE),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x304FFE)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)bluePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE3F2FD),
+      MDCPaletteTint100Name : ColorFromRGB(0xBBDEFB),
+      MDCPaletteTint200Name : ColorFromRGB(0x90CAF9),
+      MDCPaletteTint300Name : ColorFromRGB(0x64B5F6),
+      MDCPaletteTint400Name : ColorFromRGB(0x42A5F5),
+      MDCPaletteTint500Name : ColorFromRGB(0x2196F3),
+      MDCPaletteTint600Name : ColorFromRGB(0x1E88E5),
+      MDCPaletteTint700Name : ColorFromRGB(0x1976D2),
+      MDCPaletteTint800Name : ColorFromRGB(0x1565C0),
+      MDCPaletteTint900Name : ColorFromRGB(0x0D47A1)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x82B1FF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x448AFF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x2979FF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x2962FF)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)lightBluePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE1F5FE),
+      MDCPaletteTint100Name : ColorFromRGB(0xB3E5FC),
+      MDCPaletteTint200Name : ColorFromRGB(0x81D4FA),
+      MDCPaletteTint300Name : ColorFromRGB(0x4FC3F7),
+      MDCPaletteTint400Name : ColorFromRGB(0x29B6F6),
+      MDCPaletteTint500Name : ColorFromRGB(0x03A9F4),
+      MDCPaletteTint600Name : ColorFromRGB(0x039BE5),
+      MDCPaletteTint700Name : ColorFromRGB(0x0288D1),
+      MDCPaletteTint800Name : ColorFromRGB(0x0277BD),
+      MDCPaletteTint900Name : ColorFromRGB(0x01579B)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x80D8FF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x40C4FF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x00B0FF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x0091EA)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)cyanPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE0F7FA),
+      MDCPaletteTint100Name : ColorFromRGB(0xB2EBF2),
+      MDCPaletteTint200Name : ColorFromRGB(0x80DEEA),
+      MDCPaletteTint300Name : ColorFromRGB(0x4DD0E1),
+      MDCPaletteTint400Name : ColorFromRGB(0x26C6DA),
+      MDCPaletteTint500Name : ColorFromRGB(0x00BCD4),
+      MDCPaletteTint600Name : ColorFromRGB(0x00ACC1),
+      MDCPaletteTint700Name : ColorFromRGB(0x0097A7),
+      MDCPaletteTint800Name : ColorFromRGB(0x00838F),
+      MDCPaletteTint900Name : ColorFromRGB(0x006064)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x84FFFF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x18FFFF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x00E5FF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x00B8D4)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)tealPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE0F2F1),
+      MDCPaletteTint100Name : ColorFromRGB(0xB2DFDB),
+      MDCPaletteTint200Name : ColorFromRGB(0x80CBC4),
+      MDCPaletteTint300Name : ColorFromRGB(0x4DB6AC),
+      MDCPaletteTint400Name : ColorFromRGB(0x26A69A),
+      MDCPaletteTint500Name : ColorFromRGB(0x009688),
+      MDCPaletteTint600Name : ColorFromRGB(0x00897B),
+      MDCPaletteTint700Name : ColorFromRGB(0x00796B),
+      MDCPaletteTint800Name : ColorFromRGB(0x00695C),
+      MDCPaletteTint900Name : ColorFromRGB(0x004D40)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xA7FFEB),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x64FFDA),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x1DE9B6),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x00BFA5)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)greenPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE8F5E9),
+      MDCPaletteTint100Name : ColorFromRGB(0xC8E6C9),
+      MDCPaletteTint200Name : ColorFromRGB(0xA5D6A7),
+      MDCPaletteTint300Name : ColorFromRGB(0x81C784),
+      MDCPaletteTint400Name : ColorFromRGB(0x66BB6A),
+      MDCPaletteTint500Name : ColorFromRGB(0x4CAF50),
+      MDCPaletteTint600Name : ColorFromRGB(0x43A047),
+      MDCPaletteTint700Name : ColorFromRGB(0x388E3C),
+      MDCPaletteTint800Name : ColorFromRGB(0x2E7D32),
+      MDCPaletteTint900Name : ColorFromRGB(0x1B5E20)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xB9F6CA),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x69F0AE),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x00E676),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x00C853)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)lightGreenPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xF1F8E9),
+      MDCPaletteTint100Name : ColorFromRGB(0xDCEDC8),
+      MDCPaletteTint200Name : ColorFromRGB(0xC5E1A5),
+      MDCPaletteTint300Name : ColorFromRGB(0xAED581),
+      MDCPaletteTint400Name : ColorFromRGB(0x9CCC65),
+      MDCPaletteTint500Name : ColorFromRGB(0x8BC34A),
+      MDCPaletteTint600Name : ColorFromRGB(0x7CB342),
+      MDCPaletteTint700Name : ColorFromRGB(0x689F38),
+      MDCPaletteTint800Name : ColorFromRGB(0x558B2F),
+      MDCPaletteTint900Name : ColorFromRGB(0x33691E)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xCCFF90),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xB2FF59),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x76FF03),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x64DD17)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)limePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xF9FBE7),
+      MDCPaletteTint100Name : ColorFromRGB(0xF0F4C3),
+      MDCPaletteTint200Name : ColorFromRGB(0xE6EE9C),
+      MDCPaletteTint300Name : ColorFromRGB(0xDCE775),
+      MDCPaletteTint400Name : ColorFromRGB(0xD4E157),
+      MDCPaletteTint500Name : ColorFromRGB(0xCDDC39),
+      MDCPaletteTint600Name : ColorFromRGB(0xC0CA33),
+      MDCPaletteTint700Name : ColorFromRGB(0xAFB42B),
+      MDCPaletteTint800Name : ColorFromRGB(0x9E9D24),
+      MDCPaletteTint900Name : ColorFromRGB(0x827717)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xF4FF81),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xEEFF41),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xC6FF00),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xAEEA00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)yellowPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFFDE7),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFF9C4),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFF59D),
+      MDCPaletteTint300Name : ColorFromRGB(0xFFF176),
+      MDCPaletteTint400Name : ColorFromRGB(0xFFEE58),
+      MDCPaletteTint500Name : ColorFromRGB(0xFFEB3B),
+      MDCPaletteTint600Name : ColorFromRGB(0xFDD835),
+      MDCPaletteTint700Name : ColorFromRGB(0xFBC02D),
+      MDCPaletteTint800Name : ColorFromRGB(0xF9A825),
+      MDCPaletteTint900Name : ColorFromRGB(0xF57F17)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFFFF8D),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFFFF00),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFFEA00),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xFFD600)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)amberPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFF8E1),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFECB3),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFE082),
+      MDCPaletteTint300Name : ColorFromRGB(0xFFD54F),
+      MDCPaletteTint400Name : ColorFromRGB(0xFFCA28),
+      MDCPaletteTint500Name : ColorFromRGB(0xFFC107),
+      MDCPaletteTint600Name : ColorFromRGB(0xFFB300),
+      MDCPaletteTint700Name : ColorFromRGB(0xFFA000),
+      MDCPaletteTint800Name : ColorFromRGB(0xFF8F00),
+      MDCPaletteTint900Name : ColorFromRGB(0xFF6F00)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFFE57F),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFFD740),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFFC400),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xFFAB00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)orangePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFF3E0),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFE0B2),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFCC80),
+      MDCPaletteTint300Name : ColorFromRGB(0xFFB74D),
+      MDCPaletteTint400Name : ColorFromRGB(0xFFA726),
+      MDCPaletteTint500Name : ColorFromRGB(0xFF9800),
+      MDCPaletteTint600Name : ColorFromRGB(0xFB8C00),
+      MDCPaletteTint700Name : ColorFromRGB(0xF57C00),
+      MDCPaletteTint800Name : ColorFromRGB(0xEF6C00),
+      MDCPaletteTint900Name : ColorFromRGB(0xE65100)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFFD180),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFFAB40),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFF9100),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xFF6D00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)deepOrangePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFBE9E7),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFCCBC),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFAB91),
+      MDCPaletteTint300Name : ColorFromRGB(0xFF8A65),
+      MDCPaletteTint400Name : ColorFromRGB(0xFF7043),
+      MDCPaletteTint500Name : ColorFromRGB(0xFF5722),
+      MDCPaletteTint600Name : ColorFromRGB(0xF4511E),
+      MDCPaletteTint700Name : ColorFromRGB(0xE64A19),
+      MDCPaletteTint800Name : ColorFromRGB(0xD84315),
+      MDCPaletteTint900Name : ColorFromRGB(0xBF360C)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFF9E80),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFF6E40),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFF3D00),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xDD2C00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)brownPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xEFEBE9),
+      MDCPaletteTint100Name : ColorFromRGB(0xD7CCC8),
+      MDCPaletteTint200Name : ColorFromRGB(0xBCAAA4),
+      MDCPaletteTint300Name : ColorFromRGB(0xA1887F),
+      MDCPaletteTint400Name : ColorFromRGB(0x8D6E63),
+      MDCPaletteTint500Name : ColorFromRGB(0x795548),
+      MDCPaletteTint600Name : ColorFromRGB(0x6D4C41),
+      MDCPaletteTint700Name : ColorFromRGB(0x5D4037),
+      MDCPaletteTint800Name : ColorFromRGB(0x4E342E),
+      MDCPaletteTint900Name : ColorFromRGB(0x3E2723)
+    }
+                                  accents:nil];
+  });
+  return palette;
+}
+
++ (MDCPalette *)greyPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFAFAFA),
+      MDCPaletteTint100Name : ColorFromRGB(0xF5F5F5),
+      MDCPaletteTint200Name : ColorFromRGB(0xEEEEEE),
+      MDCPaletteTint300Name : ColorFromRGB(0xE0E0E0),
+      MDCPaletteTint400Name : ColorFromRGB(0xBDBDBD),
+      MDCPaletteTint500Name : ColorFromRGB(0x9E9E9E),
+      MDCPaletteTint600Name : ColorFromRGB(0x757575),
+      MDCPaletteTint700Name : ColorFromRGB(0x616161),
+      MDCPaletteTint800Name : ColorFromRGB(0x424242),
+      MDCPaletteTint900Name : ColorFromRGB(0x212121)
+    }
+                                  accents:nil];
+  });
+  return palette;
+}
+
++ (MDCPalette *)blueGreyPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xECEFF1),
+      MDCPaletteTint100Name : ColorFromRGB(0xCFD8DC),
+      MDCPaletteTint200Name : ColorFromRGB(0xB0BEC5),
+      MDCPaletteTint300Name : ColorFromRGB(0x90A4AE),
+      MDCPaletteTint400Name : ColorFromRGB(0x78909C),
+      MDCPaletteTint500Name : ColorFromRGB(0x607D8B),
+      MDCPaletteTint600Name : ColorFromRGB(0x546E7A),
+      MDCPaletteTint700Name : ColorFromRGB(0x455A64),
+      MDCPaletteTint800Name : ColorFromRGB(0x37474F),
+      MDCPaletteTint900Name : ColorFromRGB(0x263238)
+    }
+                                  accents:nil];
+  });
+  return palette;
+}
+
++ (instancetype)paletteGeneratedFromColor:(nonnull UIColor *)target500Color {
+  NSArray *tintNames = @[
+    MDCPaletteTint50Name, MDCPaletteTint100Name, MDCPaletteTint200Name, MDCPaletteTint300Name,
+    MDCPaletteTint400Name, MDCPaletteTint500Name, MDCPaletteTint600Name, MDCPaletteTint700Name,
+    MDCPaletteTint800Name, MDCPaletteTint900Name, MDCPaletteAccent100Name, MDCPaletteAccent200Name,
+    MDCPaletteAccent400Name, MDCPaletteAccent700Name
+  ];
+
+  NSMutableDictionary *tints = [[NSMutableDictionary alloc] init];
+  for (NSString *name in tintNames) {
+    [tints setObject:MDCPaletteTintFromTargetColor(target500Color, name) forKey:name];
+  }
+
+  NSArray *accentNames = @[
+    MDCPaletteAccent100Name, MDCPaletteAccent200Name, MDCPaletteAccent400Name,
+    MDCPaletteAccent700Name
+  ];
+  NSMutableDictionary *accents = [[NSMutableDictionary alloc] init];
+  for (NSString *name in accentNames) {
+    [accents setObject:MDCPaletteAccentFromTargetColor(target500Color, name) forKey:name];
+  }
+
+  return [self paletteWithTints:tints accents:accents];
+}
+
++ (instancetype)paletteWithTints:(NSDictionary<NSString *, UIColor *> *)tints
+                         accents:(NSDictionary<NSString *, UIColor *> *)accents {
+  return [[self alloc] initWithTints:tints accents:accents];
+}
+
+- (instancetype)initWithTints:(NSDictionary<const NSString *, UIColor *> *)tints
+                      accents:(NSDictionary<const NSString *, UIColor *> *)accents {
+  self = [super init];
+  if (self) {
+    _accents = accents ? [accents copy] : @{};
+
+    // Check if all the accent colors are present.
+    NSDictionary<const NSString *, UIColor *> *allTints = tints;
+    NSMutableSet<const NSString *> *requiredTintKeys =
+        [NSMutableSet setWithSet:[[self class] requiredTintKeys]];
+    [requiredTintKeys minusSet:[NSSet setWithArray:[tints allKeys]]];
+    if ([requiredTintKeys count] != 0) {
+      NSAssert(NO, @"Missing accent colors for the following keys: %@.", requiredTintKeys);
+      NSMutableDictionary<const NSString *, UIColor *> *replacementTints =
+          [NSMutableDictionary dictionaryWithDictionary:_accents];
+      for (NSString *tintKey in requiredTintKeys) {
+        [replacementTints setObject:[UIColor clearColor] forKey:tintKey];
+      }
+      allTints = replacementTints;
+    }
+
+    _tints = [allTints copy];
+  }
+  return self;
+}
+
+- (UIColor *)tint50 {
+  return _tints[MDCPaletteTint50Name];
+}
+
+- (UIColor *)tint100 {
+  return _tints[MDCPaletteTint100Name];
+}
+
+- (UIColor *)tint200 {
+  return _tints[MDCPaletteTint200Name];
+}
+
+- (UIColor *)tint300 {
+  return _tints[MDCPaletteTint300Name];
+}
+
+- (UIColor *)tint400 {
+  return _tints[MDCPaletteTint400Name];
+}
+
+- (UIColor *)tint500 {
+  return _tints[MDCPaletteTint500Name];
+}
+
+- (UIColor *)tint600 {
+  return _tints[MDCPaletteTint600Name];
+}
+
+- (UIColor *)tint700 {
+  return _tints[MDCPaletteTint700Name];
+}
+
+- (UIColor *)tint800 {
+  return _tints[MDCPaletteTint800Name];
+}
+
+- (UIColor *)tint900 {
+  return _tints[MDCPaletteTint900Name];
+}
+
+- (UIColor *)accent100 {
+  return _accents[MDCPaletteAccent100Name];
+}
+
+- (UIColor *)accent200 {
+  return _accents[MDCPaletteAccent200Name];
+}
+
+- (UIColor *)accent400 {
+  return _accents[MDCPaletteAccent400Name];
+}
+
+- (UIColor *)accent700 {
+  return _accents[MDCPaletteAccent700Name];
+}
+
+#pragma mark - Private methods
+
++ (nonnull NSSet<const NSString *> *)requiredTintKeys {
+  return [NSSet setWithArray:@[
+    MDCPaletteTint50Name, MDCPaletteTint100Name, MDCPaletteTint200Name, MDCPaletteTint300Name,
+    MDCPaletteTint400Name, MDCPaletteTint500Name, MDCPaletteTint600Name, MDCPaletteTint700Name,
+    MDCPaletteTint800Name, MDCPaletteTint900Name
+  ]];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MaterialPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MaterialPalettes.h
new file mode 100644
index 0000000..fa83aec
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/MaterialPalettes.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPalettes.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h
new file mode 100644
index 0000000..3a92cc9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+UIColor* _Nonnull MDCPaletteTintFromTargetColor(UIColor* _Nonnull targetColor,
+                                                NSString* _Nonnull tintName);
+
+UIColor* _Nonnull MDCPaletteAccentFromTargetColor(UIColor* _Nonnull targetColor,
+                                                  NSString* _Nonnull accentName);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.m
new file mode 100644
index 0000000..c9ac33c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.m
@@ -0,0 +1,206 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include "MDCPaletteExpansions.h"
+
+#include <Foundation/Foundation.h>
+
+#import "MDCPaletteNames.h"
+
+// Observed saturation ranges for tints 50, 500, 900.
+static const CGFloat kSaturation50Min = 0.06f;
+static const CGFloat kSaturation50Max = 0.12f;
+static const CGFloat kSaturation500Min = 0.60f;
+static const CGFloat kSaturation500Max = 1.00f;
+static const CGFloat kSaturation900Min = 0.70f;
+static const CGFloat kSaturation900Max = 1.00f;
+
+// Minimum value of saturation to consider a color "colorless" (e.g. white/black/grey).
+static const CGFloat kSaturationMinThreshold = 1 / 256.0f;
+
+// A small value for comparing floating point numbers that is appropriate for color components.
+static const CGFloat kComponentEpsilon = 0.5f / 256.0f;
+
+// Observed brightness ranges for tints 50, 500, 900.
+static const CGFloat kBrightness50Min = 0.95f;
+static const CGFloat kBrightness50Max = 1.00f;
+static const CGFloat kBrightness500Min = 0.50f;
+static const CGFloat kBrightness500Max = 1.00f;
+
+// Observed quadratic brightness coefficients for tints >= 500.
+static const CGFloat kBrightnessQuadracticCoeff = -0.00642857142857143f;
+static const CGFloat kBrightnessLinearCoeff = -0.03585714285714282f;
+
+// Median saturation and brightness values for A100, A200, A400, A700.
+static const CGFloat kAccentSaturation[4] = {0.49f, 0.75f, 1.00f, 1.00f};
+static const CGFloat kAccentBrightness[4] = {1.00f, 1.00f, 1.00f, 0.92f};
+
+// Ordered indices of each of the tints/accents.
+static const int kQTMColorTint50Index = 0;
+static const int kQTMColorTint100Index = 1;
+static const int kQTMColorTint200Index = 2;
+static const int kQTMColorTint300Index = 3;
+static const int kQTMColorTint400Index = 4;
+static const int kQTMColorTint500Index = 5;
+static const int kQTMColorTint600Index = 6;
+static const int kQTMColorTint700Index = 7;
+static const int kQTMColorTint800Index = 8;
+static const int kQTMColorTint900Index = 9;
+static const int kQTMColorAccent100Index = 10;
+static const int kQTMColorAccent200Index = 11;
+static const int kQTMColorAccent400Index = 12;
+static const int kQTMColorAccent700Index = 13;
+
+/** Returns a value Clamped to the range [min, max]. */
+static inline CGFloat Clamp(CGFloat value, CGFloat min, CGFloat max) {
+  if (value < min) {
+    return min;
+  } else if (value > max) {
+    return max;
+  } else {
+    return value;
+  }
+}
+
+/** Returns the linear interpolation of [min, max] at value. */
+static inline CGFloat Lerp(CGFloat value, CGFloat min, CGFloat max) {
+  return (1 - value) * min + value * max;
+}
+
+/** Returns the value t such that Lerp(t, min, max) == value. */
+static inline CGFloat InvLerp(CGFloat value, CGFloat min, CGFloat max) {
+  return (value - min) / (max - min);
+}
+
+/**
+ Returns "component > value", but accounting for floating point mathematics. The component is
+ expected to be between [0,255].
+ */
+static inline BOOL IsComponentGreaterThanValue(CGFloat component, CGFloat value) {
+  return component + kComponentEpsilon > value;
+}
+
+static void ColorToHSB(UIColor *_Nonnull color, CGFloat hsb[4]) {
+  // Pre-iOS 8 would not convert greyscale colors to HSB.
+  if (![color getHue:&hsb[0] saturation:&hsb[1] brightness:&hsb[2] alpha:&hsb[3]]) {
+    // Greyscale colors have hue and saturation of zero.
+    hsb[0] = 0;
+    hsb[1] = 0;
+    if (![color getWhite:&hsb[2] alpha:&hsb[3]]) {
+      NSCAssert(NO, @"Could not extract HSB from target color %@", color);
+      hsb[2] = 0;
+      hsb[3] = 0;
+    }
+  }
+}
+
+/** Return the ordered index of a tint/accent by name. */
+static int NameToIndex(NSString *_Nonnull name) {
+  static NSDictionary *map = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    map = @{
+      MDC_PALETTE_TINT_50_INTERNAL_NAME : @(kQTMColorTint50Index),
+      MDC_PALETTE_TINT_100_INTERNAL_NAME : @(kQTMColorTint100Index),
+      MDC_PALETTE_TINT_200_INTERNAL_NAME : @(kQTMColorTint200Index),
+      MDC_PALETTE_TINT_300_INTERNAL_NAME : @(kQTMColorTint300Index),
+      MDC_PALETTE_TINT_400_INTERNAL_NAME : @(kQTMColorTint400Index),
+      MDC_PALETTE_TINT_500_INTERNAL_NAME : @(kQTMColorTint500Index),
+      MDC_PALETTE_TINT_600_INTERNAL_NAME : @(kQTMColorTint600Index),
+      MDC_PALETTE_TINT_700_INTERNAL_NAME : @(kQTMColorTint700Index),
+      MDC_PALETTE_TINT_800_INTERNAL_NAME : @(kQTMColorTint800Index),
+      MDC_PALETTE_TINT_900_INTERNAL_NAME : @(kQTMColorTint900Index),
+      MDC_PALETTE_ACCENT_100_INTERNAL_NAME : @(kQTMColorAccent100Index),
+      MDC_PALETTE_ACCENT_200_INTERNAL_NAME : @(kQTMColorAccent200Index),
+      MDC_PALETTE_ACCENT_400_INTERNAL_NAME : @(kQTMColorAccent400Index),
+      MDC_PALETTE_ACCENT_700_INTERNAL_NAME : @(kQTMColorAccent700Index)
+    };
+  });
+
+  NSNumber *index = map[name];
+  if (index) {
+    return [index intValue];
+  } else {
+    NSCAssert(NO, @"%@ is not a valid tint/accent name.", name);
+    return kQTMColorTint500Index;
+  }
+}
+
+UIColor *MDCPaletteTintFromTargetColor(UIColor *targetColor, NSString *tintName) {
+  NSCAssert(MDCPaletteIsTintOrAccentName(tintName), @"Invalid tint/accent name %@.", tintName);
+  int tint = NameToIndex(tintName);
+
+  CGFloat hsb[4];
+  ColorToHSB(targetColor, hsb);
+
+  // Saturation: select a saturation curve from the input saturation, unless the saturation is so
+  // low to be considered 'colorless', e.g. white/black/grey, in which case skip this step.
+  CGFloat saturation = hsb[1];
+  CGFloat t;
+  if (IsComponentGreaterThanValue(hsb[1], kSaturationMinThreshold)) {
+    // Limit saturation to observed values.
+    hsb[1] = Clamp(hsb[1], kSaturation500Min, kSaturation500Max);
+
+    t = InvLerp(hsb[1], kSaturation500Min, kSaturation500Max);
+    if (tint <= kQTMColorTint500Index) {
+      CGFloat saturation50 = Lerp(t, kSaturation50Min, kSaturation50Max);
+      CGFloat u = InvLerp(tint, kQTMColorTint50Index, kQTMColorTint500Index);
+      saturation = Lerp(u, saturation50, hsb[1]);
+    } else {
+      CGFloat saturation900 = Lerp(t, kSaturation900Min, kSaturation900Max);
+      CGFloat u = InvLerp(tint, kQTMColorTint500Index, kQTMColorTint900Index);
+      saturation = Lerp(u, hsb[1], saturation900);
+    }
+  }
+
+  // Brightness: select a brightness curve from the input brightness.
+  CGFloat brightness;
+
+  // Limit brightness to observed values.
+  hsb[2] = Clamp(hsb[2], kBrightness500Min, kBrightness500Max);
+  t = InvLerp(hsb[2], kBrightness500Min, kBrightness500Max);
+
+  // The tints 50-500 are nice and linear.
+  if (tint <= kQTMColorTint500Index) {
+    CGFloat brightness50 = Lerp(t, kBrightness50Min, kBrightness50Max);
+    CGFloat u = InvLerp(tint, kQTMColorTint50Index, kQTMColorTint500Index);
+    brightness = Lerp(u, brightness50, hsb[2]);
+
+    // The tints > 500 fall off roughly quadratically.
+  } else {
+    CGFloat u = tint - kQTMColorTint500Index;
+    brightness = hsb[2] + kBrightnessQuadracticCoeff * u * u + kBrightnessLinearCoeff * u;
+  }
+
+  return [UIColor colorWithHue:hsb[0] saturation:saturation brightness:brightness alpha:1];
+}
+
+UIColor *MDCPaletteAccentFromTargetColor(UIColor *targetColor, NSString *accentName) {
+  NSCAssert(MDCPaletteIsTintOrAccentName(accentName), @"Invalid tint/accent name %@.", accentName);
+  int accent = NameToIndex(accentName);
+
+  CGFloat hsb[4];
+  ColorToHSB(targetColor, hsb);
+
+  int index = accent - kQTMColorAccent100Index;
+  NSCAssert(index >= 0 && index < 4, @"Invalid accent index %i", (int)accent);
+
+  CGFloat saturation = IsComponentGreaterThanValue(hsb[1], kSaturationMinThreshold)
+                           ? kAccentSaturation[index]
+                           : hsb[1];
+  CGFloat brightness = kAccentBrightness[index];
+  return [UIColor colorWithHue:hsb[0] saturation:saturation brightness:brightness alpha:1];
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h
new file mode 100644
index 0000000..58a3cc2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h
@@ -0,0 +1,58 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License")
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/*
+ The string values of the names of the tints and accents are required in two places:
+   - in the definitions of the API names (such as MDCPaletteTint500Name)
+   - in the private implementation, for example, to check incoming strings are correct.
+
+ We can't have both the public and the private implementations depending on each other, since that
+ would cause a dependency loop. The normal solution to a dependency loop is to factor out the
+ common part into a new "unit" and have both of the original implementations depend on this new
+ unit. In this case, the string values would get factored out into the new unit.
+
+ However, the code in question is initializing constant data (the strings), the definitions must use
+ compile-time constants. For example, if we factored out the string values as "internal" names, the
+ following would still not work because the initialization doesn't use compile-time constants.
+
+ ```objective-c
+ static const NSString *MDCPaletteTint500Name = MDCPaletteTint500InternalName;
+ ```
+
+ To get around this, we instead drop down a level and define the strings in the preprocessor, so
+ that the compiler still sees compile-time constants. This has the downside of possibly duplicating
+ strings if the compiler can't optimize string storage across compilation units.
+ */
+
+#import <Foundation/Foundation.h>
+
+#define MDC_PALETTE_TINT_50_INTERNAL_NAME @"50"
+#define MDC_PALETTE_TINT_100_INTERNAL_NAME @"100"
+#define MDC_PALETTE_TINT_200_INTERNAL_NAME @"200"
+#define MDC_PALETTE_TINT_300_INTERNAL_NAME @"300"
+#define MDC_PALETTE_TINT_400_INTERNAL_NAME @"400"
+#define MDC_PALETTE_TINT_500_INTERNAL_NAME @"500"
+#define MDC_PALETTE_TINT_600_INTERNAL_NAME @"600"
+#define MDC_PALETTE_TINT_700_INTERNAL_NAME @"700"
+#define MDC_PALETTE_TINT_800_INTERNAL_NAME @"800"
+#define MDC_PALETTE_TINT_900_INTERNAL_NAME @"900"
+#define MDC_PALETTE_ACCENT_100_INTERNAL_NAME @"A100"
+#define MDC_PALETTE_ACCENT_200_INTERNAL_NAME @"A200"
+#define MDC_PALETTE_ACCENT_400_INTERNAL_NAME @"A400"
+#define MDC_PALETTE_ACCENT_700_INTERNAL_NAME @"A700"
+
+/** Return YES if a string is one of the pre-defined tint/accent names. */
+BOOL MDCPaletteIsTintOrAccentName(NSString* _Nonnull name);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.m
new file mode 100644
index 0000000..620fb3e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.m
@@ -0,0 +1,34 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License")
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPaletteNames.h"
+
+BOOL MDCPaletteIsTintOrAccentName(NSString* _Nonnull name) {
+  return [name isEqualToString:MDC_PALETTE_TINT_50_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_100_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_200_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_300_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_400_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_500_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_600_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_700_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_800_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_900_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_100_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_200_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_400_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_700_INTERNAL_NAME];
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.h
new file mode 100644
index 0000000..3c01c65
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.h
@@ -0,0 +1,91 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** The animation mode when animating backward progress. */
+typedef NS_ENUM(NSInteger, MDCProgressViewBackwardAnimationMode) {
+
+  /** Animate negative progress by resetting to 0 and then animating to the new value. */
+  MDCProgressViewBackwardAnimationModeReset,
+
+  /** Animate negative progress by animating from the current value. */
+  MDCProgressViewBackwardAnimationModeAnimate
+};
+
+/**
+ A Material linear determinate progress view.
+
+ See https://www.google.com/design/spec/components/progress-activity.html
+ */
+IB_DESIGNABLE
+@interface MDCProgressView : UIView
+
+/**
+ The color shown for the portion of the progress view that is filled.
+
+ The default is a blue color. When changed, the trackTintColor is reset.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *progressTintColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The color shown for the portion of the progress view that is not filled.
+
+ The default is a light version of the current progressTintColor.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *trackTintColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The current progress.
+
+ The current progress is represented by a floating-point value between 0.0 and 1.0, inclusive, where
+ 1.0 indicates the completion of the task. The default value is 0.0. Values less than 0.0 and
+ greater than 1.0 are pinned to those limits.
+ To animate progress changes, use -setProgress:animated:completion:.
+ */
+@property(nonatomic, assign) float progress;
+
+/**
+ The backward progress animation mode.
+
+ When animating progress which is lower than the current progress value, this mode
+ will determine which animation to use. The default is MDCProgressViewBackwardAnimationModeReset.
+ */
+@property(nonatomic, assign) MDCProgressViewBackwardAnimationMode backwardProgressAnimationMode;
+
+/**
+ Adjusts the current progress, optionally animating the change.
+
+ @param progress The progress to set.
+ @param animated Whether the change should be animated.
+ @param completion The completion block executed at the end of the animation.
+ */
+- (void)setProgress:(float)progress
+           animated:(BOOL)animated
+         completion:(void (^__nullable)(BOOL finished))completion;
+
+/**
+ Changes the hidden state, optionally animating the change.
+
+ @param hidden The hidden state to set.
+ @param animated Whether the change should be animated.
+ @param completion The completion block executed at the end of the animation.
+ */
+- (void)setHidden:(BOOL)hidden
+         animated:(BOOL)animated
+       completion:(void (^__nullable)(BOOL finished))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.m
new file mode 100644
index 0000000..705a5ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.m
@@ -0,0 +1,292 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCProgressView.h"
+
+#import <tgmath.h>
+
+#import "MaterialRTL.h"
+
+// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t MDCProgressViewDefaultTintColor = 0x2196F3;
+
+// The ratio by which to desaturate the progress tint color to obtain the default track tint color.
+static const CGFloat MDCProgressViewTrackColorDesaturation = 0.3f;
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+static const NSTimeInterval MDCProgressViewAnimationDuration = 0.25;
+
+@interface MDCProgressView ()
+@property(nonatomic, strong) UIView *progressView;
+@property(nonatomic, strong) UIView *trackView;
+@property(nonatomic) BOOL animatingHide;
+// A UIProgressView to return the same format for the accessibility value. For example, when
+// progress is 0.497, it reports "fifty per cent".
+@property(nonatomic, readonly) UIProgressView *accessibilityProgressView;
+@end
+
+@implementation MDCProgressView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCProgressViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCProgressViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCProgressViewInit {
+  self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
+  self.backgroundColor = [UIColor clearColor];
+  self.clipsToBounds = YES;
+  self.isAccessibilityElement = YES;
+
+  _backwardProgressAnimationMode = MDCProgressViewBackwardAnimationModeReset;
+
+  _trackView = [[UIView alloc] initWithFrame:self.frame];
+  _trackView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  [self addSubview:_trackView];
+
+  _progressView = [[UIView alloc] initWithFrame:CGRectZero];
+  [self addSubview:_progressView];
+
+  _progressView.backgroundColor = [[self class] defaultProgressTintColor];
+  _trackView.backgroundColor =
+      [[self class] defaultTrackTintColorForProgressTintColor:_progressView.backgroundColor];
+}
+
+- (void)willMoveToSuperview:(UIView *)superview {
+  [super willMoveToSuperview:superview];
+  [NSObject cancelPreviousPerformRequestsWithTarget:self];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Don't update the views when the hide animation is in progress.
+  if (!self.animatingHide) {
+    [self updateProgressView];
+    [self updateTrackView];
+  }
+}
+
+- (UIColor *)progressTintColor {
+  return self.progressView.backgroundColor;
+}
+
+- (void)setProgressTintColor:(UIColor *)progressTintColor {
+  if (progressTintColor == nil) {
+    progressTintColor = [[self class] defaultProgressTintColor];
+  }
+  self.progressView.backgroundColor = progressTintColor;
+}
+
+- (UIColor *)trackTintColor {
+  return self.trackView.backgroundColor;
+}
+
+- (void)setTrackTintColor:(UIColor *)trackTintColor {
+  if (trackTintColor == nil) {
+    trackTintColor =
+        [[self class] defaultTrackTintColorForProgressTintColor:self.progressTintColor];
+  }
+  self.trackView.backgroundColor = trackTintColor;
+}
+
+- (void)setProgress:(float)progress {
+  if (progress > 1)
+    progress = 1;
+  if (progress < 0)
+    progress = 0;
+  _progress = progress;
+  [self accessibilityValueDidChange];
+  [self setNeedsLayout];
+}
+
+- (void)setProgress:(float)progress
+           animated:(BOOL)animated
+         completion:(void (^__nullable)(BOOL finished))completion {
+  if (progress < self.progress &&
+      self.backwardProgressAnimationMode == MDCProgressViewBackwardAnimationModeReset) {
+    self.progress = 0;
+    [self updateProgressView];
+  }
+
+  self.progress = progress;
+  [UIView animateWithDuration:animated ? [[self class] animationDuration] : 0
+                        delay:0
+                      options:[[self class] animationOptions]
+                   animations:^{
+                     [self updateProgressView];
+                   }
+                   completion:completion];
+}
+
+- (void)setHidden:(BOOL)hidden {
+  [super setHidden:hidden];
+  UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, hidden ? nil : self);
+}
+
+- (void)setHidden:(BOOL)hidden
+         animated:(BOOL)animated
+       completion:(void (^__nullable)(BOOL finished))completion {
+  if (hidden == self.hidden) {
+    if (completion) {
+      completion(YES);
+    }
+    return;
+  }
+
+  void (^animations)(void);
+
+  if (hidden) {
+    self.animatingHide = YES;
+    animations = ^{
+      CGFloat y = CGRectGetHeight(self.bounds);
+
+      CGRect trackViewFrame = self.trackView.frame;
+      trackViewFrame.origin.y = y;
+      trackViewFrame.size.height = 0;
+      self.trackView.frame = trackViewFrame;
+
+      CGRect progressViewFrame = self.progressView.frame;
+      progressViewFrame.origin.y = y;
+      progressViewFrame.size.height = 0;
+      self.progressView.frame = progressViewFrame;
+    };
+  } else {
+    self.hidden = NO;
+    animations = ^{
+      self.trackView.frame = self.bounds;
+
+      CGRect progressViewFrame = self.progressView.frame;
+      progressViewFrame.origin.y = 0;
+      progressViewFrame.size.height = CGRectGetHeight(self.bounds);
+      self.progressView.frame = progressViewFrame;
+    };
+  }
+
+  [UIView animateWithDuration:animated ? [[self class] animationDuration] : 0
+                        delay:0
+                      options:[[self class] animationOptions]
+                   animations:animations
+                   completion:^(BOOL finished) {
+                     if (hidden) {
+                       self.animatingHide = NO;
+                       self.hidden = YES;
+                     }
+                     if (completion)
+                       completion(finished);
+                   }];
+}
+
+#pragma mark Accessibility
+
+- (UIProgressView *)accessibilityProgressView {
+  // Accessibility values are determined by querying a UIProgressView set to the same value as our
+  // MDCProgressView.
+  static UIProgressView *accessibilityProgressView;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    accessibilityProgressView = [[UIProgressView alloc] init];
+  });
+
+  return accessibilityProgressView;
+}
+
+- (NSString *)accessibilityValue {
+  self.accessibilityProgressView.progress = self.progress;
+  return self.accessibilityProgressView.accessibilityValue;
+}
+
+- (void)accessibilityValueDidChange {
+  // Store a strong reference to self until the end of the method. Indeed,
+  // a previous -performSelector:withObject:afterDelay: might be the last thing
+  // to retain self, so calling +cancelPreviousPerformRequestsWithTarget: might
+  // deallocate self.
+  MDCProgressView *strongSelf = self;
+  // Cancel unprocessed announcements and replace them with the most up-to-date
+  // value. That way, they don't overlap and don't spam the user.
+  [NSObject cancelPreviousPerformRequestsWithTarget:strongSelf
+                                           selector:@selector(announceAccessibilityValueChange)
+                                             object:nil];
+  // Schedule a new announcement.
+  [strongSelf performSelector:@selector(announceAccessibilityValueChange)
+                   withObject:nil
+                   afterDelay:1];
+}
+
+- (void)announceAccessibilityValueChange {
+  if ([self accessibilityElementIsFocused]) {
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    [self accessibilityValue]);
+  }
+}
+
+#pragma mark Private
+
++ (NSTimeInterval)animationDuration {
+  return MDCProgressViewAnimationDuration;
+}
+
++ (UIViewAnimationOptions)animationOptions {
+  // Since the animation is fake, using a linear interpolation avoids the speeding up and slowing
+  // down that repeated easing in and out causes.
+  return UIViewAnimationOptionCurveLinear;
+}
+
++ (UIColor *)defaultProgressTintColor {
+  return MDCColorFromRGB(MDCProgressViewDefaultTintColor);
+}
+
++ (UIColor *)defaultTrackTintColorForProgressTintColor:(UIColor *)progressTintColor {
+  CGFloat hue, saturation, brightness, alpha;
+  if ([progressTintColor getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
+    CGFloat newSaturation = MIN(saturation * MDCProgressViewTrackColorDesaturation, 1.0f);
+    return [UIColor colorWithHue:hue saturation:newSaturation brightness:brightness alpha:alpha];
+  }
+  return [UIColor clearColor];
+}
+
+- (void)updateProgressView {
+  // Update progressView with the current progress value.
+  CGFloat progressWidth = ceil(self.progress * CGRectGetWidth(self.bounds));
+  CGRect progressFrame = CGRectMake(0, 0, progressWidth, CGRectGetHeight(self.bounds));
+  self.progressView.frame = MDCRectFlippedForRTL(progressFrame, CGRectGetWidth(self.bounds),
+                                                 self.mdc_effectiveUserInterfaceLayoutDirection);
+}
+
+- (void)updateTrackView {
+  const CGSize size = self.bounds.size;
+  self.trackView.frame = self.hidden ? CGRectMake(0.0, size.height, size.width, 0.0) : self.bounds;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MaterialProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MaterialProgressView.h
new file mode 100644
index 0000000..9c844f6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ProgressView/src/MaterialProgressView.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCProgressView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
new file mode 100644
index 0000000..10c620a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
@@ -0,0 +1,83 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <CoreGraphics/CoreGraphics.h>
+
+/** The shadow elevation of the app bar. */
+CG_EXTERN const CGFloat MDCShadowElevationAppBar;
+
+/** The shadow elevation of a card in its picked up state. */
+CG_EXTERN const CGFloat MDCShadowElevationCardPickedUp;
+
+/** The shadow elevation of a card in its resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationCardResting;
+
+/** The shadow elevation of dialogs. */
+CG_EXTERN const CGFloat MDCShadowElevationDialog;
+
+/** The shadow elevation of the floating action button in its pressed state. */
+CG_EXTERN const CGFloat MDCShadowElevationFABPressed;
+
+/** The shadow elevation of the floating action button in its resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationFABResting;
+
+/** The shadow elevation of a menu. */
+CG_EXTERN const CGFloat MDCShadowElevationMenu;
+
+/** The shadow elevation of a modal bottom sheet. */
+CG_EXTERN const CGFloat MDCShadowElevationModalBottomSheet;
+
+/** The shadow elevation of the navigation drawer. */
+CG_EXTERN const CGFloat MDCShadowElevationNavDrawer;
+
+/** No shadow elevation at all. */
+CG_EXTERN const CGFloat MDCShadowElevationNone;
+
+/** The shadow elevation of a picker. */
+CG_EXTERN const CGFloat MDCShadowElevationPicker;
+
+/** The shadow elevation of the quick entry in the scrolled state. */
+CG_EXTERN const CGFloat MDCShadowElevationQuickEntry;
+
+/** The shadow elevation of the quick entry in the resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationQuickEntryResting;
+
+/** The shadow elevation of a raised button in the pressed state. */
+CG_EXTERN const CGFloat MDCShadowElevationRaisedButtonPressed;
+
+/** The shadow elevation of a raised button in the resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationRaisedButtonResting;
+
+/** The shadow elevation of a refresh indicator. */
+CG_EXTERN const CGFloat MDCShadowElevationRefresh;
+
+/** The shadow elevation of the right drawer. */
+CG_EXTERN const CGFloat MDCShadowElevationRightDrawer;
+
+/** The shadow elevation of the search bar in the resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationSearchBarResting;
+
+/** The shadow elevation of the search bar in the scrolled state. */
+CG_EXTERN const CGFloat MDCShadowElevationSearchBarScrolled;
+
+/** The shadow elevation of the snackbar. */
+CG_EXTERN const CGFloat MDCShadowElevationSnackbar;
+
+/** The shadow elevation of a sub menu (+1 for each additional sub menu). */
+CG_EXTERN const CGFloat MDCShadowElevationSubMenu;
+
+/** The shadow elevation of a switch. */
+CG_EXTERN const CGFloat MDCShadowElevationSwitch;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.m
new file mode 100644
index 0000000..182f951
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.m
@@ -0,0 +1,40 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowElevations.h"
+
+const CGFloat MDCShadowElevationAppBar = 4.f;
+const CGFloat MDCShadowElevationCardPickedUp = 8.f;
+const CGFloat MDCShadowElevationCardResting = 2.f;
+const CGFloat MDCShadowElevationDialog = 24.f;
+const CGFloat MDCShadowElevationFABPressed = 12.f;
+const CGFloat MDCShadowElevationFABResting = 6.f;
+const CGFloat MDCShadowElevationMenu = 8.f;
+const CGFloat MDCShadowElevationModalBottomSheet = 16.f;
+const CGFloat MDCShadowElevationNavDrawer = 16.f;
+const CGFloat MDCShadowElevationNone = 0;
+const CGFloat MDCShadowElevationPicker = 24.f;
+const CGFloat MDCShadowElevationQuickEntry = 3.f;
+const CGFloat MDCShadowElevationQuickEntryResting = 2.f;
+const CGFloat MDCShadowElevationRaisedButtonPressed = 8.f;
+const CGFloat MDCShadowElevationRaisedButtonResting = 2.f;
+const CGFloat MDCShadowElevationRefresh = 3.f;
+const CGFloat MDCShadowElevationRightDrawer = 16.f;
+const CGFloat MDCShadowElevationSearchBarResting = 2.f;
+const CGFloat MDCShadowElevationSearchBarScrolled = 3.f;
+const CGFloat MDCShadowElevationSnackbar = 6.f;
+const CGFloat MDCShadowElevationSubMenu = 9.f;
+const CGFloat MDCShadowElevationSwitch = 1.f;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
new file mode 100644
index 0000000..3a62377
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowElevations.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
new file mode 100644
index 0000000..7fe6b46
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
@@ -0,0 +1,78 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Metrics of the Material shadow effect.
+
+ These can be used if you require your own shadow implementation but want to match the material
+ spec.
+ */
+@interface MDCShadowMetrics : NSObject
+@property(nonatomic, readonly) CGFloat topShadowRadius;
+@property(nonatomic, readonly) CGSize topShadowOffset;
+@property(nonatomic, readonly) float topShadowOpacity;
+@property(nonatomic, readonly) CGFloat bottomShadowRadius;
+@property(nonatomic, readonly) CGSize bottomShadowOffset;
+@property(nonatomic, readonly) float bottomShadowOpacity;
+
+/**
+ The shadow metrics for manually creating shadows given an elevation.
+
+ @param elevation The shadow's elevation in points.
+ @return The shadow metrics.
+ */
++ (nonnull MDCShadowMetrics *)metricsWithElevation:(CGFloat)elevation;
+@end
+
+/**
+ The Material shadow effect.
+
+ @see
+ https://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-shadows
+
+ Consider rasterizing your MDCShadowLayer if your view will not generally be animating or
+ changing size. If you need to animate a rasterized MDCShadowLayer, disable rasterization first.
+
+ For example, if self's layerClass is MDCShadowLayer, you might introduce the following code:
+
+     self.layer.shouldRasterize = YES;
+     self.layer.rasterizationScale = [UIScreen mainScreen].scale;
+ */
+@interface MDCShadowLayer : CALayer
+
+/**
+ The elevation of the layer in points.
+
+ The higher the elevation, the more spread out the shadow is. This is distinct from the layer's
+ zPosition which can be used to order overlapping layers, but will have no affect on the size of
+ the shadow.
+
+ Negative values act as if zero were specified.
+ */
+@property(nonatomic, assign) CGFloat elevation;
+
+/**
+ Whether to apply the "cutout" shadow layer mask.
+
+ If enabled, then a mask is created to ensure the interior, non-shadow part of the layer is visible.
+
+ Default is YES. Not animatable.
+ */
+@property(nonatomic, getter=isShadowMaskEnabled, assign) BOOL shadowMaskEnabled;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.m
new file mode 100644
index 0000000..ef690ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.m
@@ -0,0 +1,353 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowLayer.h"
+
+static const CGFloat kShadowElevationDialog = 24.0;
+static const float kKeyShadowOpacity = 0.26f;
+static const float kAmbientShadowOpacity = 0.08f;
+
+static NSString *const MDCShadowLayerElevationKey = @"MDCShadowLayerElevationKey";
+static NSString *const MDCShadowLayerShadowMaskEnabledKey = @"MDCShadowLayerShadowMaskEnabledKey";
+
+@implementation MDCShadowMetrics
+
++ (MDCShadowMetrics *)metricsWithElevation:(CGFloat)elevation {
+  if (0.0 < elevation) {
+    return [[MDCShadowMetrics alloc] initWithElevation:elevation];
+  } else {
+    return [MDCShadowMetrics emptyShadowMetrics];
+  }
+}
+
+- (MDCShadowMetrics *)initWithElevation:(CGFloat)elevation {
+  self = [super init];
+  if (self) {
+    _topShadowRadius = [MDCShadowMetrics ambientShadowBlur:elevation];
+    _topShadowOffset = CGSizeMake(0.0, 0.0);
+    _topShadowOpacity = kAmbientShadowOpacity;
+    _bottomShadowRadius = [MDCShadowMetrics keyShadowBlur:elevation];
+    _bottomShadowOffset = CGSizeMake(0.0, [MDCShadowMetrics keyShadowYOff:elevation]);
+    _bottomShadowOpacity = kKeyShadowOpacity;
+  }
+  return self;
+}
+
++ (MDCShadowMetrics *)emptyShadowMetrics {
+  static MDCShadowMetrics *emptyShadowMetrics;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+    emptyShadowMetrics = [[MDCShadowMetrics alloc] init];
+    emptyShadowMetrics->_topShadowRadius = (CGFloat)0.0;
+    emptyShadowMetrics->_topShadowOffset = CGSizeMake(0.0, 0.0);
+    emptyShadowMetrics->_topShadowOpacity = 0.0f;
+    emptyShadowMetrics->_bottomShadowRadius = (CGFloat)0.0;
+    emptyShadowMetrics->_bottomShadowOffset = CGSizeMake(0.0, 0.0);
+    emptyShadowMetrics->_bottomShadowOpacity = 0.0f;
+  });
+
+  return emptyShadowMetrics;
+}
+
++ (CGFloat)ambientShadowBlur:(CGFloat)points {
+  CGFloat blur = 0.889544f * points - 0.003701f;
+  return blur;
+}
+
++ (CGFloat)keyShadowBlur:(CGFloat)points {
+  CGFloat blur = 0.666920f * points - 0.001648f;
+  return blur;
+}
+
++ (CGFloat)keyShadowYOff:(CGFloat)points {
+  CGFloat yOff = 1.23118f * points - 0.03933f;
+  return yOff;
+}
+
+@end
+
+@interface MDCShadowLayer ()
+
+@property(nonatomic, strong) CAShapeLayer *topShadow;
+@property(nonatomic, strong) CAShapeLayer *bottomShadow;
+
+@end
+
+@implementation MDCShadowLayer
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _elevation = 0;
+    _shadowMaskEnabled = YES;
+
+    [self commonMDCShadowLayerInit];
+  }
+  return self;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCShadowLayerElevationKey]) {
+      _elevation = (CGFloat)[aDecoder decodeDoubleForKey:MDCShadowLayerElevationKey];
+    }
+    if ([aDecoder containsValueForKey:MDCShadowLayerShadowMaskEnabledKey]) {
+      _shadowMaskEnabled = [aDecoder decodeBoolForKey:MDCShadowLayerShadowMaskEnabledKey];
+    }
+
+    [self commonMDCShadowLayerInit];
+  }
+  return self;
+}
+
+/**
+ commonMDCShadowLayerInit creates additional layers based on the values of _elevation and
+ _shadowMaskEnabled.
+ */
+- (void)commonMDCShadowLayerInit {
+  _bottomShadow = [CAShapeLayer layer];
+  _bottomShadow.backgroundColor = [UIColor clearColor].CGColor;
+  _bottomShadow.shadowColor = [UIColor blackColor].CGColor;
+  [self addSublayer:_bottomShadow];
+
+  _topShadow = [CAShapeLayer layer];
+  _topShadow.backgroundColor = [UIColor clearColor].CGColor;
+  _topShadow.shadowColor = [UIColor blackColor].CGColor;
+  [self addSublayer:_topShadow];
+
+  // Setup shadow layer state based off _elevation and _shadowMaskEnabled
+  MDCShadowMetrics *shadowMetrics = [MDCShadowMetrics metricsWithElevation:_elevation];
+  _topShadow.shadowOffset = shadowMetrics.topShadowOffset;
+  _topShadow.shadowRadius = shadowMetrics.topShadowRadius;
+  _topShadow.shadowOpacity = shadowMetrics.topShadowOpacity;
+  _bottomShadow.shadowOffset = shadowMetrics.bottomShadowOffset;
+  _bottomShadow.shadowRadius = shadowMetrics.bottomShadowRadius;
+  _bottomShadow.shadowOpacity = shadowMetrics.bottomShadowOpacity;
+
+  // TODO(#1021): We shouldn't be calling property accessors in an init method.
+  if (_shadowMaskEnabled) {
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+  }
+}
+
+// TODO(#993): Implement missing initWithLayer:
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeDouble:_elevation forKey:MDCShadowLayerElevationKey];
+  [aCoder encodeBool:_shadowMaskEnabled forKey:MDCShadowLayerShadowMaskEnabledKey];
+  // Additional state is calculated at deserialization time based on _elevation and
+  // _shadowMaskEnabled so we don't need to store them.
+}
+
+- (void)layoutSublayers {
+  [super layoutSublayers];
+  [self commonLayoutSublayers];
+}
+
+- (void)setBounds:(CGRect)bounds {
+  BOOL sizeChanged = !CGSizeEqualToSize(self.bounds.size, bounds.size);
+  [super setBounds:bounds];
+  if (sizeChanged) {
+    // Invalidate our shadow paths.
+    _bottomShadow.shadowPath = nil;
+    _topShadow.shadowPath = nil;
+    [self setNeedsLayout];
+  }
+}
+
+#pragma mark - CALayer change monitoring.
+
+/** Returns a shadowPath based on the layer properties. */
+- (UIBezierPath *)defaultShadowPath {
+  CGFloat cornerRadius = self.cornerRadius;
+  if (0.0 < cornerRadius) {
+    return [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:cornerRadius];
+  }
+  return [UIBezierPath bezierPathWithRect:self.bounds];
+}
+
+- (void)setShadowPath:(CGPathRef)shadowPath {
+  super.shadowPath = shadowPath;
+  _topShadow.shadowPath = shadowPath;
+  _bottomShadow.shadowPath = shadowPath;
+  if (_shadowMaskEnabled) {
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+  }
+}
+
+- (void)setShadowColor:(CGColorRef)shadowColor {
+  super.shadowColor = shadowColor;
+  _topShadow.shadowColor = shadowColor;
+  _bottomShadow.shadowColor = shadowColor;
+}
+
+#pragma mark - shouldRasterize forwarding
+
+- (void)setShouldRasterize:(BOOL)shouldRasterize {
+  [super setShouldRasterize:shouldRasterize];
+  _topShadow.shouldRasterize = shouldRasterize;
+  _bottomShadow.shouldRasterize = shouldRasterize;
+}
+
+#pragma mark - Shadow Spread
+
+// Returns how far aware the shadow is spread from the edge of the layer.
++ (CGSize)shadowSpreadForElevation:(CGFloat)elevation {
+  MDCShadowMetrics *metrics = [MDCShadowMetrics metricsWithElevation:elevation];
+
+  CGSize shadowSpread = CGSizeZero;
+  shadowSpread.width = MAX(metrics.topShadowRadius, metrics.bottomShadowRadius) +
+                       MAX(metrics.topShadowOffset.width, metrics.bottomShadowOffset.width);
+  shadowSpread.height = MAX(metrics.topShadowRadius, metrics.bottomShadowRadius) +
+                        MAX(metrics.topShadowOffset.height, metrics.bottomShadowOffset.height);
+
+  return shadowSpread;
+}
+
+#pragma mark - Pseudo Shadow Masks
+
+- (void)setShadowMaskEnabled:(BOOL)shadowMaskEnabled {
+  _shadowMaskEnabled = shadowMaskEnabled;
+  if (_shadowMaskEnabled) {
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+  } else {
+    _topShadow.mask = nil;
+    _bottomShadow.mask = nil;
+  }
+}
+
+// Creates a layer mask that has a hole cut inside so that the original contents
+// of the view is no obscured by the shadow the top/bottom pseudo shadow layers
+// cast.
+- (CAShapeLayer *)shadowLayerMaskForLayer:(CALayer *)layer {
+  CAShapeLayer *maskLayer = [CAShapeLayer layer];
+
+  CGSize shadowSpread = [MDCShadowLayer shadowSpreadForElevation:kShadowElevationDialog];
+  CGRect bounds = layer.bounds;
+  CGRect maskRect = CGRectInset(bounds, -shadowSpread.width * 2, -shadowSpread.height * 2);
+
+  UIBezierPath *path = [UIBezierPath bezierPathWithRect:maskRect];
+  UIBezierPath *innerPath = nil;
+  if (self.shadowPath != nil) {
+    innerPath = [UIBezierPath bezierPathWithCGPath:(_Nonnull CGPathRef)self.shadowPath];
+  } else if (self.cornerRadius > 0) {
+    innerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.cornerRadius];
+  } else {
+    innerPath = [UIBezierPath bezierPathWithRect:self.bounds];
+  }
+  [path appendPath:innerPath];
+  [path setUsesEvenOddFillRule:YES];
+
+  maskLayer.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
+  maskLayer.bounds = maskRect;
+  maskLayer.path = path.CGPath;
+  maskLayer.fillRule = kCAFillRuleEvenOdd;
+  maskLayer.fillColor = [UIColor blackColor].CGColor;
+  return maskLayer;
+}
+
+- (void)setElevation:(CGFloat)elevation {
+  _elevation = elevation;
+  MDCShadowMetrics *shadowMetrics = [MDCShadowMetrics metricsWithElevation:elevation];
+  [self setMetrics:shadowMetrics];
+}
+
+- (void)setMetrics:(MDCShadowMetrics *)shadowMetrics {
+  CABasicAnimation *topOffsetAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOffset"];
+  topOffsetAnimation.fromValue = nil;
+  topOffsetAnimation.toValue = [NSValue valueWithCGSize:shadowMetrics.topShadowOffset];
+
+  CABasicAnimation *bottomOffsetAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOffset"];
+  bottomOffsetAnimation.fromValue = nil;
+  bottomOffsetAnimation.toValue = [NSValue valueWithCGSize:shadowMetrics.bottomShadowOffset];
+
+  CABasicAnimation *topRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"shadowRadius"];
+  topRadiusAnimation.fromValue = nil;
+  topRadiusAnimation.toValue = @(shadowMetrics.topShadowRadius);
+
+  CABasicAnimation *bottomRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"shadowRadius"];
+  bottomRadiusAnimation.fromValue = nil;
+  bottomRadiusAnimation.toValue = @(shadowMetrics.bottomShadowRadius);
+
+  CABasicAnimation *topOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
+  topOpacityAnimation.fromValue = nil;
+  topOpacityAnimation.toValue = @(shadowMetrics.topShadowOpacity);
+
+  CABasicAnimation *bottomOpacityAnimation =
+      [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
+  bottomOpacityAnimation.fromValue = nil;
+  bottomOpacityAnimation.toValue = @(shadowMetrics.bottomShadowOpacity);
+
+  // Group all animations together.
+  CAAnimationGroup *topAnimations = [CAAnimationGroup animation];
+  topAnimations.animations = @[ topOffsetAnimation, topRadiusAnimation, topOpacityAnimation ];
+
+  CAAnimationGroup *bottomAnimations = [CAAnimationGroup animation];
+  bottomAnimations.animations =
+      @[ bottomOffsetAnimation, bottomRadiusAnimation, bottomOpacityAnimation ];
+
+  [_topShadow removeAllAnimations];
+  [_bottomShadow removeAllAnimations];
+  [_topShadow addAnimation:topAnimations forKey:nil];
+  [_bottomShadow addAnimation:bottomAnimations forKey:nil];
+
+  // Set the final animation value in to the model layer.
+  _topShadow.shadowOffset = shadowMetrics.topShadowOffset;
+  _topShadow.shadowRadius = shadowMetrics.topShadowRadius;
+  _topShadow.shadowOpacity = shadowMetrics.topShadowOpacity;
+  _bottomShadow.shadowOffset = shadowMetrics.bottomShadowOffset;
+  _bottomShadow.shadowRadius = shadowMetrics.bottomShadowRadius;
+  _bottomShadow.shadowOpacity = shadowMetrics.bottomShadowOpacity;
+}
+
+#pragma mark - Private
+
+- (void)commonLayoutSublayers {
+  CGRect bounds = self.bounds;
+
+  _bottomShadow.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
+  _bottomShadow.bounds = bounds;
+  _topShadow.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
+  _topShadow.bounds = bounds;
+
+  if (_shadowMaskEnabled) {
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+  }
+  // Enforce shadowPaths because otherwise no shadows can be drawn. If a shadowPath
+  // is already set, use that, otherwise fallback to just a regular rect because path.
+  if (!_bottomShadow.shadowPath) {
+    if (self.shadowPath) {
+      _bottomShadow.shadowPath = self.shadowPath;
+    } else {
+      _bottomShadow.shadowPath = [self defaultShadowPath].CGPath;
+    }
+  }
+  if (!_topShadow.shadowPath) {
+    if (self.shadowPath) {
+      _topShadow.shadowPath = self.shadowPath;
+    } else {
+      _topShadow.shadowPath = [self defaultShadowPath].CGPath;
+    }
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
new file mode 100644
index 0000000..baf9ce6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowLayer.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MDCSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MDCSlider.h
new file mode 100644
index 0000000..018e462
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MDCSlider.h
@@ -0,0 +1,196 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCSliderDelegate;
+
+/**
+ A Material slider.
+
+ @see https://www.google.com/design/spec/components/sliders.html for full details.
+
+ Differences between UISlider and MDCSlider:
+   Does not have api to
+     set right and left icons
+     set the thumb image
+     set the right and left track images (if you wanted a custom track)
+     set the right (background track) color
+   Same features
+     set color for thumb via @c thumbColor
+     set color of track via @c trackColor
+   New features
+     making the slider a snap to discrete values via @c numberOfDiscreteValues.
+ */
+IB_DESIGNABLE
+@interface MDCSlider : UIControl <NSSecureCoding>
+
+/** The delegate for the slider. */
+@property(nullable, nonatomic, weak) id<MDCSliderDelegate> delegate;
+
+/**
+ The color of the cursor (thumb) and filled in portion of the track (left side).
+
+ Default color is blue.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *color;
+
+/*
+ The color of the unfilled track that the cursor moves along (right side).
+
+ Default color is gray.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *trackBackgroundColor;
+
+/**
+ The number of discrete values that the slider can take.
+
+ If greater than or equal to 2, the thumb will snap to the nearest discrete value when the user
+ lifts their finger or taps. The discrete values are evenly spaced between the @c minimumValue and
+ @c maximumValue. If 0 or 1, the slider's value will not change when the user releases the thumb.
+
+ The default value is zero.
+ */
+@property(nonatomic, assign) NSUInteger numberOfDiscreteValues;
+
+/**
+ The value of the slider.
+
+ To animate from the current value to the new value, instead use @see setValue:animated:. The value
+ will be clamped between @c minimumValue and @c maximumValue. Setting the value will not send an
+ action message.
+
+ The default value of this property is 0.
+ */
+@property(nonatomic, assign) CGFloat value;
+
+/**
+ Set the value of the slider, allowing you to animate the change visually.
+
+ If animated is YES, the thumb is animated into its new position. Setting the value does not
+ result in an action message being sent.
+
+ @param value The value to set the slider to.
+ @param animated If YES, the thumb will animate to its new position.
+ */
+- (void)setValue:(CGFloat)value animated:(BOOL)animated;
+
+/**
+ The minimum value of the slider.
+
+ If you change the value of this property and the @c value of the receiver is below the new minimum,
+ the current value will be adjusted to match the new minimum value.
+ If you change the value of this property and @c maximumValue of the receiver is below the new
+ minimum, the @c maximumValue will also be set to this new minimum value.
+
+ The default value of this property is 0.0.
+ */
+@property(nonatomic, assign) CGFloat minimumValue;
+
+/**
+ The maximum value of the slider.
+
+ If you change the value of this property and the @c value of the receiver is above the new maximum,
+ the current value will be adjusted to match the new maximum value.
+ If you change the value of this property and @c minimumValue of the receiver is above the new
+ maximum, the @c minimumValue will also be set to this new maximum value.
+
+ The default value of this property is 1.0.
+ */
+@property(nonatomic, assign) CGFloat maximumValue;
+
+/**
+ Indicates  whether changes in the slider's value generate continuous update events.
+
+ If YES, the slider sends update events continuously to the associated target's action method.
+ If NO, the slider only sends an action event when the user releases the slider's thumb control to
+ set the final value.
+
+ The default value of this property is YES.
+ */
+@property(nonatomic, assign, getter=isContinuous) BOOL continuous;
+
+/**
+ The value from which the filled part of the track is anchored. If set to a value between
+ minimumValue and maximumValue, then the filled/colored part of the track extends from the
+ trackAnchorValue to the thumb. Values beyond the minimum/maximum values are effectively capped.
+
+ The default value is -CGFLOAT_MAX, so the filled part of the track extends from the minimum value
+ to the thumb.
+ */
+@property(nonatomic, assign) CGFloat filledTrackAnchorValue;
+
+/**
+ Whether or not to show the numeric value label when dragging a discrete slider. If YES, consider
+ implementing MDCSliderDelegate's @c -slider:displayedStringForValue: method to customize the string
+ displayed for each discrete value.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL shouldDisplayDiscreteValueLabel;
+
+/**
+ Whether or not the thumb view should be a hollow circle when at the minimum value. For sliders
+ where the minimum value indicates that the associated property is off (for example a volume slider
+ where a value of 0 = muted), this should be set to YES. In cases where this doesn't make sense (for
+ instance a scrubber of an audio or video file), this should be set to NO.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign, getter=isThumbHollowAtStart) BOOL thumbHollowAtStart;
+
+@end
+
+/** MDCSlider delegate which allows setting custom behavior. */
+@protocol MDCSliderDelegate <NSObject>
+@optional
+
+/**
+ Called when the user taps on the MDCSlider.
+
+ If not implemented, the MDCSlider will always be allowed to jump to any value.
+ */
+- (BOOL)slider:(nonnull MDCSlider *)slider shouldJumpToValue:(CGFloat)value;
+
+/**
+ For discrete sliders, called when the slider is determining the string label to display for a given
+ discrete value.
+
+ If not implemented, or if no slider delegate is specified, the slider defaults to displaying the
+ value rounded to the closest relevant digit. For instance, 0.50000 would become "0.5"
+
+ Override this to provide custom behavior, for instance if your slider deals in percentages, the
+ above example could become "50%"
+
+ @param slider The MDCSlider sender.
+ @param value The value whose label needs to be calculated.
+ */
+- (nonnull NSString *)slider:(nonnull MDCSlider *)slider displayedStringForValue:(CGFloat)value;
+
+/**
+ Used to determine what string value should be used as the accessibility string for a given value.
+
+ If not implemented, or if no slider delegate is specified, the slider defaults to how filled the
+ slider is, as a percentage. Override this method to provide custom behavior, and when implementing,
+ you may want to also implement @c -slider:displayedStringForValue: to ensure consistency between
+ the displayed value and the accessibility label.
+
+ @param slider The MDCSlider sender.
+ @param value The value whose accessibility label needs to be calculated.
+ */
+- (nonnull NSString *)slider:(nonnull MDCSlider *)slider accessibilityLabelForValue:(CGFloat)value;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MDCSlider.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MDCSlider.m
new file mode 100644
index 0000000..ee831e1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MDCSlider.m
@@ -0,0 +1,343 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSlider.h"
+#import "private/MDCSlider_Subclassable.h"
+
+#import "MaterialThumbTrack.h"
+
+static const CGFloat kSliderDefaultWidth = 100.0f;
+static const CGFloat kSliderFrameHeight = 27.0f;
+static const CGFloat kSliderMinTouchSize = 48.0f;
+static const CGFloat kSliderThumbRadius = 6.0f;
+static const CGFloat kSliderAccessibilityIncrement = 0.1f;  // Matches UISlider's percent increment.
+static const CGFloat kSliderLightThemeTrackAlpha = 0.26f;
+
+// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t MDCBlueColor = 0x2196F3;
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+@interface MDCSlider () <MDCThumbTrackDelegate>
+
+@end
+
+@implementation MDCSlider
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCSliderInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCSliderInit];
+  }
+  return self;
+}
+
+- (void)commonMDCSliderInit {
+  _thumbTrack =
+      [[MDCThumbTrack alloc] initWithFrame:self.bounds onTintColor:[[self class] defaultColor]];
+  _thumbTrack.delegate = self;
+  _thumbTrack.disabledTrackHasThumbGaps = YES;
+  _thumbTrack.trackEndsAreInset = YES;
+  _thumbTrack.thumbRadius = kSliderThumbRadius;
+  _thumbTrack.thumbIsSmallerWhenDisabled = YES;
+  _thumbTrack.thumbIsHollowAtStart = YES;
+  _thumbTrack.thumbGrowsWhenDragging = YES;
+  _thumbTrack.shouldDisplayInk = NO;
+  _thumbTrack.shouldDisplayDiscreteDots = YES;
+  _thumbTrack.shouldDisplayDiscreteValueLabel = YES;
+  _thumbTrack.trackOffColor = [[self class] defaultTrackOffColor];
+  _thumbTrack.thumbDisabledColor = [[self class] defaultDisabledColor];
+  _thumbTrack.trackDisabledColor = [[self class] defaultDisabledColor];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackValueChanged:)
+        forControlEvents:UIControlEventValueChanged];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchDown:)
+        forControlEvents:UIControlEventTouchDown];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchUpInside:)
+        forControlEvents:UIControlEventTouchUpInside];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchUpOutside:)
+        forControlEvents:UIControlEventTouchUpOutside];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchCanceled:)
+        forControlEvents:UIControlEventTouchCancel];
+  [self addSubview:_thumbTrack];
+}
+
+#pragma mark - ThumbTrack passthrough methods
+
+- (void)setTrackBackgroundColor:(UIColor *)trackBackgroundColor {
+  _thumbTrack.trackOffColor = trackBackgroundColor ?: [[self class] defaultTrackOffColor];
+  ;
+}
+
+- (UIColor *)trackBackgroundColor {
+  return _thumbTrack.trackOffColor;
+}
+
+- (void)setColor:(UIColor *)color {
+  _thumbTrack.primaryColor = color ?: [[self class] defaultColor];
+}
+
+- (UIColor *)color {
+  return _thumbTrack.primaryColor;
+}
+
+- (NSUInteger)numberOfDiscreteValues {
+  return _thumbTrack.numDiscreteValues;
+}
+
+- (void)setNumberOfDiscreteValues:(NSUInteger)numberOfDiscreteValues {
+  _thumbTrack.numDiscreteValues = numberOfDiscreteValues;
+}
+
+- (BOOL)isContinuous {
+  return _thumbTrack.continuousUpdateEvents;
+}
+
+- (void)setContinuous:(BOOL)continuous {
+  _thumbTrack.continuousUpdateEvents = continuous;
+}
+
+- (CGFloat)value {
+  return _thumbTrack.value;
+}
+
+- (void)setValue:(CGFloat)value {
+  _thumbTrack.value = value;
+}
+
+- (void)setValue:(CGFloat)value animated:(BOOL)animated {
+  [_thumbTrack setValue:value animated:animated];
+}
+
+- (CGFloat)minimumValue {
+  return _thumbTrack.minimumValue;
+}
+
+- (void)setMinimumValue:(CGFloat)minimumValue {
+  _thumbTrack.minimumValue = minimumValue;
+}
+
+- (CGFloat)maximumValue {
+  return _thumbTrack.maximumValue;
+}
+
+- (void)setMaximumValue:(CGFloat)maximumValue {
+  _thumbTrack.maximumValue = maximumValue;
+}
+
+- (CGFloat)filledTrackAnchorValue {
+  return _thumbTrack.filledTrackAnchorValue;
+}
+
+- (void)setFilledTrackAnchorValue:(CGFloat)filledTrackAnchorValue {
+  _thumbTrack.filledTrackAnchorValue = filledTrackAnchorValue;
+}
+
+- (BOOL)shouldDisplayDiscreteValueLabel {
+  return _thumbTrack.shouldDisplayDiscreteValueLabel;
+}
+
+- (void)setShouldDisplayDiscreteValueLabel:(BOOL)shouldDisplayDiscreteValueLabel {
+  _thumbTrack.shouldDisplayDiscreteValueLabel = shouldDisplayDiscreteValueLabel;
+}
+
+- (BOOL)isThumbHollowAtStart {
+  return _thumbTrack.thumbIsHollowAtStart;
+}
+
+- (void)setThumbHollowAtStart:(BOOL)thumbHollowAtStart {
+  _thumbTrack.thumbIsHollowAtStart = thumbHollowAtStart;
+}
+
+#pragma mark - MDCThumbTrackDelegate methods
+
+- (NSString *)thumbTrack:(MDCThumbTrack *)thumbTrack stringForValue:(CGFloat)value {
+  if ([_delegate respondsToSelector:@selector(slider:displayedStringForValue:)]) {
+    return [_delegate slider:self displayedStringForValue:value];
+  }
+
+  // Default behavior
+
+  static dispatch_once_t onceToken;
+  static NSNumberFormatter *numberFormatter;
+  dispatch_once(&onceToken, ^{
+    numberFormatter = [[NSNumberFormatter alloc] init];
+    numberFormatter.maximumFractionDigits = 3;
+    numberFormatter.minimumIntegerDigits = 1;  // To get 0.5 instead of .5
+  });
+  return [numberFormatter stringFromNumber:@(value)];
+}
+
+- (BOOL)thumbTrack:(MDCThumbTrack *)thumbTrack shouldJumpToValue:(CGFloat)value {
+  return ![_delegate respondsToSelector:@selector(slider:shouldJumpToValue:)] ||
+         [_delegate slider:self shouldJumpToValue:value];
+}
+
+#pragma mark - UIControl methods
+
+- (void)setEnabled:(BOOL)enabled {
+  [super setEnabled:enabled];
+  _thumbTrack.enabled = enabled;
+}
+
+- (BOOL)isTracking {
+  return _thumbTrack.isTracking;
+}
+
+#pragma mark - UIView methods
+
+- (CGSize)intrinsicContentSize {
+  return CGSizeMake(kSliderDefaultWidth, kSliderFrameHeight);
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  CGFloat dx = MIN(0, kSliderThumbRadius - kSliderMinTouchSize / 2);
+  CGFloat dy = MIN(0, (self.bounds.size.height - kSliderMinTouchSize) / 2);
+  CGRect rect = CGRectInset(self.bounds, dx, dy);
+  return CGRectContainsPoint(rect, point);
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  _thumbTrack.frame = self.bounds;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  CGSize result = self.bounds.size;
+  result.height = kSliderFrameHeight;
+  return result;
+}
+
+#pragma mark - Accessibility
+
+- (BOOL)isAccessibilityElement {
+  return YES;
+}
+
+- (NSString *)accessibilityValue {
+  if ([_delegate respondsToSelector:@selector(slider:accessibilityLabelForValue:)]) {
+    return [_delegate slider:self accessibilityLabelForValue:self.value];
+  }
+
+  // Default behavior
+
+  static dispatch_once_t onceToken;
+  static NSNumberFormatter *numberFormatter;
+  dispatch_once(&onceToken, ^{
+    numberFormatter = [[NSNumberFormatter alloc] init];
+    numberFormatter.numberStyle = NSNumberFormatterPercentStyle;
+  });
+  CGFloat percentage = (self.value - self.minimumValue) / (self.maximumValue - self.minimumValue);
+  return [numberFormatter stringFromNumber:@(percentage)];
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  // Adding UIAccessibilityTraitAdjustable also causes an iOS accessibility hint to be spoken:
+  // "Swipe up or down with one finger to adjust the value."
+  UIAccessibilityTraits traits = super.accessibilityTraits | UIAccessibilityTraitAdjustable;
+  if (!self.enabled) {
+    traits |= UIAccessibilityTraitNotEnabled;
+  }
+  return traits;
+}
+
+- (void)accessibilityIncrement {
+  if (self.enabled) {
+    CGFloat range = self.maximumValue - self.minimumValue;
+    CGFloat newValue = self.value + kSliderAccessibilityIncrement * range;
+    [_thumbTrack setValue:newValue
+                     animated:NO
+        animateThumbAfterMove:NO
+                userGenerated:YES
+                   completion:NULL];
+
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+- (void)accessibilityDecrement {
+  if (self.enabled) {
+    CGFloat range = self.maximumValue - self.minimumValue;
+    CGFloat newValue = self.value - kSliderAccessibilityIncrement * range;
+    [_thumbTrack setValue:newValue
+                     animated:NO
+        animateThumbAfterMove:NO
+                userGenerated:YES
+                   completion:NULL];
+
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+  return YES;
+}
+
+#pragma mark - Private
+
+- (void)thumbTrackValueChanged:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventValueChanged];
+}
+
+- (void)thumbTrackTouchDown:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchDown];
+}
+
+- (void)thumbTrackTouchUpInside:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchUpInside];
+}
+
+- (void)thumbTrackTouchUpOutside:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
+}
+
+- (void)thumbTrackTouchCanceled:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchCancel];
+}
+
++ (UIColor *)defaultColor {
+  return MDCColorFromRGB(MDCBlueColor);
+}
+
++ (UIColor *)defaultTrackOffColor {
+  return [[UIColor blackColor] colorWithAlphaComponent:kSliderLightThemeTrackAlpha];
+}
+
++ (UIColor *)defaultDisabledColor {
+  return [[UIColor blackColor] colorWithAlphaComponent:kSliderLightThemeTrackAlpha];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MaterialSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MaterialSlider.h
new file mode 100644
index 0000000..310f828
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/MaterialSlider.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSlider.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h
new file mode 100644
index 0000000..87e5dd0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSlider.h"
+
+@class MDCThumbTrack;
+
+/**
+ Import this header in order to properly subclass MDCSlider including access to the internal thumb
+ track.
+ */
+@interface MDCSlider () {
+ @protected
+  /**
+   The underlying thumb track backing the slider.
+   */
+  MDCThumbTrack *_thumbTrack;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
new file mode 100644
index 0000000..0bcc4a6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
@@ -0,0 +1,125 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCSnackbarMessage;
+@protocol MDCSnackbarSuspensionToken;
+
+/**
+ Provides a means of displaying an unobtrusive message to the user.
+
+ The style and location of the message can vary depending on the configuration of the message to be
+ shown. This class will queue repeated calls to @c showMessage: and show them at the appropriate
+ time, once previous messages have been dismissed. This class is thread-safe as long as the messages
+ given to MDCSnackbarManager are not mutated after being passed to @c showMessage:
+
+ Snackbars prefer an application's main window is a subclass of @c MDCOverlayWindow. When a standard
+ UIWindow is used an attempt is made to find the top-most view controller in the view hierarchy.
+ */
+@interface MDCSnackbarManager : NSObject
+
+/**
+ Shows @c message to the user, in a style consistent with the data contained in @c message.
+
+ For messages with the same category, the firing of completion blocks has a guaranteed FIFO
+ ordering. Ordering between completion blocks of different categories is not guaranteed. This method
+ is safe to call from any thread.
+ */
++ (void)showMessage:(MDCSnackbarMessage *)message;
+
+/**
+ MDCSnackbarManager will display the messages in this view.
+
+ Call this method to choose where in the view hierarchy snackbar messages will be presented. It is
+ only necessary to provide a host view if the default behavior is unable to find one on it's own,
+ most commonly when using MDCSnackbarManager inside an application extension. By default, if you use
+ MDCSnackbarManager without calling @c setPresentationHostView, the manager will attempt to find a
+ suitable view by stepping through the application windows. Explicitly providing a host view is only
+ required if you need to manually manage the view hierarchy, or are inside a UIApplication
+ extension.
+
+ @note This method must be called from the main thread.
+ @note Calling setPresentationHostView will not change the parent of the currently visible message.
+ */
++ (void)setPresentationHostView:(UIView *)hostView;
+
+/**
+ Bypasses showing the messages of the given @c category.
+
+ Completion blocks are called, but the UI won't show any queued messages and will dismiss any
+ messages for the @c category. Calling this method with @c nil will dismiss all messages. This
+ method is safe to call from any thread.
+ */
++ (void)dismissAndCallCompletionBlocksWithCategory:(NSString *)category;
+
+/**
+ How far from the bottom of the screen messages are displayed.
+
+ If called within an animation block, the change will be animated.
+
+ @note This method must be called from the main thread.
+ @note This is meant for apps which have a navigation element such as a tab bar, which cannot
+ move and should not be obscured.
+ */
++ (void)setBottomOffset:(CGFloat)offset;
+
+#pragma mark Suspending
+
+/**
+ Suspends the display of all messages.
+
+ Any messages currently on screen will remain on screen (and dismiss normally). During this time any
+ incoming messages will be queued as normal.
+
+ @return A token suitable for use in {@c +[MDCSnackbarManager resumeWithToken:]}. Letting this
+ object deallocate is equivalent to calling {@c +[MDCSnackbarManager resumeMessagesWithToken:]}.
+ */
++ (id<MDCSnackbarSuspensionToken>)suspendAllMessages;
+
+/**
+ Suspends the display of all messages in a given category.
+
+ Any messages currently on screen will remain on screen (and dismiss normally). During this time any
+ incoming messages in this category will be queued as normal.
+
+ @param category The category for which message display will be suspended. Should not be nil.
+ @return A token suitable for use in {@c +[MDCSnackbarManager resumeMessagesWithToken:]}.
+ Letting this object dealloc is equivalent to calling
+ {@c +[MDCSnackbarManager resumeMessagesWithToken:]}.
+ */
++ (id<MDCSnackbarSuspensionToken>)suspendMessagesWithCategory:(NSString *)category;
+
+/**
+ Resumes the display of messages once there are no outstanding suspension tokens.
+
+ The provided token is invalidated and becomes useless.
+
+ @param token The suspension token to invalidate.
+ */
++ (void)resumeMessagesWithToken:(id<MDCSnackbarSuspensionToken>)token;
+
+@end
+
+/**
+ A suspension token is returned when messages are suspended by the snackbar manager.
+
+ Messages are suppressed while a suspension token is kept in memory. Messages will resume being
+ displayed when the suspension token is released or when the suspension token is passed to
+ @c resumeMessagesWithToken.
+ */
+@protocol MDCSnackbarSuspensionToken <NSObject>
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.m
new file mode 100644
index 0000000..9c71e23
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.m
@@ -0,0 +1,575 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarManager.h"
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
+#import "MaterialOverlayWindow.h"
+#import "UIApplication+AppExtensions.h"
+#import "private/MDCSnackbarMessageInternal.h"
+#import "private/MDCSnackbarMessageViewInternal.h"
+#import "private/MDCSnackbarOverlayView.h"
+
+/** Test whether any of the accessibility elements of a view is focused */
+static BOOL UIViewHasFocusedAccessibilityElement(UIView *view) {
+  for (NSInteger i = 0; i < [view accessibilityElementCount]; i++) {
+    id accessibilityElement = [view accessibilityElementAtIndex:i];
+    if ([accessibilityElement accessibilityElementIsFocused]) {
+      return YES;
+    }
+  }
+  return NO;
+};
+
+@class MDCSnackbarManagerSuspensionToken;
+
+/**
+ Special category representing all messages.
+ */
+static NSString *const kAllMessagesCategory = @"$$___ALL_MESSAGES___$$";
+
+/**
+ The 'actual' snackbar manager which will take care of showing/hiding snackbar messages.
+ */
+@interface MDCSnackbarManagerInternal : NSObject
+
+/**
+ The list of messages waiting to be displayed.
+ */
+@property(nonatomic) NSMutableArray *pendingMessages;
+
+/**
+ The current suspension tokens.
+
+ @note: Keys are the message category, or the all messages category. Values are sets of suspension
+        tokens.
+ */
+@property(nonatomic) NSMutableDictionary<NSString *, NSMutableSet<NSUUID *> *> *suspensionTokens;
+
+/**
+ The view which will host our snackbar messages.
+ */
+@property(nonatomic) MDCSnackbarOverlayView *overlayView;
+
+/**
+ The view which contains the overlayView.
+ */
+@property(nonatomic) UIView *presentationHostView;
+
+/**
+ The currently-showing snackbar.
+ */
+@property(nonatomic) MDCSnackbarMessageView *currentSnackbar;
+
+/**
+ Whether or not we are currently showing a message.
+ */
+@property(nonatomic) BOOL showingMessage;
+
+@end
+
+@interface MDCSnackbarManagerSuspensionToken : NSObject <MDCSnackbarSuspensionToken>
+
+/**
+ The unique identifier for this token.
+ */
+@property(nonatomic, readonly) NSUUID *identifier;
+
+/**
+ The category string associated with this token.
+ */
+@property(nonatomic) NSString *category;
+
+@end
+
+@implementation MDCSnackbarManagerInternal
+
++ (MDCSnackbarManagerInternal *)sharedInstance {
+  static MDCSnackbarManagerInternal *manager = nil;
+  static dispatch_once_t onceToken;
+
+  dispatch_once(&onceToken, ^{
+    manager = [[MDCSnackbarManagerInternal alloc] init];
+  });
+
+  return manager;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _pendingMessages = [[NSMutableArray alloc] init];
+    _suspensionTokens = [NSMutableDictionary dictionary];
+    _overlayView = [[MDCSnackbarOverlayView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+  }
+  return self;
+}
+
+#pragma mark - Message Displaying
+
+/**
+ Determines whether or not a message is eligible to be shown based on the snackbar manager's current
+ configuration.
+
+ @note This method should ensure that messages in the same category are not shown out of order.
+ */
+- (BOOL)shouldShowMessageRightNowMainThread:(MDCSnackbarMessage *)message {
+  // If there are outstanding suspension tokens for all messages (not just specific categories),
+  // then hold off on displaying.
+  if ([self allMessagesSuspendedMainThread]) {
+    return NO;
+  }
+
+  // If there is an outstanding suspension token for this message category, then hold off on
+  // displaying.
+  if (message.category != nil && [self categorySuspended:message.category]) {
+    return NO;
+  }
+
+  return YES;
+}
+
+- (MDCSnackbarMessage *)dequeueNextShowableMessageMainThread {
+  // NOTE: In pathological cases, the iteration through the pending messages can be an O(n)
+  //       operation. Though we expect `n` to be low, to protect against needless iteration we'll
+  //       do a quick check to see if message displaying is completely suspended.
+  if ([self allMessagesSuspendedMainThread]) {
+    return nil;
+  }
+
+  __block NSUInteger messageIndex = NSNotFound;
+  [self.pendingMessages
+      enumerateObjectsUsingBlock:^(MDCSnackbarMessage *message, NSUInteger idx, BOOL *stop) {
+        if ([self shouldShowMessageRightNowMainThread:message]) {
+          messageIndex = idx;
+          *stop = YES;
+        }
+      }];
+
+  if (messageIndex != NSNotFound) {
+    MDCSnackbarMessage *message = self.pendingMessages[messageIndex];
+    [self.pendingMessages removeObjectAtIndex:messageIndex];
+
+    return message;
+  }
+
+  return nil;
+}
+
+// Dequeues and schedules the display of a particular message.
+- (void)showNextMessageIfNecessaryMainThread {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  if (self.pendingMessages.count == 0) {
+    return;
+  }
+
+  if (!self.showingMessage) {
+    MDCSnackbarMessage *message = [self dequeueNextShowableMessageMainThread];
+
+    if (message != nil) {
+      self.showingMessage = YES;
+      [self displaySnackbarViewForMessage:message];
+    }
+  }
+}
+
+// This method should only be called from within @c showNextMessageIfNecessaryMainThread.
+- (void)displaySnackbarViewForMessage:(MDCSnackbarMessage *)message {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  __block MDCSnackbarMessageView *snackbarView = nil;
+
+  // Guard against the timer firing and trying to dismiss us multiple times.
+  __block BOOL shouldDismiss = YES;
+  MDCSnackbarMessageDismissHandler dismissHandler =
+      ^(BOOL userInitiated, MDCSnackbarMessageAction *action) {
+        // Because we start a timer to dismiss the snackbar once it is on screen, there exists the
+        // potential to try and dismiss the snackbar view multiple times, say if the user taps on
+        // the snackbar (dismissal one) and then the timer fires (dismissal two). This check ensures
+        // that the dismissal logic will only fire one time for a given Snackbar view.
+        if (shouldDismiss) {
+          shouldDismiss = NO;
+
+          // If the user
+          [self hideSnackbarViewReally:snackbarView withAction:action userPrompted:userInitiated];
+        }
+      };
+
+  Class viewClass = [message viewClass];
+  snackbarView = [[viewClass alloc] initWithMessage:message dismissHandler:dismissHandler];
+  self.currentSnackbar = snackbarView;
+
+  self.overlayView.accessibilityViewIsModal = ![self isSnackbarTransient:snackbarView];
+  self.overlayView.hidden = NO;
+  [self activateOverlay:self.overlayView];
+
+  // Once the Snackbar has finished animating on screen, start the automatic dismiss timeout, but
+  // only if the user isn't running VoiceOver.
+  [self.overlayView
+      showSnackbarView:snackbarView
+              animated:YES
+            completion:^{
+              if ([self isSnackbarTransient:snackbarView]) {
+                snackbarView.accessibilityElementsHidden = YES;
+                UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                                message.voiceNotificationText);
+
+              } else {
+                UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+                                                snackbarView);
+              }
+
+              if ([self isSnackbarTransient:snackbarView]) {
+                __weak MDCSnackbarMessageView *weakSnackbarView = snackbarView;
+                dispatch_time_t popTime =
+                    dispatch_time(DISPATCH_TIME_NOW, (int64_t)(message.duration * NSEC_PER_SEC));
+                dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
+                  MDCSnackbarMessageView *strongSnackbarView = weakSnackbarView;
+                  BOOL hasVoiceOverFocus = UIAccessibilityIsVoiceOverRunning() &&
+                                           UIViewHasFocusedAccessibilityElement(strongSnackbarView);
+                  if (strongSnackbarView && !hasVoiceOverFocus) {
+                    // Mimic the user tapping on the snackbar.
+                    [strongSnackbarView dismissWithAction:nil userInitiated:NO];
+                  }
+                });
+              }
+            }];
+}
+
+- (void)hideSnackbarViewReally:(MDCSnackbarMessageView *)snackbarView
+                    withAction:(MDCSnackbarMessageAction *)action
+                  userPrompted:(BOOL)userPrompted {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  // Mark the snackbar as being in the process of dismissal.
+  snackbarView.dismissing = YES;
+
+  MDCSnackbarMessage *message = snackbarView.message;
+
+  // Fire off the button action, if necessary. Always call the message's completion handler.
+  [message
+      executeActionHandler:action
+                completion:^{
+                  [message executeCompletionHandlerWithUserInteraction:userPrompted completion:nil];
+                }];
+
+  [self.overlayView dismissSnackbarViewAnimated:YES
+                                     completion:^{
+                                       self.overlayView.hidden = YES;
+                                       [self deactivateOverlay:self.overlayView];
+
+                                       // If VoiceOver had been enabled and the snackbarView was
+                                       // transient, the snackbar was just announced (layout was not
+                                       // reported as changed) so there is no need to post a layout
+                                       // change here.
+                                       if (![self isSnackbarTransient:snackbarView]) {
+                                         UIAccessibilityPostNotification(
+                                             UIAccessibilityLayoutChangedNotification, nil);
+                                       }
+
+                                       self.currentSnackbar = nil;
+
+                                       // Now that the snackbar view is offscreen, we can allow more
+                                       // messages to be shown.
+                                       self.showingMessage = NO;
+                                       [self showNextMessageIfNecessaryMainThread];
+                                     }];
+}
+
+#pragma mark - Helper methods
+
+- (BOOL)isSnackbarTransient:(MDCSnackbarMessageView *)snackbarView {
+  if (UIAccessibilityIsVoiceOverRunning()) {
+    return ![snackbarView shouldWaitForDismissalDuringVoiceover];
+  }
+
+  return YES;
+}
+
+#pragma mark - Overlay Activation
+
+- (void)activateOverlay:(UIView *)overlay {
+  UIWindow *window = [self bestGuessWindow];
+  UIView *targetView = nil;
+
+  if (self.presentationHostView) {
+    targetView = self.presentationHostView;
+  } else if ([window isKindOfClass:[MDCOverlayWindow class]]) {
+    // If the application's window is an overlay window, take advantage of it. Otherwise, just add
+    // our overlay view into the main view controller's hierarchy.
+    MDCOverlayWindow *overlayWindow = (MDCOverlayWindow *)window;
+    [overlayWindow activateOverlay:overlay withLevel:UIWindowLevelNormal];
+  } else {
+    // Find the most top view controller to display overlay.
+    UIViewController *topViewController = [window rootViewController];
+    while ([topViewController presentedViewController]) {
+      topViewController = [topViewController presentedViewController];
+    }
+    targetView = [topViewController view];
+  }
+
+  if (targetView) {
+    overlay.frame = targetView.bounds;
+    overlay.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+    overlay.translatesAutoresizingMaskIntoConstraints = YES;
+
+    [targetView addSubview:overlay];
+  }
+}
+
+- (UIWindow *)bestGuessWindow {
+  UIApplication *application = [UIApplication mdc_safeSharedApplication];
+
+  // Check all of the windows in existence for an overlay window, because that's what we prefer to
+  // present in.
+  for (UIWindow *window in application.windows) {
+    if ([window isKindOfClass:[MDCOverlayWindow class]]) {
+      return window;
+    }
+  }
+
+  // Next see if the application's delegate declares a window. That's a good indicator of it being
+  // the 'main' window for an application.
+  if ([application.delegate respondsToSelector:@selector(window)]) {
+    id potentialWindow = application.delegate.window;
+    if (potentialWindow != nil) {
+      return potentialWindow;
+    }
+  }
+
+  // Default to the key window, since we couldn't find anything better.
+  return [[UIApplication mdc_safeSharedApplication] keyWindow];
+}
+
+- (void)deactivateOverlay:(UIView *)overlay {
+  UIWindow *window = [[UIApplication mdc_safeSharedApplication] keyWindow];
+  if ([window isKindOfClass:[MDCOverlayWindow class]]) {
+    MDCOverlayWindow *overlayWindow = (MDCOverlayWindow *)window;
+    [overlayWindow deactivateOverlay:overlay];
+  } else {
+    [overlay removeFromSuperview];
+  }
+}
+
+#pragma mark - Public API
+
+// Must be called from the main thread only.
+- (void)showMessageMainThread:(MDCSnackbarMessage *)message {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  // Dismiss and call the completion block for all the messages from the same category.
+  [self dismissAndCallCompletionBlocksOnMainThreadWithCategory:message.category];
+
+  // Add the new message to the queue, the call to @c showNextMessageIfNecessaryMainThread will take
+  // care of getting it on screen. At this moment, @c message is the only message of its category
+  // in @c _sPendingMessages.
+  [self.pendingMessages addObject:message];
+
+  // Pulse the UI as needed.
+  [self showNextMessageIfNecessaryMainThread];
+}
+
+- (void)dismissAndCallCompletionBlocksOnMainThreadWithCategory:(NSString *)categoryToDismiss {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  // Make sure that if there is a snackbar on screen, it does not belong to the current category.
+  if (self.currentSnackbar != nil && !self.currentSnackbar.dismissing) {
+    MDCSnackbarMessage *currentMessage = self.currentSnackbar.message;
+
+    if (!categoryToDismiss || [currentMessage.category isEqualToString:categoryToDismiss]) {
+      // Mimic the user tapping on the Snackbar. This will trigger the display of other messages,
+      // but because the dismissal animations happen on the main thread, we can modify
+      // @c _sPendingMessages in this cycle of the runloop without fear of the dismiss
+      // animation interfering.
+      [self.currentSnackbar dismissWithAction:nil userInitiated:NO];
+    }
+  }
+
+  // Now that we've ensured that the currently showing snackbar has been taken care of, we can go
+  // through pending messages and fire off their completion blocks as we remove them from the
+  // queue.
+  NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
+  [self.pendingMessages
+      enumerateObjectsUsingBlock:^(MDCSnackbarMessage *pendingMessage, NSUInteger idx, BOOL *stop) {
+        if (!categoryToDismiss || [pendingMessage.category isEqualToString:categoryToDismiss]) {
+          // Mark the message for removal from the pending messages list.
+          [indexesToRemove addIndex:idx];
+
+          // Notify the outside world that this snackbar has been completed.
+          [pendingMessage executeCompletionHandlerWithUserInteraction:NO completion:nil];
+        }
+      }];
+
+  // Make sure the queued up messages aren't shown.
+  if ([indexesToRemove count]) {
+    [self.pendingMessages removeObjectsAtIndexes:indexesToRemove];
+  }
+}
+
+#pragma mark - Suspend/Resume
+
+/**
+ Returns YES if message display is completely suspended.
+ */
+- (BOOL)allMessagesSuspendedMainThread {
+  NSMutableSet *allMessageSuspensions = self.suspensionTokens[kAllMessagesCategory];
+  if (allMessageSuspensions.count > 0) {
+    return YES;
+  }
+  return NO;
+}
+
+/**
+ Returns YES if message display is suspended for the given category.
+ */
+- (BOOL)categorySuspended:(NSString *)category {
+  NSMutableSet *thisCategorySuspensions = self.suspensionTokens[category];
+  if (thisCategorySuspensions.count > 0) {
+    return YES;
+  }
+  return NO;
+}
+
+- (void)addSuspensionIdentifierMainThread:(NSUUID *)identifier forCategory:(NSString *)category {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  NSMutableSet *tokens = self.suspensionTokens[category];
+  if (tokens == nil) {
+    tokens = [NSMutableSet set];
+    self.suspensionTokens[category] = tokens;
+  }
+
+  [tokens addObject:identifier];
+}
+
+- (void)removeSuspensionIdentifierMainThread:(NSUUID *)identifier forCategory:(NSString *)category {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  NSMutableSet *tokens = self.suspensionTokens[category];
+  [tokens removeObject:identifier];
+
+  // If that was the last token for this category, do some cleanup.
+  if (tokens != nil && tokens.count == 0) {
+    [self.suspensionTokens removeObjectForKey:category];
+  }
+
+  // We may have removed the last suspend, so trigger a display.
+  [self showNextMessageIfNecessaryMainThread];
+}
+
+@end
+
+#pragma mark - Public API
+
+@implementation MDCSnackbarManager
+
++ (void)showMessage:(MDCSnackbarMessage *)inputMessage {
+  if (!inputMessage) {
+    return;
+  }
+
+  // Snag a copy now, we'll use that internally.
+  MDCSnackbarMessage *message = [inputMessage copy];
+
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager showMessageMainThread:message];
+  });
+}
+
++ (void)setPresentationHostView:(UIView *)hostView {
+  NSAssert([NSThread isMainThread], @"setPresentationHostView must be called on main thread.");
+
+  MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+  manager.presentationHostView = hostView;
+}
+
++ (void)dismissAndCallCompletionBlocksWithCategory:(NSString *)category {
+  // Snag a copy now, we'll use that internally.
+  NSString *categoryToDismiss = [category copy];
+
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager dismissAndCallCompletionBlocksOnMainThreadWithCategory:categoryToDismiss];
+  });
+}
+
++ (void)setBottomOffset:(CGFloat)offset {
+  NSAssert([NSThread isMainThread], @"setBottomOffset must be called on main thread.");
+
+  MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+  manager.overlayView.bottomOffset = offset;
+}
+
+#pragma mark - Suspension
+
++ (id<MDCSnackbarSuspensionToken>)suspendMessagesWithCategory:(NSString *)category {
+  MDCSnackbarManagerSuspensionToken *token = [[MDCSnackbarManagerSuspensionToken alloc] init];
+  token.category = category;
+
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager addSuspensionIdentifierMainThread:token.identifier forCategory:token.category];
+  });
+
+  return token;
+}
+
++ (id<MDCSnackbarSuspensionToken>)suspendAllMessages {
+  return [self suspendMessagesWithCategory:kAllMessagesCategory];
+}
+
++ (void)handleInvalidatedIdentifier:(NSUUID *)identifier forCategory:(NSString *)category {
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager removeSuspensionIdentifierMainThread:identifier forCategory:category];
+  });
+}
+
++ (void)resumeMessagesWithToken:(id<MDCSnackbarSuspensionToken>)inToken {
+  if (![inToken isKindOfClass:[MDCSnackbarManagerSuspensionToken class]]) {
+    return;
+  }
+
+  MDCSnackbarManagerSuspensionToken *token = (MDCSnackbarManagerSuspensionToken *)inToken;
+  [self handleInvalidatedIdentifier:token.identifier forCategory:token.category];
+}
+
+@end
+
+@implementation MDCSnackbarManagerSuspensionToken
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    _identifier = [NSUUID UUID];
+  }
+  return self;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
new file mode 100644
index 0000000..0ee02c9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
@@ -0,0 +1,165 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCSnackbarMessageAction;
+
+/**
+ Called when a message is finished displaying, regardless of whether or not buttons were tapped.
+ */
+typedef void (^MDCSnackbarMessageCompletionHandler)(BOOL userInitiated);
+
+/**
+ Called when the button in the snackbar is tapped.
+ */
+typedef void (^MDCSnackbarMessageActionHandler)(void);
+
+/**
+ Maximum duration allowed for a MDCSnackbarMessage.
+
+ Set to 10 seconds. If longer durations are necessary than this value consider creating a custom UI
+ for your use case.
+ */
+extern const NSTimeInterval MDCSnackbarMessageDurationMax;
+
+/**
+ Bold style attribute that can be used in attributed text.
+
+ This attribute can be set over any range of @c attributedText and that text will have the proper
+ font applied.
+ */
+extern NSString *const MDCSnackbarMessageBoldAttributeName;
+
+/**
+ Represents a message to unobtrusively show to the user.
+
+ A snackbar message provides brief feedback about an operation. Messages are passed to the snackbar
+ manager to be displayed.
+
+ Snackbars prefer an application's main window is a subclass of @c MDCOverlayWindow. When a standard
+ UIWindow is used an attempt is made to find the top-most view controller in the view hierarchy.
+ */
+@interface MDCSnackbarMessage : NSObject <NSCopying, UIAccessibilityIdentification>
+
+/**
+ Returns a MDCSnackbarMessage with its text initialized.
+
+ @param text The text to display in the message.
+ @return An initialized MDCSnackbarMessage object with @c text.
+ */
++ (instancetype)messageWithText:(NSString *)text;
+
+/**
+ Returns a MDCSnackbarMessage with its attributed text initialized.
+
+ @param attributedText The attributed text to display in the message.
+ @return An initialized MDCSnackbarMessage object with @c attributedText.
+ */
++ (instancetype)messageWithAttributedText:(NSAttributedString *)attributedText;
+
+/**
+ The primary text of the message.
+
+ Either @c text or @c attributedText must be set.
+ */
+@property(nonatomic, copy) NSString *text;
+
+/**
+ The primary text of the message with styling.
+
+ Any attributes supported by UIKit may be set, though font and color will be overridden by the
+ snackbar. Either @c text or @c attributedText must be set.
+ */
+@property(nonatomic, copy) NSAttributedString *attributedText;
+
+/**
+ Optional button to show along with the rest of the message.
+
+ A MDCSnackbarMessageAction is displayed as a button on the snackbar. If no action is set no button
+ will appear on the Snackbar.
+ */
+@property(nonatomic, strong) MDCSnackbarMessageAction *action;
+
+/**
+ The color used for button text on the snackbar in normal state.
+
+ Default is white.
+ */
+@property(nonatomic, strong) UIColor *buttonTextColor;
+
+/**
+ The color used for button text on the snackbar in highlighted state.
+
+ Default is white.
+ */
+@property(nonatomic, strong) UIColor *highlightedButtonTextColor;
+
+/**
+ How long the message should be displayed.
+
+ Defaults to 4 seconds and can be set up to the maximum duration defined by
+ @c MDCSnackbarMessageDurationMax. Any value set above this limit will use the maximum duration.
+ */
+@property(nonatomic, assign) NSTimeInterval duration;
+
+/**
+ Called when a message is finished displaying.
+
+ The message completion handler is called regardless of whether or not buttons were tapped and is
+ always called on the main thread.
+ */
+@property(nonatomic, copy) MDCSnackbarMessageCompletionHandler completionHandler;
+
+/**
+ The category of messages to which a message belongs.
+
+ Default is nil. If set, only the last message of this category will be shown, any currently
+ showing or pending messages in this category will be dismissed as if the user had directly tapped
+ the snackbar.
+ */
+@property(nonatomic, copy) NSString *category;
+
+/**
+ Redeclaration from UIAccessibility to make clear that this class supports accessibility labels.
+ */
+@property(nonatomic, copy) NSString *accessibilityLabel;
+
+/**
+ Text that should be read when the message appears on screen and VoiceOver is enabled.
+ */
+@property(nonatomic, readonly) NSString *voiceNotificationText;
+
+@end
+
+/**
+ Represents a button in a MDCSnackbarMessage.
+ */
+@interface MDCSnackbarMessageAction : NSObject <UIAccessibilityIdentification, NSCopying>
+
+/**
+ The title text on the button.
+ */
+@property(nonatomic, copy) NSString *title;
+
+/**
+ Called when the button in the snackbar is tapped.
+
+ Always called on the main thread.
+ */
+@property(nonatomic, copy) MDCSnackbarMessageActionHandler handler;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.m
new file mode 100644
index 0000000..0ad9f7a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.m
@@ -0,0 +1,165 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
+#import "private/MDCSnackbarMessageInternal.h"
+
+static const NSTimeInterval kDefaultDuration = 4.0f;
+
+const NSTimeInterval MDCSnackbarMessageDurationMax = 10;
+NSString *const MDCSnackbarMessageBoldAttributeName = @"MDCSnackbarMessageBoldAttributeName";
+
+@interface MDCSnackbarMessage ()
+
+@property(nonatomic, readonly, strong) dispatch_queue_t targetQueue;
+
+@property(nonatomic, assign) BOOL hasSetTextAlignment;
+
+@end
+
+@implementation MDCSnackbarMessage
+
+@synthesize accessibilityIdentifier;
+@dynamic text;
+
++ (instancetype)messageWithText:(NSString *)text {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  message.text = text;
+  return message;
+}
+
++ (instancetype)messageWithAttributedText:(NSAttributedString *)attributedText {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  message.attributedText = attributedText;
+  return message;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _duration = kDefaultDuration;
+  }
+  return self;
+}
+
+- (Class)viewClass {
+  return [MDCSnackbarMessageView class];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  MDCSnackbarMessage *copy = [[[self class] alloc] init];
+  copy.attributedText = self.attributedText;
+  copy.duration = self.duration;
+  copy.category = self.category;
+  copy.accessibilityLabel = self.accessibilityLabel;
+  copy.buttonTextColor = self.buttonTextColor;
+  copy.highlightedButtonTextColor = self.highlightedButtonTextColor;
+
+  // Unfortunately there's not really a concept of 'copying' a block (in the same way you would copy
+  // a string, for example). A block's pointer is immutable once it is created and copied to the
+  // heap, so we're pretty safe just using the same block.
+  copy.completionHandler = self.completionHandler;
+  copy.action = self.action;
+
+  return copy;
+}
+
+- (dispatch_queue_t)targetQueue {
+  return dispatch_get_main_queue();
+}
+
+#pragma mark Text
+
+- (void)setText:(NSString *)text {
+  self.attributedText = [[NSAttributedString alloc] initWithString:[text copy]];
+}
+
+- (NSString *)text {
+  return [self.attributedText string];
+}
+
+#pragma mark - Duration
+
+- (void)setDuration:(NSTimeInterval)duration {
+  NSAssert(duration <= MDCSnackbarMessageDurationMax,
+           @"Duration %g is longer than the maximum allowed: %g.", duration,
+           MDCSnackbarMessageDurationMax);
+  _duration = MIN(MDCSnackbarMessageDurationMax, duration);
+}
+
+#pragma mark - A11y
+
+- (NSString *)voiceNotificationText {
+  if ([self.accessibilityLabel length]) {
+    return self.accessibilityLabel;
+  } else {
+    return self.text;
+  }
+}
+
+#pragma mark - Internal
+
+- (void)executeCompletionHandlerWithUserInteraction:(BOOL)userInteraction
+                                         completion:(void (^)(void))completion {
+  if (self.completionHandler) {
+    dispatch_async(self.targetQueue, ^{
+      self.completionHandler(userInteraction);
+      if (completion) {
+        completion();
+      }
+    });
+  } else {
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+- (void)executeActionHandler:(MDCSnackbarMessageAction *)action
+                  completion:(void (^)(void))completion {
+  if (!action || !action.handler) {
+    if (completion) {
+      completion();
+    }
+    return;
+  }
+
+  // Fire off the action handler.
+  dispatch_async(self.targetQueue, ^{
+    action.handler();
+    if (completion) {
+      completion();
+    }
+  });
+}
+
+@end
+
+@implementation MDCSnackbarMessageAction
+
+@synthesize accessibilityIdentifier;
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  MDCSnackbarMessageAction *copy = [[[self class] alloc] init];
+  copy.title = self.title;
+  copy.handler = self.handler;  // See the comment on @c completionHandler above.
+  copy.accessibilityIdentifier = self.accessibilityIdentifier;
+
+  return copy;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
new file mode 100644
index 0000000..8649a8f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Class which provides the default implementation of a snackbar.
+ */
+@interface MDCSnackbarMessageView : UIView
+
+/**
+ The color for the background of the snackbar message view.
+ */
+@property(nonatomic, strong, nullable)
+    UIColor *snackbarMessageViewBackgroundColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The color for the shadow color for the snackbar message view.
+ */
+@property(nonatomic, strong, nullable)
+    UIColor *snackbarMessageViewShadowColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The color for the message text in the snackbar message view.
+ */
+@property(nonatomic, strong, nullable) UIColor *snackbarMessageViewTextColor UI_APPEARANCE_SELECTOR;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.m
new file mode 100644
index 0000000..606ea39
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.m
@@ -0,0 +1,809 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialButtons.h"
+#import "MaterialTypography.h"
+#import "private/MDCSnackbarMessageViewInternal.h"
+#import "private/MDCSnackbarOverlayView.h"
+
+NSString *const MDCSnackbarMessageTitleAutomationIdentifier =
+    @"MDCSnackbarMessageTitleAutomationIdentifier";
+NSString *const MDCSnackbarMessageViewTitleA11yHint = @"Double-tap to dismiss.";
+
+static inline UIColor *MDCRGBAColor(uint8_t r, uint8_t g, uint8_t b, float a) {
+  return [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:(a)];
+}
+
+/**
+ The thickness of the snackbar border.
+ */
+static const CGFloat kBorderWidth = 0;
+
+/**
+ Shadow coloring.
+ */
+static const CGFloat kShadowAlpha = 0.24f;
+static const CGSize kShadowOffset = (CGSize){0.0, 1.0};
+static const CGFloat kShadowSpread = 1.0f;
+
+/**
+ The radius of the corners.
+ */
+static const CGFloat kCornerRadius = 0;
+
+/**
+ Padding between the edges of the snackbar and any content.
+ */
+static UIEdgeInsets kContentMargin = (UIEdgeInsets){18.0, 24.0, 18.0, 24.0};
+
+/**
+ Padding between the image and the main title.
+ */
+static const CGFloat kTitleImagePadding = 8.0f;
+
+/**
+ Padding between the main title and the first button.
+ */
+static const CGFloat kTitleButtonPadding = 8.0f;
+
+/**
+ Padding on the edges of the buttons.
+ */
+static const CGFloat kButtonPadding = 5.0f;
+
+/**
+ The width of the snackbar.
+ */
+static const CGFloat kMinimumViewWidth_iPad = 288.0f;
+static const CGFloat kMaximumViewWidth_iPad = 568.0f;
+static const CGFloat kMinimumViewWidth_iPhone = 320.0f;
+static const CGFloat kMaximumViewWidth_iPhone = 320.0f;
+
+/**
+ The minimum height of the snackbar.
+ */
+static const CGFloat kMinimumHeight = 48.0f;
+
+/**
+ Each button will have a tag indexed starting from this value.
+ */
+static const NSInteger kButtonTagStart = 20000;
+
+/**
+ The ink radius of the action button.
+ */
+static const CGFloat kButtonInkRadius = 64.0f;
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCSnackbarMessageView () <CAAnimationDelegate>
+@end
+#endif
+
+@interface MDCSnackbarMessageView ()
+
+/**
+ Holds the icon for the image.
+ */
+@property(nonatomic, strong) UIImageView *imageView;
+
+/**
+ Holds the button views.
+ */
+@property(nonatomic, strong) NSArray *buttons;
+
+/**
+ Holds the text label for the main message.
+ */
+@property(nonatomic, strong) UILabel *label;
+
+/**
+ The constraints managing this view.
+ */
+@property(nonatomic, strong) NSArray *viewConstraints;
+
+/**
+ The view containing all of the visual content. Inset by @c kBorderWidth from the view.
+ */
+@property(nonatomic, strong) UIControl *containerView;
+
+/**
+ The view containing all of the buttons.
+ */
+@property(nonatomic, strong) UIView *buttonView;
+
+/**
+ The view containing the title and image views.
+ */
+@property(nonatomic, strong) UIView *contentView;
+
+/**
+ Holds onto the dismissal handler, called when the snackbar should dismiss due to user interaction.
+ */
+@property(nonatomic, copy) MDCSnackbarMessageDismissHandler dismissalHandler;
+
+@end
+
+@interface MDCSnackbarMessageViewButton : MDCFlatButton
+@end
+
+@implementation MDCSnackbarMessageViewButton
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.inkMaxRippleRadius = kButtonInkRadius;
+    self.inkColor = [UIColor colorWithWhite:1 alpha:0.06f];
+    self.inkStyle = MDCInkStyleUnbounded;
+  }
+  return self;
+}
+
+@end
+
+@implementation MDCSnackbarMessageView
+
++ (void)initialize {
+  [[self appearance] setSnackbarMessageViewShadowColor:MDCRGBAColor(0x00, 0x00, 0x00, 1.0f)];
+  [[self appearance] setSnackbarMessageViewBackgroundColor:MDCRGBAColor(0x32, 0x32, 0x32, 1.0f)];
+  [[self appearance] setSnackbarMessageViewTextColor:MDCRGBAColor(0xFF, 0xFF, 0xFF, 1.0f)];
+}
+
+- (void)dismissWithAction:(MDCSnackbarMessageAction *)action userInitiated:(BOOL)userInitiated {
+  if (self.dismissalHandler) {
+    self.dismissalHandler(userInitiated, action);
+
+    // In case our dismissal handler has a reference to us, release the block.
+    self.dismissalHandler = nil;
+  }
+}
+
+#pragma mark - Subclass overrides
+
++ (BOOL)requiresConstraintBasedLayout {
+  return YES;
+}
+
+- (CGFloat)minimumWidth {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? kMinimumViewWidth_iPad
+                                                              : kMinimumViewWidth_iPhone;
+}
+
+- (CGFloat)maximumWidth {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? kMaximumViewWidth_iPad
+                                                              : kMaximumViewWidth_iPhone;
+}
+
+#pragma mark - Styling the view
+
+- (UIColor *)snackbarButtonTextColor {
+  return MDCRGBAColor(0xFF, 0xFF, 0xFF, 0.6f);
+}
+
+- (UIColor *)snackbarButtonTextColorHighlighted {
+  return MDCRGBAColor(0xFF, 0xFF, 0xFF, 1.0f);
+}
+
+- (UIColor *)snackbarSeparatorColor {
+  return MDCRGBAColor(0xFF, 0xFF, 0xFF, 0.5f);
+}
+
+- (void)setSnackbarMessageViewBackgroundColor:(UIColor *)snackbarMessageViewBackgroundColor {
+  _snackbarMessageViewBackgroundColor = snackbarMessageViewBackgroundColor;
+  _containerView.backgroundColor = snackbarMessageViewBackgroundColor;
+}
+
+- (void)setSnackbarShadowColor:(UIColor *)snackbarMessageViewShadowColor {
+  _snackbarMessageViewShadowColor = snackbarMessageViewShadowColor;
+  self.layer.shadowColor = snackbarMessageViewShadowColor.CGColor;
+}
+
+- (void)setSnackbarMessageViewTextColor:(UIColor *)snackbarMessageViewTextColor {
+  _snackbarMessageViewTextColor = snackbarMessageViewTextColor;
+  self.label.textColor = _snackbarMessageViewTextColor;
+}
+
+- (void)addColorToMessageLabel:(UIColor *)color {
+  NSMutableAttributedString *messageString = [_label.attributedText mutableCopy];
+  [messageString addAttributes:@{
+    NSForegroundColorAttributeName : color,
+  }
+                         range:NSMakeRange(0, messageString.length)];
+  _label.attributedText = messageString;
+}
+
+- (instancetype)initWithMessage:(MDCSnackbarMessage *)message
+                 dismissHandler:(MDCSnackbarMessageDismissHandler)handler {
+  self = [super init];
+  if (self) {
+    _message = message;
+    _dismissalHandler = [handler copy];
+
+    self.backgroundColor = [UIColor clearColor];
+    self.layer.cornerRadius = kCornerRadius;
+    self.layer.shadowColor = _snackbarMessageViewShadowColor.CGColor;
+    self.layer.shadowOpacity = kShadowAlpha;
+    self.layer.shadowOffset = kShadowOffset;
+    self.layer.shadowRadius = kShadowSpread;
+
+    // Borders are drawn inside of the bounds of a layer. Because our border is translucent, we need
+    // to have a view with transparent background and border only (@c self). Inside will be a
+    // content view that has the dark grey color.
+    _containerView = [[UIControl alloc] init];
+    [self addSubview:_containerView];
+
+    [_containerView setTranslatesAutoresizingMaskIntoConstraints:NO];
+    _containerView.backgroundColor = _snackbarMessageViewBackgroundColor;
+    _containerView.layer.cornerRadius = kCornerRadius;
+    _containerView.layer.masksToBounds = YES;
+
+    // Listen for taps on the background of the view.
+    [_containerView addTarget:self
+                       action:@selector(handleBackgroundTapped:)
+             forControlEvents:UIControlEventTouchUpInside];
+
+    UISwipeGestureRecognizer *swipeRightGesture =
+        [[UISwipeGestureRecognizer alloc] initWithTarget:self
+                                                  action:@selector(handleBackgroundSwipedRight:)];
+    [swipeRightGesture setDirection:UISwipeGestureRecognizerDirectionRight];
+    [_containerView addGestureRecognizer:swipeRightGesture];
+
+    UISwipeGestureRecognizer *swipeLeftGesture =
+        [[UISwipeGestureRecognizer alloc] initWithTarget:self
+                                                  action:@selector(handleBackgroundSwipedLeft:)];
+    [swipeRightGesture setDirection:UISwipeGestureRecognizerDirectionLeft];
+    [_containerView addGestureRecognizer:swipeLeftGesture];
+
+    _contentView = [[UIView alloc] init];
+    [_contentView setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [_containerView addSubview:_contentView];
+    _contentView.userInteractionEnabled = NO;
+
+    _buttonView = [[UIView alloc] init];
+    [_buttonView setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [_containerView addSubview:_buttonView];
+
+    // Set up the title label.
+    _label = [[UILabel alloc] initWithFrame:CGRectZero];
+    [_contentView addSubview:_label];
+
+    NSMutableAttributedString *messageString = [message.attributedText mutableCopy];
+
+    // Find any of the bold attributes in the string, and set the proper font for those ranges.
+    // Use NSAttributedStringEnumerationLongestEffectiveRangeNotRequired as opposed to 0, otherwise
+    // it will only work if bold text is in the end.
+    [messageString
+        enumerateAttribute:MDCSnackbarMessageBoldAttributeName
+                   inRange:NSMakeRange(0, messageString.length)
+                   options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
+                usingBlock:^(id value, NSRange range, BOOL *stop) {
+                  UIFont *font = [MDCTypography body1Font];
+                  if ([value boolValue]) {
+                    font = [MDCTypography body2Font];
+                  }
+                  [messageString setAttributes:@{ NSFontAttributeName : font } range:range];
+                }];
+
+    // Apply 'global' attributes along the whole string.
+    _label.backgroundColor = [UIColor clearColor];
+    _label.textAlignment = NSTextAlignmentNatural;
+    _label.attributedText = messageString;
+    _label.numberOfLines = 0;
+    [_label setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [_label setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh
+                                            forAxis:UILayoutConstraintAxisHorizontal];
+    [_label setContentHuggingPriority:UILayoutPriorityDefaultLow
+                              forAxis:UILayoutConstraintAxisHorizontal];
+
+    // For VoiceOver purposes, the label is the primary 'button' for dismissing the snackbar, so
+    // we'll make sure the label looks like a button.
+    _label.accessibilityTraits = UIAccessibilityTraitButton;
+    _label.accessibilityIdentifier = MDCSnackbarMessageTitleAutomationIdentifier;
+    _label.accessibilityHint = MDCSnackbarMessageViewTitleA11yHint;
+
+    // If an accessibility label was set on the message model object, use that instead of the text
+    // in the label.
+    if ([message.accessibilityLabel length]) {
+      _label.accessibilityLabel = message.accessibilityLabel;
+    }
+
+    // Figure out how much horizontal space the main text needs, in order to decide if the buttons
+    // are laid out horizontally or vertically.
+    __block CGFloat availableTextWidth = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
+                                             ? kMaximumViewWidth_iPad
+                                             : kMaximumViewWidth_iPhone;
+
+    // Take into account the content padding.
+    availableTextWidth -= (kContentMargin.left + kContentMargin.right);
+
+    // If there are buttons, account for the padding between the title and the buttons.
+    if (message.action) {
+      availableTextWidth -= kTitleButtonPadding;
+    }
+
+    UIColor *textColor = [self snackbarButtonTextColor];
+    UIColor *textColorHighlighted = [self snackbarButtonTextColorHighlighted];
+
+    _label.textColor = textColor;
+
+    if (message.buttonTextColor) {
+      textColor = message.buttonTextColor;
+    }
+
+    if (message.highlightedButtonTextColor) {
+      textColorHighlighted = message.highlightedButtonTextColor;
+    }
+
+    NSDictionary *buttonAttributes = @{
+      NSFontAttributeName : [MDCTypography buttonFont],
+      NSForegroundColorAttributeName : textColor,
+    };
+
+    NSDictionary *buttonHighlightedAttributes = @{
+      NSFontAttributeName : [MDCTypography buttonFont],
+      NSForegroundColorAttributeName : textColorHighlighted,
+    };
+
+    // Add buttons to the view. We'll use this opportunity to determine how much space a button will
+    // need, to inform the layout direction.
+    NSMutableArray *actions = [NSMutableArray array];
+    if (message.action) {
+      UIView *buttonView = [[UIView alloc] init];
+      [buttonView setTranslatesAutoresizingMaskIntoConstraints:NO];
+      [_buttonView addSubview:buttonView];
+
+      UIButton *button = [[MDCSnackbarMessageViewButton alloc] init];
+      [button setTranslatesAutoresizingMaskIntoConstraints:NO];
+      button.tag = kButtonTagStart;
+      [buttonView addSubview:button];
+
+      // Style the text in the button.
+      NSAttributedString *buttonText =
+          [[NSAttributedString alloc] initWithString:message.action.title
+                                          attributes:buttonAttributes];
+      NSAttributedString *buttonHighlightedText =
+          [[NSAttributedString alloc] initWithString:message.action.title
+                                          attributes:buttonHighlightedAttributes];
+      button.titleLabel.numberOfLines = 1;
+      button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
+      button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
+      button.contentEdgeInsets = UIEdgeInsetsMake(0, kButtonPadding, 0, kButtonPadding);
+
+      // Set up the button's accessibility values.
+      button.accessibilityIdentifier = message.action.accessibilityIdentifier;
+      [button setAttributedTitle:buttonText forState:UIControlStateNormal];
+      [button setAttributedTitle:buttonHighlightedText forState:UIControlStateHighlighted];
+
+      if (message.buttonTextColor) {
+        [button setTitleColor:textColor forState:UIControlStateNormal];
+      }
+
+      // Make sure the button doesn't get too compressed.
+      [button setContentCompressionResistancePriority:UILayoutPriorityRequired
+                                              forAxis:UILayoutConstraintAxisHorizontal];
+      [button setContentHuggingPriority:UILayoutPriorityDefaultHigh
+                                forAxis:UILayoutConstraintAxisHorizontal];
+      [button addTarget:self
+                    action:@selector(handleButtonTapped:)
+          forControlEvents:UIControlEventTouchUpInside];
+
+      availableTextWidth -= [buttonText size].width;
+      availableTextWidth -= 2 * kButtonPadding;
+
+      [actions addObject:buttonView];
+    }
+
+    self.buttons = actions;
+  }
+
+  return self;
+}
+
+- (BOOL)shouldWaitForDismissalDuringVoiceover {
+  return self.message.action != nil;
+}
+
+#pragma mark - Constraints and layout
+
+- (void)updateConstraints {
+  [super updateConstraints];
+
+  if (self.viewConstraints) {
+    return;
+  }
+
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  [constraints addObjectsFromArray:[self containerViewConstraints]];
+  [constraints addObjectsFromArray:[self contentViewConstraints]];
+  [constraints addObjectsFromArray:[self horizontalButtonLayoutConstraints]];
+
+  [self addConstraints:constraints];
+  self.viewConstraints = constraints;
+}
+
+/**
+ Provides constraints to pin the container view to the size of the snackbar, inset by
+ @c kBorderWidth. Also positions the content view and button view inside of the container view.
+ */
+- (NSArray *)containerViewConstraints {
+  NSDictionary *metrics = @{
+    @"kBorderMargin" : @(kBorderWidth),
+    @"kBottomMargin" : @(kContentMargin.bottom),
+    @"kLeftMargin" : @(kContentMargin.left),
+    @"kRightMargin" : @(kContentMargin.right),
+    @"kTitleImagePadding" : @(kTitleImagePadding),
+    @"kTopMargin" : @(kContentMargin.top),
+    @"kTitleButtonPadding" : @(kTitleButtonPadding),
+  };
+  NSDictionary *views = @{
+    @"container" : self.containerView,
+    @"content" : self.contentView,
+    @"buttons" : self.buttonView,
+  };
+
+  BOOL hasButtons = (self.buttons.count > 0);
+
+  NSString *formatString = nil;  // Scratch variable.
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  // Pin the left and right edges of the container view to the snackbar.
+  formatString = @"H:|-(==kBorderMargin)-[container]-(==kBorderMargin)-|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the top and bottom edges of the container view to the snackbar.
+  formatString = @"V:|-(==kBorderMargin)-[container]-(==kBorderMargin)-|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the content to the top of the container view.
+  formatString = @"V:|-(==kTopMargin)-[content]";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the content view to the left side of the container.
+  formatString = @"H:|-(==kLeftMargin)-[content]";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // If there are no buttons, or the buttons are below the main content, then the content view
+  // should be pinned to the right side of the container. If there are horizontal buttons, the
+  // leftmost button will take care of positioning the trailing edge of the label view.
+
+  // If there are no buttons, then go ahead and pin the content view to the bottom of the
+  // container view.
+  if (!hasButtons) {
+    formatString = @"V:[content]-(==kBottomMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  }
+
+  if (!hasButtons) {
+    // There is nothing to the right of the content, so go ahead and pin it to the trailing edge of
+    // the container view.
+    formatString = @"H:[content]-(==kRightMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  } else {  // This is a horizontal layout, and there are buttons present.
+    // Align the content and buttons horizontally.
+    formatString = @"H:[content]-(==kTitleButtonPadding)-[buttons]-(==kRightMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // The buttons should take up the entire height of the container view.
+    formatString = @"V:|[buttons]|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // Pin the content to the bottom of the container view, since there's nothing below.
+    formatString = @"V:[content]-(==kBottomMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  }
+
+  return constraints;
+}
+
+/**
+ Provides constraints for the image view and label within the content view.
+ */
+- (NSArray *)contentViewConstraints {
+  NSDictionary *metrics = @{
+    @"kBottomMargin" : @(kContentMargin.bottom),
+    @"kLeftMargin" : @(kContentMargin.left),
+    @"kRightMargin" : @(kContentMargin.right),
+    @"kTitleImagePadding" : @(kTitleImagePadding),
+    @"kTopMargin" : @(kContentMargin.top),
+  };
+
+  NSMutableDictionary *views = [NSMutableDictionary dictionary];
+  views[@"label"] = self.label;
+  if (self.imageView) {
+    views[@"imageView"] = self.imageView;
+  }
+
+  NSString *formatString = nil;  // Scratch variable.
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  // The label should take up the entire height of the content view.
+  formatString = @"V:|[label]|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the label to the trailing edge of the content view.
+  formatString = @"H:[label]|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  if (self.imageView) {
+    // Constrain the image view to be no taller than @c kMaximumImageSize.
+    formatString = @"V:[imageView(<=kMaximumImageSize)]";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // Vertically center the image view within the content view.
+    [constraints addObject:[NSLayoutConstraint constraintWithItem:self.imageView
+                                                        attribute:NSLayoutAttributeCenterY
+                                                        relatedBy:NSLayoutRelationEqual
+                                                           toItem:self.contentView
+                                                        attribute:NSLayoutAttributeCenterY
+                                                       multiplier:1.0
+                                                         constant:0]];
+
+    // Constrain the image view to be no wider than @c kMaximumImageSize, and pin it to the leading
+    // edge of the content view. Pin the label to the trailing edge of the image.
+    formatString = @"H:|[imageView(<=kMaximumImageSize)]-(==kTitleImagePadding)-[label]";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  } else {
+    formatString = @"H:|[label]";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  }
+
+  return constraints;
+}
+
+/**
+ Provides constraints positioning the buttons horizontally within the button container.
+ */
+- (NSArray *)horizontalButtonLayoutConstraints {
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  NSDictionary *metrics = @{
+    @"kLeftMargin" : @(kContentMargin.left),
+    @"kRightMargin" : @(kContentMargin.right),
+    @"kTopMargin" : @(kContentMargin.top),
+    @"kBottomMargin" : @(kContentMargin.bottom),
+    @"kTitleImagePadding" : @(kTitleImagePadding),
+    @"kBorderMargin" : @(kBorderWidth),
+    @"kTitleButtonPadding" : @(kTitleButtonPadding),
+    @"kButtonPadding" : @(kButtonPadding),
+  };
+
+  __block UIView *previousButton = nil;
+  [self.buttons enumerateObjectsUsingBlock:^(UIView *button, NSUInteger idx, BOOL *stop) {
+    // Convenience dictionary of views.
+    NSMutableDictionary *views = [NSMutableDictionary dictionary];
+    views[@"buttonContainer"] = button;
+    views[@"button"] = [button viewWithTag:kButtonTagStart + idx];
+    if (previousButton) {
+      views[@"previousButton"] = previousButton;
+    }
+
+    // In a horizontal layout, the button takes on the height of the snackbar.
+    [constraints
+        addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[buttonContainer]|"
+                                                                    options:0
+                                                                    metrics:metrics
+                                                                      views:views]];
+
+    // Pin the button to the height of its container.
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[button]|"
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // Pin the button to the width of its container.
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|"
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    if (idx == 0) {
+      // The first button should be pinned to the leading edge of the button view.
+      [constraints addObjectsFromArray:[NSLayoutConstraint
+                                           constraintsWithVisualFormat:@"H:|[buttonContainer]"
+                                                               options:0
+                                                               metrics:metrics
+                                                                 views:views]];
+    }
+
+    if (idx == ([self.buttons count] - 1)) {
+      // The last button should be pinned to the trailing edge of the button view.
+      [constraints addObjectsFromArray:[NSLayoutConstraint
+                                           constraintsWithVisualFormat:@"H:[buttonContainer]|"
+                                                               options:0
+                                                               metrics:metrics
+                                                                 views:views]];
+    }
+
+    if (previousButton) {
+      // If there was a button before this one, pin this one to it.
+      NSString *formatString = @"H:[previousButton]-(==kButtonPadding)-[buttonContainer]";
+      [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                               options:0
+                                                                               metrics:metrics
+                                                                                 views:views]];
+    }
+  }];
+
+  return constraints;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // As our layout changes, make sure that the shadow path is kept up-to-date.
+  UIBezierPath *path =
+      [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:kCornerRadius];
+  self.layer.shadowPath = path.CGPath;
+}
+
+#pragma mark - Sizing
+
+- (CGSize)intrinsicContentSize {
+  CGFloat height = 0;
+
+  // Figure out which of the elements is tallest, and use that for calculating our preferred height.
+  // Images are forced to be no bigger than @c kMaximumImageSize.
+  height = MAX(height, self.label.intrinsicContentSize.height);
+
+  // Make sure that content margins are included in our calculation.
+  height += kContentMargin.top + kContentMargin.bottom;
+
+  // Make sure that the height of the image and text is larger than the minimum height;
+  height = MAX(kMinimumHeight, height);
+
+  return CGSizeMake(UIViewNoIntrinsicMetric, height);
+}
+
+#pragma mark - Event Handlers
+
+- (void)handleBackgroundSwipedRight:(UIButton *)sender {
+  CABasicAnimation *translationAnimation =
+      [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
+  translationAnimation.toValue = [NSNumber numberWithDouble:-self.frame.size.width];
+  translationAnimation.duration = MDCSnackbarTransitionDuration;
+  translationAnimation.timingFunction =
+      [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionTranslateOffScreen];
+  translationAnimation.delegate = self;
+  translationAnimation.fillMode = kCAFillModeForwards;
+  translationAnimation.removedOnCompletion = NO;
+  [self.layer addAnimation:translationAnimation forKey:@"transform.translation.x"];
+}
+
+- (void)handleBackgroundSwipedLeft:(UIButton *)sender {
+  CABasicAnimation *translationAnimation =
+      [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
+  translationAnimation.toValue = [NSNumber numberWithDouble:self.frame.size.width];
+  translationAnimation.duration = MDCSnackbarTransitionDuration;
+  translationAnimation.timingFunction =
+      [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionTranslateOffScreen];
+  translationAnimation.delegate = self;
+  translationAnimation.fillMode = kCAFillModeForwards;
+  translationAnimation.removedOnCompletion = NO;
+  [self.layer addAnimation:translationAnimation forKey:@"transform.translation.x"];
+}
+
+- (void)handleBackgroundTapped:(UIButton *)sender {
+  [self dismissWithAction:nil userInitiated:YES];
+}
+
+- (void)handleButtonTapped:(UIButton *)sender {
+  [self dismissWithAction:self.message.action userInitiated:YES];
+}
+
+- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
+  if (flag) {
+    [self dismissWithAction:nil userInitiated:YES];
+  }
+}
+
+#pragma mark - Accessibility
+
+// Override regular accessibility element ordering and ensure label
+// is read first before any buttons, if they exist.
+- (NSInteger)accessibilityElementCount {
+  return 1 + [self.buttons count];
+}
+
+- (id)accessibilityElementAtIndex:(NSInteger)index {
+  if (index == 0) {
+    return _label;
+  }
+  return [self.buttons objectAtIndex:(index - 1)];
+}
+
+- (NSInteger)indexOfAccessibilityElement:(id)element {
+  if (element == _label) {
+    return 0;
+  }
+
+  NSInteger buttonIndex = [self.buttons indexOfObject:element];
+  if (buttonIndex == NSNotFound) {
+    return NSNotFound;
+  }
+  return buttonIndex + 1;
+}
+
+#pragma mark - Animation
+
+- (void)animateContentOpacityFrom:(CGFloat)fromOpacity
+                               to:(CGFloat)toOpacity
+                         duration:(NSTimeInterval)duration
+                   timingFunction:(CAMediaTimingFunction *)timingFunction {
+  [CATransaction begin];
+
+  CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+  opacityAnimation.duration = duration;
+  opacityAnimation.fromValue = @(fromOpacity);
+  opacityAnimation.toValue = @(toOpacity);
+  opacityAnimation.timingFunction = timingFunction;
+
+  // The text and the button do not share a common view that can be animated independently of the
+  // background color, so just animate them both independently here. If this becomes more
+  // complicated, refactor to add a containing view for both and animate that.
+  [self.contentView.layer addAnimation:opacityAnimation forKey:@"opacity"];
+  [self.buttonView.layer addAnimation:opacityAnimation forKey:@"opacity"];
+
+  [CATransaction commit];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MaterialSnackbar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
new file mode 100644
index 0000000..700adbb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarManager.h"
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h
new file mode 100644
index 0000000..c51c075
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h
@@ -0,0 +1,51 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarMessage.h"
+
+/**
+ Internal-only methods used by MDCSnackbarMessage and MDCSnackbarManager.
+ */
+@interface MDCSnackbarMessage ()
+
+/**
+ The class of the view which should be instantiated in order to show this message.
+
+ The class returned by this method must be a subclass of MDCSnackbarMessageView.
+ */
+- (Class)viewClass;
+
+/**
+ Executes @c self.completionhandler on the main thread.
+
+ @c completion is called after @c self.completionHandler has executed. If @c self.completionHandler
+ is nil, then @c completion fires immediately from the calling thread.
+ */
+- (void)executeCompletionHandlerWithUserInteraction:(BOOL)userInteraction
+                                         completion:(void (^)(void))completion;
+
+/**
+ Given @c action, which must be in @c self.actions, this method will call the action handler on
+ @c self.targetQueue.
+
+ @c completion is called after the handler has executed. If @c action.handler is nil, then
+ @c completion fires immediately from the calling thread. Passing a nil @c action will immediately
+ call @c completion.
+ */
+- (void)executeActionHandler:(MDCSnackbarMessageAction *)action
+                  completion:(void (^)(void))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h
new file mode 100644
index 0000000..40e9598
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h
@@ -0,0 +1,88 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+@class MDCSnackbarMessage;
+@class MDCSnackbarMessageAction;
+
+/**
+ Called by the snackbar message view when the user interacts with the snackbar view.
+
+ @c userInitiated indicates whether or not the handler is being called due to direct user
+ interaction. @c action, if non-nil, indicates that the user chose to execute a specific action.
+ */
+typedef void (^MDCSnackbarMessageDismissHandler)(BOOL userInitiated,
+                                                 MDCSnackbarMessageAction *_Nullable action);
+
+@interface MDCSnackbarMessageView ()
+
+/**
+ If the user has tapped on the snackbar or if @c dismissWithAction:userInitiated: has been called.
+ */
+@property(nonatomic, getter=isDismissing) BOOL dismissing;
+
+/**
+ The minimum width of the snackbar.
+ */
+@property(nonatomic, readonly) CGFloat minimumWidth;
+
+/**
+ The maximum width of the snackbar.
+ */
+@property(nonatomic, readonly) CGFloat maximumWidth;
+
+/**
+ Convenience pointer to the message used to create the view.
+ */
+@property(nonatomic, nullable, readonly, strong) MDCSnackbarMessage *message;
+/**
+ Creates a snackbar view to display @c message.
+
+ The view will call @c handler when the user has interacted with the snackbar view in such a way
+ that it needs to be dismissed prior to its timer-based dismissal time.
+ */
+- (_Nonnull instancetype)initWithMessage:(MDCSnackbarMessage *_Nullable)message
+                          dismissHandler:(MDCSnackbarMessageDismissHandler _Nullable)handler;
+
+/**
+ Dismisses the message view.
+
+ Does not call the message's completion handler or any action handler. Must be called from the main
+ thread.
+
+ @param action The action that prompted the dismissal.
+ @param userInitiated Whether or not this is a user-initiated dismissal or a programmatic one.
+ */
+- (void)dismissWithAction:(MDCSnackbarMessageAction *_Nullable)action
+            userInitiated:(BOOL)userInitiated;
+
+/**
+ When VoiceOver is enabled the view should wait for user action before dismissing.
+
+ Default is YES.
+ */
+- (BOOL)shouldWaitForDismissalDuringVoiceover;
+
+/**
+ Animate the opacity text and button content.
+
+ Creates and commits a CATransaction to perform the animation.
+ */
+- (void)animateContentOpacityFrom:(CGFloat)fromOpacity
+                               to:(CGFloat)toOpacity
+                         duration:(NSTimeInterval)duration
+                   timingFunction:(CAMediaTimingFunction *_Nullable)timingFunction;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h
new file mode 100644
index 0000000..e4526e6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h
@@ -0,0 +1,65 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCSnackbarMessageView;
+
+/** The identifier reported for the snackbar. */
+OBJC_EXTERN NSString *const MDCSnackbarOverlayIdentifier;
+
+/** The time it takes to show or hide the snackbar. */
+OBJC_EXTERN NSTimeInterval const MDCSnackbarTransitionDuration;
+
+/**
+ Custom overlay view for displaying snackbars.
+ */
+@interface MDCSnackbarOverlayView : UIView
+
+/**
+ Designated initializer.
+
+ Creates an overlay view which utilizes @c watcher to get its keyboard position information.
+ */
+- (instancetype)initWithFrame:(CGRect)frame;
+
+/**
+ Shows the snackbar view with the most appropriate animation.
+
+ @param snackbarView The snackbar view to display.
+ @param animated Whether or not the show should be animated.
+ @param completion A block to execute when the presentation is finished.
+ */
+- (void)showSnackbarView:(MDCSnackbarMessageView *)snackbarView
+                animated:(BOOL)animated
+              completion:(void (^)(void))completion;
+
+/**
+ Dismisses the currently showing snackbar view.
+
+ @param animated Whether or not the dismiss should be animated.
+ @param completion A block to execute when the dismissal is finished.
+ */
+- (void)dismissSnackbarViewAnimated:(BOOL)animated completion:(void (^)(void))completion;
+
+/**
+ How far from the bottom of the screen should snackbars be presented.
+
+ If set inside of an animation block, the change will animate.
+ */
+@property(nonatomic) CGFloat bottomOffset;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.m
new file mode 100644
index 0000000..1a0cca0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.m
@@ -0,0 +1,661 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "MDCSnackbarOverlayView.h"
+
+#import "MDCSnackbarMessageView.h"
+#import "MDCSnackbarMessageViewInternal.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialKeyboardWatcher.h"
+#import "MaterialOverlays.h"
+#import "UIApplication+AppExtensions.h"
+
+NSString *const MDCSnackbarOverlayIdentifier = @"MDCSnackbar";
+
+// The time it takes to show or hide the snackbar.
+NSTimeInterval const MDCSnackbarTransitionDuration = 0.5f;
+
+// How far from the bottom of the screen should the snackbar be.
+static const CGFloat MDCSnackbarBottomMargin_iPhone = 0;
+static const CGFloat MDCSnackbarBottomMargin_iPad = 0;
+
+// How far from the sides of the screen should the snackbar be.
+static const CGFloat MDCSnackbarSideMargin_iPhone = 0;
+static const CGFloat MDCSnackbarSideMargin_iPad = 24.0f;
+
+// The maximum height of the snackbar.
+static const CGFloat kMaximumHeight = 80.0f;
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCSnackbarOverlayView () <CAAnimationDelegate>
+@end
+#endif
+
+@interface MDCSnackbarOverlayView ()
+
+/**
+ The snackbar view to show. Setting this property simply puts the snackbar view into the window
+ hierarchy and installs constraints which will keep it pinned to the bottom of the screen.
+ */
+@property(nonatomic) MDCSnackbarMessageView *snackbarView;
+
+/**
+ The object which will notify us of changes in the keyboard position.
+ */
+@property(nonatomic) MDCKeyboardWatcher *watcher;
+
+/**
+ The layout constraint which determines the bottom of the containing view. Setting the constant
+ to a negative value will cause snackbars to appear from a point above the bottom of the screen.
+ */
+@property(nonatomic) NSLayoutConstraint *bottomConstraint;
+
+/**
+ The view which actually houses the snackbar. This view is sized to be the same width and height as
+ ourselves, except offset from the bottom, based on the keyboard height as well as any user-set
+ content offsets.
+ */
+@property(nonatomic) UIView *containingView;
+
+/**
+ Whether or not we are triggering a layout change ourselves. This is to distinguish when our bounds
+ are changing due to rotation rather than us adding/removing a snackbar.
+ */
+@property(nonatomic) BOOL manualLayoutChange;
+
+/**
+ If we received a rotation event, this is the duration that should be used.
+ */
+@property(nonatomic) NSTimeInterval rotationDuration;
+
+/**
+ The constraint used to pin the bottom of the snackbar to the bottom of the screen.
+ */
+@property(nonatomic) NSLayoutConstraint *snackbarOnscreenConstraint;
+
+/**
+ The constraint used to pin the top of the snackbar to the bottom of the screen.
+ */
+@property(nonatomic) NSLayoutConstraint *snackbarOffscreenConstraint;
+
+@end
+
+@implementation MDCSnackbarOverlayView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+
+  MDCKeyboardWatcher *watcher = [MDCKeyboardWatcher sharedKeyboardWatcher];
+
+  if (self) {
+    _watcher = watcher;
+    _containingView = [[UIView alloc] initWithFrame:frame];
+    _containingView.translatesAutoresizingMaskIntoConstraints = NO;
+    _containingView.clipsToBounds = YES;
+    [self addSubview:_containingView];
+
+    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillShow:)
+               name:MDCKeyboardWatcherKeyboardWillShowNotification
+             object:watcher];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillBeHidden:)
+               name:MDCKeyboardWatcherKeyboardWillHideNotification
+             object:watcher];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillChangeFrame:)
+               name:MDCKeyboardWatcherKeyboardWillChangeFrameNotification
+             object:watcher];
+
+    [nc addObserver:self
+           selector:@selector(willRotate:)
+               name:UIApplicationWillChangeStatusBarOrientationNotification
+             object:nil];
+
+    [nc addObserver:self
+           selector:@selector(didRotate:)
+               name:UIApplicationDidChangeStatusBarOrientationNotification
+             object:nil];
+
+    [self setupContainerConstraints];
+  }
+  return self;
+}
+
+/**
+ Installs constraints for the ever-present container view.
+
+ @note These constraints remain installed for the life of the overlay view, whereas the
+       constraints installed in @c setsnackbarView: come and go with the current snackbar.
+ */
+- (void)setupContainerConstraints {
+  [self addConstraint:[NSLayoutConstraint constraintWithItem:_containingView
+                                                   attribute:NSLayoutAttributeLeading
+                                                   relatedBy:NSLayoutRelationEqual
+                                                      toItem:self
+                                                   attribute:NSLayoutAttributeLeading
+                                                  multiplier:1.0
+                                                    constant:0]];
+
+  [self addConstraint:[NSLayoutConstraint constraintWithItem:_containingView
+                                                   attribute:NSLayoutAttributeTrailing
+                                                   relatedBy:NSLayoutRelationEqual
+                                                      toItem:self
+                                                   attribute:NSLayoutAttributeTrailing
+                                                  multiplier:1.0
+                                                    constant:0]];
+
+  [self addConstraint:[NSLayoutConstraint constraintWithItem:_containingView
+                                                   attribute:NSLayoutAttributeTop
+                                                   relatedBy:NSLayoutRelationEqual
+                                                      toItem:self
+                                                   attribute:NSLayoutAttributeTop
+                                                  multiplier:1.0
+                                                    constant:0]];
+
+  self.bottomConstraint = [NSLayoutConstraint constraintWithItem:_containingView
+                                                       attribute:NSLayoutAttributeBottom
+                                                       relatedBy:NSLayoutRelationEqual
+                                                          toItem:self
+                                                       attribute:NSLayoutAttributeBottom
+                                                      multiplier:1.0
+                                                        constant:-[self dynamicBottomMargin]];
+  [self addConstraint:self.bottomConstraint];
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+/**
+ The bottom margin which is dependent on the keyboard and application-wide settings, and may
+ change at any time during runtime.
+ */
+- (CGFloat)dynamicBottomMargin {
+  CGFloat keyboardHeight = self.watcher.keyboardOffset;
+  CGFloat userHeight = self.bottomOffset;
+
+  return MAX(keyboardHeight, userHeight);
+}
+
+/**
+ The bottom margin which is dependent on device type and cannot change.
+ */
+- (CGFloat)staticBottomMargin {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? MDCSnackbarBottomMargin_iPad
+                                                              : MDCSnackbarBottomMargin_iPhone;
+}
+
+- (CGFloat)sideMargin {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? MDCSnackbarSideMargin_iPad
+                                                              : MDCSnackbarSideMargin_iPhone;
+}
+
+- (void)setSnackbarView:(MDCSnackbarMessageView *)snackbarView {
+  if (_snackbarView != snackbarView) {
+    [_snackbarView removeFromSuperview];
+    _snackbarView = snackbarView;
+
+    CGFloat bottomMargin = [self staticBottomMargin];
+    CGFloat sideMargin = [self sideMargin];
+
+    BOOL fullWidth = UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad;
+
+    UIView *container = self.containingView;
+
+    if (snackbarView) {
+      [container addSubview:snackbarView];
+
+      // Pin the snackbar to the bottom of the screen.
+      [snackbarView setTranslatesAutoresizingMaskIntoConstraints:NO];
+
+      [container addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                            attribute:NSLayoutAttributeCenterX
+                                                            relatedBy:NSLayoutRelationEqual
+                                                               toItem:container
+                                                            attribute:NSLayoutAttributeCenterX
+                                                           multiplier:1.0
+                                                             constant:0]];
+
+      if (fullWidth) {
+        [container addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                              attribute:NSLayoutAttributeWidth
+                                                              relatedBy:NSLayoutRelationEqual
+                                                                 toItem:container
+                                                              attribute:NSLayoutAttributeWidth
+                                                             multiplier:1.0
+                                                               constant:-2 * sideMargin]];
+      } else {
+        // If not full width, ensure that it doesn't get any larger than our own width.
+        [container
+            addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                       attribute:NSLayoutAttributeWidth
+                                                       relatedBy:NSLayoutRelationLessThanOrEqual
+                                                          toItem:container
+                                                       attribute:NSLayoutAttributeWidth
+                                                      multiplier:1.0
+                                                        constant:-2 * sideMargin]];
+
+        // Also ensure that it doesn't get any smaller than its own minimum width.
+        [container
+            addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                       attribute:NSLayoutAttributeWidth
+                                                       relatedBy:NSLayoutRelationGreaterThanOrEqual
+                                                          toItem:nil
+                                                       attribute:NSLayoutAttributeNotAnAttribute
+                                                      multiplier:1.0
+                                                        constant:[snackbarView minimumWidth]]];
+
+        // Also ensure that it doesn't get any larger than its own maximum width.
+        [container
+            addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                       attribute:NSLayoutAttributeWidth
+                                                       relatedBy:NSLayoutRelationLessThanOrEqual
+                                                          toItem:nil
+                                                       attribute:NSLayoutAttributeNotAnAttribute
+                                                      multiplier:1.0
+                                                        constant:[snackbarView maximumWidth]]];
+      }
+
+      // Always pin the snackbar to the bottom of the container.
+      _snackbarOnscreenConstraint = [NSLayoutConstraint constraintWithItem:snackbarView
+                                                                 attribute:NSLayoutAttributeBottom
+                                                                 relatedBy:NSLayoutRelationEqual
+                                                                    toItem:container
+                                                                 attribute:NSLayoutAttributeBottom
+                                                                multiplier:1.0
+                                                                  constant:-bottomMargin];
+      _snackbarOnscreenConstraint.active = NO;  // snackbar starts off-screen.
+      _snackbarOnscreenConstraint.priority = UILayoutPriorityDefaultHigh;
+      [container addConstraint:_snackbarOnscreenConstraint];
+
+      _snackbarOffscreenConstraint = [NSLayoutConstraint constraintWithItem:snackbarView
+                                                                  attribute:NSLayoutAttributeTop
+                                                                  relatedBy:NSLayoutRelationEqual
+                                                                     toItem:container
+                                                                  attribute:NSLayoutAttributeBottom
+                                                                 multiplier:1.0
+                                                                   constant:-bottomMargin];
+      _snackbarOffscreenConstraint.active = YES;
+      [container addConstraint:_snackbarOffscreenConstraint];
+
+      // Always limit the height of the snackbar.
+      [container
+          addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                     attribute:NSLayoutAttributeHeight
+                                                     relatedBy:NSLayoutRelationLessThanOrEqual
+                                                        toItem:nil
+                                                     attribute:NSLayoutAttributeNotAnAttribute
+                                                    multiplier:1.0
+                                                      constant:kMaximumHeight]];
+    }
+  }
+}
+
+// All we care about is whether or not we tapped on the snackbar view. Everything else should pass
+// through to other windows. Only ask the snackbar view if the given point belongs, and ignore all
+// other touches.
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  BOOL result = NO;
+
+  if (self.snackbarView) {
+    CGPoint snackbarPoint = [self convertPoint:point toView:self.snackbarView];
+    result = [self.snackbarView pointInside:snackbarPoint withEvent:event];
+  }
+
+  return result;
+}
+
+- (void)triggerSnackbarLayoutChange {
+  self.manualLayoutChange = YES;
+  [self layoutIfNeeded];
+  self.manualLayoutChange = NO;
+}
+
+- (CGRect)snackbarRectInScreenCoordinates {
+  if (self.snackbarView == nil) {
+    return CGRectNull;
+  }
+
+  UIWindow *window = self.snackbarView.window;
+  if (window == nil) {
+    return CGRectNull;
+  }
+
+  UIScreen *screen = window.screen;
+  if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
+    return [self.snackbarView convertRect:self.snackbarView.bounds
+                        toCoordinateSpace:screen.fixedCoordinateSpace];
+  }
+
+  CGRect snackbarWindowFrame =
+      [window convertRect:self.snackbarView.bounds fromView:self.snackbarView];
+  CGRect snackbarScreenFrame = [window convertRect:snackbarWindowFrame toWindow:nil];
+  return snackbarScreenFrame;
+}
+
+#pragma mark - Presentation/Dismissal
+
+- (void)showSnackbarView:(MDCSnackbarMessageView *)snackbarView
+                animated:(BOOL)animated
+              completion:(void (^)(void))completion {
+  self.snackbarView = snackbarView;  // Install the snackbar.
+
+  if (animated) {
+    [self slideInMessageView:snackbarView completion:completion];
+  } else {
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+- (void)dismissSnackbarViewAnimated:(BOOL)animated completion:(void (^)(void))completion {
+  if (animated) {
+    [self slideOutMessageView:self.snackbarView
+                   completion:^{
+                     self.snackbarView = nil;  // Uninstall the snackbar
+
+                     if (completion) {
+                       completion();
+                     }
+                   }];
+  } else {
+    self.snackbarView = nil;
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+#pragma mark - Fade Animation
+
+- (void)fadeInsnackbarView:(MDCSnackbarMessageView *)snackbarView
+                completion:(void (^)(void))completion {
+  snackbarView.alpha = 0;
+
+  // Make sure that the snackbar has been properly sized before fading in.
+  [self triggerSnackbarLayoutChange];
+
+  void (^animations)(void) = ^{
+    self.snackbarView.alpha = 1.0;
+  };
+  void (^realCompletion)(BOOL) = ^(BOOL finished) {
+    if (completion) {
+      completion();
+    }
+  };
+
+  UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut;
+  CAMediaTimingFunction *function = nil;
+
+  MDCAnimationTimingFunction materialCurve = MDCAnimationTimingFunctionEaseOut;
+  function = [CAMediaTimingFunction mdc_functionWithType:materialCurve];
+
+  [MDCSnackbarOverlayView animateWithDuration:MDCSnackbarTransitionDuration
+                                        curve:materialCurve
+                                   animations:animations
+                                   completion:realCompletion];
+
+  // Notify the overlay system.
+  [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                            duration:MDCSnackbarTransitionDuration
+                               curve:curve
+                      timingFunction:function];
+}
+
+#pragma mark - Slide Animation
+
+- (void)slideMessageView:(MDCSnackbarMessageView *)snackbarView
+                onscreen:(BOOL)onscreen
+      fromContentOpacity:(CGFloat)fromContentOpacity
+        toContentOpacity:(CGFloat)toContentOpacity
+              completion:(void (^)(void))completion {
+  // Prepare to move the snackbar.
+  _snackbarOnscreenConstraint.active = onscreen;
+  _snackbarOffscreenConstraint.active = !onscreen;
+  [_containingView setNeedsUpdateConstraints];
+
+  CAMediaTimingFunction *timingFunction =
+      [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionEaseInOut];
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:timingFunction];
+
+  // We use UIView animation inside a CATransaction in order to use the custom animation curve.
+  [UIView animateWithDuration:MDCSnackbarTransitionDuration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseInOut
+      animations:^{
+        // Trigger snackbar animation.
+        [_containingView layoutIfNeeded];
+      }
+      completion:^(BOOL finished) {
+        if (completion) {
+          completion();
+        }
+      }];
+
+  [snackbarView animateContentOpacityFrom:fromContentOpacity
+                                       to:toContentOpacity
+                                 duration:MDCSnackbarTransitionDuration
+                           timingFunction:timingFunction];
+  [CATransaction commit];
+
+  // Notify the overlay system.
+  [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                            duration:MDCSnackbarTransitionDuration
+                               curve:0
+                      timingFunction:timingFunction];
+}
+
+- (void)slideInMessageView:(MDCSnackbarMessageView *)snackbarView
+                completion:(void (^)(void))completion {
+  // Make sure that the snackbar has been properly sized to calculate the translation value.
+  [self triggerSnackbarLayoutChange];
+
+  [self slideMessageView:snackbarView
+                onscreen:YES
+      fromContentOpacity:0
+        toContentOpacity:1
+              completion:completion];
+}
+
+- (void)slideOutMessageView:(MDCSnackbarMessageView *)snackbarView
+                 completion:(void (^)(void))completion {
+  // Make sure that the snackbar has been properly sized to calculate the translation value.
+  [self triggerSnackbarLayoutChange];
+
+  [self slideMessageView:snackbarView
+                onscreen:NO
+      fromContentOpacity:1
+        toContentOpacity:0
+              completion:completion];
+}
+
+#pragma mark - Keyboard Notifications
+
+- (void)updatesnackbarPositionWithKeyboardUserInfo:(NSDictionary *)userInfo {
+  // Always set the bottom constraint, even if there isn't a snackbar currently displayed.
+  void (^updateBlock)(void) = ^{
+    self.bottomConstraint.constant = -[self dynamicBottomMargin];
+    [self triggerSnackbarLayoutChange];
+  };
+
+  if (self.snackbarView) {
+    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
+    UIViewAnimationCurve curve =
+        [userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
+    UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState | curve << 16;
+
+    [UIView animateWithDuration:duration
+                          delay:0
+                        options:options
+                     animations:updateBlock
+                     completion:nil];
+
+    // Notify the overlay system that a change is happening.
+    [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                              duration:duration
+                                 curve:curve
+                        timingFunction:nil];
+  } else {
+    updateBlock();
+  }
+}
+
+- (void)keyboardWillShow:(NSNotification *)notification {
+  [self updatesnackbarPositionWithKeyboardUserInfo:[notification userInfo]];
+}
+
+- (void)keyboardWillBeHidden:(NSNotification *)notification {
+  [self updatesnackbarPositionWithKeyboardUserInfo:[notification userInfo]];
+}
+
+- (void)keyboardWillChangeFrame:(NSNotification *)notification {
+  [self updatesnackbarPositionWithKeyboardUserInfo:[notification userInfo]];
+}
+
+#pragma mark - Bottom Offset
+
+- (void)setBottomOffset:(CGFloat)bottomOffset {
+  if (_bottomOffset != bottomOffset) {
+    _bottomOffset = bottomOffset;
+
+    self.bottomConstraint.constant = -[self dynamicBottomMargin];
+    [self triggerSnackbarLayoutChange];
+  }
+}
+
+#pragma mark - Rotation
+
+- (void)handleRotation {
+  if (self.snackbarView != nil) {
+    [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                              duration:self.rotationDuration
+                                 curve:UIViewAnimationCurveEaseInOut
+                        timingFunction:nil];
+  }
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  if (!self.manualLayoutChange && self.rotationDuration > 0) {
+    [self handleRotation];
+  }
+}
+
+- (void)willRotate:(NSNotification *)notification {
+  UIApplication *application = [UIApplication mdc_safeSharedApplication];
+  UIInterfaceOrientation currentOrientation = application.statusBarOrientation;
+  UIInterfaceOrientation targetOrientation =
+      [notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
+
+  NSTimeInterval duration = application.statusBarOrientationAnimationDuration;
+
+  // If this is a landscape->landscape or portrait->portrait rotation, then double the duration.
+  BOOL currentIsLandscape = UIInterfaceOrientationIsLandscape(currentOrientation);
+  BOOL targetIsLandscape = UIInterfaceOrientationIsLandscape(targetOrientation);
+  if (currentIsLandscape == targetIsLandscape) {
+    duration = 2 * duration;
+  }
+
+  self.rotationDuration = duration;
+
+  // On iOS 7, the layout of this overlay view will have already occurred by the time the will
+  // rotation notification is posted. In that event, we need to report rotation here. Opting to
+  // check for version using the UIDevice string methods because we need to perform this check even
+  // if the app was compiled on an iOS 7 SDK and is running on an iOS 8 device.
+  NSString *version = [[UIDevice currentDevice] systemVersion];
+  if ([version compare:@"8.0" options:NSNumericSearch] == NSOrderedAscending) {
+    [self handleRotation];
+  }
+}
+
+- (void)didRotate:(NSNotification *)notification {
+  // The UIApplicationDidChangeStatusBarOrientationNotification happens pretty much immediately
+  // after the willRotate notification, before any layouts are changed. By delaying this until the
+  // next runloop, any rotation-related layout changes will occur, and we can know that they were
+  // due to rotation.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    self.rotationDuration = -1;
+  });
+}
+
+#pragma mark - Overlay Support
+
+- (void)notifyOverlayChangeWithFrame:(CGRect)frame
+                            duration:(NSTimeInterval)duration
+                               curve:(UIViewAnimationCurve)curve
+                      timingFunction:(CAMediaTimingFunction *)timingFunction {
+  NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{
+    MDCOverlayIdentifierKey : MDCSnackbarOverlayIdentifier,
+    MDCOverlayFrameKey : [NSValue valueWithCGRect:frame],
+    MDCOverlayTransitionDurationKey : @(duration),
+  }];
+
+  if (duration > 0) {
+    if (timingFunction != nil) {
+      userInfo[MDCOverlayTransitionTimingFunctionKey] = timingFunction;
+    } else {
+      userInfo[MDCOverlayTransitionCurveKey] = @(curve);
+    }
+  }
+
+  // Notify the overlay system that a change is happening
+  [[NSNotificationCenter defaultCenter] postNotificationName:MDCOverlayDidChangeNotification
+                                                      object:nil
+                                                    userInfo:userInfo];
+}
+
+#pragma mark - UIAccessibilityAction
+
+- (BOOL)accessibilityPerformEscape {
+  if (self.snackbarView) {
+    [self.snackbarView dismissWithAction:nil userInitiated:YES];
+    return YES;
+  } else {
+    return NO;
+  }
+}
+
+#pragma mark - Timing functions
+
+static void WrapWithTimingFunctionForCurve(MDCAnimationTimingFunction mediaTiming,
+                                           void (^block)(void)) {
+  [CATransaction begin];
+  [CATransaction
+      setAnimationTimingFunction:[CAMediaTimingFunction mdc_functionWithType:mediaTiming]];
+  block();
+  [CATransaction commit];
+}
+
++ (void)animateWithDuration:(NSTimeInterval)duration
+                      curve:(MDCAnimationTimingFunction)curve
+                 animations:(void (^)(void))animations
+                 completion:(void (^)(BOOL finished))completion {
+  WrapWithTimingFunctionForCurve(curve, ^{
+    [UIView animateWithDuration:duration animations:animations completion:completion];
+  });
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.h
new file mode 100644
index 0000000..701cd43
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.h
@@ -0,0 +1,154 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCTabBarAlignment.h"
+#import "MDCTabBarItemAppearance.h"
+
+@class MDCTabBarItem;
+@protocol MDCTabBarDelegate;
+
+/**
+ A material tab bar for switching between views of grouped content.
+
+ Clients are responsible for responding to changes to the selected tab and updating the selected
+ tab as necessary.
+
+ Note: This class is not intended to be subclassed.
+
+ @see https://www.google.com/design/spec/components/tabs.html
+ */
+IB_DESIGNABLE
+@interface MDCTabBar : UIView
+
+/** Return the desired height for the tab bar given an item appearance. */
++ (CGFloat)defaultHeightForItemAppearance:(MDCTabBarItemAppearance)appearance;
+
+/**
+ Items displayed in the tab bar.
+
+ If the new items do not contain the currently selected item, the selection will be reset to nil.
+ Changes to this property are not animated.
+ */
+@property(nonatomic, copy, nonnull) NSArray<UITabBarItem *> *items;
+
+/**
+ The currently selected item. Setting to nil will clear the selection.
+
+ Changes to `selectedItem` are not animated.
+ */
+@property(nonatomic, strong, nullable) UITabBarItem *selectedItem;
+
+/** The tab bar's delegate. */
+@property(nonatomic, weak, nullable) IBOutlet id<MDCTabBarDelegate> delegate;
+
+/**
+ Tint color for the tab bar, which determines the color of the tab indicator bar. If
+ selectedItemTintColor is nil, tintColor also affects tinting of selected item titles and images.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *tintColor;
+
+/**
+ Tint color for selected items. If nil, selected items will be tinted using the tab bar's
+ inherited tintColor instead. Default: Opaque white.
+ */
+@property(nonatomic, nullable) UIColor *selectedItemTintColor UI_APPEARANCE_SELECTOR;
+
+/** Tint color for unselected items. Default: Semi-transparent white. */
+@property(nonatomic, nonnull) UIColor *unselectedItemTintColor UI_APPEARANCE_SELECTOR;
+
+/** Ink color for taps on tab bar items. Default: Semi-transparent white. */
+@property(nonatomic, nonnull) UIColor *inkColor UI_APPEARANCE_SELECTOR;
+
+/**
+ Tint color to apply to the tab bar background.
+
+ If nil, the receiver uses the default background appearance. Default: nil.
+ */
+@property(nonatomic, nullable) UIColor *barTintColor UI_APPEARANCE_SELECTOR;
+
+/**
+ Horizontal alignment of tabs within the tab bar. Changes are not animated. Default alignment is
+ MDCTabBarAlignmentLeading.
+ */
+@property(nonatomic) MDCTabBarAlignment alignment;
+
+/**
+ Appearance of tabs within the tab bar. Changes are not animated. Default appearance is
+ MDCTabBarItemAppearanceTitles.
+ */
+@property(nonatomic) MDCTabBarItemAppearance itemAppearance;
+
+/**
+ Indicates if all tab titles should be uppercased for display. If NO, item titles will be
+ displayed verbatim.
+
+ Default is YES and is recommended whenever possible.
+ */
+@property(nonatomic) BOOL displaysUppercaseTitles;
+
+/**
+ Select an item with optional animation. Setting to nil will clear the selection.
+
+ `selectedItem` must be nil or in `items`.
+ */
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem animated:(BOOL)animated;
+
+/** Updates the alignment with optional animation. */
+- (void)setAlignment:(MDCTabBarAlignment)alignment animated:(BOOL)animated;
+
+@end
+
+#pragma mark -
+
+/** Accessibility-related methods on MDCTabBar. */
+@interface MDCTabBar (MDCAccessibility)
+
+/**
+ Get the accessibility element representing the given item. Returns nil if item is not in `items`
+ or if the item is not on screen.
+
+ The accessibility element returned from this method may be used as the focused element after a
+ run loop iteration.
+ */
+- (nullable id)accessibilityElementForItem:(nonnull UITabBarItem *)item;
+
+@end
+
+#pragma mark -
+
+/**
+ Delegate protocol for MDCTabBar. Clients may implement this protocol to receive notifications of
+ selection changes in the tab bar.
+ */
+@protocol MDCTabBarDelegate <NSObject>
+
+@optional
+
+/**
+ Called before the selected item changes by user action. This method is not called for programmatic
+ changes to the tab bar's selected item.
+ */
+- (void)tabBar:(nonnull MDCTabBar *)tabBar willSelectItem:(nonnull UITabBarItem *)item;
+
+/**
+ Called when the selected item changes by user action. This method is not called for programmatic
+ changes to the tab bar's selected item.
+ */
+- (void)tabBar:(nonnull MDCTabBar *)tabBar didSelectItem:(nonnull UITabBarItem *)item;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.m
new file mode 100644
index 0000000..77659de
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.m
@@ -0,0 +1,311 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCTabBar.h"
+
+#import "MaterialInk.h"
+#import "MaterialTypography.h"
+#import "private/MDCItemBar.h"
+#import "private/MDCItemBarAlignment.h"
+#import "private/MDCItemBarStyle.h"
+
+/// Padding between image and title in points, according to the spec.
+static const CGFloat kImageTitleSpecPadding = 10;
+
+/// Adjustment added to spec measurements to compensate for internal paddings.
+static const CGFloat kImageTitlePaddingAdjustment = -3;
+
+// Heights based on the spec: https://www.google.com/design/spec/components/tabs.html
+
+/// Height for image-only tab bars, in points.
+static const CGFloat kImageOnlyBarHeight = 48;
+
+/// Height for image-only tab bars, in points.
+static const CGFloat kTitleOnlyBarHeight = 48;
+
+/// Height for image-and-title tab bars, in points.
+static const CGFloat kTitledImageBarHeight = 72;
+
+static MDCTabBarAlignment MDCTabBarAlignmentForItemBarAlignment(MDCItemBarAlignment alignment) {
+  switch (alignment) {
+    case MDCItemBarAlignmentCenter:
+      return MDCTabBarAlignmentCenter;
+
+    case MDCItemBarAlignmentLeading:
+      return MDCTabBarAlignmentLeading;
+
+    case MDCItemBarAlignmentJustified:
+      return MDCTabBarAlignmentJustified;
+
+    case MDCItemBarAlignmentCenterSelected:
+      return MDCTabBarAlignmentCenterSelected;
+  }
+
+  NSCAssert(0, @"Invalid alignment value %zd", alignment);
+  return MDCTabBarAlignmentLeading;
+}
+
+static MDCItemBarAlignment MDCItemBarAlignmentForTabBarAlignment(MDCTabBarAlignment alignment) {
+  switch (alignment) {
+    case MDCTabBarAlignmentCenter:
+      return MDCItemBarAlignmentCenter;
+
+    case MDCTabBarAlignmentLeading:
+      return MDCItemBarAlignmentLeading;
+
+    case MDCTabBarAlignmentJustified:
+      return MDCItemBarAlignmentJustified;
+
+    case MDCTabBarAlignmentCenterSelected:
+      return MDCItemBarAlignmentCenterSelected;
+  }
+
+  NSCAssert(0, @"Invalid alignment value %zd", alignment);
+  return MDCItemBarAlignmentLeading;
+}
+
+@interface MDCTabBar () <MDCItemBarDelegate>
+@end
+
+@implementation MDCTabBar {
+  /// Item bar responsible for displaying the actual tab bar content.
+  MDCItemBar *_itemBar;
+}
+// Inherit UIView's tintColor logic.
+@dynamic tintColor;
+
+#pragma mark - Initialization
+
++ (void)initialize {
+  [[[self class] appearance] setSelectedItemTintColor:[UIColor whiteColor]];
+  [[[self class] appearance] setUnselectedItemTintColor:[UIColor colorWithWhite:1.0 alpha:0.7f]];
+  [[[self class] appearance] setInkColor:[UIColor colorWithWhite:1.0 alpha:0.7f]];
+  [[[self class] appearance] setBarTintColor:nil];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCTabBarInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCTabBarInit];
+  }
+  return self;
+}
+
+- (void)commonMDCTabBarInit {
+  _itemAppearance = MDCTabBarItemAppearanceTitles;
+  _displaysUppercaseTitles = YES;
+
+  // Create item bar.
+  _itemBar = [[MDCItemBar alloc] initWithFrame:self.bounds];
+  _itemBar.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+  _itemBar.delegate = self;
+  _itemBar.alignment = MDCItemBarAlignmentLeading;
+  [self addSubview:_itemBar];
+
+  [self updateItemBarStyle];
+}
+
+#pragma mark - Public
+
++ (CGFloat)defaultHeightForItemAppearance:(MDCTabBarItemAppearance)appearance {
+  return [MDCItemBar defaultHeightForStyle:[self defaultStyleForItemAppearance:appearance]];
+}
+
+- (NSArray<UITabBarItem *> *)items {
+  return _itemBar.items;
+}
+
+- (void)setItems:(NSArray<UITabBarItem *> *)items {
+  [_itemBar setItems:items];
+}
+
+- (UITabBarItem *)selectedItem {
+  return _itemBar.selectedItem;
+}
+
+- (void)setSelectedItem:(UITabBarItem *)selectedItem {
+  [_itemBar setSelectedItem:selectedItem];
+}
+
+- (void)setSelectedItem:(UITabBarItem *)selectedItem animated:(BOOL)animated {
+  [_itemBar setSelectedItem:selectedItem animated:animated];
+}
+
+- (void)setBarTintColor:(UIColor *)barTintColor {
+  if (_barTintColor != barTintColor && ![_barTintColor isEqual:barTintColor]) {
+    _barTintColor = barTintColor;
+
+    // Update background color.
+    _itemBar.backgroundColor = barTintColor;
+  }
+}
+
+- (void)setInkColor:(UIColor *)inkColor {
+  if (_inkColor != inkColor && ![_inkColor isEqual:inkColor]) {
+    _inkColor = inkColor;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (MDCTabBarAlignment)alignment {
+  return MDCTabBarAlignmentForItemBarAlignment(_itemBar.alignment);
+}
+
+- (void)setAlignment:(MDCTabBarAlignment)alignment {
+  [_itemBar setAlignment:MDCItemBarAlignmentForTabBarAlignment(alignment)];
+}
+
+- (void)setAlignment:(MDCTabBarAlignment)alignment animated:(BOOL)animated {
+  [_itemBar setAlignment:MDCItemBarAlignmentForTabBarAlignment(alignment) animated:animated];
+}
+
+- (void)setItemAppearance:(MDCTabBarItemAppearance)itemAppearance {
+  if (itemAppearance != _itemAppearance) {
+    _itemAppearance = itemAppearance;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (void)setSelectedItemTintColor:(UIColor *)selectedItemTintColor {
+  if (_selectedItemTintColor != selectedItemTintColor &&
+      ![_selectedItemTintColor isEqual:selectedItemTintColor]) {
+    _selectedItemTintColor = selectedItemTintColor;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (void)setUnselectedItemTintColor:(UIColor *)unselectedItemTintColor {
+  if (_unselectedItemTintColor != unselectedItemTintColor &&
+      ![_unselectedItemTintColor isEqual:unselectedItemTintColor]) {
+    _unselectedItemTintColor = unselectedItemTintColor;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (void)setDisplaysUppercaseTitles:(BOOL)displaysUppercaseTitles {
+  if (displaysUppercaseTitles != _displaysUppercaseTitles) {
+    _displaysUppercaseTitles = displaysUppercaseTitles;
+
+    [self updateItemBarStyle];
+  }
+}
+
+#pragma mark - MDCItemBarDelegate
+
+- (void)itemBar:(MDCItemBar *)itemBar didSelectItem:(UITabBarItem *)item {
+  id<MDCTabBarDelegate> delegate = self.delegate;
+  if ([delegate respondsToSelector:@selector(tabBar:didSelectItem:)]) {
+    [delegate tabBar:self didSelectItem:item];
+  }
+}
+
+- (void)itemBar:(MDCItemBar *)itemBar willSelectItem:(UITabBarItem *)item {
+  id<MDCTabBarDelegate> delegate = self.delegate;
+  if ([delegate respondsToSelector:@selector(tabBar:willSelectItem:)]) {
+    [delegate tabBar:self willSelectItem:item];
+  }
+}
+
+#pragma mark - UIView
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  [self updateItemBarStyle];
+}
+
+- (CGSize)intrinsicContentSize {
+  return _itemBar.intrinsicContentSize;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return [_itemBar sizeThatFits:size];
+}
+
+#pragma mark - Private
+
++ (MDCItemBarStyle *)defaultStyleForItemAppearance:(MDCTabBarItemAppearance)appearance {
+  MDCItemBarStyle *style = [[MDCItemBarStyle alloc] init];
+
+  style.shouldDisplaySelectionIndicator = YES;
+  style.shouldGrowOnSelection = NO;
+  style.titleFont = [MDCTypography buttonFont];
+  style.inkStyle = MDCInkStyleBounded;
+  style.titleImagePadding = (kImageTitleSpecPadding + kImageTitlePaddingAdjustment);
+
+  BOOL displayImage = NO;
+  BOOL displayTitle = NO;
+  CGFloat defaultHeight = 0;
+  switch (appearance) {
+    case MDCTabBarItemAppearanceImages:
+      displayImage = YES;
+      defaultHeight = kImageOnlyBarHeight;
+      break;
+
+    case MDCTabBarItemAppearanceTitles:
+      displayTitle = YES;
+      defaultHeight = kTitleOnlyBarHeight;
+      break;
+
+    case MDCTabBarItemAppearanceTitledImages:
+      displayImage = YES;
+      displayTitle = YES;
+      defaultHeight = kTitledImageBarHeight;
+      break;
+
+    default:
+      NSAssert(0, @"Invalid appearance value %zd", appearance);
+      displayTitle = YES;
+      defaultHeight = kTitleOnlyBarHeight;
+      break;
+  }
+  style.shouldDisplayImage = displayImage;
+  style.shouldDisplayTitle = displayTitle;
+  style.defaultHeight = defaultHeight;
+
+  // Only show badge with images.
+  style.shouldDisplayBadge = displayImage;
+
+  return style;
+}
+
+- (void)updateItemBarStyle {
+  MDCItemBarStyle *style;
+
+  style = [[self class] defaultStyleForItemAppearance:_itemAppearance];
+
+  style.selectionIndicatorColor = self.tintColor;
+  style.inkColor = _inkColor;
+  style.selectedTitleColor = (_selectedItemTintColor ?: self.tintColor);
+  style.titleColor = _unselectedItemTintColor;
+  style.displaysUppercaseTitles = _displaysUppercaseTitles;
+
+  [_itemBar applyStyle:style];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
new file mode 100644
index 0000000..7e78559
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
@@ -0,0 +1,38 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/** Alignment styles for items in a tab bar. */
+typedef NS_ENUM(NSInteger, MDCTabBarAlignment) {
+  /** Items are aligned on the leading edge and sized to fit their content. */
+  MDCTabBarAlignmentLeading,
+
+  /**
+   Items are justified to equal size across the width of the screen. Overscrolling is disabled
+   for this alignment.
+   */
+  MDCTabBarAlignmentJustified,
+
+  /**
+   Items are sized to fit their content and center-aligned as a group. If they do not fit in view,
+   they will be leading-aligned instead.
+   */
+  MDCTabBarAlignmentCenter,
+
+  /** Tabs are center-aligned on the selected item. */
+  MDCTabBarAlignmentCenterSelected,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
new file mode 100644
index 0000000..f8e00a3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Appearance for content within tab bar items. */
+typedef NS_ENUM(NSInteger, MDCTabBarItemAppearance) {
+  /** Tabs are shown as titles. Badges are not supported for this appearance. */
+  MDCTabBarItemAppearanceTitles,
+
+  /** Tabs are shown as images. */
+  MDCTabBarItemAppearanceImages,
+
+  /** Tabs are shown as images with titles underneath. */
+  MDCTabBarItemAppearanceTitledImages,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ar.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ar.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b02b103
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ar.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d‏ من‏ %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "علامة تبويب";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/bg.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/bg.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/bg.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ca.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ca.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2cb6f30
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ca.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestanya";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/cs.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/cs.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..dcde450
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/cs.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d z %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "karta";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/da.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/da.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..78a052a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/da.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d af %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "fane";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/de.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/de.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..bc8b328
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/de.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d von %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Tabulatortaste";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/el.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/el.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..eeb2245
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/el.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d από %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "καρτέλα";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_AU.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_AU.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_AU.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_GB.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_GB.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_GB.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_IN.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_IN.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_IN.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..5ebb933
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestaña";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_419.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_419.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2cd61d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_419.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestaña";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_MX.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_MX.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2cd61d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_MX.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestaña";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fa.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fa.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..57be590
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fa.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d از %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "برگه";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fi.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fi.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..7f42728
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fi.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "välilehti";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2262686
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d sur %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "onglet";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr_CA.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr_CA.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..1520591
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr_CA.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "onglet";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/he.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/he.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b692f77
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/he.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d מתוך %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "כרטיסייה";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hi.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hi.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..6898e9d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hi.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d में से %1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "टैब";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..8d77fb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d od %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "kartica";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hu.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hu.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..97e1739
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hu.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d/%1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "lapfül";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hy.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hy.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2467de9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hy.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d-ը՝ %2$d-ից";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "ներդիր";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/id.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/id.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..1275b47
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/id.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d dari %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/it.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/it.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..7fa1e7c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/it.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d di %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "scheda";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/iw.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/iw.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b692f77
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/iw.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d מתוך %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "כרטיסייה";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ja.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ja.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..c4393cc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ja.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "タブ";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ka.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ka.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2140c25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ka.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d / %2$d-დან";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "ჩანართი";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/kk.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/kk.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..57bf878
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/kk.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d/%1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "қойынды";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/km.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/km.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..e4f3c95
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/km.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d នៃ %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "ថេប​";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ko.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ko.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..874831f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ko.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d개 중 %1$d번째";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lo.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lo.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..d94fbd0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lo.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d ຈາກທັງໝົດ %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lt.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lt.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..7194c55
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lt.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d iš %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "skirtukas";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lv.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lv.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lv.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/mn.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/mn.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..d26886f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/mn.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d-н %1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "чихтэй хуудас";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ms.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ms.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..f82885d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ms.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d daripada %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nb.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nb.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..36e5452
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nb.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d av %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "fane";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nl.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nl.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..393b1cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nl.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d van %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tabblad";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/no.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/no.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..36e5452
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/no.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d av %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "fane";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pl.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pl.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..e1ebe01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pl.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d z %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "karta";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..cd88f7f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "guia";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_BR.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_BR.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..cd88f7f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_BR.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "guia";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_PT.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_PT.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..29e3015
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_PT.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "separador";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ro.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ro.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..00d64e5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ro.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d din %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "filă";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ru.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ru.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..0a8615e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ru.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d из %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "вкладка";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sk.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sk.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..dcde450
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sk.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d z %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "karta";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sq.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sq.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..219bddd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sq.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d nga %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "skedë";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..bc3da09
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d од %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "картица";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sv.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sv.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..ea114a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sv.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d av %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "flik";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/th.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/th.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..e70128f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/th.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d จาก %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "แท็บ";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/tr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/tr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..d6cc265
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/tr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "sekme";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/uk.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/uk.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..bef0ed7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/uk.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d з %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Вкладка";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/vi.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/vi.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..377764c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/vi.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d trên %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_CN.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_CN.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b7239a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_CN.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "第 %1$d 个,共 %2$d 个";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "标签";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_HK.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_HK.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..f187f88
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_HK.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "第 %1$d 個,共 %2$d 個";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "標籤";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_TW.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_TW.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..cab6ccb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_TW.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "第 %1$d 個,共 %2$d 個";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "分頁";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.h
new file mode 100644
index 0000000..d18be31
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCTabBar.h"
+#import "MDCTabBarAlignment.h"
+#import "MDCTabBarItemAppearance.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.h
new file mode 100644
index 0000000..9654db1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.h
@@ -0,0 +1,109 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCItemBarAlignment.h"
+
+@class MDCItemBarStyle;
+@protocol MDCItemBarDelegate;
+
+/**
+ A horizontally-scrollable list of tab-like items.
+
+ This is the private shared implementation of MDCTabBar and MDCBottomNavigationBar. It should not
+ be used directly and is not guaranteed to have a stable API.
+ */
+@interface MDCItemBar : UIView
+
+/** Return the default height for the item bar given a style. */
++ (CGFloat)defaultHeightForStyle:(nonnull MDCItemBarStyle *)style;
+
+/**
+ Items displayed in bar.
+
+ If the new items do not contain the currently selected item, the selection will be reset to the
+ first item. Changes to this property are not animated. May not be nil.
+ */
+@property(nonatomic, copy, nonnull) NSArray<UITabBarItem *> *items;
+
+/**
+ The currently selected item. May be nil if `items` is empty.
+
+ Changes to `selectedItem` are not animated.
+ */
+@property(nonatomic, strong, nullable) UITabBarItem *selectedItem;
+
+/** The item bar's delegate. */
+@property(nonatomic, weak, nullable) id<MDCItemBarDelegate> delegate;
+
+/**
+ Select an item with optional animation. Raises an NSInvalidArgumentException if selectedItem is
+ not in `items`.
+ */
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem animated:(BOOL)animated;
+
+/**
+ Horizontal alignment of items. Changes are not animated. Default alignment is
+ MDCItemBarAlignmentLeading.
+ */
+@property(nonatomic) MDCItemBarAlignment alignment;
+
+/** Updates the alignment with optional animation. */
+- (void)setAlignment:(MDCItemBarAlignment)alignment animated:(BOOL)animated;
+
+#pragma mark - Styling
+
+/** Updates the bar to use the given style properties. */
+- (void)applyStyle:(nonnull MDCItemBarStyle *)itemStyle;
+
+@end
+
+/**
+ Delegate protocol for MDCItemBar. Clients may implement this protocol to receive notifications of
+ selection changes.
+ */
+@protocol MDCItemBarDelegate <NSObject>
+
+/**
+ Called before the selected item changes by user action. This method is not called for programmatic
+ changes to the bar's selected item.
+ */
+- (void)itemBar:(nonnull MDCItemBar *)itemBar willSelectItem:(nonnull UITabBarItem *)item;
+
+/**
+ Called when the selected item changes by user action. This method is not called for programmatic
+ changes to the bar's selected item.
+ */
+- (void)itemBar:(nonnull MDCItemBar *)itemBar didSelectItem:(nonnull UITabBarItem *)item;
+
+@end
+
+#pragma mark -
+
+/** Accessibility-related methods on MDCItemBar. */
+@interface MDCItemBar (MDCItemBarAccessibility)
+
+/**
+ * Get the accessibility element representing the given item. Returns nil if item is not in `items`
+ * or if the item is not on screen.
+ *
+ * The accessibility element returned from this method may be used as the focused element after a
+ * run loop iteration.
+ */
+- (nullable id)accessibilityElementForItem:(nonnull UITabBarItem *)item;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.m
new file mode 100644
index 0000000..1e53584
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.m
@@ -0,0 +1,923 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCItemBar.h"
+
+#import "MDCItemBarCell.h"
+#import "MDCItemBarStyle.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialRTL.h"
+
+/// Height in points of the bar shown under selected items.
+static const CGFloat kSelectionIndicatorHeight = 2.0f;
+
+/// Cell reuse identifier for item bar cells.
+static NSString *const kItemReuseID = @"MDCItem";
+
+/// Default duration in seconds for selection change animations.
+static const NSTimeInterval kDefaultAnimationDuration = 0.3f;
+
+/// Placeholder width for cells, which get per-item sizing.
+static const CGFloat kPlaceholderCellWidth = 10.0f;
+
+/// Horizontal insets in regular size class layouts.
+static const CGFloat kRegularInset = 56.0f;
+
+/// Horizontal insets in compact size class layouts.
+static const CGFloat kCompactInset = 8.0f;
+
+/// KVO context pointer identifying changes in MDCItemBarItem properties.
+static void *kItemPropertyContext = &kItemPropertyContext;
+
+/// Custom flow layout for item content. Selectively works around bugs with RTL and flow layout:
+/// Radar 22828797: "UICollectionView with variable-sized items does not reverse item order in RTL."
+/// - On iOS 9.0 and later when a UICollectionViewFlow layout has custom-sized items via
+///   collectionView:layout:sizeForItemAtIndexPath:, it does not perform automatic right-to-left
+///   layout of items. We work around this by detecting incorrect ordering by the superclass and
+///   correcting the layout attributes.
+/// Radar 22828629, 22828529
+/// - On iOS 9 and later, the default scroll location for horizontally-scrolling collection views in
+///   RTL is correct, but resets to the left when scrolling an item to visible or manually scrolling
+///   the content. We work around this by padding collection content to always fill the scroll view.
+@interface MDCItemBarFlowLayout : UICollectionViewFlowLayout
+@end
+
+#pragma mark -
+
+@interface MDCItemBar () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
+@end
+
+@implementation MDCItemBar {
+  // Collection view and layout for items.
+  UICollectionView *_collectionView;
+  UICollectionViewFlowLayout *_flowLayout;
+
+  /// Underline displayed under the active item.
+  UIView *_selectionIndicator;
+
+  /// Index path of the previously selected item.
+  NSIndexPath *_lastSelectedIndexPath;
+
+  /// Size of the view at last layout, for deduplicating changes.
+  CGSize _lastSize;
+
+  /// Horizontal size class at the last item metrics update. Used to calculate deltas.
+  UIUserInterfaceSizeClass _horizontalSizeClassAtLastMetricsUpdate;
+
+  /// Current style properties.
+  MDCItemBarStyle *_style;
+}
+
++ (CGFloat)defaultHeightForStyle:(nonnull MDCItemBarStyle *)style {
+  return style.defaultHeight;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonItemBarInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonItemBarInit];
+  }
+  return self;
+}
+
+- (void)commonItemBarInit {
+  _alignment = MDCItemBarAlignmentLeading;
+  _style = [[MDCItemBarStyle alloc] init];
+  _items = @[];
+  _horizontalSizeClassAtLastMetricsUpdate = UIUserInterfaceSizeClassUnspecified;
+
+  // Configure the collection view.
+  _flowLayout = [self generatedFlowLayout];
+  UICollectionView *collectionView =
+      [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:_flowLayout];
+  collectionView.backgroundColor = [UIColor clearColor];
+  collectionView.clipsToBounds = YES;
+  collectionView.scrollsToTop = NO;
+  collectionView.showsHorizontalScrollIndicator = NO;
+  collectionView.showsVerticalScrollIndicator = NO;
+  collectionView.dataSource = self;
+  collectionView.delegate = self;
+  collectionView.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+  [collectionView registerClass:[MDCItemBarCell class] forCellWithReuseIdentifier:kItemReuseID];
+
+  _collectionView = collectionView;
+  [self addSubview:_collectionView];
+
+  // Configure the selection indicator view.
+  _selectionIndicator =
+      [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, kSelectionIndicatorHeight)];
+  _selectionIndicator.backgroundColor = [UIColor whiteColor];
+  _selectionIndicator.opaque = YES;
+  [_collectionView addSubview:_selectionIndicator];
+
+  // Set initial properties.
+  [self updateAlignmentAnimated:NO];
+  [self updateScrollProperties];
+  [self updateColors];
+  [self updateSelectionIndicatorVisibility];
+}
+
+- (void)dealloc {
+  // Clear out item observations.
+  [self stopObservingItems];
+
+  _collectionView.delegate = nil;
+}
+
+#pragma mark - Public
+
+- (void)applyStyle:(MDCItemBarStyle *)style {
+  if (style != _style && ![style isEqual:_style]) {
+    _style = [style copy];
+
+    // Update all style-dependent properties.
+    [self updateColors];
+    [self updateAlignmentAnimated:NO];
+    [self updateSelectionIndicatorVisibility];
+    [self configureVisibleCells];
+    [self invalidateIntrinsicContentSize];
+  }
+}
+
+- (void)setItems:(NSArray<UITabBarItem *> *)items {
+  NSAssert([NSThread isMainThread], @"Item array may only be set on the main thread");
+  NSParameterAssert(items != nil);
+
+  if (_items != items && ![_items isEqual:items]) {
+    // Stop observing old items.
+    [self stopObservingItems];
+
+    _items = [items copy];
+
+    [self reload];
+
+    // Reset selection to a valid item.
+    if (![_items containsObject:_selectedItem]) {
+      self.selectedItem = [_items firstObject];
+    }
+
+    // Start observing new items for changes.
+    [self startObservingItems];
+  }
+}
+
+- (void)setAlignment:(MDCItemBarAlignment)alignment {
+  [self setAlignment:alignment animated:NO];
+}
+
+- (void)setAlignment:(MDCItemBarAlignment)alignment animated:(BOOL)animated {
+  if (_alignment != alignment) {
+    _alignment = alignment;
+
+    [self updateAlignmentAnimated:animated];
+  }
+}
+
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem {
+  [self setSelectedItem:selectedItem animated:NO];
+}
+
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem animated:(BOOL)animated {
+  if (_selectedItem != selectedItem) {
+    NSInteger itemIndex = [_items indexOfObject:selectedItem];
+    if (itemIndex == NSNotFound) {
+      [[NSException exceptionWithName:NSInvalidArgumentException
+                               reason:@"Invalid item"
+                             userInfo:nil] raise];
+    }
+
+    _selectedItem = selectedItem;
+    [self selectItemAtIndex:itemIndex animated:animated];
+  }
+}
+
+#pragma mark - Accessibility
+
+- (id)accessibilityElementForItem:(UITabBarItem *)item {
+  NSUInteger index = [_items indexOfObject:item];
+  if (index != NSNotFound) {
+    NSArray<NSIndexPath *> *visibleItems = [_collectionView indexPathsForVisibleItems];
+    NSIndexPath *indexPath = [self indexPathForItemAtIndex:index];
+    if ([visibleItems containsObject:indexPath]) {
+      MDCItemBarCell *itemCell =
+          (MDCItemBarCell *)[_collectionView cellForItemAtIndexPath:indexPath];
+      return itemCell;
+    }
+  }
+  return nil;
+}
+
+#pragma mark - NSObject
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context {
+  if (context == kItemPropertyContext) {
+    // MDCItemBarItem change, must be on the main thread.
+    NSAssert([NSThread isMainThread], @"Item bar items may only be updated on the main thread.");
+    NSAssert([object isKindOfClass:[UITabBarItem class]], @"Change in unexpected object type");
+
+    UITabBarItem *item = object;
+    NSInteger itemIndex = [_items indexOfObject:item];
+    NSAssert(itemIndex != NSNotFound, @"Inconsistency: Change in unowned item bar item.");
+
+    // Update the cell for the given item if it's visible.
+    if (itemIndex != NSNotFound) {
+      NSIndexPath *indexPath = [self indexPathForItemAtIndex:itemIndex];
+      UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath];
+      if (cell) {
+        NSAssert([cell isKindOfClass:[MDCItemBarCell class]], @"All cells must be MDCItemBarCell");
+        MDCItemBarCell *itemCell = (MDCItemBarCell *)cell;
+        [itemCell updateWithItem:item atIndex:itemIndex count:_items.count];
+      }
+    }
+  } else {
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+  }
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  const CGRect bounds = self.bounds;
+
+  _collectionView.frame = bounds;
+
+  // Update collection metrics if the size has changed.
+  if (!CGSizeEqualToSize(bounds.size, _lastSize)) {
+    [self updateFlowLayoutMetrics];
+
+    if (_lastSelectedIndexPath) {
+      // Ensure selected item is aligned properly on resize.
+      [self selectItemAtIndex:_lastSelectedIndexPath.item animated:NO];
+    }
+  }
+  _lastSize = bounds.size;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  size.height = [[self class] defaultHeightForStyle:_style];
+  return size;
+}
+
+- (CGSize)intrinsicContentSize {
+  return CGSizeMake(UIViewNoIntrinsicMetric, [[self class] defaultHeightForStyle:_style]);
+}
+
+- (void)didMoveToWindow {
+  [super didMoveToWindow];
+
+  // New window: Update for potentially updated size class.
+  [self updateFlowLayoutMetrics];
+}
+
+- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection {
+  [super traitCollectionDidChange:previousTraitCollection];
+
+  // Update metrics for potentially updated size class.
+  [self updateFlowLayoutMetrics];
+}
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  [self updateColors];
+}
+
+#pragma mark - UICollectionViewDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  if (_collectionView == collectionView) {
+    UITabBarItem *item = [self itemAtIndexPath:indexPath];
+
+    // Notify delegate of impending selection.
+    id<MDCItemBarDelegate> delegate = self.delegate;
+    if ([delegate respondsToSelector:@selector(itemBar:willSelectItem:)]) {
+      [delegate itemBar:self willSelectItem:item];
+    }
+  }
+  return YES;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  if (_collectionView == collectionView) {
+    // Update selected item.
+    UITabBarItem *item = [self itemAtIndexPath:indexPath];
+    _selectedItem = item;
+
+    // Notify delegate of new selection.
+    id<MDCItemBarDelegate> delegate = self.delegate;
+    if ([delegate respondsToSelector:@selector(itemBar:didSelectItem:)]) {
+      [delegate itemBar:self didSelectItem:item];
+    }
+
+    // Update UI to reflect newly selected item.
+    [self didSelectItemAtIndexPath:indexPath animateTransition:YES];
+    [_collectionView scrollToItemAtIndexPath:indexPath
+                            atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
+                                    animated:YES];
+  }
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView
+     numberOfItemsInSection:(NSInteger)section {
+  if ((_collectionView == collectionView) && section == 0) {
+    return [_items count];
+  }
+  return 0;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  NSParameterAssert(_collectionView == collectionView);
+
+  MDCItemBarCell *itemCell =
+      [collectionView dequeueReusableCellWithReuseIdentifier:kItemReuseID forIndexPath:indexPath];
+  UITabBarItem *item = [self itemAtIndexPath:indexPath];
+
+  [self configureCell:itemCell];
+  [itemCell updateWithItem:item atIndex:indexPath.item count:_items.count];
+
+  return itemCell;
+}
+
+#pragma mark - UICollectionViewDelegateFlowLayout
+
+- (CGSize)collectionView:(UICollectionView *)collectionView
+                    layout:(UICollectionViewLayout *)collectionViewLayout
+    sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
+  NSParameterAssert(_collectionView == collectionView);
+
+  UITabBarItem *item = [self itemAtIndexPath:indexPath];
+
+  const CGFloat itemHeight = CGRectGetHeight(self.bounds);
+  CGSize size = CGSizeMake(CGFLOAT_MAX, itemHeight);
+
+  // Size cell to fit content.
+  size = [MDCItemBarCell sizeThatFits:size
+                  horizontalSizeClass:[self horizontalSizeClass]
+                                 item:item
+                                style:_style];
+
+  // Divide justified items evenly across the view.
+  if (_alignment == MDCItemBarAlignmentJustified) {
+    NSInteger count = [self collectionView:_collectionView numberOfItemsInSection:0];
+    size.width = _collectionView.bounds.size.width / MAX(count, 1);
+  }
+
+  // Constrain width if necessary.
+  if (_style.maximumItemWidth > 0) {
+    size.width = MIN(size.width, _style.maximumItemWidth);
+  }
+
+  // Force height to our height.
+  size.height = itemHeight;
+
+  return size;
+}
+
+#pragma mark - Private
+
++ (NSArray *)observableItemKeys {
+  static dispatch_once_t onceToken;
+  static NSArray *s_keys = nil;
+  dispatch_once(&onceToken, ^{
+    s_keys = @[
+      NSStringFromSelector(@selector(title)), NSStringFromSelector(@selector(image)),
+      NSStringFromSelector(@selector(badgeValue)),
+      NSStringFromSelector(@selector(accessibilityIdentifier))
+    ];
+  });
+  return s_keys;
+}
+
+- (void)startObservingItems {
+  NSAssert([NSThread isMainThread], @"Main thread required for KVO registration");
+
+  for (UITabBarItem *item in _items) {
+    for (NSString *key in [[self class] observableItemKeys]) {
+      [item addObserver:self forKeyPath:key options:0 context:kItemPropertyContext];
+    }
+  }
+}
+
+- (void)stopObservingItems {
+  NSAssert([NSThread isMainThread], @"Main thread required for KVO unregistration");
+
+  for (UITabBarItem *item in _items) {
+    for (NSString *key in [[self class] observableItemKeys]) {
+      [item removeObserver:self forKeyPath:key context:kItemPropertyContext];
+    }
+  }
+}
+
+- (UIUserInterfaceSizeClass)horizontalSizeClass {
+  // Use trait collection's horizontalSizeClass if available.
+  if ([self respondsToSelector:@selector(traitCollection)]) {
+    return self.traitCollection.horizontalSizeClass;
+  }
+
+  // Pre-iOS 8: Use fixed size class for device.
+  BOOL isPad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
+  return isPad ? UIUserInterfaceSizeClassRegular : UIUserInterfaceSizeClassCompact;
+}
+
+- (void)selectItemAtIndex:(NSInteger)index animated:(BOOL)animated {
+  NSParameterAssert(index >= 0 && index < (NSInteger)[_items count]);
+
+  NSIndexPath *indexPath = [self indexPathForItemAtIndex:index];
+  [_collectionView selectItemAtIndexPath:indexPath
+                                animated:animated
+                          scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
+  [self didSelectItemAtIndexPath:indexPath animateTransition:animated];
+}
+
+- (UITabBarItem *)itemAtIndexPath:(NSIndexPath *)indexPath {
+  return _items[indexPath.item];
+}
+
+- (NSIndexPath *)indexPathForItemAtIndex:(NSInteger)index {
+  return [NSIndexPath indexPathForItem:index inSection:0];
+}
+
+- (void)reload {
+  [_collectionView reloadData];
+  [self updateFlowLayoutMetrics];
+}
+
+- (UICollectionViewFlowLayout *)generatedFlowLayout {
+  UICollectionViewFlowLayout *flowLayout = [[MDCItemBarFlowLayout alloc] init];
+  CGFloat itemHeight = CGRectGetHeight(self.bounds);
+  flowLayout.itemSize = CGSizeMake(kPlaceholderCellWidth, itemHeight);
+  flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
+  flowLayout.sectionInset = UIEdgeInsetsZero;
+  flowLayout.minimumInteritemSpacing = 0.0f;
+  flowLayout.minimumLineSpacing = 0.0f;
+  return flowLayout;
+}
+
+- (void)didSelectItemAtIndexPath:(NSIndexPath *)indexPath animateTransition:(BOOL)animate {
+  void (^animationBlock)(void) = ^{
+    [self updateSelectionIndicatorToIndexPath:indexPath];
+  };
+
+  if (animate) {
+    CAMediaTimingFunction *easeInOutFunction =
+        [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionEaseInOut];
+    [UIView mdc_animateWithTimingFunction:easeInOutFunction
+                                 duration:kDefaultAnimationDuration
+                                    delay:0
+                                  options:UIViewAnimationOptionBeginFromCurrentState
+                               animations:animationBlock
+                               completion:nil];
+  } else {
+    animationBlock();
+  }
+
+  _lastSelectedIndexPath = indexPath;
+}
+
+- (void)updateAlignmentAnimated:(BOOL)animated {
+  [self updateScrollProperties];
+  [self updateFlowLayoutMetricsAnimated:animated];
+}
+
+/// Sets _selectionIndicator's bounds and center to display under the item at the given index path
+/// with no animation. May be called from an animation block to animate the transition.
+- (void)updateSelectionIndicatorToIndexPath:(NSIndexPath *)indexPath {
+  if (!indexPath) {
+    return;
+  }
+
+  // Use layout attributes as the cell may not be visible or loaded yet.
+  UICollectionViewLayoutAttributes *attributes =
+      [_flowLayout layoutAttributesForItemAtIndexPath:indexPath];
+
+  // Size selection indicator to a fixed height, equal in width to the selected item's cell.
+  CGRect selectionIndicatorBounds = attributes.bounds;
+  selectionIndicatorBounds.size.height = kSelectionIndicatorHeight;
+
+  // Center selection indicator under cell.
+  CGPoint selectionIndicatorCenter = attributes.center;
+  selectionIndicatorCenter.y =
+      CGRectGetMaxY(_collectionView.bounds) - (kSelectionIndicatorHeight / 2.0f);
+
+  _selectionIndicator.bounds = selectionIndicatorBounds;
+  _selectionIndicator.center = selectionIndicatorCenter;
+}
+
+- (void)updateFlowLayoutMetricsAnimated:(BOOL)animate {
+  void (^animationBlock)() = ^{
+    [self updateFlowLayoutMetrics];
+  };
+
+  if (animate) {
+    CAMediaTimingFunction *easeInOutFunction =
+        [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionEaseInOut];
+    [UIView mdc_animateWithTimingFunction:easeInOutFunction
+                                 duration:kDefaultAnimationDuration
+                                    delay:0.0f
+                                  options:UIViewAnimationOptionBeginFromCurrentState
+                               animations:animationBlock
+                               completion:nil];
+  } else {
+    animationBlock();
+  }
+}
+
+- (void)updateScrollProperties {
+  _collectionView.alwaysBounceHorizontal = (_alignment != MDCItemBarAlignmentJustified);
+}
+
+- (void)updateFlowLayoutMetrics {
+  // Layout metrics cannot be updated while offscreen.
+  if (!self.window) {
+    return;
+  }
+
+  UIUserInterfaceSizeClass horizontalSizeClass = [self horizontalSizeClass];
+
+  UIEdgeInsets newSectionInset = UIEdgeInsetsZero;
+  switch (_alignment) {
+    case MDCItemBarAlignmentLeading:
+      newSectionInset = [self leadingAlignedInsetsForHorizontalSizeClass:horizontalSizeClass];
+      break;
+    case MDCItemBarAlignmentJustified:
+      newSectionInset = [self justifiedInsets];
+      break;
+    case MDCItemBarAlignmentCenter:
+      newSectionInset = [self centeredInsetsForHorizontalSizeClass:horizontalSizeClass];
+      break;
+    case MDCItemBarAlignmentCenterSelected:
+      newSectionInset = [self centerSelectedInsets];
+      break;
+  }
+
+  UIEdgeInsets oldSectionInset = _flowLayout.sectionInset;
+  if (UIEdgeInsetsEqualToEdgeInsets(oldSectionInset, newSectionInset) &&
+      _alignment != MDCItemBarAlignmentJustified) {
+    // No change - can bail early, except when the item alignment is "justified". When justified,
+    // the layout metrics need updating due to change in view size or orientation.
+    return;
+  }
+
+  // Rather than just updating the sectionInset on the existing flowLayout, a new layout object
+  // is created. This gives more control over whether the change is animated or not - as there is
+  // no control when updating flow layout sectionInset (it's always animated).
+  UICollectionViewFlowLayout *flowLayout = [self generatedFlowLayout];
+  flowLayout.sectionInset = newSectionInset;
+  _flowLayout = flowLayout;
+
+  // This is not animated because -updateFlowLayoutMetrics may be called in an animation block and
+  // the change will be still get animated anyway - using NO avoids 'double' animation and allows
+  // this method to be used without animation.
+  NSAssert(_collectionView.window, @"Collection view must be in a window to update layout");
+  [_collectionView setCollectionViewLayout:_flowLayout animated:NO];
+
+  // Update selection indicator to potentially new location and size
+  // Not animated for the same reason as mentioned above.
+  [self updateSelectionIndicatorToIndexPath:_lastSelectedIndexPath];
+
+  _horizontalSizeClassAtLastMetricsUpdate = horizontalSizeClass;
+}
+
+- (UIEdgeInsets)leadingAlignedInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
+  const BOOL isRegular = (sizeClass == UIUserInterfaceSizeClassRegular);
+  const CGFloat inset = isRegular ? kRegularInset : kCompactInset;
+  return UIEdgeInsetsMake(0.0f, inset, 0.0f, inset);
+}
+
+- (UIEdgeInsets)justifiedInsets {
+  // Center items, which will be at most the width of the view.
+  CGFloat itemWidths = [self totalWidthOfAllItems];
+  CGFloat sideInsets = floorf((float)(_collectionView.bounds.size.width - itemWidths) / 2.0f);
+  return UIEdgeInsetsMake(0.0, sideInsets, 0.0, sideInsets);
+}
+
+- (UIEdgeInsets)centeredInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
+  CGFloat itemWidths = [self totalWidthOfAllItems];
+  CGFloat viewWidth = _collectionView.bounds.size.width;
+  UIEdgeInsets insets = [self leadingAlignedInsetsForHorizontalSizeClass:sizeClass];
+  if (itemWidths <= (viewWidth - insets.left - insets.right)) {
+    CGFloat sideInsets = (_collectionView.bounds.size.width - itemWidths) / 2.0f;
+    return UIEdgeInsetsMake(0.0, sideInsets, 0.0, sideInsets);
+  }
+  return insets;
+}
+
+- (UIEdgeInsets)centerSelectedInsets {
+  UIEdgeInsets sectionInset = UIEdgeInsetsZero;
+
+  NSInteger count = [self collectionView:_collectionView numberOfItemsInSection:0];
+  if (count > 0) {
+    CGRect bounds = _collectionView.bounds;
+    CGFloat halfBoundsWidth = bounds.size.width / 2.0f;
+
+    CGSize firstSize = [self collectionView:_collectionView
+                                     layout:_flowLayout
+                     sizeForItemAtIndexPath:[self indexPathForItemAtIndex:0]];
+    CGSize lastSize = [self collectionView:_collectionView
+                                    layout:_flowLayout
+                    sizeForItemAtIndexPath:[self indexPathForItemAtIndex:count - 1]];
+
+    // Left inset is equal to the space to the left of the first item when centered.
+    CGFloat halfFirstWidth = firstSize.width / 2.0f;
+    sectionInset.left = halfBoundsWidth - halfFirstWidth;
+
+    // Right inset is equal to the space to the right of the last item when centered.
+    CGFloat halfLastWidth = lastSize.width / 2.0f;
+    sectionInset.right = halfBoundsWidth - halfLastWidth;
+  }
+  return sectionInset;
+}
+
+- (CGFloat)totalWidthOfAllItems {
+  CGFloat itemWidths = 0;
+  NSInteger count = [self collectionView:_collectionView numberOfItemsInSection:0];
+  for (NSInteger itemIndex = 0; itemIndex < count; itemIndex++) {
+    CGSize itemSize = [self collectionView:_collectionView
+                                    layout:_flowLayout
+                    sizeForItemAtIndexPath:[self indexPathForItemAtIndex:itemIndex]];
+    itemWidths += itemSize.width;
+  }
+  return itemWidths;
+}
+
+- (void)configureCell:(MDCItemBarCell *)cell {
+  // Configure content style
+  [cell applyStyle:_style];
+}
+
+- (void)configureVisibleCells {
+  for (UICollectionViewCell *cell in _collectionView.visibleCells) {
+    if ([cell isKindOfClass:[MDCItemBarCell class]]) {
+      MDCItemBarCell *itemCell = (MDCItemBarCell *)cell;
+      [self configureCell:itemCell];
+    }
+  }
+}
+
+- (void)updateColors {
+  [self configureVisibleCells];
+
+  _selectionIndicator.backgroundColor = _style.selectionIndicatorColor;
+}
+
+- (void)updateSelectionIndicatorVisibility {
+  _selectionIndicator.hidden = !_style.shouldDisplaySelectionIndicator;
+}
+
+@end
+
+#pragma mark -
+
+@implementation MDCItemBarFlowLayout {
+  /// Map from item index paths to RTL-corrected layout attributes. If no RTL correction is in
+  /// effect, this will be set to nil.
+  NSDictionary *_correctedAttributesForIndexPath;
+
+  /// Controls the use of a padded collection view content size.
+  BOOL _isPaddingCollectionViewContentSize;
+
+  /// Collection view content size which will be used if padding is in effect.
+  CGSize _paddedCollectionViewContentSize;
+}
+
+- (void)prepareLayout {
+  [super prepareLayout];
+
+  // Post-process the superclass layout to determine which workarounds need to be applied.
+  BOOL shouldRelayoutAttributesForRTL = [self shouldRelayoutAttributesForRTL];
+  BOOL shouldPadContentSizeForRTL = [self shouldPadContentSizeForRTL];
+
+  // Build a new map of adjusted attributes if needed.
+  if (shouldRelayoutAttributesForRTL || shouldPadContentSizeForRTL) {
+    NSMutableDictionary *newAttributes = [NSMutableDictionary dictionary];
+    const NSInteger sectionCount = self.collectionView.numberOfSections;
+    for (NSInteger sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
+      const NSInteger itemCount = [self.collectionView numberOfItemsInSection:sectionIndex];
+      for (NSInteger itemIndex = 0; itemIndex < itemCount; itemIndex++) {
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:sectionIndex];
+
+        // Must call super here to ensure we get un-corrected attributes.
+        UICollectionViewLayoutAttributes *attributes =
+            [super layoutAttributesForItemAtIndexPath:indexPath];
+
+        // Flip attribute order for RTL. This must happen before padding because attributes are
+        // flipped using the original un-padded bounds.
+        if (shouldRelayoutAttributesForRTL) {
+          attributes = [self flippedAttributesFromAttributes:attributes];
+        }
+
+        // Apply per-item content size padding.
+        if (shouldPadContentSizeForRTL) {
+          attributes = [self paddedAttributesFromAttributes:attributes];
+        }
+
+        newAttributes[indexPath] = attributes;
+      }
+    }
+    _correctedAttributesForIndexPath = newAttributes;
+  } else {
+    // Clear out the map to indicate that no corrections are in effect.
+    _correctedAttributesForIndexPath = nil;
+  }
+
+  // Apply global content size padding.
+  if (shouldPadContentSizeForRTL) {
+    _isPaddingCollectionViewContentSize = YES;
+    _paddedCollectionViewContentSize = self.collectionView.bounds.size;
+  } else {
+    _isPaddingCollectionViewContentSize = NO;
+  }
+}
+
+- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:
+        (NSIndexPath *)indexPath {
+  if (_correctedAttributesForIndexPath) {
+    return _correctedAttributesForIndexPath[indexPath];
+  }
+
+  // No RTL correction needed.
+  return [super layoutAttributesForItemAtIndexPath:indexPath];
+}
+
+- (nullable NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
+  if (_correctedAttributesForIndexPath) {
+    NSPredicate *predicate =
+        [NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *layoutAttributes,
+                                              NSDictionary *__nullable bindings) {
+          return CGRectIntersectsRect(layoutAttributes.frame, rect);
+        }];
+    return [_correctedAttributesForIndexPath.allValues filteredArrayUsingPredicate:predicate];
+  }
+
+  // No RTL correction needed.
+  return [super layoutAttributesForElementsInRect:rect];
+}
+
+- (CGSize)collectionViewContentSize {
+  if (_isPaddingCollectionViewContentSize) {
+    return _paddedCollectionViewContentSize;
+  }
+  return [super collectionViewContentSize];
+}
+
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
+  if (!CGSizeEqualToSize(newBounds.size, self.collectionView.bounds.size)) {
+    // Padding depends on the size of the collection view, need to relayout for size changes.
+    return YES;
+  }
+  return [super shouldInvalidateLayoutForBoundsChange:newBounds];
+}
+
+#pragma mark - Private
+
+/// Computes RTL-flipped attributes given superclass-calculated attributes.
+- (UICollectionViewLayoutAttributes *)flippedAttributesFromAttributes:
+        (UICollectionViewLayoutAttributes *)attributes {
+  UICollectionViewLayoutAttributes *newAttributes = [attributes copy];
+
+  CGRect itemFrame = attributes.frame;
+
+  // Must call super here to ensure we have the original collection bounds.
+  CGRect collectionBounds = {CGPointZero, [super collectionViewContentSize]};
+  newAttributes.frame = MDCRectFlippedForRTL(itemFrame, CGRectGetWidth(collectionBounds),
+                                             UIUserInterfaceLayoutDirectionRightToLeft);
+
+  return newAttributes;
+}
+
+- (BOOL)shouldEnforceRightToLeftLayout {
+  BOOL enforceRTL = NO;
+
+  // Prior to iOS 9 RTL was not automatically applied, so we don't need to apply any fixes.
+  NSOperatingSystemVersion iOS9Version = {9, 0, 0};
+  NSProcessInfo *processInfo = [NSProcessInfo processInfo];
+  if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] &&
+      [processInfo isOperatingSystemAtLeastVersion:iOS9Version]) {
+    if (self.collectionView.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      enforceRTL = YES;
+    }
+  }
+
+  return enforceRTL;
+}
+
+/// Indicates if the superclass' layout appears to have been layed out in a left-to-right order. If
+/// there are zero or one items total, this always returns NO.
+/// Note: This is used to detect incorrect layouts due to radar 22828797 by detecting the actual
+/// layout ordering from superclass-generated layout frames. When there's no error (item frames are
+/// already arranged RTL), this returns NO. We use this approach for two purposes:
+/// * Robustly detecting the error condition. The bug occurs under specific conditions that would be
+///   difficult to detect reliably, and given item bars are simple linear layouts it's more robust
+///   to detect the error and correct it.
+/// * Automatically disabling this workaround if the underlying bug is fixed in an unknown future OS
+///   version. At time of writing (iOS 9.2) the bug has not been fixed. Detecting the error directly
+///   and correcting it should allow this implementation to continue to produce correct results
+///   without an immediate need for changes.
+- (BOOL)shouldRelayoutAttributesForRTL {
+  // The logic contained here only applies to horizontally-scrolling flow layouts. This should
+  // always be the case for MDCItemBar, but check for safety.
+  NSParameterAssert(self.scrollDirection == UICollectionViewScrollDirectionHorizontal);
+
+  if (![self shouldEnforceRightToLeftLayout]) {
+    return NO;
+  }
+
+  CGRect previousFrame = CGRectNull;
+
+  const NSInteger sectionCount = self.collectionView.numberOfSections;
+  for (NSInteger sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
+    const NSInteger itemCount = [self.collectionView numberOfItemsInSection:sectionIndex];
+    for (NSInteger itemIndex = 0; itemIndex < itemCount; itemIndex++) {
+      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:sectionIndex];
+
+      // Must call super here to ensure we get un-corrected attributes.
+      UICollectionViewLayoutAttributes *attributes =
+          [super layoutAttributesForItemAtIndexPath:indexPath];
+
+      CGRect frame = attributes.frame;
+      // If any adjacent pairs of attributes have centers that are ordered left-to-right, assume the
+      // whole layout is ordered left-to-right.
+      if (!CGRectIsNull(previousFrame) && (CGRectGetMidX(previousFrame) < CGRectGetMidX(frame))) {
+        return YES;
+      }
+
+      // Set up for next iteration.
+      previousFrame = frame;
+    }
+  }
+
+  // There are either fewer than 2 items (in which case order doesn't matter) or the whole thing is
+  // ordered RTL.
+  return NO;
+}
+
+/// Indicates if the collection's content is narrower than the collection view.
+/// Note: This is used to detect conditions under which collection view scrolling bugs happen in RTL
+/// layouts. If and when the underlying bugs are fixed in an unknown future iOS version, this method
+/// will continue to return YES and trigger harmless but unnecessary workarounds.
+- (BOOL)shouldPadContentSizeForRTL {
+  if (![self shouldEnforceRightToLeftLayout]) {
+    return NO;
+  }
+
+  // When the content is narrower than the scroll view bounds, we need to pad all attribute frames
+  // on the left to prevent the layout from "jumping" to the origin under various situations.
+  // Must call super here to ensure we have the original collection content size.
+  CGSize contentSize = [super collectionViewContentSize];
+  CGRect scrollBounds = self.collectionView.bounds;
+  return contentSize.width < CGRectGetWidth(scrollBounds);
+}
+
+- (UICollectionViewLayoutAttributes *)paddedAttributesFromAttributes:
+        (UICollectionViewLayoutAttributes *)attributes {
+  // Must call super here to ensure we have the original collection content size.
+  CGSize contentSize = [super collectionViewContentSize];
+  CGRect scrollBounds = self.collectionView.bounds;
+
+  CGFloat leftPadding = CGRectGetWidth(scrollBounds) - contentSize.width;
+
+  UICollectionViewLayoutAttributes *newAttributes = [attributes copy];
+
+  // Shift frame to the right to counteract the content size width expansion.
+  CGRect itemFrame = attributes.frame;
+  itemFrame.origin.x += leftPadding;
+
+  newAttributes.frame = itemFrame;
+
+  return newAttributes;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h
new file mode 100644
index 0000000..b3a6412
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h
@@ -0,0 +1,35 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/** Alignment styles for items in a tab bar. */
+typedef NS_ENUM(NSInteger, MDCItemBarAlignment) {
+  /** Items are aligned on the leading edge and sized to fit their content. */
+  MDCItemBarAlignmentLeading,
+
+  /** Items are justified to equal size across the width of the screen. */
+  MDCItemBarAlignmentJustified,
+
+  /**
+   * Items are sized to fit their content and center-aligned as a group. If they do not fit in view,
+   * they will be leading-aligned instead.
+   */
+  MDCItemBarAlignmentCenter,
+
+  /** Items are center-aligned on the selected item. */
+  MDCItemBarAlignmentCenterSelected,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h
new file mode 100644
index 0000000..c734a40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h
@@ -0,0 +1,50 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCItemBarStyle;
+
+/** View displaying an individual item in an item bar. */
+@interface MDCItemBarCell : UICollectionViewCell
+
+/** Returns the optimal size for the item with the given size class and content view object. */
++ (CGSize)sizeThatFits:(CGSize)size
+    horizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass
+                   item:(nonnull UITabBarItem *)item
+                  style:(nonnull MDCItemBarStyle *)style;
+
+/** Returns the additional insets applied outside item content for the given size class. */
++ (UIEdgeInsets)edgeInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass;
+
+/** Title for the tab. Defaults to the empty string. */
+@property(nonatomic, copy, nonnull) NSString *title;
+
+/** Image shown on the tab. Defaults to nil. */
+@property(nonatomic, strong, nullable) UIImage *image;
+
+/** Text displayed in upper-right corner of the tab. Uses title color. */
+@property(nonatomic, copy, nullable) NSString *badgeValue;
+
+/** Updates the cell to use the given style properties. */
+- (void)applyStyle:(nonnull MDCItemBarStyle *)itemStyle;
+
+/** Updates the cell to display the given item. */
+- (void)updateWithItem:(nonnull UITabBarItem *)item
+               atIndex:(NSInteger)itemIndex
+                 count:(NSInteger)itemCount;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.m
new file mode 100644
index 0000000..049924d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.m
@@ -0,0 +1,562 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCItemBarCell.h"
+
+#import "MDCItemBarStringConstants.h"
+#import "MDCItemBarStyle.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialInk.h"
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+/// Padding between the bottom of the cell and its content, in points.
+static const CGFloat kBottomPadding = 20.0f;
+
+/// Size of image in points.
+static const CGSize kImageSize = {24, 24};
+
+/// Font point size for badges.
+static const CGFloat kBadgeFontSize = 12;
+
+/// Padding between top of the cell and the badge.
+static const CGFloat kBadgeTopPadding = 6;
+
+/// Maximum width of a badge. This allows for 3 characters before truncation.
+static const CGFloat kBadgeMaxWidth = 22;
+
+/// File name of the bundle (without the '.bundle' extension) containing resources.
+static NSString *const kResourceBundleName = @"MaterialTabs";
+
+/// String table name containing localized strings.
+static NSString *const kStringTableName = @"MaterialTabs";
+
+/// Scale factor applied to the title of bottom navigation items when selected.
+const CGFloat kSelectedNavigationTitleScaleFactor = (16.0f / 14.0f);
+
+/// Vertical translation applied to image components bottom navigation items when selected.
+const CGFloat kSelectedNavigationImageYOffset = -2;
+
+/// Duration of selection animations in applicable content styles.
+static const NSTimeInterval kSelectionAnimationDuration = 0.3f;
+
+@implementation MDCItemBarCell {
+  UILabel *_titleLabel;
+  UIImageView *_imageView;
+  UILabel *_badgeLabel;
+  MDCInkTouchController *_inkTouchController;
+
+  MDCItemBarStyle *_style;
+
+  NSInteger _itemIndex;
+  NSInteger _itemCount;
+}
+
+#pragma mark - Init
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    _style = [[MDCItemBarStyle alloc] init];
+    _title = @"";
+    _itemIndex = NSNotFound;
+
+    self.isAccessibilityElement = YES;
+
+    // Create initial subviews
+    [self updateSubviews];
+
+    // Set up ink controller to splash ink on taps.
+    _inkTouchController = [[MDCInkTouchController alloc] initWithView:self];
+    [_inkTouchController addInkView];
+
+    [self updateInk];
+    [self updateColors];
+    [self updateTransformsAnimated:NO];
+  }
+  return self;
+}
+
+#pragma mark - Public
+
++ (UIEdgeInsets)edgeInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
+  // Padding from spec: https://www.google.com/design/spec/components/tabs.html
+  CGFloat outerPadding = (sizeClass == UIUserInterfaceSizeClassRegular) ? 24.0f : 12.0f;
+  return UIEdgeInsetsMake(0.0, outerPadding, 0.0, outerPadding);
+}
+
++ (CGSize)sizeThatFits:(CGSize)size
+    horizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass
+                   item:(UITabBarItem *)item
+                  style:(MDCItemBarStyle *)style {
+  UIEdgeInsets insets = [self edgeInsetsForHorizontalSizeClass:sizeClass];
+  NSString *title = [self displayedTitleForTitle:item.title style:style];
+
+  CGRect textBounds = CGRectZero;
+
+  // Only compute text bounding rect if necessary (all except image-only items)
+  if (style.shouldDisplayTitle) {
+    UIFont *font = style.titleFont;
+    NSDictionary *titleAttributes = @{NSFontAttributeName : font};
+    textBounds = [title boundingRectWithSize:size
+                                     options:NSStringDrawingTruncatesLastVisibleLine
+                                  attributes:titleAttributes
+                                     context:nil];
+  }
+
+  CGRect badgeBounds = CGRectZero;
+
+  // Only compute badge bounding rect if necessary.
+  NSString *badge = item.badgeValue;
+  if (style.shouldDisplayBadge && badge.length > 0) {
+    UIFont *badgeFont = [[MDCTypography fontLoader] regularFontOfSize:kBadgeFontSize];
+    NSDictionary *badgeAttributes = @{NSFontAttributeName : badgeFont};
+    badgeBounds = [badge boundingRectWithSize:size
+                                      options:NSStringDrawingTruncatesLastVisibleLine
+                                   attributes:badgeAttributes
+                                      context:nil];
+  }
+
+  // Determine size based on content style.
+  CGRect bounds = CGRectZero;
+  if (style.shouldDisplayTitle) {
+    if (style.shouldDisplayImage) {
+      // Title and image
+      bounds.size.width = MAX(textBounds.size.width, kImageSize.width + badgeBounds.size.width * 2);
+      bounds.size.height = textBounds.size.height + style.titleImagePadding + kImageSize.height;
+    } else {
+      // Just title
+      bounds = textBounds;
+    }
+  } else {
+    if (style.shouldDisplayImage) {
+      // Image only.
+      bounds.size = kImageSize;
+      bounds.size.width += badgeBounds.size.width * 2;
+    } else {
+      // No image or title: NOP.
+    }
+  }
+
+  // Constrain to provided width.
+  bounds.size.width = MIN(bounds.size.width, size.width);
+
+  // Add insets.
+  bounds.size.width += insets.left + insets.right;
+  bounds.size.height += insets.top + insets.bottom;
+
+  // Snap to integral coordinates.
+  bounds = CGRectIntegral(bounds);
+  return bounds.size;
+}
+
+- (void)setTitle:(NSString *)title {
+  _title = [title copy];
+  [self updateDisplayedTitle];
+}
+
+- (void)setImage:(nullable UIImage *)image {
+  _image = image;
+  [self updateDisplayedImage];
+}
+
+- (void)setBadgeValue:(nullable NSString *)badgeValue {
+  _badgeValue = [badgeValue copy];
+  _badgeLabel.text = badgeValue;
+  [self setNeedsLayout];
+}
+
+- (void)applyStyle:(MDCItemBarStyle *)style {
+  if (style != _style && ![style isEqual:_style]) {
+    _style = style;
+
+    [self updateDisplayedTitle];
+    [self updateTitleTextColor];
+    [self updateInk];
+    [self updateSubviews];
+    [self updateTitleFont];
+    [self updateTransformsAnimated:NO];
+    [self setNeedsLayout];
+  }
+}
+
+- (void)updateWithItem:(UITabBarItem *)item
+               atIndex:(NSInteger)itemIndex
+                 count:(NSInteger)itemCount {
+  self.title = item.title;
+  self.image = item.image;
+  self.badgeValue = item.badgeValue;
+  self.accessibilityIdentifier = item.accessibilityIdentifier;
+
+  _itemIndex = itemIndex;
+  _itemCount = itemCount;
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  UIEdgeInsets insets = [[self class] minimumEdgeInsets];
+  CGRect contentBounds = UIEdgeInsetsInsetRect(self.contentView.bounds, insets);
+
+  CGPoint imageCenter = CGPointZero;
+  CGPoint titleCenter = CGPointZero;
+  CGPoint badgeCenter = CGPointZero;
+  CGRect imageBounds = CGRectZero;
+  CGRect titleBounds = CGRectZero;
+  CGRect badgeBounds = CGRectZero;
+
+  // Image has a fixed size and is horizontally centered, regardless of content style.
+  imageBounds.size = kImageSize;
+  imageCenter.x = (float)round(CGRectGetMidX(contentBounds));
+
+  CGSize titleSize = [_titleLabel sizeThatFits:contentBounds.size];
+  titleSize.width = MIN(titleSize.width, CGRectGetWidth(contentBounds));
+
+  // Title is a fixed height based on content and is placed full-width, regardless of content style.
+  titleCenter.x = roundf((float)CGRectGetMidX(contentBounds));
+  titleBounds.size.width = ceilf((float)CGRectGetWidth(contentBounds));
+  titleBounds.size.height = ceilf((float)titleSize.height);
+
+  // Horizontally align the badge.
+  CGSize badgeSize = [_badgeLabel sizeThatFits:contentBounds.size];
+  badgeSize.width = MIN(kBadgeMaxWidth, badgeSize.width);
+  badgeBounds.size = badgeSize;
+
+  if (_style.shouldDisplayBadge) {
+    CGFloat badgeOffset = ((float)imageBounds.size.width / 2.0f) + ((float)badgeSize.width / 2.0f);
+    if (self.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      badgeOffset *= -1;
+    }
+
+    badgeCenter.x = imageCenter.x + badgeOffset;
+    badgeCenter.y = kBadgeTopPadding + ((float)badgeSize.height / 2.0f);
+  }
+
+  // Place components vertically
+  if (_style.shouldDisplayTitle) {
+    if (_style.shouldDisplayImage) {
+      // Image and title, center both vertically together.
+      const CGFloat padding = _style.titleImagePadding;
+      const CGFloat totalHeight = titleSize.height + padding + kImageSize.height;
+      const CGFloat yOrigin = (float)round(CGRectGetMidY(contentBounds) - totalHeight / 2.0f);
+      imageCenter.y = yOrigin + ((float)kImageSize.height / 2.0f);
+      titleCenter.y = yOrigin + kImageSize.height + padding + ((float)titleSize.height / 2.0f);
+      titleCenter.y = roundf((float)titleCenter.y);
+
+    } else {
+      // Title only, center vertically.
+      // +1 for slight adjustment to font baseline for centered title labels.
+      const CGFloat centeredTitleYOffset = 1.0f;
+      titleCenter.y = contentBounds.size.height - kBottomPadding - titleSize.height +
+                      centeredTitleYOffset + ((float)titleSize.height / 2.0f);
+      titleCenter.y = roundf((float)titleCenter.y);
+    }
+  } else {
+    if (_style.shouldDisplayImage) {
+      // Image only, center image vertically
+      imageCenter.y = (float)round(CGRectGetMidY(contentBounds));
+    } else {
+      // Nothing: NOP
+    }
+  }
+
+  _imageView.center = imageCenter;
+  _imageView.bounds = imageBounds;
+
+  _badgeLabel.center = badgeCenter;
+  _badgeLabel.bounds = badgeBounds;
+
+  _titleLabel.center = titleCenter;
+  _titleLabel.bounds = titleBounds;
+}
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  [self updateTitleTextColor];
+}
+
+- (void)didMoveToWindow {
+  [super didMoveToWindow];
+
+  if (self.window) {
+    [self updateTransformsAnimated:NO];
+  }
+}
+
+#pragma mark - UICollectionReusableView
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+  [self updateTitleTextColor];
+  [self updateAccessibilityTraits];
+  [_inkTouchController cancelInkTouchProcessing];
+}
+
+#pragma mark - UICollectionViewCell
+
+- (void)setSelected:(BOOL)selected {
+  // Do not animate if selected is being set before the cell is in the view hierarchy.
+  BOOL animate = (self.window != nil);
+
+  [super setSelected:selected];
+  [self updateTitleTextColor];
+  [self updateAccessibilityTraits];
+  [self updateTransformsAnimated:animate];
+}
+
+- (void)setHighlighted:(BOOL)highlighted {
+  [super setHighlighted:highlighted];
+  [self updateTitleTextColor];
+}
+
+#pragma mark - UIAccessibility
+
+- (nullable NSString *)accessibilityLabel {
+  NSMutableArray *labelComponents = [NSMutableArray array];
+
+  // Use untransformed title as accessibility label to ensure accurate reading.
+  NSString *titleComponent = _title;
+  if (titleComponent.length > 0) {
+    [labelComponents addObject:titleComponent];
+  }
+
+  if (_badgeValue.length > 0 && !_badgeLabel.hidden) {
+    [labelComponents addObject:_badgeValue];
+  }
+
+  // Describe as "tab, X of Y"
+  NSString *tabLabel =
+      [[self class] localizedStringWithKey:kMDCItemBarStringKeyAccessibilityTabElementLabel];
+  if (tabLabel) {
+    [labelComponents addObject:tabLabel];
+  }
+
+  NSString *positionFormat =
+      [[self class] localizedStringWithKey:kMDCItemBarStringKeyAccessibilityTabPositionFormat];
+  if (positionFormat) {
+    if (_itemIndex != NSNotFound && _itemCount > 0) {
+      int position = (int)(_itemIndex + 1);
+      NSString *localizedPosition =
+          [NSString localizedStringWithFormat:positionFormat, position, (int)_itemCount];
+      [labelComponents addObject:localizedPosition];
+    }
+  }
+
+  // Speak components with a pause in between.
+  return [labelComponents componentsJoinedByString:@", "];
+}
+
+#pragma mark - Private
+
++ (UIEdgeInsets)minimumEdgeInsets {
+  const CGFloat outerPadding = 2.0f;
+  return UIEdgeInsetsMake(0.0, outerPadding, 0.0, outerPadding);
+}
+
++ (NSString *)localizedStringWithKey:(NSString *)key {
+  NSBundle *containingBundle = [NSBundle bundleForClass:self];
+  NSURL *resourceBundleURL =
+      [containingBundle URLForResource:kResourceBundleName withExtension:@"bundle"];
+  NSBundle *resourceBundle = [NSBundle bundleWithURL:resourceBundleURL];
+  return [resourceBundle localizedStringForKey:key value:nil table:kStringTableName];
+}
+
++ (NSString *)displayedTitleForTitle:(NSString *)title style:(MDCItemBarStyle *)style {
+  NSString *displayedTitle = title;
+  if (style.displaysUppercaseTitles) {
+    displayedTitle = [displayedTitle uppercaseStringWithLocale:nil];
+  }
+  return displayedTitle;
+}
+
+- (UIUserInterfaceSizeClass)horizontalSizeClass {
+  // Use trait collection's horizontalSizeClass if available.
+  if ([self respondsToSelector:@selector(traitCollection)]) {
+    return self.traitCollection.horizontalSizeClass;
+  }
+
+  // Pre-iOS 8: Use fixed size class for device.
+  const BOOL isPad = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad;
+  return isPad ? UIUserInterfaceSizeClassRegular : UIUserInterfaceSizeClassCompact;
+}
+
+/// Ensures that subviews exist and have the correct visibility for the current content style.
+- (void)updateSubviews {
+  if (_style.shouldDisplayImage) {
+    // Create image view if needed.
+    if (!_imageView) {
+      _imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
+      _imageView.contentMode = UIViewContentModeCenter;
+      [self.contentView addSubview:_imageView];
+
+      // Display our image in the new image view.
+      [self updateDisplayedImage];
+    }
+
+    _imageView.hidden = NO;
+  } else {
+    _imageView.hidden = YES;
+  }
+
+  if (_style.shouldDisplayTitle) {
+    // Create title label if needed.
+    if (!_titleLabel) {
+      CGRect titleFrame = self.contentView.bounds;
+      _titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
+      _titleLabel.autoresizingMask =
+          UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+      _titleLabel.numberOfLines = 1;
+      _titleLabel.textAlignment = NSTextAlignmentCenter;
+
+      [self.contentView addSubview:_titleLabel];
+
+      // Display title and update color for the new label.
+      [self updateDisplayedTitle];
+      [self updateTitleTextColor];
+      [self updateTitleFont];
+    }
+
+    _titleLabel.hidden = NO;
+  } else {
+    _titleLabel.hidden = YES;
+  }
+
+  if (_style.shouldDisplayBadge) {
+    if (!_badgeLabel) {
+      _badgeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+      _badgeLabel.numberOfLines = 1;
+      _badgeLabel.font = [[MDCTypography fontLoader] regularFontOfSize:kBadgeFontSize];
+      [self.contentView addSubview:_badgeLabel];
+      _badgeLabel.text = _badgeValue;
+    }
+    _badgeLabel.hidden = NO;
+  } else {
+    _badgeLabel.hidden = YES;
+  }
+}
+
+- (void)updateColors {
+  [self updateTitleTextColor];
+  [self updateInk];
+}
+
+- (void)updateTitleTextColor {
+  UIColor *textColor = _style.titleColor;
+  if (self.isHighlighted || self.isSelected) {
+    textColor = _style.selectedTitleColor;
+  }
+  _titleLabel.textColor = textColor;
+  _badgeLabel.textColor = textColor;
+  _imageView.tintColor = textColor;
+}
+
+- (void)updateTransformsAnimated:(BOOL)animated {
+  CGAffineTransform titleTransform = CGAffineTransformIdentity;
+  CGAffineTransform imageTransform = CGAffineTransformIdentity;
+
+  UIScreen *screen = self.window.screen;
+  const CGFloat screenScale = (screen ? screen.scale : 1);
+  CGFloat titleContentsScale = screenScale;
+
+  // Apply transforms to the selected item if appropriate.
+  if (_style.shouldGrowOnSelection) {
+    const CGFloat titleScaleFactor = self.selected ? kSelectedNavigationTitleScaleFactor : 1;
+    const CGFloat imageYTransform = self.selected ? kSelectedNavigationImageYOffset : 0;
+
+    /// Vertical offset in points from the bottom of the label to its baseline.
+    const CGFloat titleBaselineOffset = 3.5;
+
+    // Scale title up from the baseline.
+    titleTransform = CGAffineTransformMakeTranslation(0, titleBaselineOffset);
+    titleTransform = CGAffineTransformScale(titleTransform, titleScaleFactor, titleScaleFactor);
+    titleTransform = CGAffineTransformTranslate(titleTransform, 0, -titleBaselineOffset);
+
+    // Shift image up by a small amount.
+    imageTransform = CGAffineTransformMakeTranslation(0, imageYTransform);
+
+    // Render the title with a higher contents scale to reduce aliasing after the scale.
+    titleContentsScale = ceilf((float)(titleScaleFactor * screenScale));
+  }
+
+  void (^performAnimations)(void) = ^{
+    // Update the title scale and redraw if it'll be ending at a higher scale
+    // to minimize aliasing during animation.
+    if (titleContentsScale > _titleLabel.layer.contentsScale) {
+      _titleLabel.layer.contentsScale = titleContentsScale;
+      [_titleLabel setNeedsDisplay];
+    }
+
+    // Set the transforms.
+    _titleLabel.transform = titleTransform;
+    _badgeLabel.transform = imageTransform;
+    _imageView.transform = imageTransform;
+  };
+  void (^completeAnimations)(BOOL) = ^(BOOL finished) {
+    if (titleContentsScale != _titleLabel.layer.contentsScale) {
+      // Update the title with the final contents scale and redraw.
+      _titleLabel.layer.contentsScale = titleContentsScale;
+      [_titleLabel setNeedsDisplay];
+    }
+  };
+
+  if (animated) {
+    CAMediaTimingFunction *translateTimingFunction =
+        [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionTranslate];
+    [UIView mdc_animateWithTimingFunction:translateTimingFunction
+                                 duration:kSelectionAnimationDuration
+                                    delay:0
+                                  options:0
+                               animations:performAnimations
+                               completion:completeAnimations];
+  } else {
+    performAnimations();
+    completeAnimations(YES);
+  }
+}
+
+- (void)updateTitleFont {
+  _titleLabel.font = _style.titleFont;
+}
+
+- (void)updateInk {
+  MDCInkView *inkView = _inkTouchController.defaultInkView;
+  inkView.inkColor = _style.inkColor;
+  inkView.inkStyle = _style.inkStyle;
+}
+
+- (void)updateAccessibilityTraits {
+  if (self.isSelected) {
+    self.accessibilityTraits |= UIAccessibilityTraitSelected;
+  } else {
+    self.accessibilityTraits &= ~UIAccessibilityTraitSelected;
+  }
+}
+
+- (void)updateDisplayedImage {
+  _imageView.image = _image;
+}
+
+- (void)updateDisplayedTitle {
+  if (!_titleLabel.hidden) {
+    _titleLabel.text = [[self class] displayedTitleForTitle:_title style:_style];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h
new file mode 100644
index 0000000..a23785a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+static NSString *const kMDCItemBarStringKeyAccessibilityTabElementLabel =
+    @"MaterialTabsAccessibilityTabElementLabel";
+
+static NSString *const kMDCItemBarStringKeyAccessibilityTabPositionFormat =
+    @"MaterialTabsAccessibilityTabPositionFormat";
+
+static NSString *const kMDCItemBarStringsTableName = @"MaterialTabs";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h
new file mode 100644
index 0000000..e892b3e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h
@@ -0,0 +1,76 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialInk.h"
+
+/** Describes the visual style of individual items in an item bar. */
+@interface MDCItemBarStyle : NSObject <NSCopying>
+
+/** The default height of the bar. */
+@property(nonatomic) CGFloat defaultHeight;
+
+/** Determines if the selection indicator bar should be shown. */
+@property(nonatomic) BOOL shouldDisplaySelectionIndicator;
+
+/** Color used for the selection indicator bar which indicates the selected item. */
+@property(nonatomic, strong, nullable) UIColor *selectionIndicatorColor;
+
+/** The maximum width for individual items within the bar. If zero, items have no maximum width. */
+@property(nonatomic) CGFloat maximumItemWidth;
+
+#pragma mark - Item Style
+
+/** Indicates if the title should be displayed. */
+@property(nonatomic) BOOL shouldDisplayTitle;
+
+/** Indicates if the image should be displayed. */
+@property(nonatomic) BOOL shouldDisplayImage;
+
+/** Indicates if a badge may be shown. */
+@property(nonatomic) BOOL shouldDisplayBadge;
+
+/** Indicates if the cell's components should grow slightly when selected. (Bottom navigation) */
+@property(nonatomic) BOOL shouldGrowOnSelection;
+
+/** Color of title text when not selected. Default is opaque white. */
+@property(nonatomic, strong, nonnull) UIColor *titleColor;
+
+/** Color of title text when selected. Default is opaque white. */
+@property(nonatomic, strong, nonnull) UIColor *selectedTitleColor;
+
+/** Font used for item titles. */
+@property(nonatomic, nonnull) UIFont *titleFont;
+
+/** Style of ink animations on item interaction. */
+@property(nonatomic) MDCInkStyle inkStyle;
+
+/** Color of ink splashes. Default is 25% white. */
+@property(nonatomic, strong, nonnull) UIColor *inkColor;
+
+/** Padding in points between the title and image components, according to the MD spec. */
+@property(nonatomic) CGFloat titleImagePadding;
+
+/**
+ Indicates if all tab titles should be uppercased for display. If NO, item titles will be
+ displayed verbatim.
+
+ Default is YES and is recommended whenever possible.
+ */
+@property(nonatomic) BOOL displaysUppercaseTitles;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.m
new file mode 100644
index 0000000..fdd4947
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.m
@@ -0,0 +1,54 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCItemBarStyle.h"
+
+@implementation MDCItemBarStyle
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _titleColor = [UIColor whiteColor];
+    _displaysUppercaseTitles = YES;
+    _shouldDisplayTitle = YES;
+    _shouldDisplaySelectionIndicator = YES;
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  MDCItemBarStyle *newStyle = [[[self class] alloc] init];
+
+  newStyle.defaultHeight = _defaultHeight;
+  newStyle.shouldDisplaySelectionIndicator = _shouldDisplaySelectionIndicator;
+  newStyle.selectionIndicatorColor = _selectionIndicatorColor;
+  newStyle.maximumItemWidth = _maximumItemWidth;
+  newStyle.shouldDisplayTitle = _shouldDisplayTitle;
+  newStyle.shouldDisplayImage = _shouldDisplayImage;
+  newStyle.shouldDisplayBadge = _shouldDisplayBadge;
+  newStyle.shouldGrowOnSelection = _shouldGrowOnSelection;
+  newStyle.titleColor = _titleColor;
+  newStyle.selectedTitleColor = _selectedTitleColor;
+  newStyle.titleFont = _titleFont;
+  newStyle.inkStyle = _inkStyle;
+  newStyle.inkColor = _inkColor;
+  newStyle.titleImagePadding = _titleImagePadding;
+  newStyle.displaysUppercaseTitles = _displaysUppercaseTitles;
+
+  return newStyle;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCFontTextStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCFontTextStyle.h
new file mode 100644
index 0000000..4b8c2fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCFontTextStyle.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ Material font text styles
+
+ These styles are defined in:
+ https://material.io/guidelines/style/typography.html
+ This enumeration is a set of semantic descriptions intended to describe the fonts returned by
+ + [UIFont mdc_preferredFontForMaterialTextStyle:]
+ + [UIFontDescriptor mdc_preferredFontDescriptorForMaterialTextStyle:]
+ */
+typedef NS_ENUM(NSInteger, MDCFontTextStyle) {
+  MDCFontTextStyleBody1,
+  MDCFontTextStyleBody2,
+  MDCFontTextStyleCaption,
+  MDCFontTextStyleHeadline,
+  MDCFontTextStyleSubheadline,
+  MDCFontTextStyleTitle,
+  MDCFontTextStyleDisplay1,
+  MDCFontTextStyleDisplay2,
+  MDCFontTextStyleDisplay3,
+  MDCFontTextStyleDisplay4,
+  MDCFontTextStyleButton,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCTypography.h
new file mode 100644
index 0000000..5949cc7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCTypography.h
@@ -0,0 +1,188 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ MDCTypography uses this protocol to delegate responsibility of loading the custom fonts.
+
+ The spec defines the Roboto font family and uses three fonts in the named styles. Use this
+ protocol to define your own fonts if there is a brand need.
+
+ @see https://www.google.com/design/spec/style/typography.html#typography-styles
+ */
+@protocol MDCTypographyFontLoading <NSObject>
+@required
+
+/** Asks the receiver to return a font with a light weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)lightFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return a font with a normal weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)regularFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return a font with a medium weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)mediumFontOfSize:(CGFloat)fontSize;
+
+@optional
+
+/** Asks the receiver to return a font with a bold weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)boldFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return an italic font. FontSize must be larger tha 0. */
+- (nonnull UIFont *)italicFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return a font with an italic bold weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)boldItalicFontOfSize:(CGFloat)fontSize;
+
+/** Returns a bold version of the specified font. */
+- (nonnull UIFont *)boldFontFromFont:(nonnull UIFont *)font;
+
+/** Returns an italic version of the specified font. */
+- (nonnull UIFont *)italicFontFromFont:(nonnull UIFont *)font;
+/**
+ Asks the receiver to determine if a particular font would be considered "large" for the purposes of
+ calculating contrast ratios.
+
+ Large fonts are defined as greater than 18pt normal or 14pt bold. If the passed font is nil, then
+ this method returns NO.
+ For more see: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
+
+ @param font The font to examine, or nil.
+ @return YES if the font is non-nil and is considered "large".
+ */
+- (BOOL)isLargeForContrastRatios:(nonnull UIFont *)font;
+
+@end
+
+/**
+ Typographic constants and helpers.
+
+ To use these fonts, you must add MaterialTypography.bundle to your target.
+
+ @see https://www.google.com/design/spec/style/typography.html#typography-styles
+ */
+@interface MDCTypography : NSObject
+
+#pragma mark - Font loader access
+
+/** Set the font loader in order to use a non-system font. */
++ (void)setFontLoader:(nonnull id<MDCTypographyFontLoading>)fontLoader;
+
+/** Get the current font loader. */
++ (nonnull id<MDCTypographyFontLoading>)fontLoader;
+
+#pragma mark - Display fonts (extra large fonts)
+
+/** Returns the display 4 font. (largest of the display font sizes) */
++ (nonnull UIFont *)display4Font;
+
+/** Returns the recommended opacity of black text for the display fonts 4. */
++ (CGFloat)display4FontOpacity;
+
+/** Returns the display 3 font. (second largest of the display font sizes) */
++ (nonnull UIFont *)display3Font;
+
+/** Returns the recommended opacity of black text for the display fonts 3. */
++ (CGFloat)display3FontOpacity;
+
+/** Returns the display 2 font. (third largest of the display font sizes) */
++ (nonnull UIFont *)display2Font;
+
+/** Returns the recommended opacity of black text for the display fonts 2. */
++ (CGFloat)display2FontOpacity;
+
+/** Returns the display 1 font. (smallest of the display font sizes) */
++ (nonnull UIFont *)display1Font;
+
+/** Returns the recommended opacity of black text for the display fonts 1. */
++ (CGFloat)display1FontOpacity;
+
+#pragma mark - Common UI fonts
+
+/** Returns the headline font. */
++ (nonnull UIFont *)headlineFont;
+
+/** Returns the recommended opacity of black text for the headline font. */
++ (CGFloat)headlineFontOpacity;
+
+/** Returns the title font. */
++ (nonnull UIFont *)titleFont;
+
+/** Returns the recommended opacity of black text for the title font. */
++ (CGFloat)titleFontOpacity;
+
+/** Returns the subhead font. (subtitle) */
++ (nonnull UIFont *)subheadFont;
+
+/** Returns the recommended opacity of black text for the subhead font. */
++ (CGFloat)subheadFontOpacity;
+
+/** Returns the body 2 text font. (bold text) */
++ (nonnull UIFont *)body2Font;
+
+/** Returns the recommended opacity of black text for the body 2 font. */
++ (CGFloat)body2FontOpacity;
+
+/** Returns the body 1 text font. (normal text) */
++ (nonnull UIFont *)body1Font;
+
+/** Returns the recommended opacity of black text for the body 1 font. */
++ (CGFloat)body1FontOpacity;
+
+/** Returns the caption font. (a small font for image captions) */
++ (nonnull UIFont *)captionFont;
+
+/** Returns the recommended opacity of black text for the caption font. */
++ (CGFloat)captionFontOpacity;
+
+/** Returns a font for buttons. */
++ (nonnull UIFont *)buttonFont;
+
+/** Returns the recommended opacity of black text for the button font. */
++ (CGFloat)buttonFontOpacity;
+
+/** Returns a bold version of the specified font. */
++ (nonnull UIFont *)boldFontFromFont:(nonnull UIFont *)font;
+
+/** Returns an italic version of the specified font. */
++ (nonnull UIFont *)italicFontFromFont:(nonnull UIFont *)font;
+
+/**
+ Asks the receiver to determine if a particular font would be considered "large" for the purposes of
+ calculating contrast ratios.
+
+ Large fonts are defined as greater than 18pt normal or 14pt bold. If the passed font is nil, then
+ this method returns NO.
+ For more see: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
+
+ @param font The font to examine.
+ @return YES if the font is non-nil and is considered "large".
+ */
++ (BOOL)isLargeForContrastRatios:(nonnull UIFont *)font;
+
+@end
+
+/**
+ MDCSystemFontLoader allows you to use the system font for @c MDCTypography.
+
+ #### Example
+
+ ```
+ [MDCTypography setFontLoader:[[MDCSystemFontLoader alloc] init]];
+ ```
+ */
+@interface MDCSystemFontLoader : NSObject <MDCTypographyFontLoading>
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCTypography.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCTypography.m
new file mode 100644
index 0000000..0c02d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MDCTypography.m
@@ -0,0 +1,259 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCTypography.h"
+#import "private/UIFont+MaterialTypographyPrivate.h"
+
+static id<MDCTypographyFontLoading> gFontLoader = nil;
+const CGFloat MDCTypographyStandardOpacity = 0.87f;
+const CGFloat MDCTypographySecondaryOpacity = 0.54f;
+
+@implementation MDCTypography
+
+#pragma mark - Font loader access
+
++ (void)setFontLoader:(id<MDCTypographyFontLoading>)fontLoader {
+  gFontLoader = fontLoader;
+  NSAssert(gFontLoader,
+           @"Font loader can't be null. The font loader will be reset to the default font loader.");
+  if (!gFontLoader) {
+    gFontLoader = [self defaultFontLoader];
+  }
+}
+
++ (id<MDCTypographyFontLoading>)fontLoader {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    if (!gFontLoader) {
+      gFontLoader = [self defaultFontLoader];
+    }
+  });
+  return gFontLoader;
+}
+
+#pragma mark - Display fonts (extra large fonts)
+
++ (UIFont *)display4Font {
+  return [[self fontLoader] lightFontOfSize:112];
+}
+
++ (CGFloat)display4FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)display3Font {
+  return [[self fontLoader] regularFontOfSize:56];
+}
+
++ (CGFloat)display3FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)display2Font {
+  return [[self fontLoader] regularFontOfSize:45];
+}
+
++ (CGFloat)display2FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)display1Font {
+  return [[self fontLoader] regularFontOfSize:34];
+}
+
++ (CGFloat)display1FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
+#pragma mark - Common UI fonts.
+
++ (UIFont *)headlineFont {
+  return [[self fontLoader] regularFontOfSize:24];
+}
+
++ (CGFloat)headlineFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)titleFont {
+  return [[self fontLoader] mediumFontOfSize:20];
+}
+
++ (CGFloat)titleFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)subheadFont {
+  return [[self fontLoader] regularFontOfSize:16];
+}
+
++ (CGFloat)subheadFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)body2Font {
+  return [[self fontLoader] mediumFontOfSize:14];
+}
+
++ (CGFloat)body2FontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)body1Font {
+  return [[self fontLoader] regularFontOfSize:14];
+}
+
++ (CGFloat)body1FontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)captionFont {
+  return [[self fontLoader] regularFontOfSize:12];
+}
+
++ (CGFloat)captionFontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)buttonFont {
+  return [[self fontLoader] mediumFontOfSize:14];
+}
+
++ (CGFloat)buttonFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (BOOL)isLargeForContrastRatios:(nonnull UIFont *)font {
+  id<MDCTypographyFontLoading> fontLoader = [self fontLoader];
+
+  if ([fontLoader respondsToSelector:@selector(isLargeForContrastRatios:)]) {
+    return [fontLoader isLargeForContrastRatios:font];
+  }
+
+  // Copied from [MDFTextAccessibility isLargeForContrastRatios:]
+  UIFontDescriptor *fontDescriptor = font.fontDescriptor;
+  BOOL isBold =
+      (fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold;
+  return font.pointSize >= 18 || (isBold && font.pointSize >= 14);
+}
+
++ (UIFont *)italicFontFromFont:(UIFont *)font {
+  SEL selector = @selector(italicFontFromFont:);
+  if ([self.fontLoader respondsToSelector:selector]) {
+    return [self.fontLoader italicFontFromFont:font];
+  }
+  UIFontDescriptor *fontDescriptor =
+      [font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic];
+  return [UIFont fontWithDescriptor:fontDescriptor size:0] ?:
+      [UIFont italicSystemFontOfSize:font.pointSize];
+}
+
++ (UIFont *)boldFontFromFont:(UIFont *)font {
+  SEL selector = @selector(boldFontFromFont:);
+  if ([self.fontLoader respondsToSelector:selector]) {
+    return [self.fontLoader boldFontFromFont:font];
+  }
+  UIFontDescriptorSymbolicTraits traits = UIFontDescriptorTraitBold;
+  if (font.mdc_slant != 0) {
+    traits = traits | UIFontDescriptorTraitItalic;
+  }
+  UIFontDescriptor *fontDescriptor = [font.fontDescriptor fontDescriptorWithSymbolicTraits:traits];
+  return [UIFont fontWithDescriptor:fontDescriptor size:0] ?:
+      [UIFont boldSystemFontOfSize:font.pointSize];
+}
+
+#pragma mark - Private
+
++ (id<MDCTypographyFontLoading>)defaultFontLoader {
+  return [[MDCSystemFontLoader alloc] init];
+}
+
+@end
+
+@implementation MDCSystemFontLoader
+
+- (UIFont *)lightFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightLight];
+  }
+  return [UIFont fontWithName:@"HelveticaNeue-Light" size:fontSize];
+}
+
+- (UIFont *)regularFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightRegular];
+  }
+  return [UIFont systemFontOfSize:fontSize];
+}
+
+- (UIFont *)mediumFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightMedium];
+  }
+  return [UIFont fontWithName:@"HelveticaNeue-Medium" size:fontSize];
+}
+
+- (UIFont *)boldFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightSemibold];
+  }
+  return [UIFont boldSystemFontOfSize:fontSize];
+}
+
+- (UIFont *)italicFontOfSize:(CGFloat)fontSize {
+  return [UIFont italicSystemFontOfSize:fontSize];
+}
+
+- (UIFont *)boldItalicFontOfSize:(CGFloat)fontSize {
+  UIFont *regular = [self regularFontOfSize:fontSize];
+  UIFontDescriptor *descriptor = [regular.fontDescriptor
+      fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold | UIFontDescriptorTraitItalic];
+  return [UIFont fontWithDescriptor:descriptor size:fontSize];
+}
+
+- (BOOL)isLargeForContrastRatios:(UIFont *)font {
+  if (font.pointSize >= 18) {
+    return YES;
+  }
+  if (font.pointSize < 14) {
+    return NO;
+  }
+
+  UIFontDescriptor *fontDescriptor = font.fontDescriptor;
+  if ((fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold) {
+    return YES;
+  }
+
+  CGFloat MDCFontWeightMedium = (CGFloat)0.23;
+// Based on Apple's SDK-Based Development: Using Weakly Linked Methods, Functions, and Symbols.
+// https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-1114537-BABHHJBC
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+#pragma clang diagnostic ignored "-Wunreachable-code"
+  if (&UIFontWeightMedium != NULL) {
+    MDCFontWeightMedium = UIFontWeightMedium;
+  }
+#pragma clang diagnostic pop
+
+  // We treat system font medium as large for accessibility when larger than 14.
+  if (font.mdc_weight >= MDCFontWeightMedium) {
+    return YES;
+  }
+
+  return NO;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MaterialTypography.h
new file mode 100644
index 0000000..1275c7a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/MaterialTypography.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ The Typography component provides methods for getting sized fonts and opacities following Material
+ style guidelines.
+
+ This header is the umbrella header for the component and should be imported by consumers of the
+ Typography component. Please do not directly import other headers. This will allow the componet to
+ expand or contract the header file space without consumer modifications.
+ */
+
+#import "MDCFontTextStyle.h"
+#import "MDCTypography.h"
+#import "UIFont+MaterialTypography.h"
+#import "UIFontDescriptor+MaterialTypography.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
new file mode 100644
index 0000000..49b9468
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCFontTextStyle.h"
+
+@interface UIFont (MaterialTypography)
+
+/**
+ Returns an instance of the font associated with the Material text style and scaled based on the
+ content size category.
+
+ @param style The Material font text style for which to return a font.
+ @return The font associated with the specified style.
+ */
++ (nonnull UIFont *)mdc_preferredFontForMaterialTextStyle:(MDCFontTextStyle)style;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.m
new file mode 100644
index 0000000..94abe31
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.m
@@ -0,0 +1,38 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIFont+MaterialTypography.h"
+
+#import "MDCTypography.h"
+#import "UIFontDescriptor+MaterialTypography.h"
+
+@implementation UIFont (MaterialTypography)
+
++ (UIFont *)mdc_preferredFontForMaterialTextStyle:(MDCFontTextStyle)style {
+  // Due to the way iOS handles missing glyphs in fonts, we do not support using a custom font
+  // loader with Dynamic Type.
+  id<MDCTypographyFontLoading> fontLoader = [MDCTypography fontLoader];
+  if (![fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
+    NSLog(@"MaterialTypography : Custom font loaders are not compatible with Dynamic Type.");
+  }
+
+  UIFontDescriptor *fontDescriptor =
+      [UIFontDescriptor mdc_preferredFontDescriptorForMaterialTextStyle:style];
+
+  // Size is included in the fontDescriptor, so we pass in 0.0 in the parameter.
+  UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0.0];
+
+  return font;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
new file mode 100644
index 0000000..3a2f31f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
@@ -0,0 +1,30 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCFontTextStyle.h"
+
+@interface UIFontDescriptor (MaterialTypography)
+
+/**
+ Returns an instance of the font descriptor associated with the Material text style and scaled
+ based on the content size category.
+
+ @param style The Material font text style for which to return a font descriptor.
+ @return The font descriptor associated with the specified style.
+ */
++ (nonnull UIFontDescriptor *)mdc_preferredFontDescriptorForMaterialTextStyle:
+        (MDCFontTextStyle)style;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.m
new file mode 100644
index 0000000..396ff0a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.m
@@ -0,0 +1,47 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIFontDescriptor+MaterialTypography.h"
+
+#import "UIApplication+AppExtensions.h"
+
+#import "private/MDCFontTraits.h"
+
+@implementation UIFontDescriptor (MaterialTypography)
+
++ (nonnull UIFontDescriptor *)mdc_preferredFontDescriptorForMaterialTextStyle:
+        (MDCFontTextStyle)style {
+  // iOS' default UIContentSizeCategory is Large.
+  NSString *sizeCategory = UIContentSizeCategoryLarge;
+
+  // If we are within an application, query the preferredContentSizeCategory.
+  if ([UIApplication mdc_safeSharedApplication]) {
+    sizeCategory = [UIApplication mdc_safeSharedApplication].preferredContentSizeCategory;
+  }
+
+  // TODO(#1179): We should include our leading and tracking metrics when creating this descriptor.
+  MDCFontTraits *materialTraits =
+      [MDCFontTraits traitsForTextStyle:style sizeCategory:sizeCategory];
+
+  NSDictionary *traits = @{ UIFontWeightTrait : @(materialTraits.weight) };
+  NSDictionary *attributes = @{
+    UIFontDescriptorSizeAttribute : @(materialTraits.pointSize),
+    UIFontDescriptorTraitsAttribute : traits
+  };
+
+  UIFontDescriptor *fontDescriptor = [[UIFontDescriptor alloc] initWithFontAttributes:attributes];
+
+  return fontDescriptor;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.h
new file mode 100644
index 0000000..d623b40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.h
@@ -0,0 +1,59 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCFontTextStyle.h"
+
+/**
+ Provides a means of storing defining font metrics based on size categories.
+
+ This class is based off Apple recommendation in WWDC 2016 - 803 - Typography and Fonts @ 17:33.
+ */
+@interface MDCFontTraits : NSObject
+
+/**
+ The size to which the font is scaled.
+
+ This value, in points, must be greater than 0.0.
+ */
+@property(nonatomic, readonly) CGFloat pointSize;
+
+/**
+ The weight of the font, specified as a font weight constant.
+
+ For a list of possible values, see "Font Weights” in UIFontDescriptor. Avoid passing an arbitrary
+ floating-point number for weight, because a font might not include a variant for every weight.
+ */
+@property(nonatomic, readonly) CGFloat weight;
+
+/**
+ The leading value represents additional space between lines of text and is measured in points.
+ */
+@property(nonatomic, readonly) CGFloat leading;
+
+/**
+ The tracking value represents additional horizontal space between glyphs and is measured in points.
+ */
+@property(nonatomic, readonly) CGFloat tracking;
+
+/**
+ @param style MDCFontStyle of font traits being requested.
+ @param sizeCategory UIContentSizeCategory of the font traits being requested.
+
+ @return Font traits that can be used to initialize a UIFont or UIFontDescriptor.
+ */
++ (nonnull MDCFontTraits *)traitsForTextStyle:(MDCFontTextStyle)style
+                                 sizeCategory:(nonnull NSString *)sizeCategory;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.m
new file mode 100644
index 0000000..27eeede
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.m
@@ -0,0 +1,493 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFontTraits.h"
+
+static NSDictionary<NSString *, MDCFontTraits *> *_body1Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_body2Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_buttonTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_captionTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display1Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display2Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display3Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display4Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_headlineTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_subheadlineTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_titleTraits;
+
+static NSDictionary<NSNumber *, NSDictionary *> *_styleTable;
+
+@interface MDCFontTraits (MaterialTypographyPrivate)
+
++ (instancetype)traitsWithPointSize:(CGFloat)pointSize
+                             weight:(CGFloat)weight
+                            leading:(CGFloat)leading
+                           tracking:(CGFloat)tracking;
+
+- (instancetype)initWithPointSize:(CGFloat)pointSize
+                           weight:(CGFloat)weight
+                          leading:(CGFloat)leading
+                         tracking:(CGFloat)tracking;
+
+@end
+
+@implementation MDCFontTraits
+
++ (void)initialize {
+  _body1Traits = @{
+    UIContentSizeCategoryExtraSmall :
+        [MDCFontTraits traitsWithPointSize:11 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategorySmall :
+        [MDCFontTraits traitsWithPointSize:12 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryMedium :
+        [MDCFontTraits traitsWithPointSize:13 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryLarge :
+        [MDCFontTraits traitsWithPointSize:14 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryExtraLarge :
+        [MDCFontTraits traitsWithPointSize:16 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:18 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:20 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityMedium :
+        [MDCFontTraits traitsWithPointSize:25 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityLarge :
+        [MDCFontTraits traitsWithPointSize:30 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraLarge :
+        [MDCFontTraits traitsWithPointSize:37 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:44 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:52 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+  };
+
+  _body2Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:12
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:13
+                                                                    weight:UIFontWeightMedium
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:16
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:18
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:20
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityMedium :
+        [[MDCFontTraits alloc] initWithPointSize:25
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityLarge :
+        [[MDCFontTraits alloc] initWithPointSize:30
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:37
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:44
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:52
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _buttonTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:12
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:13
+                                                                    weight:UIFontWeightMedium
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:16
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:18
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:20
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _captionTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:12
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:16
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:18
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display1Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:28
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:30
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:32
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:34
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:36
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:38
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:40
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display2Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:39
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:41
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:43
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:45
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:47
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:49
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:51
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display3Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:50
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:52
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:54
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:56
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:58
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:60
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:62
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display4Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:100
+                                                                        weight:UIFontWeightLight
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:104
+                                                                   weight:UIFontWeightLight
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:108
+                                                                    weight:UIFontWeightLight
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:112
+                                                                   weight:UIFontWeightLight
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:116
+                                                                        weight:UIFontWeightLight
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:120
+                                          weight:UIFontWeightLight
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:124
+                                          weight:UIFontWeightLight
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _headlineTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:21
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:22
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:23
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:24
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:26
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:28
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:30
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _subheadlineTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:13
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:15
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:16
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:18
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:20
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:22
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _titleTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:17
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:18
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:19
+                                                                    weight:UIFontWeightMedium
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:20
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:22
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:24
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:26
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _styleTable = @{
+    @(MDCFontTextStyleBody1) : _body1Traits,
+    @(MDCFontTextStyleBody2) : _body2Traits,
+    @(MDCFontTextStyleButton) : _buttonTraits,
+    @(MDCFontTextStyleCaption) : _captionTraits,
+    @(MDCFontTextStyleDisplay1) : _display1Traits,
+    @(MDCFontTextStyleDisplay2) : _display2Traits,
+    @(MDCFontTextStyleDisplay3) : _display3Traits,
+    @(MDCFontTextStyleDisplay4) : _display4Traits,
+    @(MDCFontTextStyleHeadline) : _headlineTraits,
+    @(MDCFontTextStyleSubheadline) : _subheadlineTraits,
+    @(MDCFontTextStyleTitle) : _titleTraits
+  };
+}
+
++ (instancetype)traitsWithPointSize:(CGFloat)pointSize
+                             weight:(CGFloat)weight
+                            leading:(CGFloat)leading
+                           tracking:(CGFloat)tracking {
+  return [[MDCFontTraits alloc] initWithPointSize:pointSize
+                                           weight:weight
+                                          leading:leading
+                                         tracking:tracking];
+}
+
+- (instancetype)initWithPointSize:(CGFloat)pointSize
+                           weight:(CGFloat)weight
+                          leading:(CGFloat)leading
+                         tracking:(CGFloat)tracking {
+  self = [super init];
+  if (self) {
+    _pointSize = pointSize;
+    _weight = weight;
+    _leading = leading;
+    _tracking = tracking;
+  }
+
+  return self;
+}
+
++ (MDCFontTraits *)traitsForTextStyle:(MDCFontTextStyle)style
+                         sizeCategory:(NSString *)sizeCategory {
+  NSDictionary *traitsTable = _styleTable[@(style)];
+  NSCAssert(traitsTable, @"traitsTable cannot be nil. Is style valid?");
+
+  MDCFontTraits *traits;
+  if (traitsTable) {
+    if (sizeCategory) {
+      traits = traitsTable[sizeCategory];
+    }
+
+    // If you have queried the table for a sizeCategory that doesn't exist, we will return the
+    // traits for XXXL.  This handles the case where the values are requested for one of the
+    // accessibility size categories beyond XXXL such as
+    // UIContentSizeCategoryAccessibilityExtraLarge.  Accessbility size categories are only
+    // defined for the Body Font Style.
+    if (traits == nil) {
+      traits = traitsTable[UIContentSizeCategoryExtraExtraExtraLarge];
+    }
+  }
+
+  return traits;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h
new file mode 100644
index 0000000..8349357
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface UIFont (MaterialTypographyPrivate)
+
+/**
+ Returns the weight of the font.
+
+ @return A value between -1.0 (very thin) to 1.0 (very thick).
+
+ Regular weight is 0.0.
+ */
+- (CGFloat)mdc_weight;
+
+/**
+ Returns the slant of the font.
+
+ @return more than 0 when italic and 0 when not italic.
+
+ Regular slant is 0.0.
+ */
+- (CGFloat)mdc_slant;
+
+/**
+ Returns an extended description of the font including name, pointsize and weight.
+ */
+- (nonnull NSString *)mdc_extendedDescription;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m
new file mode 100644
index 0000000..c2ba020
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m
@@ -0,0 +1,98 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIFont+MaterialTypographyPrivate.h"
+
+@implementation UIFont (MaterialTypographyPrivate)
+
+/*
+ Returns a string indicating the weight of the font.  These weights were added in iOS 8.2.
+ */
++ (NSString *)mdc_fontWeightDescription:(CGFloat)weight {
+// The UIFontWeight enumeration was added in iOS 8.2
+#if defined(__IPHONE_8_2)
+  if (weight == UIFontWeightUltraLight) {
+    return @"UltraLight";
+  } else if (weight == UIFontWeightThin) {
+    return @"Thin";
+  } else if (weight == UIFontWeightLight) {
+    return @"Light";
+  } else if (weight == UIFontWeightRegular) {
+    return @"Regular";
+  } else if (weight == UIFontWeightMedium) {
+    return @"Medium";
+  } else if (weight == UIFontWeightSemibold) {
+    return @"Semibold";
+  } else if (weight == UIFontWeightBold) {
+    return @"Bold";
+  } else if (weight == UIFontWeightHeavy) {
+    return @"Heavy";
+  } else if (weight == UIFontWeightBlack) {
+    return @"Black";
+  } else {
+    NSString *description = [NSString stringWithFormat:@"(%.3f)", weight];
+    return description;
+  }
+#else
+  NSString *description = [NSString stringWithFormat:@"(%.3f)", weight];
+  return description;
+#endif
+}
+
+- (CGFloat)mdc_weight {
+  // The default font weight is UIFontWeightRegular, which is 0.0.
+  CGFloat weight = 0.0;
+
+  NSDictionary *fontTraits = [self.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
+  if (fontTraits) {
+    NSNumber *weightNumber = fontTraits[UIFontWeightTrait];
+    if (weightNumber) {
+      weight = [weightNumber floatValue];
+    }
+  }
+
+  return weight;
+}
+
+- (CGFloat)mdc_slant {
+  CGFloat slant = 0.0;
+
+  NSDictionary *fontTraits = [self.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
+  if (fontTraits) {
+    NSNumber *slantNumber = fontTraits[UIFontSlantTrait];
+    if (slantNumber) {
+      slant = [slantNumber floatValue];
+    }
+  }
+
+  return slant;
+}
+
+- (NSString *)mdc_weightString {
+  CGFloat weight = [self mdc_weight];
+  NSString *weightString = [UIFont mdc_fontWeightDescription:weight];
+
+  return weightString;
+}
+
+- (NSString *)mdc_extendedDescription {
+  NSMutableString *extendedDescription = [[NSMutableString alloc] init];
+  [extendedDescription appendFormat:@"%@ : ", self.fontName];
+  [extendedDescription appendFormat:@"%@ : ", self.familyName];
+  [extendedDescription appendFormat:@"%.1f pt : ", self.pointSize];
+  [extendedDescription appendFormat:@"%@", [self mdc_weightString]];
+
+  return extendedDescription;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/MaterialApplication.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/MaterialApplication.h
new file mode 100644
index 0000000..15c2350
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/MaterialApplication.h
@@ -0,0 +1,16 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+#import "UIApplication+AppExtensions.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
new file mode 100644
index 0000000..38a741f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
@@ -0,0 +1,36 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ UIApplication extension for working with sharedApplication inside of app extensions.
+ */
+@interface UIApplication (AppExtensions)
+
+/**
+ Returns sharedApplication if it is available otherwise returns nil.
+
+ This is a wrapper around sharedApplication which is safe to compile and use in app extensions.
+ */
++ (UIApplication *)mdc_safeSharedApplication;
+
+/**
+ Returns YES if called inside an application extension otherwise returns NO.
+ */
++ (BOOL)mdc_isAppExtension;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.m
new file mode 100644
index 0000000..988aebb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.m
@@ -0,0 +1,43 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIApplication+AppExtensions.h"
+
+@implementation UIApplication (AppExtensions)
+
++ (UIApplication *)mdc_safeSharedApplication {
+  static UIApplication *application;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    if (![self mdc_isAppExtension]) {
+      // We can't call sharedApplication directly or else this won't build for app extensions.
+      application = [[UIApplication class] performSelector:@selector(sharedApplication)];
+    }
+  });
+  return application;
+}
+
++ (BOOL)mdc_isAppExtension {
+  static BOOL isAppExtension;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    isAppExtension =
+        [[[NSBundle mainBundle] executablePath] rangeOfString:@".appex/"].location != NSNotFound;
+  });
+  return isAppExtension;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
new file mode 100644
index 0000000..8623555
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file is normally automatically generated by running ./scripts/sync_icons.sh
+// It has been temporarily modified manually to support the transition to a new style for this icon.
+
+@interface MDCIcons (ic_arrow_back)
+
+/*
+ Returns the path for the ic_arrow_back image contained in
+ MaterialIcons_ic_arrow_back.bundle.
+
+ Defaults to the old style.
+ */
++ (nonnull NSString *)pathFor_ic_arrow_back;
+
+/*
+ Change the style returned by `pathFor_ic_arrow_back`.
+
+ @param useNewStyle Use the new iOS style OR Material style for ic_arrow_back.
+ */
++ (void)ic_arrow_backUseNewStyle:(BOOL)useNewStyle;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m
new file mode 100644
index 0000000..88d51a9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m
@@ -0,0 +1,50 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file is normally automatically generated by running ./scripts/sync_icons.sh
+// It has been temporarily modified manually to support the transition to a new style for this icon.
+
+#import "MaterialIcons+ic_arrow_back.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_arrow_back";
+static NSString *const kIconName = @"ic_arrow_back";
+static NSString *const kNewIconName = @"ic_arrow_back_ios";
+
+static NSString *__icArrowBackIconName = @"ic_arrow_back_ios";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_arrow_back =
+    0;
+
+@implementation MDCIcons (ic_arrow_back)
+
++ (nonnull NSString *)pathFor_ic_arrow_back {
+  return [self pathForIconName:__icArrowBackIconName withBundleName:kBundleName];
+}
+
+// TODO(samnm): Remove this method and __icArrowBackIconName after transitioning all clients to the
+// new icon style.
++ (void)ic_arrow_backUseNewStyle:(BOOL)useNewStyle {
+  if (useNewStyle) {
+    __icArrowBackIconName = kNewIconName;
+  } else {
+    __icArrowBackIconName = kIconName;
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png
new file mode 100644
index 0000000..ad38830
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png
new file mode 100644
index 0000000..6842725
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png
new file mode 100644
index 0000000..2cebb5b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png
new file mode 100644
index 0000000..a467fe7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png
new file mode 100644
index 0000000..2189a16
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png
new file mode 100644
index 0000000..923672c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
new file mode 100644
index 0000000..1749c3e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_check)
+
+/*
+ Returns the path for the ic_check image contained in
+ MaterialIcons_ic_check.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_check;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m
new file mode 100644
index 0000000..0299dfa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_check.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_check";
+static NSString *const kIconName = @"ic_check";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_check = 0;
+
+@implementation MDCIcons (ic_check)
+
++ (nonnull NSString *)pathFor_ic_check {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png
new file mode 100644
index 0000000..1c14c9c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png
new file mode 100644
index 0000000..64a4944
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png
new file mode 100644
index 0000000..b26a2c0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
new file mode 100644
index 0000000..73e73fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_check_circle)
+
+/*
+ Returns the path for the ic_check_circle image contained in
+ MaterialIcons_ic_check_circle.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_check_circle;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m
new file mode 100644
index 0000000..a8b510b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_check_circle.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_check_circle";
+static NSString *const kIconName = @"ic_check_circle";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_check_circle =
+    0;
+
+@implementation MDCIcons (ic_check_circle)
+
++ (nonnull NSString *)pathFor_ic_check_circle {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png
new file mode 100644
index 0000000..a2caa18
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png
new file mode 100644
index 0000000..86bf38e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png
new file mode 100644
index 0000000..1c2ddcd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
new file mode 100644
index 0000000..5f67578
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_chevron_right)
+
+/*
+ Returns the path for the ic_chevron_right image contained in
+ MaterialIcons_ic_chevron_right.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_chevron_right;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m
new file mode 100644
index 0000000..31687e7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_chevron_right.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_chevron_right";
+static NSString *const kIconName = @"ic_chevron_right";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((
+    visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_chevron_right = 0;
+
+@implementation MDCIcons (ic_chevron_right)
+
++ (nonnull NSString *)pathFor_ic_chevron_right {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png
new file mode 100644
index 0000000..c11a2a5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png
new file mode 100644
index 0000000..23338b8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png
new file mode 100644
index 0000000..f97c51b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
new file mode 100644
index 0000000..1f39ab6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_info)
+
+/*
+ Returns the path for the ic_info image contained in
+ MaterialIcons_ic_info.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_info;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m
new file mode 100644
index 0000000..24ad43e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_info.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_info";
+static NSString *const kIconName = @"ic_info";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_info = 0;
+
+@implementation MDCIcons (ic_info)
+
++ (nonnull NSString *)pathFor_ic_info {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png
new file mode 100644
index 0000000..5ef3dc0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png
new file mode 100644
index 0000000..46ed12a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png
new file mode 100644
index 0000000..a81eeb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
new file mode 100644
index 0000000..70a2dfb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_radio_button_unchecked)
+
+/*
+ Returns the path for the ic_radio_button_unchecked image contained in
+ MaterialIcons_ic_radio_button_unchecked.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_radio_button_unchecked;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m
new file mode 100644
index 0000000..293c7d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_radio_button_unchecked.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_radio_button_unchecked";
+static NSString *const kIconName = @"ic_radio_button_unchecked";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility(
+    "default"))) char MDCIconsExportToSuppressLibToolWarning_ic_radio_button_unchecked = 0;
+
+@implementation MDCIcons (ic_radio_button_unchecked)
+
++ (nonnull NSString *)pathFor_ic_radio_button_unchecked {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png
new file mode 100644
index 0000000..4c0688f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png
new file mode 100644
index 0000000..daa867f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png
new file mode 100644
index 0000000..d8c8636
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
new file mode 100644
index 0000000..74b8f35
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_reorder)
+
+/*
+ Returns the path for the ic_reorder image contained in
+ MaterialIcons_ic_reorder.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_reorder;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m
new file mode 100644
index 0000000..e649635
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_reorder.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_reorder";
+static NSString *const kIconName = @"ic_reorder";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_reorder = 0;
+
+@implementation MDCIcons (ic_reorder)
+
++ (nonnull NSString *)pathFor_ic_reorder {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png
new file mode 100644
index 0000000..d18997c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png
new file mode 100644
index 0000000..0b080a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png
new file mode 100644
index 0000000..0a66529
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
new file mode 100644
index 0000000..37cde09
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
@@ -0,0 +1,31 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCIcons.h"
+
+/**
+ The MDCIcons class is designed to be extended by adding individual icon extensions to a project.
+
+ Individual icons can be accessed by importing their MaterialIcons+<icon_name>.h header and calling
+ [MDCIcons pathFor_<icon_name>] to get the icon's file system path.
+ */
+@interface MDCIcons (BundleLoader)
+
+/** Returns a disk path for an icon contained within a bundle of a given name. */
++ (nonnull NSString *)pathForIconName:(nonnull NSString *)iconName
+                       withBundleName:(nonnull NSString *)bundleName;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.h
new file mode 100644
index 0000000..b02150c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.h
@@ -0,0 +1,30 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ The MDCIcons class is designed to be extended by adding individual icon extensions to a project.
+
+ Individual icons can be accessed by importing their MaterialIcons+<icon_name>.h header and calling
+ [MDCIcons pathFor_<icon_name>] to get the icon's file system path.
+ */
+@interface MDCIcons : NSObject
+
+// This object is not intended to be instantiated.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.m
new file mode 100644
index 0000000..49fa111
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.m
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCIcons.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+@implementation MDCIcons
+
++ (nonnull NSString *)pathForIconName:(nonnull NSString *)iconName
+                       withBundleName:(nonnull NSString *)bundleName {
+  NSBundle *baseBundle = [NSBundle bundleForClass:[self class]];
+  NSString *bundlePath = [baseBundle pathForResource:bundleName ofType:@"bundle"];
+  NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
+  NSAssert(bundle, @"Missing bundle %@ containing icon %@.", bundleName, iconName);
+  return [bundle pathForResource:iconName ofType:@"png"];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MaterialIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MaterialIcons.h
new file mode 100644
index 0000000..f7cc1bf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Icons/src/MaterialIcons.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCIcons.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
new file mode 100644
index 0000000..a24239a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
@@ -0,0 +1,54 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+// These notifications mirror their UIKeyboard* counterparts. They are posted after the keyboard
+// watcher has updated its own internal state, so listeners are safe to query the keyboard watcher
+// for its values.
+OBJC_EXTERN NSString *const MDCKeyboardWatcherKeyboardWillShowNotification;
+OBJC_EXTERN NSString *const MDCKeyboardWatcherKeyboardWillHideNotification;
+OBJC_EXTERN NSString *const MDCKeyboardWatcherKeyboardWillChangeFrameNotification;
+
+/**
+ An object which will watch the state of the keyboard.
+
+ The keyboard watcher calculates an offset representing the distance from the top of the keyboard to
+ the bottom of the screen.
+ */
+@interface MDCKeyboardWatcher : NSObject
+
+/**
+ Shared singleton instance of MDCKeyboardWatcher.
+ */
++ (instancetype)sharedKeyboardWatcher;
+
+/** Extract the animation duration from the keyboard notification */
++ (NSTimeInterval)animationDurationFromKeyboardNotification:(NSNotification *)notification;
+
+/** Extract the animation curve option from the keyboard notification */
++ (UIViewAnimationOptions)animationCurveOptionFromKeyboardNotification:
+        (NSNotification *)notification;
+
+/**
+ The distance from the top of the keyboard to the bottom of the screen.
+
+ Zero if the keyboard is not currently showing or is not docked.
+ */
+@property(nonatomic, readonly) CGFloat keyboardOffset;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m
new file mode 100644
index 0000000..24a3e7a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m
@@ -0,0 +1,270 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCKeyboardWatcher.h"
+#import "UIApplication+AppExtensions.h"
+
+NSString *const MDCKeyboardWatcherKeyboardWillShowNotification =
+    @"MDCKeyboardWatcherKeyboardWillShowNotification";
+NSString *const MDCKeyboardWatcherKeyboardWillHideNotification =
+    @"MDCKeyboardWatcherKeyboardWillHideNotification";
+NSString *const MDCKeyboardWatcherKeyboardWillChangeFrameNotification =
+    @"MDCKeyboardWatcherKeyboardWillChangeFrameNotification";
+
+static MDCKeyboardWatcher *_sKeyboardWatcher;
+
+@interface MDCKeyboardWatcher ()
+
+/** The keyboard's frame, in rotation-compensated screen coordinates. */
+@property(nonatomic) CGRect keyboardFrame;
+
+@end
+
+@implementation MDCKeyboardWatcher
+
+// Because at the time of writing, there is no public API for answering the question: "Is the
+// keyboard currently showing?", we must watch the keyboard's show/hide notifications and maintain
+// that state on our own. The only time early enough to start watching the keyboard is at +load, so
+// we must create a watcher then.
++ (void)load {
+  @autoreleasepool {
+    _sKeyboardWatcher = [[MDCKeyboardWatcher alloc] init];
+  }
+}
+
++ (instancetype)sharedKeyboardWatcher {
+  return _sKeyboardWatcher;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillShow:)
+               name:UIKeyboardWillShowNotification
+             object:nil];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillHide:)
+               name:UIKeyboardWillHideNotification
+             object:nil];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillChangeFrame:)
+               name:UIKeyboardWillChangeFrameNotification
+             object:nil];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark - Keyboard Notifications
+
+- (BOOL)deviceUsesCoordinateSpaces {
+  static BOOL useCoordinateSpace = NO;
+
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    UIScreen *screen = [UIScreen mainScreen];
+    useCoordinateSpace = [screen respondsToSelector:@selector(fixedCoordinateSpace)];
+  });
+
+  return useCoordinateSpace;
+}
+
+- (void)updateKeyboardOffsetWithKeyboardUserInfo:(NSDictionary *)userInfo
+                                     forceHidden:(BOOL)forceHidden {
+  CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
+  UIScreen *screen = [UIScreen mainScreen];
+
+  // If we are supposed to be hidden, it doesn't matter what the keyboard rects are, the keyboard
+  // offset is 0. This applies in scenarios where a keyboard is showing on a view controller inside
+  // of a navigation controller, and that controller is popped. Instead of the normal keyboard
+  // vertical dismiss animation, the keyboard actually slides away with the view controller. In that
+  // scenario, the keyboard dictionaries do not reflect the keyboard going to the bottom of the
+  // screen. As such, we need to take into account the extra knowledge that the keyboard is being
+  // hidden, and drive the keyboard offset that way.
+  if (forceHidden) {
+    self.keyboardFrame = CGRectZero;
+    return;
+  }
+
+  // On iOS 8, the window orientation is corrected logically after transforms, so there is
+  // no need to swap the width and height like we had to on iOS 7 and below..
+  BOOL isiOS8Device = [self deviceUsesCoordinateSpaces];
+
+  // iOS 8 doesn't notify us of a new keyboard rect when a keyboard dock or undocks to/from the
+  // bottom of the screen. The more common case of no frame is a keyboard undocking and moving
+  // around, so on iOS 8 we'll take a missing frame to indicate an undocked keyboard. Unfortunately
+  // when the keyboard is re-docked, we won't know, and won't be able to re-update the offset.
+  // This also means that our "failure" mode is at the bottom of the screen, so we shouldn't get
+  // into a situation where the offset is too far up with no keyboard on screen.
+  if (CGRectIsEmpty(keyboardRect)) {
+    if (isiOS8Device) {
+      // Set the offset to zero, as if the keyboard was undocked.
+      self.keyboardFrame = CGRectZero;
+    }
+    return;
+  }
+
+  CGRect screenBounds = [screen bounds];
+  CGRect intersection = CGRectIntersection(screenBounds, keyboardRect);
+
+  UIInterfaceOrientation orientation =
+      [[UIApplication mdc_safeSharedApplication] statusBarOrientation];
+
+  BOOL isDockedKeyboard = YES;
+
+  if (!isiOS8Device) {
+    if (UIInterfaceOrientationIsLandscape(orientation)) {
+      CGFloat width = intersection.size.width;
+      CGFloat x = intersection.origin.x;
+
+      intersection.size.width = intersection.size.height;
+      intersection.size.height = width;
+
+      intersection.origin.x = intersection.origin.y;
+      intersection.origin.y = x;
+    }
+
+    // These calculations all depend on the fixed screen coordinate space, so we use the keyboard
+    // rectangle instead of @c intersection, which has already accounted for rotation.
+    switch (orientation) {
+      case UIInterfaceOrientationPortraitUpsideDown:
+        isDockedKeyboard = CGRectGetMinY(keyboardRect) == CGRectGetMinY(screenBounds);
+        break;
+      case UIInterfaceOrientationLandscapeLeft:
+        isDockedKeyboard = CGRectGetMaxX(keyboardRect) == CGRectGetMaxX(screenBounds);
+        break;
+      case UIInterfaceOrientationLandscapeRight:
+        isDockedKeyboard = CGRectGetMinX(keyboardRect) == CGRectGetMinX(screenBounds);
+        break;
+      case UIInterfaceOrientationPortrait:
+      case UIInterfaceOrientationUnknown:
+        isDockedKeyboard = CGRectGetMaxY(keyboardRect) == CGRectGetMaxY(screenBounds);
+        break;
+    }
+  } else {
+    // On an iPad an input accessory view may be shown on the screen even if there is an external
+    // keyboard attached. In that case, iOS will build a software keyboard with an accessory view
+    // attached to the top. It then sets the frame of this keyboard to be below the bounds of the
+    // screen so only the top accessory view is rendered.
+    // We handle this by considering software keyboards with a MaxY >= screen.MaxY as being docked.
+    isDockedKeyboard = CGRectGetMaxY(keyboardRect) >= CGRectGetMaxY(screenBounds);
+  }
+
+  // If the keyboard is docked and the intersection of the keyboard and the screen is
+  // non-zero update our stored keyboard frame.
+  // If the keyboard is undocked, split, or not visible set the keyboard frame to CGRectZero.
+  if (isDockedKeyboard && !CGRectIsEmpty(intersection)) {
+    self.keyboardFrame = intersection;
+  } else {
+    self.keyboardFrame = CGRectZero;
+  }
+}
+
+- (CGFloat)keyboardOffset {
+  return CGRectGetHeight(self.keyboardFrame);
+}
+
++ (NSTimeInterval)animationDurationFromKeyboardNotification:(NSNotification *)notification {
+  if (![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillShowNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillHideNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillChangeFrameNotification]) {
+    NSAssert(NO, @"Cannot extract the animation duration from a non-keyboard notification.");
+
+    return 0.0;
+  }
+
+  NSNumber *animationDurationNumber = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];
+  NSTimeInterval animationDuration = (NSTimeInterval)[animationDurationNumber doubleValue];
+
+  return animationDuration;
+}
+
+/** Convert UIViewAnimationCurve to UIViewAnimationOptions */
+static UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve animationCurve) {
+  switch (animationCurve) {
+    case UIViewAnimationCurveEaseInOut:
+      return UIViewAnimationOptionCurveEaseInOut;
+    case UIViewAnimationCurveEaseIn:
+      return UIViewAnimationOptionCurveEaseIn;
+    case UIViewAnimationCurveEaseOut:
+      return UIViewAnimationOptionCurveEaseOut;
+    case UIViewAnimationCurveLinear:
+      return UIViewAnimationOptionCurveLinear;
+  }
+
+  // UIKit unpredictably returns values that aren't declared in UIViewAnimationCurve, so we can't
+  // assert here.
+  // UIKeyboardWillChangeFrameNotification can post with a curve of 7.
+  // Based on how UIViewAnimationOptions are defined in UIView.h, (animationCurve << 16) may an
+  // be acceptable return value for unrecognized curves.
+  return UIViewAnimationOptionCurveEaseInOut;
+}
+
++ (UIViewAnimationOptions)animationCurveOptionFromKeyboardNotification:
+        (NSNotification *)notification {
+  if (![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillShowNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillHideNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillChangeFrameNotification]) {
+    NSAssert(NO, @"Cannot extract the animation curve option from a non-keyboard notification.");
+
+    return UIViewAnimationOptionCurveEaseInOut;
+  }
+
+  NSNumber *animationCurveNumber = notification.userInfo[UIKeyboardAnimationCurveUserInfoKey];
+  UIViewAnimationCurve animationCurve = (UIViewAnimationCurve)[animationCurveNumber integerValue];
+  UIViewAnimationOptions animationCurveOption = animationOptionsWithCurve(animationCurve);
+
+  return animationCurveOption;
+}
+
+#pragma mark - Notifications
+
+- (void)updateOffsetWithUserInfo:(NSDictionary *)userInfo
+                     forceHidden:(BOOL)forceHidden
+              notificationToPost:(NSString *)notificationToPost {
+  [self updateKeyboardOffsetWithKeyboardUserInfo:userInfo forceHidden:forceHidden];
+  [[NSNotificationCenter defaultCenter] postNotificationName:notificationToPost
+                                                      object:self
+                                                    userInfo:userInfo];
+}
+
+- (void)keyboardWillShow:(NSNotification *)notification {
+  [self updateOffsetWithUserInfo:notification.userInfo
+                     forceHidden:NO
+              notificationToPost:MDCKeyboardWatcherKeyboardWillShowNotification];
+}
+
+- (void)keyboardWillHide:(NSNotification *)notification {
+  [self updateOffsetWithUserInfo:notification.userInfo
+                     forceHidden:YES
+              notificationToPost:MDCKeyboardWatcherKeyboardWillHideNotification];
+}
+
+- (void)keyboardWillChangeFrame:(NSNotification *)notification {
+  [self updateOffsetWithUserInfo:notification.userInfo
+                     forceHidden:NO
+              notificationToPost:MDCKeyboardWatcherKeyboardWillChangeFrameNotification];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
new file mode 100644
index 0000000..15dc165
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCKeyboardWatcher.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
new file mode 100644
index 0000000..fab2f14
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
@@ -0,0 +1,77 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ These variables are intentionally static (even though this is a header file). We don't want
+ various MDC components to have to link in the overlay manager just to post overlay change
+ notifications. Any implementors who import this file will get copies of the constants which can
+ be used without linking the overlay component.
+ */
+
+/**
+ Overlay implementors should post this notification when a change in overlay frame occurs.
+
+ Use the keys below to define the features of the overlay transition.
+ */
+static NSString *const MDCOverlayDidChangeNotification = @"MDCOverlayDidChangeNotification";
+
+/**
+ The user info key indicating the identifier of the overlay.
+
+ Should be an NSString unique to the component in question. Required.
+ */
+static NSString *const MDCOverlayIdentifierKey = @"identifier";
+
+/**
+ The user info key indicating the frame of the overlay.
+
+ Should only be present if the overlay is onscreen, otherwise omit this key. The value of the key is
+ an NSValue containing a CGRect, in absolute screen coordinates (that is, in iOS 8's fixed
+ coordinate space).
+ */
+static NSString *const MDCOverlayFrameKey = @"frame";
+
+/**
+ The user info key indicating the duration of the overlay transition animation.
+
+ Should be an NSNumber containing a NSTimeInterval.
+ */
+static NSString *const MDCOverlayTransitionDurationKey = @"duration";
+
+/**
+ The user info key indicating the curve of the transition animation.
+
+ Should be an NSNumber containing an NSInteger (UIViewAnimationCurve). If the duration is non-zero,
+ either this key or the curve key should be present in the dictionary.
+ */
+static NSString *const MDCOverlayTransitionCurveKey = @"curve";
+
+/**
+ The user info key indicating the timing function of the transition animation.
+ Should be a CAMediaTimingFunction. If the duration is non-zero, either this key or the curve key
+ should be present in the dictionary.
+ */
+static NSString *const MDCOverlayTransitionTimingFunctionKey = @"timingFunction";
+
+/**
+ This key indicates that the given overlay change needs to animate immediately.
+
+ Some animations, such as the iOS keyboard animation, need to run immediately (and cannot be
+ coalesced). Should be an NSNumber containing a BOOL.
+ */
+static NSString *const MDCOverlayTransitionImmediacyKey = @"runImmediately";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
new file mode 100644
index 0000000..7bd6539
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
@@ -0,0 +1,60 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Class responsible for reporting changes to overlays on a given screen.
+ */
+@interface MDCOverlayObserver : NSObject
+
+/**
+ Returns the overlay observer for the given screen.
+
+ If @c screen is nil, the main screen is used.
+ */
++ (instancetype)observerForScreen:(UIScreen *)screen;
+
+/**
+ Adds a target/action pair to listen for changes to overlays.
+
+ If an overlay is already showing when this method is called, then a call to the target/action will
+ be made immediately with an unanimated transition.
+
+ @param target The object which will be the target of @c action
+ @param action The method to invoke on @c target. This method should take a single argument, an
+               object that conforms to @c MDCOverlayTransitioning.
+ */
+- (void)addTarget:(id)target action:(SEL)action;
+
+/**
+ Prevents the given target/action pair from being notified of overlay changes.
+
+ @param target The target to stop notifying of changes. If multiple @c actions have been
+               registered, then @c target may still receive notifications via other selectors.
+ @param action The method which will no longer be called when overlay changes occur.
+ */
+- (void)removeTarget:(id)target action:(SEL)action;
+
+/**
+ Prevents the given target from being notified of any overlay changes.
+
+ @param target The target to stop notifying of changes. This will remove any and all target-action
+               pairs registered via @c addTarget:action:.
+ */
+- (void)removeTarget:(id)target;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.m
new file mode 100644
index 0000000..f6db943
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.m
@@ -0,0 +1,303 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayObserver.h"
+
+#import <CoreFoundation/CoreFoundation.h>
+#import <CoreGraphics/CoreGraphics.h>
+#import <UIKit/UIKit.h>
+
+#import "MDCOverlayImplementor.h"
+#import "MDCOverlayTransitioning.h"
+#import "private/MDCOverlayAnimationObserver.h"
+#import "private/MDCOverlayObserverOverlay.h"
+#import "private/MDCOverlayObserverTransition.h"
+
+@interface MDCOverlayObserver () <MDCOverlayAnimationObserverDelegate>
+
+/** The list of overlays currently known to this observer. */
+@property(nonatomic) NSMutableDictionary *overlays;
+
+/** The currently-pending transition. */
+@property(nonatomic) MDCOverlayObserverTransition *pendingTransition;
+
+/** The table holding the target-action mapping. */
+@property(nonatomic) NSMapTable *actionTable;
+
+/** The animation observer used to coalesce events. */
+@property(nonatomic, strong) MDCOverlayAnimationObserver *observer;
+
+@end
+
+@implementation MDCOverlayObserver
+
+static MDCOverlayObserver *_sOverlayObserver;
+
+// This class must be available before the keyboard (or any other overlay contributor) has a chance
+// to report overlay changes. The +load method is the only safe place early enough.
++ (void)load {
+  @autoreleasepool {
+    _sOverlayObserver = [[MDCOverlayObserver alloc] init];
+  }
+}
+
++ (instancetype)observerForScreen:(UIScreen *)screen {
+  NSParameterAssert(screen == nil || screen == [UIScreen mainScreen]);
+  return _sOverlayObserver;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    _overlays = [NSMutableDictionary dictionary];
+    _observer = [[MDCOverlayAnimationObserver alloc] init];
+    _observer.delegate = self;
+
+    // Set up the target/action table. The keys will be weak pointers to objects, with no calls to
+    // hashing done only on the pointer address (as opposed to calling -hash/-isEqual:).
+    // The values will be strong references to objects.
+    NSPointerFunctionsOptions keyOptions =
+        (NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality);
+    NSPointerFunctionsOptions valueOptions =
+        (NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality);
+    _actionTable = [NSMapTable mapTableWithKeyOptions:keyOptions valueOptions:valueOptions];
+
+    // Register to hear when an overlay changes.
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(handleOverlayChangeNotification:)
+                                                 name:MDCOverlayDidChangeNotification
+                                               object:nil];
+  }
+  return self;
+}
+
+#pragma mark - Overlays
+
+- (MDCOverlayObserverOverlay *)overlayWithIdentifier:(NSString *)identifier {
+  return self.overlays[identifier];
+}
+
+- (MDCOverlayObserverOverlay *)buildOverlayWithIdentifier:(NSString *)identifier {
+  MDCOverlayObserverOverlay *overlay = self.overlays[identifier];
+  if (overlay == nil) {
+    overlay = [[MDCOverlayObserverOverlay alloc] init];
+    overlay.identifier = identifier;
+    self.overlays[identifier] = overlay;
+  }
+
+  return overlay;
+}
+
+- (void)removeOverlayWithIdentifier:(NSString *)identifier {
+  [self.overlays removeObjectForKey:identifier];
+}
+
+- (NSArray *)sortedOverlays {
+  NSArray *sortedKeys = [[self.overlays allKeys] sortedArrayUsingSelector:@selector(compare:)];
+
+  NSMutableArray *result = [NSMutableArray array];
+  for (NSString *key in sortedKeys) {
+    [result addObject:self.overlays[key]];
+  }
+
+  return result;
+}
+
+#pragma mark - Input Sources
+
+- (BOOL)updateOverlay:(NSString *)identifier withFrame:(CGRect)frame {
+  BOOL changed = NO;
+
+  MDCOverlayObserverOverlay *existingOverlay = [self overlayWithIdentifier:identifier];
+
+  if (existingOverlay != nil) {
+    if (CGRectIsEmpty(frame)) {
+      // We're getting rid of this overlay entirely.
+      [self removeOverlayWithIdentifier:identifier];
+      changed = YES;
+    } else if (!CGRectEqualToRect(existingOverlay.frame, frame)) {
+      // We're changing to a new frame for this overlay.
+      existingOverlay.frame = frame;
+      changed = YES;
+    }
+  } else if (!CGRectIsEmpty(frame)) {
+    MDCOverlayObserverOverlay *overlay = [self buildOverlayWithIdentifier:identifier];
+    overlay.frame = frame;
+    changed = YES;
+  }
+
+  return changed;
+}
+
+- (void)handleOverlayChangeNotification:(NSNotification *)note {
+  NSDictionary *userInfo = note.userInfo;
+  NSString *identifier = userInfo[MDCOverlayIdentifierKey];
+
+  // Don't even bother if an identifier wasn't provided.
+  if (identifier.length == 0) {
+    return;
+  }
+
+  NSValue *frame = userInfo[MDCOverlayFrameKey] ?: [NSValue valueWithCGRect:CGRectNull];
+  NSNumber *duration = userInfo[MDCOverlayTransitionDurationKey];
+
+  // Update the overlay frame.
+  BOOL updated = [self updateOverlay:identifier withFrame:[frame CGRectValue]];
+
+  // If there was actually a change, set up a transition.
+  if (updated) {
+    if (self.pendingTransition == nil) {
+      self.pendingTransition = [[MDCOverlayObserverTransition alloc] init];
+      [self.observer messageDelegateOnNextRunloop];
+    }
+  }
+
+  // If we were given a duration, then update the animation parameters.
+  if (self.pendingTransition != nil && duration != nil) {
+    self.pendingTransition.duration = duration.doubleValue;
+    self.pendingTransition.customTimingFunction = userInfo[MDCOverlayTransitionTimingFunctionKey];
+    self.pendingTransition.animationCurve =
+        ((NSNumber *)userInfo[MDCOverlayTransitionCurveKey]).integerValue;
+
+    // If this update requires us to run the animation immediately, go ahead and fire it off.
+    NSNumber *runImmediately = userInfo[MDCOverlayTransitionImmediacyKey];
+    if (runImmediately.boolValue) {
+      [self fireTransition];
+    }
+  }
+}
+
+#pragma mark - Target/Action
+
+- (NSInvocation *)buildInvocationForTarget:(id)target action:(SEL)action {
+  NSMethodSignature *signature = [target methodSignatureForSelector:action];
+  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+  [invocation setTarget:target];
+  [invocation setSelector:action];
+
+  return invocation;
+}
+
+- (void)invokeTarget:(NSInvocation *)invocation
+      withTransition:(MDCOverlayObserverTransition *)transition {
+  NSParameterAssert(invocation != nil);
+  NSParameterAssert(transition != nil);
+
+  [invocation setArgument:&transition atIndex:2];
+  [invocation invoke];
+}
+
+- (NSUInteger)indexOfInvocationForTarget:(id)target action:(SEL)action {
+  NSMutableArray *invocations = [self.actionTable objectForKey:target];
+
+  if (invocations == nil) {
+    return NSNotFound;
+  }
+
+  return [invocations
+      indexOfObjectPassingTest:^BOOL(NSInvocation *invocation, NSUInteger idx, BOOL *stop) {
+        return invocation.selector == action;
+      }];
+}
+
+- (void)addTarget:(id)target action:(SEL)action {
+  NSParameterAssert(target != nil);
+
+  NSUInteger foundIndex = [self indexOfInvocationForTarget:target action:action];
+  if (foundIndex != NSNotFound) {
+    return;
+  }
+
+  NSInvocation *invocation = [self buildInvocationForTarget:target action:action];
+  NSParameterAssert(invocation != nil);
+
+  NSMutableArray *invocations = [self.actionTable objectForKey:target];
+  if (invocations == nil) {
+    invocations = [NSMutableArray array];
+    [self.actionTable setObject:invocations forKey:target];
+  }
+
+  [invocations addObject:invocation];
+
+  if (self.overlays.count > 0) {
+    // If there's already a pending transition, let the runloop take care of it, otherwise create
+    // one and call it immediately on just the newly-added target, so that it can get its initial
+    // value.
+    if (self.pendingTransition == nil) {
+      MDCOverlayObserverTransition *transition = [[MDCOverlayObserverTransition alloc] init];
+      transition.overlays = [self sortedOverlays];
+
+      [self invokeTarget:invocation withTransition:transition];
+
+      // Run the (non-animated) transition.
+      [transition runAnimation];
+    }
+  }
+}
+
+- (void)removeTarget:(id)target {
+  NSParameterAssert(target != nil);
+
+  [self.actionTable removeObjectForKey:target];
+}
+
+- (void)removeTarget:(id)target action:(SEL)action {
+  NSParameterAssert(target != nil);
+
+  NSUInteger foundIndex = [self indexOfInvocationForTarget:target action:action];
+
+  if (foundIndex != NSNotFound) {
+    NSMutableArray *invocations = [self.actionTable objectForKey:target];
+
+    if (invocations.count == 1) {
+      // Clean up all the invocations if this was the only one.
+      [self removeTarget:target];
+    } else {
+      // Otherwise remove this single invocation.
+      [invocations removeObjectAtIndex:foundIndex];
+    }
+  }
+}
+
+#pragma mark - Runloop Observer
+
+- (void)fireTransition {
+  if (self.pendingTransition == nil) {
+    return;
+  }
+
+  // Update the transition with the latest set of overlays.
+  self.pendingTransition.overlays = [self sortedOverlays];
+
+  // Call all of our targets and let them know a transition has happened.
+  for (id target in self.actionTable) {
+    NSArray *invocations = [self.actionTable objectForKey:target];
+    for (NSInvocation *invocation in invocations) {
+      [self invokeTarget:invocation withTransition:self.pendingTransition];
+    }
+  }
+
+  // Actually run the transition animation.
+  [self.pendingTransition runAnimation];
+
+  self.pendingTransition = nil;
+}
+
+- (void)animationObserverDidEndRunloop:(MDCOverlayAnimationObserver *)observer {
+  [self fireTransition];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
new file mode 100644
index 0000000..76d6ea5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
@@ -0,0 +1,108 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Protocol representing a single overlay on the screen.
+ */
+@protocol MDCOverlay <NSObject>
+
+/**
+ A unique identifier for the overlay. Opaque.
+ */
+@property(nonatomic, readonly, copy) NSString *identifier;
+
+/**
+ The frame of the overlay, in screen coordinates.
+ */
+@property(nonatomic, readonly) CGRect frame;
+
+/**
+ Returns the frame of the overlay, in @c targetView's coordinate space.
+
+ The result may go outside of the bounds of @c targetView.
+ */
+- (CGRect)overlayFrameInView:(UIView *)targetView;
+
+@end
+
+/**
+ Protocol representing a change in the overlays currently on screen.
+ */
+@protocol MDCOverlayTransitioning <NSObject>
+
+/**
+ The duration of the animation used to change the overlay frames.
+
+ A duration of 0 means the transition is not animated.
+ */
+@property(nonatomic, readonly) NSTimeInterval duration;
+
+/**
+ If animated, the timing function that should be used when animating the overlay frame change.
+
+ If @c duration is 0, this value is undefined.
+ */
+@property(nonatomic, readonly) CAMediaTimingFunction *customTimingFunction;
+
+/**
+ If animated, the curve that should be used when animating the overlay frame change.
+
+ If @c duration is 0, or if @c customTimingFunction is non-nil, then this value is undefined.
+ */
+@property(nonatomic, readonly) UIViewAnimationCurve animationCurve;
+
+/**
+ The union of the frames for every overlay currently on screen, in screen coordinates.
+
+ This frame is the smallest frame which encompasses all of the overlays currently on screen.
+
+ @note This is generally the frame you want, but it can be "greedy" in that the reported frame may
+       not be the most accurate reflection of the overlays on screen. Imagine an overlay that is
+       half the screen's width above a full-width view. The resulting composite frame will be the
+       full width of the screen plus the height of the two views.
+ */
+@property(nonatomic, readonly) CGRect compositeFrame;
+
+/**
+ The value of @c compositeFrame in @c targetView's coordinate space.
+
+ The result may go outside of the bounds of @c targetView.
+ */
+- (CGRect)compositeFrameInView:(UIView *)targetView;
+
+/**
+ Enumerates through each overlay on the screen, calling @c handler for each one.
+ */
+- (void)enumerateOverlays:(void (^)(id<MDCOverlay> overlay, NSUInteger idx, BOOL *stop))handler;
+
+/**
+ Runs @c animations alongside the overlay transition animation.
+ */
+- (void)animateAlongsideTransition:(void (^)(void))animations;
+
+/**
+ Runs @c animations alongside the overlay transition animation, calling @c completion when the
+ animation is finished.
+
+ @note Any curves specified in @c options will be ignored.
+ */
+- (void)animateAlongsideTransitionWithOptions:(UIViewAnimationOptions)options
+                                   animations:(void (^)(void))animations
+                                   completion:(void (^)(BOOL finished))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MaterialOverlays.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
new file mode 100644
index 0000000..7e5e8fa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
@@ -0,0 +1,22 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Availability.h>
+#import <Foundation/Foundation.h>
+
+#import "MDCOverlayImplementor.h"
+#import "MDCOverlayObserver.h"
+#import "MDCOverlayTransitioning.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h
new file mode 100644
index 0000000..9c7cb17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h
@@ -0,0 +1,52 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol MDCOverlayAnimationObserverDelegate;
+
+/**
+ Utility class which will call its delegate at the end of the current runloop cycle.
+
+ Called before CoreAnimation has had a chance to commit any pending implicit @c CATransactions.
+ */
+@interface MDCOverlayAnimationObserver : NSObject
+
+/**
+ Called to tell the observer that it should call the @c delegate at the end of the next runloop.
+
+ Without calling this method, the observer will not call the delegate.
+ */
+- (void)messageDelegateOnNextRunloop;
+
+/**
+ The delegate to notify when the end of the runloop has occurred.
+ */
+@property(nonatomic, weak) id<MDCOverlayAnimationObserverDelegate> delegate;
+
+@end
+
+/**
+ Delegate protocol for @c MDCOverlayAnimationObserver.
+ */
+@protocol MDCOverlayAnimationObserverDelegate <NSObject>
+
+/**
+ Called at the end of the current runloop, before CoreAnimation commits any implicit transactions.
+ */
+- (void)animationObserverDidEndRunloop:(MDCOverlayAnimationObserver *)observer;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m
new file mode 100644
index 0000000..e3e0bf5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m
@@ -0,0 +1,107 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayAnimationObserver.h"
+
+@interface MDCOverlayAnimationObserver () {
+ @public
+  /** Whether or not the observer has been primed and should report a runloop end event. */
+  BOOL _primed;  // Raw ivar to allow direct access from the runloop observer callback.
+}
+
+/**
+ The runloop observer being used on the current runloop.
+ */
+@property(nonatomic, strong) __attribute__((NSObject)) CFRunLoopObserverRef observer;
+
+/**
+ Called by the runloop observer C function.
+ */
+- (void)handleObserverFired;
+
+@end
+
+#pragma mark - Runloop Observer
+
+static void runloopObserverCallback(CFRunLoopObserverRef observer,
+                                    CFRunLoopActivity activity,
+                                    void *info) {
+  MDCOverlayAnimationObserver *animationObserver = (__bridge MDCOverlayAnimationObserver *)info;
+  if (animationObserver != NULL && animationObserver->_primed) {
+    [animationObserver handleObserverFired];
+  }
+}
+
+@implementation MDCOverlayAnimationObserver
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    [self installRunloopObserver];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self uninstallRunloopObserver];
+}
+
+- (void)messageDelegateOnNextRunloop {
+  _primed = YES;
+}
+
+#pragma mark - Runloop Observer
+
+- (void)installRunloopObserver {
+  if (self.observer != NULL) {
+    return;
+  }
+
+  CFRunLoopRef runloop = CFRunLoopGetMain();
+  CFRunLoopObserverContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
+
+  CFRunLoopObserverRef observer =
+      CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting,
+                              YES,  // Repeats
+                              0,    // Order. Lower == earlier.
+                              &runloopObserverCallback, &context);
+
+  if (observer != NULL) {
+    // Schedule the observer and hold on to it.
+    self.observer = observer;
+    CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes);
+
+    // Clean up.
+    CFRelease(observer);
+  }
+}
+
+- (void)uninstallRunloopObserver {
+  if (self.observer == NULL) {
+    return;
+  }
+
+  CFRunLoopRef runloop = CFRunLoopGetMain();
+  CFRunLoopRemoveObserver(runloop, self.observer, kCFRunLoopCommonModes);
+  self.observer = nil;
+}
+
+- (void)handleObserverFired {
+  [self.delegate animationObserverDidEndRunloop:self];
+  _primed = NO;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h
new file mode 100644
index 0000000..970ef4c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCOverlayTransitioning.h"
+
+/**
+ Object representing a single overlay being displayed on screen.
+ */
+@interface MDCOverlayObserverOverlay : NSObject <MDCOverlay>
+
+/**
+ The unique identifier for the given overlay.
+ */
+@property(nonatomic, copy) NSString *identifier;
+
+/**
+ The frame of the overlay, in screen coordinates.
+ */
+@property(nonatomic) CGRect frame;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m
new file mode 100644
index 0000000..90dfe24
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m
@@ -0,0 +1,26 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayObserverOverlay.h"
+#import "MDCOverlayUtilities.h"
+
+@implementation MDCOverlayObserverOverlay
+
+- (CGRect)overlayFrameInView:(UIView *)targetView {
+  return MDCOverlayConvertRectToView(self.frame, targetView);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h
new file mode 100644
index 0000000..6034f22
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h
@@ -0,0 +1,52 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCOverlayTransitioning.h"
+
+/**
+ Object representing the a transition between overlays on screen.
+ */
+@interface MDCOverlayObserverTransition : NSObject <MDCOverlayTransitioning>
+
+/**
+ If animated, the timing function of the transition animation.
+ */
+@property(nonatomic) CAMediaTimingFunction *customTimingFunction;
+
+/**
+ If animated, the curve of the transition animation.
+ */
+@property(nonatomic) UIViewAnimationCurve animationCurve;
+
+/**
+ If animated, the duration of the transition animation.
+ */
+@property(nonatomic) NSTimeInterval duration;
+
+/**
+ The overlays represented by this transition.
+ */
+@property(nonatomic, copy) NSArray *overlays;
+
+/**
+ Sets up an animation block (or none) and executes all of the animation blocks registered as part
+ of the MDCOverlayTransitioning protocol.
+ */
+- (void)runAnimation;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.m
new file mode 100644
index 0000000..3c6e987
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.m
@@ -0,0 +1,160 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayObserverTransition.h"
+
+#import "MDCOverlayObserverOverlay.h"
+#import "MDCOverlayUtilities.h"
+
+@interface MDCOverlayObserverTransition ()
+
+/**
+ Blocks to run as part of the transition.
+ */
+@property(nonatomic) NSMutableArray *animationBlocks;
+
+/**
+ Completion blocks to run when the transition animation finishes.
+ */
+@property(nonatomic) NSMutableArray *completionBlocks;
+
+@end
+
+@implementation MDCOverlayObserverTransition
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    _animationBlocks = [NSMutableArray array];
+    _completionBlocks = [NSMutableArray array];
+  }
+  return self;
+}
+
+/**
+ Runs the given animation block with the provided animation options, knowing that this method will
+ only run as part of @c runAnimation.
+ */
+- (void)runAnimationWithOptions:(UIViewAnimationOptions)options
+                     animations:(void (^)(void))animations {
+  if (self.duration > 0) {
+    UIViewAnimationOptions optionsToUse = options;
+
+    // Don't let the caller override the curve or the duration.
+    optionsToUse &= ~UIViewAnimationOptionOverrideInheritedDuration;
+    optionsToUse &= ~UIViewAnimationOptionOverrideInheritedOptions;
+
+    // Run a nested animation. We'll use a token animation duration, which will be ignored because
+    // this will be a nested animation.
+    [UIView animateWithDuration:1.0f
+                          delay:0.0f
+                        options:optionsToUse
+                     animations:animations
+                     completion:nil];
+  } else {
+    // Just execute the animation block if non-animated.
+    animations();
+  }
+}
+
+- (void)animateAlongsideTransitionWithOptions:(UIViewAnimationOptions)options
+                                   animations:(void (^)(void))animations
+                                   completion:(void (^)(BOOL finished))completion {
+  if (animations != nil) {
+    // Capture the options and animation block, to be executed later when @c runAnimation is called.
+    void (^animationToRun)(void) = ^{
+      [self runAnimationWithOptions:options animations:animations];
+    };
+
+    [self.animationBlocks addObject:[animationToRun copy]];
+  }
+
+  if (completion != nil) {
+    [self.completionBlocks addObject:[completion copy]];
+  }
+}
+
+- (void)animateAlongsideTransition:(void (^)(void))animations {
+  [self animateAlongsideTransitionWithOptions:0 animations:animations completion:nil];
+}
+
+- (void)runAnimation {
+  void (^animations)(void) = ^{
+    for (void (^animation)(void) in self.animationBlocks) {
+      animation();
+    }
+  };
+
+  void (^completions)(BOOL) = ^(BOOL finished) {
+    for (void (^completion)(BOOL) in self.completionBlocks) {
+      completion(finished);
+    }
+  };
+
+  if (self.duration > 0) {
+    CAMediaTimingFunction *customTiming = self.customTimingFunction;
+
+    BOOL animationsEnabled = [UIView areAnimationsEnabled];
+    [UIView setAnimationsEnabled:YES];
+
+    if (customTiming != nil) {
+      [CATransaction begin];
+      [CATransaction setAnimationTimingFunction:customTiming];
+    }
+
+    [UIView animateWithDuration:self.duration
+                          delay:0
+                        options:self.animationCurve << 16
+                     animations:animations
+                     completion:completions];
+
+    if (customTiming != nil) {
+      [CATransaction commit];
+    }
+
+    [UIView setAnimationsEnabled:animationsEnabled];
+  } else {
+    animations();
+    completions(YES);
+  }
+}
+
+- (CGRect)compositeFrame {
+  CGRect frame = CGRectNull;
+
+  for (MDCOverlayObserverOverlay *overlay in self.overlays) {
+    frame = CGRectUnion(frame, overlay.frame);
+  }
+
+  return frame;
+}
+
+- (CGRect)compositeFrameInView:(UIView *)targetView {
+  return MDCOverlayConvertRectToView(self.compositeFrame, targetView);
+}
+
+- (void)enumerateOverlays:(void (^)(id<MDCOverlay> overlay, NSUInteger idx, BOOL *stop))handler {
+  if (handler == nil) {
+    return;
+  }
+
+  [self.overlays
+      enumerateObjectsUsingBlock:^(MDCOverlayObserverOverlay *overlay, NSUInteger idx, BOOL *stop) {
+        handler(overlay, idx, stop);
+      }];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h
new file mode 100644
index 0000000..db1a749
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Utility function which converts a rectangle in overlay coordinates into the local coordinate
+ space of the given @c target
+ */
+OBJC_EXPORT CGRect MDCOverlayConvertRectToView(CGRect overlayFrame, UIView *targetView);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.m
new file mode 100644
index 0000000..3f1e04d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.m
@@ -0,0 +1,34 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayUtilities.h"
+
+CGRect MDCOverlayConvertRectToView(CGRect screenRect, UIView *target) {
+  if (target != nil && !CGRectIsNull(screenRect)) {
+    // Overlay rectangles are in screen fixed coordinates in iOS 8. If available, we'll use that
+    // API to do the conversion.
+    UIScreen *screen = [UIScreen mainScreen];
+    if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
+      return [target convertRect:screenRect fromCoordinateSpace:screen.fixedCoordinateSpace];
+    }
+
+    // If we can't use coordinate spaces (iOS 8 only), then convert the rectangle from screen
+    // coordinates to our own view. On iOS 7 and below, the window is the same size as the screen's
+    // bounds, so we can safely convert from window coordinates here and get the same outcome.
+    return [target convertRect:screenRect fromView:nil];
+  }
+  return CGRectNull;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.h
new file mode 100644
index 0000000..2f97c25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.h
@@ -0,0 +1,93 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Leading autoresizing mask based on layoutDirection. 'Leading' is 'Left' in
+ UIUserInterfaceLayoutDirectionLeftToRight, 'Right' otherwise.
+
+ @param layoutDirection The layout direction to consider to compute the autoresizing mask.
+ @return The leading margin part of an autoresizing mask.
+ */
+UIViewAutoresizing MDCAutoresizingFlexibleLeadingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection);
+
+/**
+ Trailing autoresizing masks based on layoutDirection. 'Trailing' is 'Right' in
+ UIUserInterfaceLayoutDirectionLeftToRight, 'Left' otherwise.
+
+ @param layoutDirection The layout direction to consider to compute the autoresizing mask.
+ @return The trailing margin part of an autoresizing mask.
+ */
+UIViewAutoresizing MDCAutoresizingFlexibleTrailingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection);
+
+/**
+ The frame to use when actually laying out a view in its superview.
+
+ A view is conceptually positioned within its superview in terms of leading/trailing. When it's time
+ to actually lay out (i.e. setting frames), leading/trailing needs to be converted to left/right,
+ based on the layout direction. Use this method to compute the international frame to use at layout
+ time.
+
+ @note Example: placing a view 50pts wide at 10pts from the leading edge of its parent 100pts wide.
+   CGRect frame = MDCRectFlippedForRTL(CGRectMake(10, originY, 50, height), 100, layoutDirection);
+
+ In LTR, frame is { { 10, originY }, { 50, height } }.
+  +----------------------------------------100----------------------------------------+
+  |                                                                                   |
+  | 10 +--------------------50--------------------+                                   |
+  |    |                                          |                                   |
+  |    +------------------------------------------+                                   |
+  |                                                                                   |
+  +----------------------------------------100----------------------------------------+
+
+ In RTL, frame is { { 40, originY }, { 50, height } }.
+  +----------------------------------------100----------------------------------------+
+  |                                                                                   |
+  |                                40 +--------------------50--------------------+    |
+  |                                   |                                          |    |
+  |                                   +------------------------------------------+    |
+  |                                                                                   |
+  +----------------------------------------100----------------------------------------+
+
+ @param leftToRightRect The frame to convert.
+ @param boundingWidth The superview's bounds's width.
+ @param layoutDirection The layout direction to consider to compute the layout origin.
+ @return The frame ready for layout, already internationalized based on the layout direction.
+ */
+CGRect MDCRectFlippedForRTL(CGRect leftToRightRect,
+                            CGFloat boundingWidth,
+                            UIUserInterfaceLayoutDirection layoutDirection);
+
+/**
+ Creates an UIEdgeInsets instance from the parameters while obeying layoutDirection.
+
+ If layoutDirection is UIUserInterfaceLayoutDirectionLeftToRight, then the left inset is leading and
+ the right inset is trailing, otherwise they are reversed.
+
+ @param top The top inset.
+ @param leading The leading inset.
+ @param bottom The bottom inset.
+ @param trailing The trailing inset.
+ @return Insets in terms of left/right, already internationalized based on the layout direction.
+ */
+UIEdgeInsets MDCInsetsMakeWithLayoutDirection(CGFloat top,
+                                              CGFloat leading,
+                                              CGFloat bottom,
+                                              CGFloat trailing,
+                                              UIUserInterfaceLayoutDirection layoutDirection);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.m
new file mode 100644
index 0000000..2708c4d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.m
@@ -0,0 +1,80 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCRTL.h"
+
+static CGFloat MDCOriginForLeadingInset(CGFloat leadingInset,
+                                        CGFloat width,
+                                        CGFloat boundingWidth,
+                                        UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return leadingInset;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return boundingWidth - leadingInset - width;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIUserInterfaceLayoutDirectionLeftToRight;
+}
+
+UIViewAutoresizing MDCAutoresizingFlexibleLeadingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return UIViewAutoresizingFlexibleLeftMargin;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return UIViewAutoresizingFlexibleRightMargin;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIViewAutoresizingFlexibleLeftMargin;
+}
+
+UIViewAutoresizing MDCAutoresizingFlexibleTrailingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return UIViewAutoresizingFlexibleRightMargin;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return UIViewAutoresizingFlexibleLeftMargin;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIViewAutoresizingFlexibleRightMargin;
+}
+
+CGRect MDCRectFlippedForRTL(CGRect leftToRightRect,
+                            CGFloat boundingWidth,
+                            UIUserInterfaceLayoutDirection layoutDirection) {
+  leftToRightRect = CGRectStandardize(leftToRightRect);
+  leftToRightRect.origin.x =
+      MDCOriginForLeadingInset(CGRectGetMinX(leftToRightRect), CGRectGetWidth(leftToRightRect),
+                               boundingWidth, layoutDirection);
+  return leftToRightRect;
+}
+
+UIEdgeInsets MDCInsetsMakeWithLayoutDirection(CGFloat top,
+                                              CGFloat leading,
+                                              CGFloat bottom,
+                                              CGFloat trailing,
+                                              UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return UIEdgeInsetsMake(top, leading, bottom, trailing);
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return UIEdgeInsetsMake(top, trailing, bottom, leading);
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIEdgeInsetsMake(top, leading, bottom, trailing);
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MaterialRTL.h
new file mode 100644
index 0000000..8d3de97
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/MaterialRTL.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCRTL.h"
+#import "UIImage+MaterialRTL.h"
+#import "UIView+MaterialRTL.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
new file mode 100644
index 0000000..68d02af
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
@@ -0,0 +1,38 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Partial backporting of iOS 9's `-[UIImage imageFlippedForRightToLeftLayoutDirection]`. In Apple's
+ iOS 9 implementation, the image is not actually flipped, but prepared to be flipped when displayed
+ in a Right-to-Left environment, i.e. it's just an additional flag on the UIImage (like
+ `imageOrientation`, `scale` or `resizingMode` for example). On iOS 8, the partial backporting
+ actually flips the image, so this method should only be called when in an RTL environment already.
+ TODO: consider solutions to complete the backporting to get the same behavior.
+ https://github.com/material-components/material-components-ios/issues/599
+ */
+
+@interface UIImage (MaterialRTL)
+
+/**
+ On iOS 9 and above, returns a copy of the current image, prepared to flip horizontally if it's in a
+ right-to-left layout. Prior to iOS 9, it returns the image already flipped in place. For that
+ reason, it should be called only in RTL environments.
+ */
+- (UIImage *)mdc_imageFlippedForRightToLeftLayoutDirection;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.m
new file mode 100644
index 0000000..9f87fe7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.m
@@ -0,0 +1,134 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIImage+MaterialRTL.h"
+
+/** Returns the horizontally flipped version of the given UIImageOrientation. */
+static UIImageOrientation MDCRTLMirroredOrientation(UIImageOrientation sourceOrientation) {
+  switch (sourceOrientation) {
+    case UIImageOrientationUp:
+      return UIImageOrientationUpMirrored;
+    case UIImageOrientationDown:
+      return UIImageOrientationDownMirrored;
+    case UIImageOrientationLeft:
+      return UIImageOrientationLeftMirrored;
+    case UIImageOrientationRight:
+      return UIImageOrientationRightMirrored;
+    case UIImageOrientationUpMirrored:
+      return UIImageOrientationUp;
+    case UIImageOrientationDownMirrored:
+      return UIImageOrientationDown;
+    case UIImageOrientationLeftMirrored:
+      return UIImageOrientationLeft;
+    case UIImageOrientationRightMirrored:
+      return UIImageOrientationRight;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)sourceOrientation);
+  return UIImageOrientationUpMirrored;
+}
+
+/**
+ Returns a copy of the image actually flipped. The orientation and scale are consumed, while the
+ rendering mode is ported to the new image.
+ On iOS 9 and above, use `-[UIView imageFlippedForRightToLeftLayoutDirection]` instead.
+ */
+static UIImage *MDCRTLFlippedImage(UIImage *image) {
+  NSCAssert(![image respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)],
+            @"Do not call this method on iOS 9 and above.");
+  CGSize size = [image size];
+  CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
+
+  UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale);
+  CGContextRef context = UIGraphicsGetCurrentContext();
+  CGContextSetShouldAntialias(context, true);
+  CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
+
+  // Note: UIKit's and CoreGraphics coordinates systems are flipped vertically (UIKit's Y axis goes
+  // down, while CoreGraphics' goes up).
+  switch (image.imageOrientation) {
+    case UIImageOrientationUp:
+      CGContextScaleCTM(context, -1, -1);
+      CGContextTranslateCTM(context, -rect.size.width, -rect.size.height);
+      break;
+    case UIImageOrientationDown:
+      // Orientation down is equivalent to a 180º rotation. The difference in coordinates systems is
+      // thus sufficient and nothing needs to be down to flip the image.
+      break;
+    case UIImageOrientationLeft:
+      CGContextRotateCTM(context, -(CGFloat)M_PI / 2.f);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    case UIImageOrientationRight:
+      CGContextRotateCTM(context, (CGFloat)M_PI / 2);
+      CGContextTranslateCTM(context, 0, -rect.size.width);
+      break;
+    case UIImageOrientationUpMirrored:
+      CGContextScaleCTM(context, 1, -1);
+      CGContextTranslateCTM(context, 0, -rect.size.height);
+      break;
+    case UIImageOrientationDownMirrored:
+      CGContextScaleCTM(context, -1, 1);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    case UIImageOrientationLeftMirrored:
+      CGContextRotateCTM(context, -(CGFloat)M_PI / 2);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      CGContextScaleCTM(context, -1, 1);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    case UIImageOrientationRightMirrored:
+      CGContextRotateCTM(context, (CGFloat)M_PI / 2);
+      CGContextTranslateCTM(context, 0, -rect.size.width);
+      CGContextScaleCTM(context, -1, 1);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    default:
+      NSCAssert(NO, @"Invalid enumeration value %i.", (int)image.imageOrientation);
+  }
+
+  CGContextDrawImage(context, rect, image.CGImage);
+
+  UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext();
+  UIGraphicsEndImageContext();
+
+  // Port the rendering mode.
+  flippedImage = [flippedImage imageWithRenderingMode:image.renderingMode];
+  return flippedImage;
+}
+
+@implementation UIImage (MaterialRTL)
+
+- (UIImage *)mdc_imageFlippedForRightToLeftLayoutDirection {
+  // On iOS 9 and above, UIImage supports being prepared for flipping. Otherwise, do the flip
+  // manually.
+  if ([self respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)]) {
+    return [self imageFlippedForRightToLeftLayoutDirection];
+  } else {
+    // -[UIImage imageWithCGImage:scale:orientation:] looses the rendering mode.
+    // If the image has a default rendering mode (i.e. UIImageRenderingModeAutomatic), it is fine to
+    // use it.
+    //
+    if (self.renderingMode == UIImageRenderingModeAutomatic) {
+      return [[self class] imageWithCGImage:self.CGImage
+                                      scale:self.scale
+                                orientation:MDCRTLMirroredOrientation(self.imageOrientation)];
+    } else {  // Otherwise, flip the image manually.
+      return MDCRTLFlippedImage(self);
+    }
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
new file mode 100644
index 0000000..5f42535
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
@@ -0,0 +1,80 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Complete backporting of iOS 9's `-[UIView semanticContentAttribute]` and
+ `+[UIView userInterfaceLayoutDirectionForSemanticContentAttribute:]`, and iOS 10's
+ `-[UIView effectiveUserInterfaceLayoutDirection]` and
+ `+[UIView userInterfaceLayoutDirectionForSemanticContentAttribute:relativeToLayoutDirection:]`.
+ */
+
+@interface UIView (MaterialRTL)
+
+/**
+ A semantic description of the view's contents, used to determine whether the view should be flipped
+ when switching between left-to-right and right-to-left layouts.
+
+ @note Default:
+   - iOS 8 and below: UISemanticContentAttributeUnspecified.
+   - iOS 9 and above: same as -[UIView semanticContentAttribute]
+ */
+@property(nonatomic, setter=mdc_setSemanticContentAttribute:)
+    UISemanticContentAttribute mdc_semanticContentAttribute;
+
+/**
+ The user interface layout direction appropriate for arranging the immediate content of this view.
+
+ Always consult the mdc_effectiveUserInterfaceLayoutDirection of the view whose immediate content is
+ being arranged or drawn. Do not assume that the value propagates through the view's subtree.
+
+ @note
+   - iOS 9 and below: same as +[UIView mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:]
+   - iOS 10 and above: same as -[UIView effectiveUserInterfaceLayoutDirection]
+ */
+@property(nonatomic, readonly)
+    UIUserInterfaceLayoutDirection mdc_effectiveUserInterfaceLayoutDirection;
+
+/**
+ Returns the layout direction implied by the provided semantic content attribute relative to the
+ application-wide layout direction (as returned by
+ UIApplication.sharedApplication.userInterfaceLayoutDirection).
+
+ @param semanticContentAttribute The semantic content attribute.
+ @return The layout direction.
+ */
++ (UIUserInterfaceLayoutDirection)mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute;
+
+/**
+ Returns the layout direction implied by the provided semantic content attribute relative to the
+ provided layout direction. For example, when provided a layout direction of
+ RightToLeft and a semantic content attribute of Playback, this method returns LeftToRight. Layout
+ and drawing code can use this method to determine how to arrange elements, but might find it easier
+ to query the container view's mdc_effectiveUserInterfaceLayoutDirection property instead.
+
+ @param semanticContentAttribute The semantic content attribute.
+ @param layoutDirection The layout direction to consider.
+ @return The implied layout direction.
+ */
++ (UIUserInterfaceLayoutDirection)
+    mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute
+                                      relativeToLayoutDirection:
+                                          (UIUserInterfaceLayoutDirection)layoutDirection;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.m
new file mode 100644
index 0000000..1729e27
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.m
@@ -0,0 +1,151 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIView+MaterialRTL.h"
+
+#import <objc/runtime.h>
+
+#define MDC_BASE_SDK_EQUAL_OR_ABOVE(x) \
+  (defined(__IPHONE_##x) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_##x))
+
+static inline UIUserInterfaceLayoutDirection
+    MDCUserInterfaceLayoutDirectionForSemanticContentAttributeRelativeToLayoutDirection(
+        UISemanticContentAttribute semanticContentAttribute,
+        UIUserInterfaceLayoutDirection userInterfaceLayoutDirection) {
+  switch (semanticContentAttribute) {
+    case UISemanticContentAttributeUnspecified:
+      return userInterfaceLayoutDirection;
+    case UISemanticContentAttributePlayback:
+    case UISemanticContentAttributeSpatial:
+    case UISemanticContentAttributeForceLeftToRight:
+      return UIUserInterfaceLayoutDirectionLeftToRight;
+    case UISemanticContentAttributeForceRightToLeft:
+      return UIUserInterfaceLayoutDirectionRightToLeft;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)semanticContentAttribute);
+  return userInterfaceLayoutDirection;
+}
+
+@interface UIView (MaterialRTLPrivate)
+
+// On iOS 9 and above, mdc_semanticContentAttribute is backed by UIKit's semanticContentAttribute.
+// On iOS 8 and below, mdc_semanticContentAttribute is backed by an associated object.
+@property(nonatomic, setter=mdc_setAssociatedSemanticContentAttribute:)
+    UISemanticContentAttribute mdc_associatedSemanticContentAttribute;
+
+@end
+
+@implementation UIView (MaterialRTL)
+
+- (UISemanticContentAttribute)mdc_semanticContentAttribute {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  if ([self respondsToSelector:@selector(semanticContentAttribute)]) {
+    return self.semanticContentAttribute;
+  } else
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  {
+    return self.mdc_associatedSemanticContentAttribute;
+  }
+}
+
+- (void)mdc_setSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  if ([self respondsToSelector:@selector(semanticContentAttribute)]) {
+    self.semanticContentAttribute = semanticContentAttribute;
+  } else
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  {
+    self.mdc_associatedSemanticContentAttribute = semanticContentAttribute;
+  }
+
+  // Invalidate the layout.
+  [self setNeedsLayout];
+}
+
+- (UIUserInterfaceLayoutDirection)mdc_effectiveUserInterfaceLayoutDirection {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+  if ([self respondsToSelector:@selector(effectiveUserInterfaceLayoutDirection)]) {
+    return self.effectiveUserInterfaceLayoutDirection;
+  } else {
+    return [UIView mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+                       self.mdc_semanticContentAttribute];
+  }
+#else
+  return [UIView mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+                     self.mdc_semanticContentAttribute];
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+}
+
++ (UIUserInterfaceLayoutDirection)mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)attribute {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  if ([self
+          respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:)]) {
+    return [self userInterfaceLayoutDirectionForSemanticContentAttribute:attribute];
+  } else
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  {
+    // Use a default of Left-to-Right, as UIKit in iOS 8 and below doesn't support native RTL
+    // layout.
+    UIUserInterfaceLayoutDirection applicationLayoutDirection =
+        UIUserInterfaceLayoutDirectionLeftToRight;
+    return [self
+        mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:attribute
+                                          relativeToLayoutDirection:applicationLayoutDirection];
+  }
+}
+
++ (UIUserInterfaceLayoutDirection)
+    mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute
+                                      relativeToLayoutDirection:
+                                          (UIUserInterfaceLayoutDirection)layoutDirection {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+  if ([self
+          respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:
+                                                                     relativeToLayoutDirection:)]) {
+    return [self userInterfaceLayoutDirectionForSemanticContentAttribute:semanticContentAttribute
+                                               relativeToLayoutDirection:layoutDirection];
+  } else {
+    return MDCUserInterfaceLayoutDirectionForSemanticContentAttributeRelativeToLayoutDirection(
+        semanticContentAttribute, layoutDirection);
+  }
+#else
+  return MDCUserInterfaceLayoutDirectionForSemanticContentAttributeRelativeToLayoutDirection(
+      semanticContentAttribute, layoutDirection);
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+}
+
+@end
+
+@implementation UIView (MaterialRTLPrivate)
+
+- (UISemanticContentAttribute)mdc_associatedSemanticContentAttribute {
+  NSNumber *semanticContentAttributeNumber =
+      objc_getAssociatedObject(self, @selector(mdc_semanticContentAttribute));
+  if (semanticContentAttributeNumber) {
+    return [semanticContentAttributeNumber integerValue];
+  }
+  return UISemanticContentAttributeUnspecified;
+}
+
+- (void)mdc_setAssociatedSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute {
+  objc_setAssociatedObject(self, @selector(mdc_semanticContentAttribute),
+                           @(semanticContentAttribute), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
new file mode 100644
index 0000000..f453b18
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCNumericValueLabel : UIView
+
+/** The background color of the value label. */
+@property(nonatomic, retain) UIColor *backgroundColor;
+
+/** The text color of the label. */
+@property(nonatomic, retain) UIColor *textColor;
+
+/** The size of the value label. */
+@property(nonatomic) CGFloat fontSize;
+
+/** The text to be displayed in the value label. */
+@property(nonatomic, copy) NSString *text;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.m
new file mode 100644
index 0000000..0beaac4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.m
@@ -0,0 +1,147 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCNumericValueLabel.h"
+
+#import "MDCTypography.h"
+
+static const CGFloat kAnchorPointY = 1.15f;
+static const CGFloat kBezierSmoothingFactor = 0.0625f;
+static const CGFloat kLabelInsetSize = 6.f;
+
+@implementation MDCNumericValueLabel {
+  CAShapeLayer *_marker;
+  UILabel *_label;
+}
+
+/**
+ Inits a new numeric value label. Note that we expect the frame to be taller than it is wide, in
+ order to correctly display the "ice cream cone" shape.
+ */
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.backgroundColor = [UIColor clearColor];
+
+    _marker = [CAShapeLayer layer];
+    _marker.fillRule = kCAFillRuleNonZero;
+    [self.layer addSublayer:_marker];
+
+    _label = [[UILabel alloc] init];
+    _label.textAlignment = NSTextAlignmentCenter;
+    _label.textColor = [UIColor whiteColor];  // Default text color, override by setting textColor
+    _label.font = [MDCTypography body1Font];  // Default font size, override by setting fontSize
+    _label.adjustsFontSizeToFitWidth = YES;
+    _label.minimumScaleFactor = 0.7f;
+    [self addSubview:_label];
+
+    // So that scaling happens in relation to slightly below the thumb track. Also has the nice
+    // effect of letting us set the view's "center" to be on the track, but have the view actually
+    // appear above the thumb track.
+    self.layer.anchorPoint = CGPointMake(0.5f, kAnchorPointY);
+  }
+  return self;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  CGFloat width = self.bounds.size.width;
+  CGFloat radius = width / 2;
+  CGFloat height = self.bounds.size.height;
+  CGFloat bezierSmoothingPixels = height * kBezierSmoothingFactor;
+
+  CGMutablePathRef path = CGPathCreateMutable();
+
+  // We're drawing a shape that looks something like this:
+  //   __
+  //  (  )
+  //   \/
+
+  // Calculate what point on the circle the lines on the bottom should touch. If you're interested
+  // in the Math, we found these formulas like this:
+  // 1. x^2 + y^2 = r defines the circle
+  // 2. y = H - mx defines a family of lines from (0,H) where H is the height of the whole shape
+  // 3. Now we try to find m such that the system of equations has only one (x,y) solution that
+  //    satisfies both equations. This amounts to finding the line from (0,H) to the circle that
+  //    only touches the circle one time.
+  // 4. Substitute y = H - mx into first equation. x^2 + (H-mx)^2 = r^2
+  // 5. Simplify and set to 0. (1 + m^2)x^2 + (-2Hm)x + (H^2 - r^2) = 0
+  // 6. We now have a quadratic equation of the form ax^2 + bx + c = 0. Such equations have only
+  //    one solution if and only if the discriminant d = b^2 - 4ac = 0
+  // 7. Set discriminant to 0 and solve for m. 0 = (-2Hm)^2 - 4(1 + m^2)(H^2 - r^2)
+  // 8. m = sqrt((H^2 - r^2)/(r^2))
+  // 9. Now use quadratic formula to solve for x. x = (r * sqrt(H^2 - r^2)) / H
+  // 10. Plug into original equation to get y. y = r^2 / H
+  CGFloat x = (radius * sqrtf((float)(height * height - radius * radius))) / height;
+  CGFloat y = radius * radius / height;
+
+  // Calculate the angles at which the left and right lines touch the circle
+  CGFloat angleDelta = atanf((float)(y / x));
+  CGFloat startAngle = (float)M_PI - angleDelta;
+  CGFloat endAngle = angleDelta;
+
+  CGPathMoveToPoint(path, NULL, radius, height);
+
+  // Draws line from bottom to left side of circle, curving slightly to smooth the shape
+  CGPathAddCurveToPoint(path, NULL, radius, height, radius - x, radius + y + bezierSmoothingPixels,
+                        radius - x, radius + y);
+
+  // Draw the part of the circle that we need
+  CGPathAddArc(path, NULL, radius, radius, radius, startAngle, endAngle, NO);
+
+  // Curve back down from the right side of the circle to the bottom of the shape
+  CGPathAddCurveToPoint(path, NULL, radius + x, radius + y + bezierSmoothingPixels, radius, height,
+                        radius, height);
+  CGPathCloseSubpath(path);
+
+  _marker.path = path;
+  CGPathRelease(path);
+
+  // Place the label as well
+  _label.frame = CGRectInset(CGRectMake(0, 0, width, width), kLabelInsetSize, kLabelInsetSize);
+}
+
+- (void)setBackgroundColor:(UIColor *)backgroundColor {
+  _backgroundColor = backgroundColor;
+  _marker.fillColor = _backgroundColor.CGColor;
+}
+
+- (UIColor *)textColor {
+  return _label.textColor;
+}
+
+- (void)setTextColor:(UIColor *)textColor {
+  _label.textColor = textColor;
+}
+
+- (CGFloat)fontSize {
+  return _label.font.pointSize;
+}
+
+- (void)setFontSize:(CGFloat)fontSize {
+  _label.font = [[MDCTypography fontLoader] regularFontOfSize:fontSize];
+}
+
+- (NSString *)text {
+  return _label.text;
+}
+
+- (void)setText:(NSString *)text {
+  _label.text = text;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
new file mode 100644
index 0000000..f3ac73a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
@@ -0,0 +1,261 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCThumbView;
+@protocol MDCThumbTrackDelegate;
+
+@interface MDCThumbTrack : UIControl
+
+/** The delegate for the thumb track. */
+@property(nullable, nonatomic, weak) id<MDCThumbTrackDelegate> delegate;
+
+@property(nullable, nonatomic, strong) UIColor *primaryColor;
+
+/** The color of the thumb off color. */
+@property(nullable, nonatomic, strong) UIColor *thumbOffColor;
+
+/** The color of the track off color. */
+@property(nullable, nonatomic, strong) UIColor *trackOffColor;
+
+/** The color of the thumb disabled color. */
+@property(nullable, nonatomic, strong) UIColor *thumbDisabledColor;
+
+/** The color of the track disabled color. */
+@property(nullable, nonatomic, strong) UIColor *trackDisabledColor;
+
+/** Dummy property to unbreak internal clients. */
+/** TODO(#1216): Remove this property */
+@property(nonatomic, assign) BOOL interpolateOnOffColors;
+
+/**
+ The number of discrete values that the thumb can take along the track. If this property is zero,
+ then the slider operates continuously and doesn't do any snapping after the user releases the
+ thumb. If this property is greater or equal to two, then the thumb will snap to the nearest
+ discrete value on when the user lifts their finger or taps. The set of discrete values is
+ equivalent to
+ { minimumValue +  (i / (numDiscreteValues - 1.0)) * (maximumValue - minimumValue) } for
+ i = 0..numDiscreteValues-1.
+
+ The default value is zero. If numDiscreteValues is set to one, then the thumb track will act as
+ if numDiscreteValues is zero and will judge you silently.
+ */
+@property(nonatomic, assign) NSUInteger numDiscreteValues;
+
+/**
+  The value of the thumb along the track.
+
+ Setting this property causes the receiver to redraw itself using the new value. To render an
+ animated transition from the current value to the new value you should use the setValue:animated:
+ method instead. Setting the value to does not result in an action message being sent.
+
+ If you try to set a value that is below the minimum or above the maximum value, the minimum or
+ maximum value is set instead. The default value of this property is 0.0.
+ */
+@property(nonatomic, assign) CGFloat value;
+
+/**
+  The minimum value of the thumb along the track.
+
+ If you change the value of this property, and the current value of the receiver is below the new
+ minimum, the current value is adjusted to match the new minimum value automatically.
+
+ The default value of this property is 0.0.
+ */
+@property(nonatomic, assign) CGFloat minimumValue;
+
+/**
+ The maximum value of the thumb along the track.
+
+ If you change the value of this property, and the current value of the receiver is above the new
+ maximum, the current value is adjusted to match the new maximum value automatically.
+
+ The default value of this property is 1.0.
+ */
+@property(nonatomic, assign) CGFloat maximumValue;
+
+/** The current position of the center of the thumb in this view's coordinates. */
+@property(nonatomic, assign, readonly) CGPoint thumbPosition;
+
+/** The height of the track that the thumb moves along. */
+@property(nonatomic, assign) CGFloat trackHeight;
+
+/** The radius of the track thumb that moves along the track. */
+@property(nonatomic, assign) CGFloat thumbRadius;
+
+/** Whether or not the thumb should be smaller when the track is disabled. Defaults to NO. */
+@property(nonatomic, assign) BOOL thumbIsSmallerWhenDisabled;
+
+/**
+ Whether or not the thumb view should be a hollow circle when at the start position. Defaults to
+ NO.
+ */
+@property(nonatomic, assign) BOOL thumbIsHollowAtStart;
+
+/** Whether or not the thumb should grow when the user is dragging it. Default is NO. */
+@property(nonatomic, assign) BOOL thumbGrowsWhenDragging;
+
+/** The max radius of the ripple when the user touches the thumb. */
+@property(nonatomic, assign) CGFloat thumbMaxRippleRadius;
+
+/** Whether the thumb should display ink splashes on touch. */
+@property(nonatomic, assign) BOOL shouldDisplayInk;
+
+/** Whether or not to display dots indicating discrete locations. Default is NO. */
+@property(nonatomic, assign) BOOL shouldDisplayDiscreteDots;
+
+/** Whether or not to show the numeric value label when dragging a discrete slider. */
+@property(nonatomic, assign) BOOL shouldDisplayDiscreteValueLabel;
+
+/** Whether a disabled thumb track includes gaps on either side of the thumb. The default is NO. */
+@property(nonatomic, assign) BOOL disabledTrackHasThumbGaps;
+
+/** Whether the ends of the thumb track should be rounded. The default is NO. */
+@property(nonatomic, assign) BOOL trackEndsAreRounded;
+
+/** Whether the ends of the track are inset by the radius of the thumb. The default is NO. */
+@property(nonatomic, assign) BOOL trackEndsAreInset;
+
+/**
+ The value from which the filled part of the track is anchored. If set to a value between
+ minimumValue and maximumValue, then the filled/colored part of the track extends from the
+ trackAnchorValue to the thumb. Values beyond the minimum/maximum values are effectively capped.
+ The default value is -CGFLOAT_MAX, so the filled part of the track extends from the minimum value
+ to the thumb.
+ */
+@property(nonatomic, assign) CGFloat filledTrackAnchorValue;
+
+/** The thumb view that user moves along the track. */
+@property(nullable, nonatomic, strong) MDCThumbView *thumbView;
+
+/**
+ Contains a Boolean value indicating whether a user's changes in the value generate continuous
+ update events.
+
+ If YES, the slider sends update events continuously to the associated target’s action method.
+ If NO, the slider only sends an action event when the user releases the slider’s thumb control to
+ set the final value.
+
+ The default value of this property is YES.
+ */
+@property(nonatomic, assign) BOOL continuousUpdateEvents;
+
+/**
+ Whether the control should react to pan gestures all along the track, or just on the thumb.
+
+ The default value of this property is NO.
+ */
+@property(nonatomic, assign) BOOL panningAllowedOnEntireControl;
+
+/**
+ Whether the control should react to taps on the thumb itself, as opposed to the track.
+
+ The default value of this property is NO.
+ */
+@property(nonatomic, assign) BOOL tapsAllowedOnThumb;
+
+/**
+ Initialize an instance with a particular frame and color group.
+
+ Designated initializer.
+ */
+- (nonnull instancetype)initWithFrame:(CGRect)frame onTintColor:(nullable UIColor *)onTintColor;
+
+/**
+ Set the value of the thumb along the track.
+
+ If animated is YES, the thumb is animated into its new position. Setting the value does not
+ result in an action message being sent.
+
+ @param value The value to set the slider to.
+ @param animated If YES, the thumb will animate to its new position.
+ */
+- (void)setValue:(CGFloat)value animated:(BOOL)animated;
+
+/**
+ Set the value of the thumb along the track.
+
+ If animated is YES, the thumb is animated into its new position. Setting the value to does not
+ result in an action message being sent.
+
+ @param value The value to set the thumb to.
+ @param animated If YES, the change of value will be animated.
+ @param animateThumbAfterMove If YES, animate the thumb to its new state after moving it into place.
+ @param userGenerated Is this call a direct result of a user's action?
+ @param completion If not NULL, the block will be called after the value is set.
+ */
+- (void)setValue:(CGFloat)value
+                 animated:(BOOL)animated
+    animateThumbAfterMove:(BOOL)animateThumbAfterMove
+            userGenerated:(BOOL)userGenerated
+               completion:(nullable void (^)())completion;
+
+/** Set the @c icon shown on the thumb. */
+- (void)setIcon:(nullable UIImage *)icon;
+
+/** Disable setting multitouch. Has to be NO. */
+- (void)setMultipleTouchEnabled:(BOOL)multipleTouchEnabled NS_UNAVAILABLE;
+
+@end
+
+/** MDCThumbtrack delegate which allows setting custom behavior. */
+@protocol MDCThumbTrackDelegate <NSObject>
+@optional
+
+/**
+ For discrete thumb tracks, used when determining the string label to display for a given discrete
+ value.
+
+ If not implemented, or if no delegate is specified, the thumb track displays the empty string ""
+ for all values.
+
+ @param thumbTrack The thumb track sender.
+ @param value The value whose label needs to be calculated.
+ */
+- (nonnull NSString *)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack stringForValue:(CGFloat)value;
+
+/**
+ Called when the user taps on the MDCThumbTrack.
+ If not implemented, the MDCThumbTrack will always be allowed to jump to any value.
+ */
+- (BOOL)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack shouldJumpToValue:(CGFloat)value;
+
+/**
+ Called when the thumb track will jump to a specific value.
+
+ @param thumbTrack The @c MDCThumbTrack sender.
+ @param value The new value for the slider.
+ */
+- (void)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack willJumpToValue:(CGFloat)value;
+
+/**
+ Called when the thumb track will animate to a specific value.
+
+ @param thumbTrack The @c MDCThumbTrack sender.
+ @param value The new value for the slider.
+ */
+- (void)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack willAnimateToValue:(CGFloat)value;
+
+/**
+ Called just after the thumb track has animated to a specific value.
+
+ @param thumbTrack The @c MDCThumbTrack sender.
+ @param value The new value for the slider.
+ */
+- (void)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack didAnimateToValue:(CGFloat)value;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.m
new file mode 100644
index 0000000..8ed4ce0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.m
@@ -0,0 +1,1146 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCThumbTrack.h"
+
+#import "MDCNumericValueLabel.h"
+#import "MDCThumbView.h"
+#import "MaterialInk.h"
+#import "MaterialRTL.h"
+
+static const CGFloat kAnimationDuration = 0.25f;
+static const CGFloat kThumbChangeAnimationDuration = 0.12f;
+static const CGFloat kDefaultThumbBorderWidth = 2.0f;
+static const CGFloat kDefaultThumbRadius = 6.0f;
+static const CGFloat kDefaultTrackHeight = 2.0f;
+static const CGFloat kDefaultFilledTrackAnchorValue = -CGFLOAT_MAX;
+static const CGFloat kTrackOnAlpha = 0.5f;
+static const CGFloat kMinTouchSize = 48.0f;
+static const CGFloat kThumbSlopFactor = 3.5f;
+static const CGFloat kValueLabelHeight = 48.f;
+static const CGFloat kValueLabelWidth = 0.81f * kValueLabelHeight;
+static const CGFloat kValueLabelFontSize = 12.f;
+
+// Credit to the Beacon Tools iOS team for the idea for this implementations
+@interface MDCDiscreteDotView : UIView
+
+@property(nonatomic, assign) NSUInteger numDiscreteDots;
+
+@end
+
+@implementation MDCDiscreteDotView
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    self.backgroundColor = [UIColor clearColor];
+  }
+  return self;
+}
+
+- (void)setFrame:(CGRect)frame {
+  [super setFrame:frame];
+  [self setNeedsDisplay];
+}
+
+- (void)drawRect:(CGRect)rect {
+  [super drawRect:rect];
+
+  if (_numDiscreteDots >= 2) {
+    CGContextRef contextRef = UIGraphicsGetCurrentContext();
+    CGContextSetFillColorWithColor(contextRef, [UIColor blackColor].CGColor);
+
+    CGRect circleRect = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height);
+    CGFloat increment = (self.bounds.size.width - self.bounds.size.height) / (_numDiscreteDots - 1);
+
+    for (NSUInteger i = 0; i < _numDiscreteDots; i++) {
+      circleRect.origin.x = (i * increment);
+      CGContextFillEllipseInRect(contextRef, circleRect);
+    }
+  }
+}
+
+- (void)setNumDiscreteDots:(NSUInteger)numDiscreteDots {
+  _numDiscreteDots = numDiscreteDots;
+  [self setNeedsDisplay];
+}
+
+@end
+
+// TODO(iangordon): Properly handle broken tgmath
+static inline CGFloat Fabs(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return fabs(value);
+#else
+  return fabsf(value);
+#endif
+}
+static inline CGFloat Round(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return round(value);
+#else
+  return roundf(value);
+#endif
+}
+
+static inline CGFloat Hypot(CGFloat x, CGFloat y) {
+#if CGFLOAT_IS_DOUBLE
+  return hypot(x, y);
+#else
+  return hypotf(x, y);
+#endif
+}
+
+static inline bool CGFloatEqual(CGFloat a, CGFloat b) {
+  const CGFloat constantK = 3;
+#if CGFLOAT_IS_DOUBLE
+  const CGFloat epsilon = DBL_EPSILON;
+  const CGFloat min = DBL_MIN;
+#else
+  const CGFloat epsilon = FLT_EPSILON;
+  const CGFloat min = FLT_MIN;
+#endif
+  return (Fabs(a - b) < constantK * epsilon * Fabs(a + b) || Fabs(a - b) < min);
+}
+
+/**
+ Returns the distance between two points.
+
+ @param point1 a CGPoint to measure from.
+ @param point2 a CGPoint to meature to.
+
+ @return Absolute straight line distance.
+ */
+static inline CGFloat DistanceFromPointToPoint(CGPoint point1, CGPoint point2) {
+  return Hypot(point1.x - point2.x, point1.y - point2.y);
+}
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCThumbTrack () <CAAnimationDelegate>
+@end
+#endif
+
+@interface MDCThumbTrack () <MDCInkTouchControllerDelegate>
+@end
+
+@implementation MDCThumbTrack {
+  CGFloat _lastDispatchedValue;
+  UIColor *_thumbOnColor;
+  UIColor *_trackOnColor;
+  UIColor *_clearColor;
+  MDCInkTouchController *_touchController;
+  UIView *_trackView;
+  CAShapeLayer *_trackMaskLayer;
+  CALayer *_trackOnLayer;
+  MDCDiscreteDotView *_discreteDots;
+  BOOL _shouldDisplayInk;
+  MDCNumericValueLabel *_valueLabel;
+  UIPanGestureRecognizer *_dummyPanRecognizer;
+
+  // Attributes to handle interaction. To associate touches to previous touches, we keep a reference
+  // to the current touch, since the system reuses the same memory address when sending subsequent
+  // touches for the same gesture. If _currentTouch == nil, then there's no interaction going on.
+  UITouch *_currentTouch;
+  BOOL _isDraggingThumb;
+  BOOL _didChangeValueDuringPan;
+  CGFloat _panThumbGrabPosition;
+}
+
+// TODO(iangordon): ThumbView is not respecting the bounds of ThumbTrack
+- (instancetype)initWithFrame:(CGRect)frame {
+  return [self initWithFrame:frame onTintColor:nil];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame onTintColor:(UIColor *)onTintColor {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.userInteractionEnabled = YES;
+    [super setMultipleTouchEnabled:NO];  // We only want one touch event at a time
+    _continuousUpdateEvents = YES;
+    _lastDispatchedValue = _value;
+    _maximumValue = 1;
+    _trackHeight = kDefaultTrackHeight;
+    _thumbRadius = kDefaultThumbRadius;
+    _filledTrackAnchorValue = kDefaultFilledTrackAnchorValue;
+    _shouldDisplayInk = YES;
+
+    // Default thumb view.
+    CGRect thumbFrame = CGRectMake(0, 0, self.thumbRadius * 2, self.thumbRadius * 2);
+    _thumbView = [[MDCThumbView alloc] initWithFrame:thumbFrame];
+    _thumbView.borderWidth = kDefaultThumbBorderWidth;
+    _thumbView.cornerRadius = self.thumbRadius;
+    _thumbView.layer.zPosition = 1;
+    [self addSubview:_thumbView];
+
+    _trackView = [[UIView alloc] init];
+    _trackView.userInteractionEnabled = NO;
+    _trackMaskLayer = [CAShapeLayer layer];
+    _trackMaskLayer.fillRule = kCAFillRuleEvenOdd;
+    _trackView.layer.mask = _trackMaskLayer;
+
+    _trackOnLayer = [CALayer layer];
+    [_trackView.layer addSublayer:_trackOnLayer];
+
+    [self addSubview:_trackView];
+
+    // Set up ink layer.
+    _touchController = [[MDCInkTouchController alloc] initWithView:_thumbView];
+    _touchController.delegate = self;
+
+    [_touchController addInkView];
+
+    _touchController.defaultInkView.inkStyle = MDCInkStyleUnbounded;
+
+    // Set colors.
+    if (onTintColor == nil) {
+      onTintColor = [UIColor blueColor];
+    }
+    self.primaryColor = onTintColor;
+    _clearColor = [UIColor colorWithWhite:1.0f alpha:0.0f];
+
+    // We add this UIPanGestureRecognizer to our view so that any superviews of the thumb track know
+    // when we are dragging the thumb track, and can treat it accordingly. Specifically, without
+    // this if a ThumbTrack is contained within a UIScrollView, the scroll view will cancel any
+    // touch events sent to the thumb track whenever the view is scrolling, regardless of whether or
+    // not we're in the middle of dragging the thumb. Adding a dummy gesture recognizer lets the
+    // scroll view know that we are in the middle of dragging, so those touch events shouldn't be
+    // cancelled.
+    //
+    // Note that an alternative to this would be to set canCancelContentTouches = NO on the
+    // UIScrollView, but because we can't guarantee that the thumb track will always be contained in
+    // scroll views configured like that, we have to handle it within the thumb track.
+    _dummyPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
+    _dummyPanRecognizer.cancelsTouchesInView = NO;
+    [self updateDummyPanRecognizerTarget];
+
+    [self setValue:_minimumValue animated:NO];
+  }
+  return self;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self updateTrackMask];
+  [self updateThumbTrackAnimated:NO animateThumbAfterMove:NO previousValue:_value completion:nil];
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  CGFloat dx = MIN(0, kDefaultThumbRadius - kMinTouchSize / 2);
+  CGFloat dy = MIN(0, (self.bounds.size.height - kMinTouchSize) / 2);
+  CGRect rect = CGRectInset(self.bounds, dx, dy);
+  return CGRectContainsPoint(rect, point);
+}
+
+#pragma mark - Properties
+
+- (void)setPrimaryColor:(UIColor *)primaryColor {
+  if (primaryColor == nil) {
+    primaryColor = [UIColor blueColor];  // YSNBH
+  }
+  _primaryColor = primaryColor;
+  _thumbOnColor = primaryColor;
+  _trackOnColor = primaryColor;
+
+  _touchController.defaultInkView.inkColor = [primaryColor colorWithAlphaComponent:kTrackOnAlpha];
+  [self setNeedsLayout];
+}
+
+- (void)setThumbOffColor:(UIColor *)thumbOffColor {
+  _thumbOffColor = thumbOffColor;
+}
+
+- (void)setThumbDisabledColor:(UIColor *)thumbDisabledColor {
+  _thumbDisabledColor = thumbDisabledColor;
+  [self setNeedsLayout];
+}
+
+- (void)setTrackOffColor:(UIColor *)trackOffColor {
+  _trackOffColor = trackOffColor;
+  [self setNeedsLayout];
+}
+
+- (void)setTrackDisabledColor:(UIColor *)trackDisabledColor {
+  _trackDisabledColor = trackDisabledColor;
+  [self setNeedsLayout];
+}
+
+- (void)setShouldDisplayDiscreteDots:(BOOL)shouldDisplayDiscreteDots {
+  if (_shouldDisplayDiscreteDots != shouldDisplayDiscreteDots) {
+    if (shouldDisplayDiscreteDots) {
+      _discreteDots = [[MDCDiscreteDotView alloc] init];
+      _discreteDots.alpha = 0.0;
+      [_trackView addSubview:_discreteDots];
+    } else {
+      [_discreteDots removeFromSuperview];
+      _discreteDots = nil;
+    }
+    _shouldDisplayDiscreteDots = shouldDisplayDiscreteDots;
+  }
+}
+
+- (void)setShouldDisplayDiscreteValueLabel:(BOOL)shouldDisplayDiscreteValueLabel {
+  if (_shouldDisplayDiscreteValueLabel == shouldDisplayDiscreteValueLabel) {
+    return;
+  }
+
+  _shouldDisplayDiscreteValueLabel = shouldDisplayDiscreteValueLabel;
+
+  if (shouldDisplayDiscreteValueLabel) {
+    _valueLabel = [[MDCNumericValueLabel alloc]
+        initWithFrame:CGRectMake(0, 0, kValueLabelWidth, kValueLabelHeight)];
+    // Effectively 0, but setting it to 0 results in animation not happening
+    _valueLabel.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
+    _valueLabel.fontSize = kValueLabelFontSize;
+    [self addSubview:_valueLabel];
+  } else {
+    [_valueLabel removeFromSuperview];
+    _valueLabel = nil;
+  }
+}
+
+- (void)setMinimumValue:(CGFloat)minimumValue {
+  _minimumValue = minimumValue;
+  CGFloat previousValue = _value;
+  if (_value < _minimumValue) {
+    _value = _minimumValue;
+  }
+  if (_maximumValue < _minimumValue) {
+    _maximumValue = _minimumValue;
+  }
+  [self updateThumbTrackAnimated:NO
+           animateThumbAfterMove:NO
+                   previousValue:previousValue
+                      completion:NULL];
+}
+
+- (void)setMaximumValue:(CGFloat)maximumValue {
+  _maximumValue = maximumValue;
+  CGFloat previousValue = _value;
+  if (_value > _maximumValue) {
+    _value = _maximumValue;
+  }
+  if (_minimumValue > _maximumValue) {
+    _minimumValue = _maximumValue;
+  }
+  [self updateThumbTrackAnimated:NO
+           animateThumbAfterMove:NO
+                   previousValue:previousValue
+                      completion:NULL];
+}
+
+- (void)setTrackEndsAreRounded:(BOOL)trackEndsAreRounded {
+  _trackEndsAreRounded = trackEndsAreRounded;
+
+  if (_trackEndsAreRounded) {
+    _trackView.layer.cornerRadius = _trackHeight / 2;
+  } else {
+    _trackView.layer.cornerRadius = 0;
+  }
+}
+
+- (void)setPanningAllowedOnEntireControl:(BOOL)panningAllowedOnEntireControl {
+  if (_panningAllowedOnEntireControl != panningAllowedOnEntireControl) {
+    _panningAllowedOnEntireControl = panningAllowedOnEntireControl;
+    [self updateDummyPanRecognizerTarget];
+  }
+}
+
+- (void)setFilledTrackAnchorValue:(CGFloat)filledTrackAnchorValue {
+  _filledTrackAnchorValue = MAX(_minimumValue, MIN(filledTrackAnchorValue, _maximumValue));
+  [self setNeedsLayout];
+}
+
+- (void)setValue:(CGFloat)value {
+  [self setValue:value animated:NO];
+}
+
+- (void)setValue:(CGFloat)value animated:(BOOL)animated {
+  [self setValue:value
+                   animated:animated
+      animateThumbAfterMove:animated
+              userGenerated:NO
+                 completion:NULL];
+}
+
+- (void)setValue:(CGFloat)value
+                 animated:(BOOL)animated
+    animateThumbAfterMove:(BOOL)animateThumbAfterMove
+            userGenerated:(BOOL)userGenerated
+               completion:(void (^)())completion {
+  CGFloat previousValue = _value;
+  CGFloat newValue = MAX(_minimumValue, MIN(value, _maximumValue));
+  newValue = [self closestValueToTargetValue:newValue];
+  if (newValue != previousValue &&
+      [_delegate respondsToSelector:@selector(thumbTrack:willJumpToValue:)]) {
+    [self.delegate thumbTrack:self willJumpToValue:newValue];
+  }
+  _value = newValue;
+
+  if (!userGenerated) {
+    _lastDispatchedValue = _value;
+  }
+
+  if (_value != previousValue) {
+    [self interruptAnimation];
+    [self updateThumbTrackAnimated:animated
+             animateThumbAfterMove:animateThumbAfterMove
+                     previousValue:previousValue
+                        completion:completion];
+  }
+}
+
+- (void)setNumDiscreteValues:(NSUInteger)numDiscreteValues {
+  _numDiscreteValues = numDiscreteValues;
+  _discreteDots.numDiscreteDots = numDiscreteValues;
+  [self setValue:_value];
+}
+
+- (void)setThumbRadius:(CGFloat)thumbRadius {
+  _thumbRadius = thumbRadius;
+  [self setDisplayThumbRadius:_thumbRadius];
+}
+
+- (void)setDisplayThumbRadius:(CGFloat)thumbRadius {
+  _thumbView.cornerRadius = thumbRadius;
+  CGPoint thumbCenter = _thumbView.center;
+  _thumbView.frame = CGRectMake(thumbCenter.x - thumbRadius, thumbCenter.y - thumbRadius,
+                                2 * thumbRadius, 2 * thumbRadius);
+}
+
+- (CGFloat)thumbMaxRippleRadius {
+  return _touchController.defaultInkView.maxRippleRadius;
+}
+
+- (void)setThumbMaxRippleRadius:(CGFloat)thumbMaxRippleRadius {
+  _touchController.defaultInkView.maxRippleRadius = thumbMaxRippleRadius;
+}
+
+- (void)setIcon:(nullable UIImage *)icon {
+  [_thumbView setIcon:icon];
+}
+
+- (void)setEnabled:(BOOL)enabled {
+  [super setEnabled:enabled];
+  if (enabled) {
+    [self setPrimaryColor:_primaryColor];
+  }
+  [self setNeedsLayout];
+}
+
+#pragma mark - MDCInkTouchControllerDelegate
+
+- (BOOL)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+    shouldProcessInkTouchesAtTouchLocation:(CGPoint)location {
+  return _shouldDisplayInk;
+}
+
+#pragma mark - Animation helpers
+
+- (CAMediaTimingFunction *)timingFunctionFromUIViewAnimationOptions:
+        (UIViewAnimationOptions)options {
+  NSString *name;
+
+  // It's important to check these in this order, due to their actual values specified in UIView.h:
+  // UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // default
+  // UIViewAnimationOptionCurveEaseIn               = 1 << 16,
+  // UIViewAnimationOptionCurveEaseOut              = 2 << 16,
+  // UIViewAnimationOptionCurveLinear               = 3 << 16,
+  if ((options & UIViewAnimationOptionCurveLinear) == UIViewAnimationOptionCurveLinear) {
+    name = kCAMediaTimingFunctionEaseIn;
+  } else if ((options & UIViewAnimationOptionCurveEaseIn) == UIViewAnimationOptionCurveEaseIn) {
+    name = kCAMediaTimingFunctionEaseIn;
+  } else if ((options & UIViewAnimationOptionCurveEaseOut) == UIViewAnimationOptionCurveEaseOut) {
+    name = kCAMediaTimingFunctionEaseOut;
+  } else {
+    name = kCAMediaTimingFunctionEaseInEaseOut;
+  }
+
+  return [CAMediaTimingFunction functionWithName:name];
+}
+
+- (void)interruptAnimation {
+  if (_thumbView.layer.presentationLayer) {
+    _thumbView.layer.position = [(CALayer *)_thumbView.layer.presentationLayer position];
+    _valueLabel.layer.position = [(CALayer *)_valueLabel.layer.presentationLayer position];
+  }
+  [_thumbView.layer removeAllAnimations];
+  [_trackView.layer removeAllAnimations];
+  [_valueLabel.layer removeAllAnimations];
+  [_trackOnLayer removeAllAnimations];
+}
+
+#pragma mark - Layout and animation
+
+/**
+ Updates the state of the thumb track. First updates the views with properties that should change
+ before the animation. Then performs the main update block, which is animated or not as specified by
+ the `animated` parameter. After this completes, the secondary animation kicks in, again
+ animated or not as specified by `animateThumbAfterMove`. After this completes, the `completion`
+ handler is run.
+ */
+- (void)updateThumbTrackAnimated:(BOOL)animated
+           animateThumbAfterMove:(BOOL)animateThumbAfterMove
+                   previousValue:(CGFloat)previousValue
+                      completion:(void (^)())completion {
+  [self updateViewsNoAnimation];
+
+  UIViewAnimationOptions baseAnimationOptions =
+      UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction;
+  // Note that UIViewAnimationOptionCurveEaseInOut == 0, so by not specifying it, these options
+  // default to animating with Ease in / Ease out
+
+  if (animated) {
+    // UIView animateWithDuration:delay:options:animations: takes a different block signature.
+    void (^animationCompletion)(BOOL) = ^void(BOOL finished) {
+      if (!finished) {
+        // If we were interrupted, we shoudldn't complete the second animation.
+        return;
+      }
+
+      // Do secondary animation and return.
+      [self updateThumbAfterMoveAnimated:animateThumbAfterMove
+                                 options:baseAnimationOptions
+                              completion:completion];
+    };
+
+    BOOL crossesAnchor =
+        (previousValue < _filledTrackAnchorValue && _filledTrackAnchorValue < _value) ||
+        (_value < _filledTrackAnchorValue && _filledTrackAnchorValue < previousValue);
+    if (crossesAnchor) {
+      CGFloat currentValue = _value;
+      CGFloat animationDurationToAnchor =
+          (Fabs(previousValue - _filledTrackAnchorValue) / Fabs(previousValue - currentValue)) *
+          kAnimationDuration;
+      void (^afterCrossingAnchorAnimation)(BOOL) = ^void(BOOL finished) {
+        UIViewAnimationOptions options = baseAnimationOptions | UIViewAnimationOptionCurveEaseOut;
+        [UIView animateWithDuration:(kAnimationDuration - animationDurationToAnchor)
+                              delay:0.0f
+                            options:options
+                         animations:^{
+                           [self updateViewsMainIsAnimated:animated
+                                              withDuration:(kAnimationDuration -
+                                                            animationDurationToAnchor)
+                                          animationOptions:options];
+                         }
+                         completion:animationCompletion];
+      };
+      UIViewAnimationOptions options = baseAnimationOptions | UIViewAnimationOptionCurveEaseIn;
+      [UIView animateWithDuration:animationDurationToAnchor
+                            delay:0.0f
+                          options:options
+                       animations:^{
+                         _value = _filledTrackAnchorValue;
+                         [self updateViewsMainIsAnimated:animated
+                                            withDuration:animationDurationToAnchor
+                                        animationOptions:options];
+                         _value = currentValue;
+                       }
+                       completion:afterCrossingAnchorAnimation];
+    } else {
+      [UIView animateWithDuration:kAnimationDuration
+                            delay:0.0f
+                          options:baseAnimationOptions
+                       animations:^{
+                         [self updateViewsMainIsAnimated:animated
+                                            withDuration:kAnimationDuration
+                                        animationOptions:baseAnimationOptions];
+                       }
+                       completion:animationCompletion];
+    }
+  } else {
+    [self updateViewsMainIsAnimated:animated
+                       withDuration:0.0f
+                   animationOptions:baseAnimationOptions];
+    [self updateThumbAfterMoveAnimated:animateThumbAfterMove
+                               options:baseAnimationOptions
+                            completion:completion];
+  }
+}
+
+- (void)updateThumbAfterMoveAnimated:(BOOL)animated
+                             options:(UIViewAnimationOptions)animationOptions
+                          completion:(void (^)())completion {
+  if (animated) {
+    [UIView animateWithDuration:kThumbChangeAnimationDuration
+        delay:0.0f
+        options:animationOptions
+        animations:^{
+          [self updateViewsForThumbAfterMoveIsAnimated:animated
+                                          withDuration:kThumbChangeAnimationDuration];
+        }
+        completion:^void(BOOL _) {
+          if (completion) {
+            completion();
+          }
+        }];
+  } else {
+    [self updateViewsForThumbAfterMoveIsAnimated:animated withDuration:0.0f];
+
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+/**
+ Updates the display of the ThumbTrack with properties we want to appear instantly, before the
+ animated properties are animated.
+ */
+- (void)updateViewsNoAnimation {
+  // If not enabled, adjust thumbView accordingly
+  if (self.enabled) {
+    // Set thumb color if needed. Note that setting color to hollow start state happes in secondary
+    // animation block (-updateViewsSecondaryAnimated:withDuration:).
+    if (!_thumbIsHollowAtStart || ![self isValueAtMinimum]) {
+      [self updateTrackMask];
+
+      _thumbView.backgroundColor = _thumbOnColor;
+      _thumbView.layer.borderColor = _thumbOnColor.CGColor;
+    }
+  } else {
+    _thumbView.backgroundColor = _thumbDisabledColor;
+    _thumbView.layer.borderColor = _clearColor.CGColor;
+
+    if (_thumbIsSmallerWhenDisabled) {
+      [self setDisplayThumbRadius:_thumbRadius - _trackHeight];
+    }
+  }
+}
+
+/**
+ Updates the properties of the ThumbTrack that are animated in the main animation body. May be
+ called from within a UIView animation block.
+ */
+- (void)updateViewsMainIsAnimated:(BOOL)animated
+                     withDuration:(NSTimeInterval)duration
+                 animationOptions:(UIViewAnimationOptions)animationOptions {
+  // Move thumb position.
+  CGPoint point = [self thumbPositionForValue:_value];
+  _thumbView.center = point;
+
+  // Re-draw track position
+  if (_trackEndsAreInset) {
+    _trackView.frame = CGRectMake(_thumbRadius, CGRectGetMidY(self.bounds) - (_trackHeight / 2),
+                                  CGRectGetWidth(self.bounds) - (_thumbRadius * 2), _trackHeight);
+  } else {
+    _trackView.frame = CGRectMake(0, CGRectGetMidY(self.bounds) - (_trackHeight / 2),
+                                  CGRectGetWidth(self.bounds), _trackHeight);
+  }
+
+  // Make sure discrete dots match up
+  _discreteDots.frame = [_trackView bounds];
+
+  // Make sure Numeric Value Label matches up
+  if (_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 1) {
+    // Note that "center" here doesn't refer to the actual center, but rather the anchor point,
+    // which is re-defined to be slightly below the bottom of the label
+    _valueLabel.center = [self numericValueLabelPositionForValue:_value];
+    _valueLabel.backgroundColor = _trackOnColor;
+    _valueLabel.textColor = [UIColor whiteColor];
+    if ([_delegate respondsToSelector:@selector(thumbTrack:stringForValue:)]) {
+      _valueLabel.text = [_delegate thumbTrack:self stringForValue:_value];
+    }
+  }
+
+  // Update colors, etc.
+  if (self.enabled) {
+    _trackView.backgroundColor = _trackOffColor;
+    _trackOnLayer.backgroundColor = _trackOnColor.CGColor;
+
+    CGFloat anchorXValue = [self trackPositionForValue:_filledTrackAnchorValue].x;
+    CGFloat currentXValue = [self trackPositionForValue:_value].x;
+
+    CGFloat trackOnXValue = MIN(currentXValue, anchorXValue);
+    if (_trackEndsAreInset) {
+      // Account for the fact that the layer's coords are relative to the frame of the track.
+      trackOnXValue -= _thumbRadius;
+    }
+
+    // We have to use a CATransaction here because CALayer.frame is only animatable using this
+    // method, not the UIVIew block-based animation that the rest of this method uses. We use
+    // the timing function and duration passed in in order to match with the other animations.
+    [CATransaction begin];
+    [CATransaction
+        setAnimationTimingFunction:[self
+                                       timingFunctionFromUIViewAnimationOptions:animationOptions]];
+    [CATransaction setAnimationDuration:duration];
+    _trackOnLayer.frame =
+        CGRectMake(trackOnXValue, 0, Fabs(currentXValue - anchorXValue), _trackHeight);
+    [CATransaction commit];
+  } else {
+    // Set background colors for disabled state.
+    _trackView.backgroundColor = _trackDisabledColor;
+    _trackOnLayer.backgroundColor = _clearColor.CGColor;
+
+    // Update mask again, since thumb may have moved
+    [self updateTrackMask];
+  }
+}
+
+/**
+ Updates the properties of the ThumbTrack that animate after the thumb move has finished, i.e. after
+ the main animation block completes. May be called from within a UIView animation block.
+ */
+- (void)updateViewsForThumbAfterMoveIsAnimated:(BOOL)animated
+                                  withDuration:(NSTimeInterval)duration {
+  if (_shouldDisplayDiscreteDots) {
+    if (self.enabled && _isDraggingThumb) {
+      _discreteDots.alpha = 1.0;
+    } else {
+      _discreteDots.alpha = 0.0;
+    }
+  }
+
+  if (_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 1) {
+    if (self.enabled && _isDraggingThumb) {
+      _valueLabel.transform = CGAffineTransformIdentity;
+    } else {
+      _valueLabel.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
+    }
+  }
+
+  if (!self.enabled) {
+    // The following changes only matter if the track is enabled.
+    return;
+  }
+
+  if ([self isValueAtMinimum] && _thumbIsHollowAtStart) {
+    [self updateTrackMask];
+
+    _thumbView.backgroundColor = _clearColor;
+    _thumbView.layer.borderColor = _trackOffColor.CGColor;
+  }
+
+  CGFloat radius;
+  if (_isDraggingThumb) {
+    if (_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 1) {
+      radius = 0;
+    } else {
+      radius = _thumbRadius + _trackHeight;
+    }
+  } else {
+    radius = _thumbRadius;
+  }
+
+  if (radius == _thumbView.layer.cornerRadius || !_thumbGrowsWhenDragging) {
+    // No need to change anything
+    return;
+  }
+
+  if (animated) {
+    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
+    anim.timingFunction =
+        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+    anim.fromValue = [NSNumber numberWithDouble:_thumbView.layer.cornerRadius];
+    anim.toValue = [NSNumber numberWithDouble:radius];
+    anim.duration = duration;
+    anim.delegate = self;
+    anim.removedOnCompletion = NO;  // We'll remove it ourselves as the delegate
+    [_thumbView.layer addAnimation:anim forKey:anim.keyPath];
+  }
+  [self setDisplayThumbRadius:radius];  // Updates frame and corner radius
+
+  [self updateTrackMask];
+}
+
+// Used to make sure we update the mask after animating the thumb growing or shrinking. Specifically
+// in the case where the thumb is at the start and hollow, forgetting to update could leave the mask
+// in a strange visual state.
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
+  if (anim == [_thumbView.layer animationForKey:@"cornerRadius"]) {
+    [_thumbView.layer removeAllAnimations];
+    [self updateTrackMask];
+  }
+}
+
+- (void)updateTrackMask {
+  // Adding 1pt to the top and bottom is necessary to account for the behavior of CAShapeLayer,
+  // which according Apple's documentation "may favor speed over accuracy" when rasterizing.
+  // https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CAShapeLayer_class
+  // This means that its rasterization sometimes doesn't line up with the UIView that it's masking,
+  // particularly when that view's edges fall on a subpixel. Adding the extra pt on the top and
+  // bottom accounts for this case here, and ensures that none of the _trackView appears where it
+  // isn't supposed to.
+  // This fixes https://github.com/material-components/material-components-ios/issues/566 for all
+  // orientations.
+  CGRect maskFrame = CGRectMake(0, -1, CGRectGetWidth(self.bounds), _trackHeight + 2);
+
+  CGMutablePathRef path = CGPathCreateMutable();
+  CGPathAddRect(path, NULL, maskFrame);
+
+  CGFloat radius = _thumbView.layer.cornerRadius;
+  if (_thumbView.layer.presentationLayer != NULL) {
+    // If we're animating (growing or shrinking) lean on the side of the smaller radius, to prevent
+    // a gap from appearing between the thumb and the track in the intermediate frames.
+    radius = MIN(((CALayer *)_thumbView.layer.presentationLayer).cornerRadius, radius);
+  }
+  radius = MAX(radius, _thumbRadius);
+
+  if ((!self.enabled && _disabledTrackHasThumbGaps) ||
+      ([self isValueAtMinimum] && _thumbIsHollowAtStart &&
+       !(_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 0 && _isDraggingThumb))) {
+    // The reason we calculate this explicitly instead of just using _thumbView.frame is because
+    // the thumb view might not be have the exact radius of _thumbRadius, depending on if the track
+    // is disabled or if a user is dragging the thumb.
+    CGRect gapMaskFrame = CGRectMake(_thumbView.center.x - radius, _thumbView.center.y - radius,
+                                     radius * 2, radius * 2);
+    gapMaskFrame = [self convertRect:gapMaskFrame toView:_trackView];
+    CGPathAddRect(path, NULL, gapMaskFrame);
+  }
+
+  _trackMaskLayer.path = path;
+  CGPathRelease(path);
+}
+
+#pragma mark - Interaction Helpers
+
+- (CGPoint)thumbPosition {
+  return _thumbView.center;
+}
+
+- (CGPoint)thumbPositionForValue:(CGFloat)value {
+  CGFloat relValue = [self relativeValueForValue:value];
+  return CGPointMake(_thumbRadius + self.thumbPanRange * relValue, self.frame.size.height / 2);
+}
+
+/**
+ Gives the point on the thumb track that we should set as the "center" of the numeric value label.
+ Keep in mind that this doesn't actually correspond to the geometric center of the label, but rather
+ the anchor point which falls to the bottom of the label. So by setting this point to be on the
+ track we automatically get the property of the numeric value label hovering slightly above the
+ track.
+ */
+- (CGPoint)numericValueLabelPositionForValue:(CGFloat)value {
+  CGFloat relValue = [self relativeValueForValue:value];
+
+  // To account for the discrete dots on the left and right sides
+  CGFloat range = self.thumbPanRange - _trackHeight;
+  return CGPointMake(_thumbRadius + (_trackHeight / 2) + range * relValue,
+                     self.frame.size.height / 2);
+}
+
+- (CGFloat)valueForThumbPosition:(CGPoint)position {
+  CGFloat relValue = (position.x - _thumbRadius) / self.thumbPanRange;
+  relValue = MAX(0, MIN(relValue, 1));
+  // For RTL we invert the value
+  if (self.mdc_effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
+    relValue = 1 - relValue;
+  }
+  return (1 - relValue) * _minimumValue + relValue * _maximumValue;
+}
+
+// Describes where on the track the specified value would fall. Differs from
+// -thumbPositionForValue: because it varies by whether or not the track ends are inset. Note that
+// if the edges are inset, the two values are equivalent, but if not, this point's x value can
+// differ from the thumb's x value by at most _thumbRadius.
+- (CGPoint)trackPositionForValue:(CGFloat)value {
+  if (_trackEndsAreInset) {
+    return [self thumbPositionForValue:value];
+  }
+
+  CGFloat xValue = [self relativeValueForValue:value] * self.bounds.size.width;
+  return CGPointMake(xValue, self.frame.size.height / 2);
+}
+
+- (BOOL)isPointOnThumb:(CGPoint)point {
+  // Note that we let the thumb's draggable area extend beyond its actual view to account for
+  // the imprecise nature of hit targets on device.
+  return DistanceFromPointToPoint(point, _thumbView.center) <= (_thumbRadius * kThumbSlopFactor);
+}
+
+- (BOOL)isValueAtMinimum {
+  return _value == _minimumValue;
+}
+
+- (CGFloat)thumbPanOffset {
+  return _thumbView.frame.origin.x / self.thumbPanRange;
+}
+
+- (CGFloat)thumbPanRange {
+  return self.bounds.size.width - (self.thumbRadius * 2);
+}
+
+- (CGFloat)relativeValueForValue:(CGFloat)value {
+  value = MAX(_minimumValue, MIN(value, _maximumValue));
+  if (CGFloatEqual(_minimumValue, _maximumValue)) {
+    return _minimumValue;
+  }
+  CGFloat relValue = (value - _minimumValue) / Fabs(_minimumValue - _maximumValue);
+  // For RTL we invert the value
+  if (self.mdc_effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
+    relValue = 1 - relValue;
+  }
+  return relValue;
+}
+
+- (CGFloat)closestValueToTargetValue:(CGFloat)targetValue {
+  if (_numDiscreteValues < 2) {
+    return targetValue;
+  }
+  if (CGFloatEqual(_minimumValue, _maximumValue)) {
+    return _minimumValue;
+  }
+
+  CGFloat scaledTargetValue = (targetValue - _minimumValue) / (_maximumValue - _minimumValue);
+  CGFloat snappedValue =
+      Round((_numDiscreteValues - 1) * scaledTargetValue) / (_numDiscreteValues - 1.0f);
+  return (1 - snappedValue) * _minimumValue + snappedValue * _maximumValue;
+}
+
+- (void)updateDummyPanRecognizerTarget {
+  [_dummyPanRecognizer.view removeGestureRecognizer:_dummyPanRecognizer];
+  UIView *panTarget = _panningAllowedOnEntireControl ? self : _thumbView;
+  [panTarget addGestureRecognizer:_dummyPanRecognizer];
+}
+
+#pragma mark - Color Helpers
+
+- (UIColor *)colorInterpolatedFromColor:(UIColor *)fromColor
+                                toColor:(UIColor *)toColor
+                                percent:(CGFloat)percent {
+  // Clamp percent to [0.0, 1.0]
+  percent = MAX(0, percent);
+  percent = MIN(1, percent);
+
+  CGFloat r1, g1, b1, a1;
+  r1 = g1 = b1 = a1 = 1;
+  if (![fromColor getRed:&r1 green:&g1 blue:&b1 alpha:&a1]) {
+    [fromColor getWhite:&r1 alpha:&a1];
+    g1 = b1 = r1;
+  };
+
+  CGFloat r2, g2, b2, a2;
+  r2 = g2 = b2 = a2 = 1;
+  if (![toColor getRed:&r2 green:&g2 blue:&b2 alpha:&a2]) {
+    [toColor getWhite:&r2 alpha:&a2];
+    g2 = b2 = r2;
+  }
+
+  CGFloat rfinal = r1 * (1 - percent) + r2 * percent;
+  CGFloat gfinal = g1 * (1 - percent) + g2 * percent;
+  CGFloat bfinal = b1 * (1 - percent) + b2 * percent;
+  CGFloat afinal = a1 * (1 - percent) + a2 * percent;
+
+  return [UIColor colorWithRed:rfinal green:gfinal blue:bfinal alpha:afinal];
+}
+
+#pragma mark - UIResponder Events
+
+/**
+ We implement our own touch handling here instead of using gesture recognizers. This allows more
+ fine grained control over how the thumb track behaves, including more specific logic over what
+ counts as a tap vs. a drag.
+
+ Note that we must use -touchesBegan:, -touchesMoves:, etc here, rather than the UIControl methods
+ -beginDraggingWithTouch:withEvent:, -continueDraggingWithTouch:withEvent:, etc. This is because
+ with those events, we are forced to disable user interaction on our subviews else the events could
+ be swallowed up by their event handlers and not ours. We can't do this because the we have an ink
+ controller attached to the thumb view, and that needs to receive touch events in order to know when
+ to display ink.
+
+ Using -touchesBegan:, etc. solves this problem because we can handle touches ourselves as well as
+ continue to have them pass through to the contained thumb view. So we get our custom event handling
+ without disabling the ink display, hurray!
+
+ Because we set `multipleTouchEnabled = NO`, the sets of touches in these methods will always be of
+ size 1. For this reason, we can simply call `-anyObject` on the set instead of iterating through
+ every touch.
+ */
+
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  if (!self.enabled || _currentTouch != nil) {
+    return;
+  }
+
+  UITouch *touch = [touches anyObject];
+  CGPoint touchLoc = [[touches anyObject] locationInView:self];
+
+  _currentTouch = touch;
+  _didChangeValueDuringPan = NO;
+
+  _isDraggingThumb = _panningAllowedOnEntireControl || [self isPointOnThumb:touchLoc];
+
+  if (_isDraggingThumb) {
+    // Start panning
+    _panThumbGrabPosition = touchLoc.x - self.thumbPosition.x;
+
+    // Grow the thumb
+    [self updateThumbTrackAnimated:NO
+             animateThumbAfterMove:YES
+                     previousValue:_value
+                        completion:nil];
+  }
+
+  [self sendActionsForControlEvents:UIControlEventTouchDown];
+}
+
+- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  UITouch *touch = [touches anyObject];
+  if (!self.enabled || touch != _currentTouch) {
+    return;
+  }
+
+  if (!_isDraggingThumb) {
+    // The rest is dragging logic
+    return;
+  }
+
+  CGPoint touchLoc = [touch locationInView:self];
+  CGFloat thumbPosition = touchLoc.x - _panThumbGrabPosition;
+  CGFloat previousValue = _value;
+  CGFloat value = [self valueForThumbPosition:CGPointMake(thumbPosition, 0)];
+
+  BOOL shouldAnimate = _numDiscreteValues > 1;
+  [self setValue:value
+                   animated:shouldAnimate
+      animateThumbAfterMove:YES
+              userGenerated:YES
+                 completion:NULL];
+  [self sendContinuousChangeAction];
+
+  if (_value != previousValue) {
+    // We made a move, now this action can't later count as a tap
+    _didChangeValueDuringPan = YES;
+  }
+
+  if ([self pointInside:touchLoc withEvent:nil]) {
+    [self sendActionsForControlEvents:UIControlEventTouchDragInside];
+  } else {
+    [self sendActionsForControlEvents:UIControlEventTouchDragOutside];
+  }
+}
+
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  UITouch *touch = [touches anyObject];
+  if (touch == _currentTouch) {
+    BOOL wasDragging = _isDraggingThumb;
+    _isDraggingThumb = NO;
+    _currentTouch = nil;
+
+    if (wasDragging) {
+      // Shrink the thumb
+      [self updateThumbTrackAnimated:NO
+               animateThumbAfterMove:YES
+                       previousValue:_value
+                          completion:nil];
+    }
+
+    [self sendActionsForControlEvents:UIControlEventTouchCancel];
+
+    if (!_continuousUpdateEvents && wasDragging) {
+      [self sendDiscreteChangeAction];
+    }
+  }
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  UITouch *touch = [touches anyObject];
+  if (!self.enabled || touch != _currentTouch) {
+    return;
+  }
+
+  BOOL wasDragging = _isDraggingThumb;
+  _isDraggingThumb = NO;
+  _currentTouch = nil;
+
+  if (wasDragging) {
+    // Shrink the thumb
+    [self updateThumbTrackAnimated:NO
+             animateThumbAfterMove:YES
+                     previousValue:_value
+                        completion:nil];
+  }
+
+  CGPoint touchLoc = [touch locationInView:self];
+  if ([self pointInside:touchLoc withEvent:nil]) {
+    if (!_didChangeValueDuringPan && (_tapsAllowedOnThumb || ![self isPointOnThumb:touchLoc])) {
+      // Treat it like a tap
+      if (![_delegate respondsToSelector:@selector(thumbTrack:shouldJumpToValue:)] ||
+          [self.delegate thumbTrack:self shouldJumpToValue:[self valueForThumbPosition:touchLoc]]) {
+        [self setValueFromThumbPosition:touchLoc isTap:YES];
+      }
+    }
+
+    [self sendActionsForControlEvents:UIControlEventTouchUpInside];
+  } else {
+    [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
+  }
+
+  if (!_continuousUpdateEvents && wasDragging) {
+    [self sendDiscreteChangeAction];
+  }
+}
+
+- (void)setValueFromThumbPosition:(CGPoint)position isTap:(BOOL)isTap {
+  // Having two discrete values is a special case (e.g. the switch) in which any tap just flips the
+  // value between the two discrete values, irrespective of the tap location.
+  CGFloat value;
+  if (isTap && _numDiscreteValues == 2) {
+    // If we are at the maximum then make it the minimum:
+    // For switch like thumb tracks where there is only 2 values we ignore the position of the tap
+    // and toggle between the minimum and maximum values.
+    value = _value < CGFloatEqual(_value, _minimumValue) ? _maximumValue : _minimumValue;
+  } else {
+    value = [self valueForThumbPosition:position];
+  }
+  __weak MDCThumbTrack *weakSelf = self;
+  if ([_delegate respondsToSelector:@selector(thumbTrack:willAnimateToValue:)]) {
+    [_delegate thumbTrack:self willAnimateToValue:value];
+  }
+
+  if (isTap && _numDiscreteValues > 1 && _shouldDisplayDiscreteDots) {
+    _discreteDots.alpha = 1.0;
+  }
+
+  [self setValue:value
+                   animated:YES
+      animateThumbAfterMove:YES
+              userGenerated:YES
+                 completion:^{
+                   MDCThumbTrack *strongSelf = weakSelf;
+                   [strongSelf sendDiscreteChangeAction];
+                   if (strongSelf &&
+                       [strongSelf->_delegate
+                           respondsToSelector:@selector(thumbTrack:didAnimateToValue:)]) {
+                     [strongSelf->_delegate thumbTrack:weakSelf didAnimateToValue:value];
+                   }
+                 }];
+}
+
+#pragma mark - Events
+
+- (void)sendContinuousChangeAction {
+  if (_continuousUpdateEvents && _value != _lastDispatchedValue) {
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    _lastDispatchedValue = _value;
+  }
+}
+
+- (void)sendDiscreteChangeAction {
+  if (_value != _lastDispatchedValue) {
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    _lastDispatchedValue = _value;
+  }
+}
+
+#pragma mark - UIControl methods
+
+- (BOOL)isTracking {
+  return _isDraggingThumb;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
new file mode 100644
index 0000000..2a3840c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCThumbView : UIView
+
+/** A boolean value indicating whether the thumb view has a shadow. */
+@property(nonatomic, assign) BOOL hasShadow;
+
+/** The border width of the thumbview layer. */
+@property(nonatomic, assign) CGFloat borderWidth;
+
+/** The corner radius of the thumbview layer. */
+@property(nonatomic, assign) CGFloat cornerRadius;
+
+/** Set the @c icon shown on the thumb. */
+- (void)setIcon:(nullable UIImage *)icon;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.m
new file mode 100644
index 0000000..1720f1c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.m
@@ -0,0 +1,103 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCThumbView.h"
+
+#import "MaterialShadowElevations.h"
+#import "MaterialShadowLayer.h"
+
+@interface MDCThumbView ()
+
+@property(nonatomic, strong) UIImageView *iconView;
+
+@end
+
+@implementation MDCThumbView
+
+static const CGFloat kMinTouchSize = 48;
+
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    // TODO: Remove once MDCShadowLayer is rasterized by default.
+    self.layer.shouldRasterize = YES;
+    self.layer.rasterizationScale = [UIScreen mainScreen].scale;
+  }
+  return self;
+}
+
+- (void)setBorderWidth:(CGFloat)borderWidth {
+  _borderWidth = borderWidth;
+  self.layer.borderWidth = borderWidth;
+}
+
+- (void)setCornerRadius:(CGFloat)cornerRadius {
+  _cornerRadius = cornerRadius;
+  self.layer.cornerRadius = cornerRadius;
+  [self setNeedsLayout];
+}
+
+- (void)setHasShadow:(BOOL)hasShadow {
+  _hasShadow = hasShadow;
+  [[self shadowLayer]
+      setElevation:(hasShadow) ? MDCShadowElevationCardResting : MDCShadowElevationNone];
+}
+
+- (MDCShadowLayer *)shadowLayer {
+  return (MDCShadowLayer *)self.layer;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  self.layer.shadowPath =
+      [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:_cornerRadius].CGPath;
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  CGFloat dx = MIN(0, _cornerRadius - kMinTouchSize / 2);
+  // Converts point to presentation layer coordinate system so gesture will land on the right visual
+  // position. Assuming superview is not animated.
+  if (self.layer.presentationLayer) {
+    point = [(CALayer *)self.layer.presentationLayer convertPoint:point
+                                                        fromLayer:self.layer.modelLayer];
+  }
+  CGRect rect = CGRectInset(self.bounds, dx, dx);
+  return CGRectContainsPoint(rect, point);
+}
+
+- (void)setIcon:(nullable UIImage *)icon {
+  if (icon == _iconView.image || [icon isEqual:_iconView.image])
+    return;
+
+  if (_iconView) {
+    [_iconView removeFromSuperview];
+    _iconView = nil;
+  }
+  if (icon) {
+    _iconView = [[UIImageView alloc] initWithImage:icon];
+    [self addSubview:_iconView];
+    // Calculate the inner square of the thumbs circle.
+    CGFloat sideLength = (CGFloat)sin(45.0 / 180.0 * M_PI) * _cornerRadius * 2;
+    CGFloat topLeft = _cornerRadius - (sideLength / 2);
+    _iconView.frame = CGRectMake(topLeft, topLeft, sideLength, sideLength);
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
new file mode 100644
index 0000000..b09f1bd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCThumbTrack.h"
+#import "MDCThumbView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/project.pbxproj b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5e30b70
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/project.pbxproj
@@ -0,0 +1,2757 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		02B3889D3E871468F88E5DBE7E9C5E21 /* MDCButton.m in Sources */ = {isa = PBXBuildFile; fileRef = BE257A301C797B8D3C24053EFEF0DB5A /* MDCButton.m */; };
+		04EC8CBF409C803BF749B2F9E8E38E0B /* MaterialTabs.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C1F25227166DC67A877DFCA5594F74B /* MaterialTabs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		051B40934BCB60C81579E65ED35CD7A0 /* ic_reorder@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 87D692B9AD07C602ED145B594F3FF7D9 /* ic_reorder@3x.png */; };
+		05E5A4ADDD5472838AAB9FFF46AF2137 /* MDCIcons.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF39A7F429701947B09DCBEB4A07F05 /* MDCIcons.m */; };
+		05FF239C8670278A10D7BD58DD5260E1 /* UIView+MDCTimingFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 7941C852DB02A5C5D4BE708004028A52 /* UIView+MDCTimingFunction.m */; };
+		0617544187F62EC4C98A6BEE1428C5D6 /* MaterialSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = 60852389E40D9EF0F70B7BF97E7B998D /* MaterialSlider.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		07484E38806037944055D0BF76806FA4 /* MDCPageControlIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = B56398DA0E3930C91FF640F861706411 /* MDCPageControlIndicator.m */; };
+		091A8578BC600F0579CD4CB9A119DCD8 /* ic_radio_button_unchecked@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 62057440CF0144D03DEB925C378645B7 /* ic_radio_button_unchecked@3x.png */; };
+		0B0FE5E1667FA17C1026EF1F92C1A63F /* MDCFlexibleHeaderContainerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 621F64FAC8A6CDF22ADF8271D04409C6 /* MDCFlexibleHeaderContainerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		0CD124B11142B650BF877996F9F0E07A /* MDCProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C914D35C46E85C26AA1E246E17CECE5 /* MDCProgressView.m */; };
+		0D20BD182D66DBDD7E4D6CB7F77CF9F3 /* MaterialCollectionLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 444B921CA054B6ED8B57713242404400 /* MaterialCollectionLayoutAttributes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		0E3515A7AE66C29F70F654BA2B8EA7BA /* MDCPaletteExpansions.h in Headers */ = {isa = PBXBuildFile; fileRef = C4899C25A4830FCF08B2BB4F8ABC361A /* MDCPaletteExpansions.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		0E47C9B2997E679B24FA498EE2363228 /* MaterialInk.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C21154B03011C9702C295079DCF65E1 /* MaterialInk.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		0EBDEC7917FC21DD3AD7979621EA2307 /* MaterialIcons+ic_arrow_back.m in Sources */ = {isa = PBXBuildFile; fileRef = C830C5EEEAE60B4A9283F0C2F0A02094 /* MaterialIcons+ic_arrow_back.m */; };
+		10B1D8ED7E2CF740C124B7C74CDBB74E /* MDCShadowElevations.m in Sources */ = {isa = PBXBuildFile; fileRef = CC56C512FD3A98A296C04156DD8DFEC9 /* MDCShadowElevations.m */; };
+		1274CD4A2DD52C98C966921502C57446 /* MDCAppBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CA3D76D548F43BB8F241C55FB9D5656 /* MDCAppBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		140D1BAA0F86861FA7A3A788F41C2DAC /* MDCOverlayObserverOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 16E650750C1D8383CFF76B265B232D54 /* MDCOverlayObserverOverlay.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		14612015079E6E117DED63E2337F4346 /* MaterialIcons+ic_radio_button_unchecked.m in Sources */ = {isa = PBXBuildFile; fileRef = C19F7B7784CFCB4369498613360AA4CB /* MaterialIcons+ic_radio_button_unchecked.m */; };
+		14D517DDB1CB758C5FAA1B5963590CDF /* UIViewController+MaterialDialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D3E3C231B7AE692FCE91C1216645EA3 /* UIViewController+MaterialDialogs.m */; };
+		173E8E625D765B2536A2145C9F528898 /* MaterialShadowElevations.h in Headers */ = {isa = PBXBuildFile; fileRef = 03CE9EF2998E990D7C6C15AC4AEFF20D /* MaterialShadowElevations.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		195B84DD18A2352DA5EDEC2F347F0985 /* MDCPaletteExpansions.m in Sources */ = {isa = PBXBuildFile; fileRef = 67D647688DBDE7C289D22CFAADF4006C /* MDCPaletteExpansions.m */; };
+		1A0003B88CFC06F475A1A7D437E14A27 /* NSArray+MDFUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F9B634EE11CC423F51EE3D659001D14 /* NSArray+MDFUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		1B25CFC33E70C55ADB21117C2E0BC425 /* MDCCollectionViewTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 158DFD17C32FF1158E4896DD754DDC6B /* MDCCollectionViewTextCell.m */; };
+		1C4083843A8D6038A7EAA2DD85FDC174 /* MaterialNavigationBar.h in Headers */ = {isa = PBXBuildFile; fileRef = B73577CD8AEFE5DA6EB995CC8F2C92A7 /* MaterialNavigationBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1D8C9CF5687E222D0C1919213AA0116A /* MDCActivityIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97262CDCD801553DA99ECC7847E39E98 /* MDCActivityIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		203C4032B594FAEFC8C97B3AFB740B1D /* MaterialIcons+ic_info.m in Sources */ = {isa = PBXBuildFile; fileRef = B52A38C1D2775315C12601204EF0524E /* MaterialIcons+ic_info.m */; };
+		218A5004AD1E67EDB82023BF74D6E81D /* MDCOverlayWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = D100E5E7F62D86CE9CCC97B487779DEC /* MDCOverlayWindow.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		24900323EF8B3538F240F4824D3BC843 /* ic_info.png in Resources */ = {isa = PBXBuildFile; fileRef = ACCED250D3351A0D22EEA492436EBE80 /* ic_info.png */; };
+		24CD705DC0032088FFF4C5DF861B0099 /* MDCCollectionViewFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C2D56E186EC25B2AD48EF7EC5DB131 /* MDCCollectionViewFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		25160F444E7DF39397B6D6AFC4F07141 /* MDCFlexibleHeaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE3924624B8CAFC171FD153BBFC8449 /* MDCFlexibleHeaderView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		274573598F1BA1A5256CA32D7689462A /* MDCItemBarStringConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = EDD61B881B917B05AFD9539341F931FD /* MDCItemBarStringConstants.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		28D9B87B12B0ADC9D2B6D6A0DCADC59A /* MDCItemBarAlignment.h in Headers */ = {isa = PBXBuildFile; fileRef = 5677CC19D390C501CCA90EEE390AAE6D /* MDCItemBarAlignment.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		293557804A5EBF6C30C51757363B057B /* MDCSnackbarOverlayView.h in Headers */ = {isa = PBXBuildFile; fileRef = 98BE3C2752BDFA411D8AD43231FF4BCC /* MDCSnackbarOverlayView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		29508FF7916F5B95D6F4F940601AC975 /* MDCProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1119E38AD872AC586FC0B36077CBD452 /* MDCProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		299DD5695C130C8315A9E5FA786ECEAB /* MDCThumbTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E05EB6FB230393D92DC9A1584D7DE50 /* MDCThumbTrack.m */; };
+		2A316D54A91DA5CD37F5231CC2E36978 /* MDCRTL.m in Sources */ = {isa = PBXBuildFile; fileRef = B12139AB4284238F1123EB1E38B230E1 /* MDCRTL.m */; };
+		2AA0B61EABF1D62E39ABB6309B1E93CB /* ic_arrow_back_ios@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 33072B9B16A9B8DAAEDE9D6B449679D2 /* ic_arrow_back_ios@2x.png */; };
+		2AB6A1D688CF1EA0FA6345D547CF931D /* MDCCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 931A07F6E4357134E2E8449CFE5E056E /* MDCCollectionViewFlowLayout.m */; };
+		2DE4DA16A223502BDAE19CB16707EA25 /* ic_check_circle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 38A6CB047FC50FA03168F50ACA26C75B /* ic_check_circle@3x.png */; };
+		2EB0AB22EC4D7AB16E9074A5013DD61C /* MDCThumbView.h in Headers */ = {isa = PBXBuildFile; fileRef = D49CC986145361BA86D40441881692D8 /* MDCThumbView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3019DD7715B81601126A4182935F7DA9 /* MaterialIcons+ic_chevron_right.h in Headers */ = {isa = PBXBuildFile; fileRef = F398E51F9526801442D77BE9612F9C62 /* MaterialIcons+ic_chevron_right.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		303E2CEF1A7B2F29A77E3275D5543798 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */; };
+		3109CBFCFA85CBFA88B4F9FA1F3A16D1 /* MDFTextAccessibility-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 506805F39B4A029793221A2B4824A062 /* MDFTextAccessibility-Bridging-Header.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		34FBD1D58C8BD1C74A876169FB1C15CA /* MDCOverlayWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F9741A397ADB188B83497B96D7D30F5 /* MDCOverlayWindow.m */; };
+		3516A50767315A26E2D625A823474101 /* MaterialProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = C67AC2707AD0B4EC907D6DC6B79DD436 /* MaterialProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3584E7D333209DF162223D26DF0E795F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 409899CE1143F81E8130E2069D59605B /* CoreGraphics.framework */; };
+		35BDD24AF246B8AF9D163CF7005C3A27 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */; };
+		373D05814A0C88B4A0635C5A79FF822B /* MDCInkView.h in Headers */ = {isa = PBXBuildFile; fileRef = EF3D4AABE18C6B0D033BD47108A9156D /* MDCInkView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3998D3B0FBE92AB251C8FE66F7214BF9 /* MDCDialogShadowedView.m in Sources */ = {isa = PBXBuildFile; fileRef = B3AB010097D6D3763F9664DCA9A711EB /* MDCDialogShadowedView.m */; };
+		3A2F4061FB79B93EA5C9B8DA9094EED5 /* MaterialPageControlStrings_table.h in Headers */ = {isa = PBXBuildFile; fileRef = 61C0E2BD02828C530EA209D50ED1B519 /* MaterialPageControlStrings_table.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		3BFFD555516224FB8FF319A087BCA29F /* MDCCollectionInfoBarView.h in Headers */ = {isa = PBXBuildFile; fileRef = 206E1270F7CD7132605A140A429FE475 /* MDCCollectionInfoBarView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		3C9EA68F25AD2F27CE9EA4F444C56FA6 /* ic_chevron_right@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 35901EA242A4B2DE85C2894CC9194C1F /* ic_chevron_right@3x.png */; };
+		3D2B20D0F1D2DF6518A6E97129778190 /* MaterialIcons+ic_chevron_right.m in Sources */ = {isa = PBXBuildFile; fileRef = 654AA469F888FFF8F1CE4AA611FD6B69 /* MaterialIcons+ic_chevron_right.m */; };
+		3D2BB082025D1252507C363E4714C625 /* MaterialDialogs.h in Headers */ = {isa = PBXBuildFile; fileRef = 84467817302E2399BA95D3A909871AFA /* MaterialDialogs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		40FECE7BF976712334BCAD110F2E2051 /* MDCSnackbarManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 25F7B26DAEC96431ECEEC467ADA2CF28 /* MDCSnackbarManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		421078E41926305DF11196F6FB28AD42 /* MDFImageCalculations.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D40D28A97062B1CC07236668DC678AD /* MDFImageCalculations.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		4211DA431C07D51F55AB2D9000F745DB /* ic_arrow_back_ios.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F9E8F936B7FA4CE55F6D4A70EDF478C /* ic_arrow_back_ios.png */; };
+		45002548D32FF2E02C25B5EA30BBCA89 /* ic_info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 029A97895F42B6AB7B7209A3BB20DCA8 /* ic_info@2x.png */; };
+		451AD57BB35CAD3C692F082E93B99BF3 /* MDCCollectionViewTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BF097DEAD72714A366668962C25EC9B /* MDCCollectionViewTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		46CB2D9B298AA3F30C5D42BC04F39E94 /* MDCDialogPresentationController.h in Headers */ = {isa = PBXBuildFile; fileRef = B4CDE57035DA000166BF394A847F6AE2 /* MDCDialogPresentationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4717C3070FA97344C11B65BACF2DDF3C /* MDCCollectionViewEditingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = F14A5EBD4362C79FF3F8A7262FEA2D5B /* MDCCollectionViewEditingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		47C39E63B795E98E36A83BBAC82BF86F /* MaterialCollectionCells.h in Headers */ = {isa = PBXBuildFile; fileRef = A32E50911D7DB6FBC3E4CC4ECCBA1596 /* MaterialCollectionCells.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		48887AC621143DD5D40DBFE5A4E23883 /* MaterialFlexibleHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A7FE223E125A19DB7A772510BF0DEB2 /* MaterialFlexibleHeader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		49C5DD0A16846BF2E4806A9510D2998D /* MDCCollectionViewEditing.h in Headers */ = {isa = PBXBuildFile; fileRef = 752EC7F93FEFE96C89367CBBBB8CB32B /* MDCCollectionViewEditing.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4A9EFA8C13DFEB3A8EF9E7AB8802A3D1 /* MDCHeaderStackView.m in Sources */ = {isa = PBXBuildFile; fileRef = EB1C6A347A3B1B5278B6179E7E7A6C7E /* MDCHeaderStackView.m */; };
+		4AC16280803615380CABD4379AA69D65 /* MDCPaletteNames.h in Headers */ = {isa = PBXBuildFile; fileRef = C078D453FB972AF56047785185938933 /* MDCPaletteNames.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		4C2B4BA673669811FBFF71DF09D6F550 /* MaterialKeyboardWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = F5A94E964BB75BF779F888AE07B3F95C /* MaterialKeyboardWatcher.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4C9D6933282639AAEDFCE3760D663370 /* ic_check@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8917229D3430B609F88F33A180E7063C /* ic_check@2x.png */; };
+		4CBD21241E82CCBA918B0E72FF122FF7 /* ic_arrow_back_ios@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = E95DB580D0830673D87F39AEFDA6EF67 /* ic_arrow_back_ios@3x.png */; };
+		4E8DA5386F2879E77B2E23D0E03C4A9B /* MDCButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 12BE96DCA235623AF7766C60CCFAE1C7 /* MDCButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		5180979CE3EEB34F06466107253D6BB1 /* MDCPaletteNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 98F8E9B6EBCFF521C01B78E4BD1039BD /* MDCPaletteNames.m */; };
+		520EC00A1A0B6B3827DA1F4A7E655C0A /* MDCOverlayAnimationObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 81B08B2D4EB2559D2497B7BB8B215DF3 /* MDCOverlayAnimationObserver.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		52C9FD65F3A7015BF99A651500F2D24C /* MaterialFeatureHighlight.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BEB5E003D1847D87CC74803474B2EF /* MaterialFeatureHighlight.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		53BB396FE274D0FB6F22F98138F0A130 /* MDCCollectionViewStyler.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F5CD9392CF68CA57F883CA8A1DA6BE /* MDCCollectionViewStyler.m */; };
+		54AC6E6DC67C3C418A85ED4983EC39D5 /* ic_chevron_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 7EBAFD93350BF0CF6E8CE57A39A1FA5D /* ic_chevron_right.png */; };
+		54BB836815554D4144AC9824136B8FA9 /* MDCCollectionViewLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6677BBD93E7A4672F9AEA51236310EDF /* MDCCollectionViewLayoutAttributes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		5685049F462A3F846BF0EA56103E153C /* MDCButton+Subclassing.h in Headers */ = {isa = PBXBuildFile; fileRef = F82A46DDAA89ACF53DA3C47CC04971EF /* MDCButton+Subclassing.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		586B689107644E8DFF068DC9A1E927D6 /* MDCSnackbarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F5AE307F5EF407D47769AC7313B9DCA /* MDCSnackbarManager.m */; };
+		58FB26F7D268DF6E49DE32787ECF53B3 /* MDCSnackbarMessageView.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E7B70BE2622CF3F81A0AD037E21C47 /* MDCSnackbarMessageView.m */; };
+		59F2E39B0B51CF3480C2FE2A1B3B0CBA /* ic_radio_button_unchecked.png in Resources */ = {isa = PBXBuildFile; fileRef = 17AAA691CE308745D666AC354DEBD7D1 /* ic_radio_button_unchecked.png */; };
+		5A23C9982240753826D25F3648BE3915 /* MDCCollectionGridBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 683A8B83E16F375FE011E9C5AA0221EE /* MDCCollectionGridBackgroundView.m */; };
+		5C146662CCCE2C78543F8A049B696E66 /* MDCKeyboardWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 06A99FC5FF2D8E635C719D756C525052 /* MDCKeyboardWatcher.m */; };
+		5C20F66911408C3E193E604D21F47677 /* Pods-BuildingBeautifulApps-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8272252EDEB9A0A290A95F34B0A4AEBD /* Pods-BuildingBeautifulApps-dummy.m */; };
+		5CEE44CB5B97F207D902E967A7A28542 /* MDCItemBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CADC6B616AB3936666BDBD42A2705DE6 /* MDCItemBar.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		5E944DEC856408844CB086300051AD03 /* MDCPageControlIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97E9347E0E620A695CA9575055B9A219 /* MDCPageControlIndicator.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		5EBEA9BE9A76AE4BA005EF74784B9739 /* MDCFlatButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F0E678DFEF2B507BAEF2FFD1EF23228 /* MDCFlatButton.m */; };
+		601F6E1396EAC24AD0DF4FC09872F769 /* MDCCollectionInfoBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B1990C768D7EBE9880314C80B89B32 /* MDCCollectionInfoBarView.m */; };
+		610644D23738415ACB073C8B072244BB /* MDCIcons+BundleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = E22DE5B99BE8057D6452C77B5B4A8D39 /* MDCIcons+BundleLoader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		624BA0196EC0BA2C9AAE7D4DE3AB068A /* MDCOverlayObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = D9E396F14C5448B3C15F7B48AFC85B6F /* MDCOverlayObserver.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		63188636F2C3E07CE98221656B929588 /* CAMediaTimingFunction+MDCAnimationTiming.m in Sources */ = {isa = PBXBuildFile; fileRef = 10B9C9D65FA83AC626EFF1C6A94BA402 /* CAMediaTimingFunction+MDCAnimationTiming.m */; };
+		63793D388D09869517A2472AE9C612B3 /* MDCSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8DD7BF09A1359D0C22AD2D99DF9967 /* MDCSlider.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		641CD6C953ADD27482B6CDBCCF24CD6A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F7BDB2580B244756CFA046131516EF2 /* QuartzCore.framework */; };
+		64BD87D6A0EE900D83D40B3A793CB98B /* ic_check.png in Resources */ = {isa = PBXBuildFile; fileRef = 7C5778E1102FA874A7F4F6FFD400C7DE /* ic_check.png */; };
+		65E9B44BBB842E8838653E605F87B3CD /* MDCAlertController.m in Sources */ = {isa = PBXBuildFile; fileRef = C3CE561D11742D1092438C75CE67C1D4 /* MDCAlertController.m */; };
+		677A054DB9F431CF6C98E570A8223F50 /* MDCAppBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D570439942906B139B693491F7E71ED /* MDCAppBar.m */; };
+		67E00C690CF9CFB20C51270B46B6A1CB /* MDCCollectionViewStylingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 041B9228D9CF59ABFD7ACB6A1D468715 /* MDCCollectionViewStylingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		67ED336DA6AA8B8497F1539842808631 /* MDCFontTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B2F589B283B574F2B354D14386BBF8 /* MDCFontTraits.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		68E150F63885364AA7143698177876C6 /* MDCFloatingButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F64F50AD20E83F81710454204053A744 /* MDCFloatingButton.m */; };
+		69CD5189E440D7767EE5B771A9FEE03D /* MDCButtonBar+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D79A92B4599903B71AD908CC7E5B0213 /* MDCButtonBar+Private.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		69EA046EE6873743400E09466C970A14 /* UIFont+MaterialTypographyPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4277E14F56DAC15ABD24D97EDC26ADEA /* UIFont+MaterialTypographyPrivate.m */; };
+		6BA617C860537C13AE7EA0AF05DF96FA /* MDCOverlayObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = E601CD11978BE11A131D16DA1717A354 /* MDCOverlayObserver.m */; };
+		6C84F71A1D807C4CB432B7B933F4FF6F /* MDFTextAccessibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AF4F84748B988E39D513A50701185FC /* MDFTextAccessibility.m */; };
+		6CE23956E33CA9B2981055C2A5541077 /* MDCSnackbarMessageViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 522F0C6B92C308F6D1B7BB497022A769 /* MDCSnackbarMessageViewInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		6E5609D839CCD3390C33DFDEC3502382 /* MDCTabBar.h in Headers */ = {isa = PBXBuildFile; fileRef = BDAF0CDE00CDA3F4B1CE9E7374239490 /* MDCTabBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6FBA9C40C2CC499C9E549022E8CC48A9 /* MDCInkTouchController.h in Headers */ = {isa = PBXBuildFile; fileRef = E47ED49AEF9D2FE77E92679C5569563D /* MDCInkTouchController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6FE4364F0DE10004ECF20D68071F4739 /* MDCActivityIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 45DA800B226D1DE08F69E5BDDC45E203 /* MDCActivityIndicator.m */; };
+		701A7F5C929096A5A4AAD770AA8CC8A1 /* MDCFeatureHighlightView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13923E685C01C84D742BF61E9A51D084 /* MDCFeatureHighlightView.m */; };
+		704742BFFD1D9BAE18AC34F964C43044 /* MDCOverlayObserverOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 523EEB14DB0CEFD241559CCC496E445B /* MDCOverlayObserverOverlay.m */; };
+		71FF2344ED69DD4EC1BD52B6334C79EE /* MDCFeatureHighlightLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3462BC5FFFCC355901DAA536C77A5A /* MDCFeatureHighlightLayer.m */; };
+		723E8EEE2D1B59FC03F6158CCF391D2C /* MDCItemBarStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 2792F28B4CCFEB1DCDCDBB8636947EBC /* MDCItemBarStyle.m */; };
+		7321A0DEBC74D9ED66E36F9A27FF0CCD /* MaterialShadowLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77C440E4189E05E40980CE67AF6A977D /* MaterialShadowLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7339A37AFA0F1A69B86239CE639CC15D /* MaterialRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = E88C708F20439859824CDC2F79216421 /* MaterialRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		73A9FEFF284BE8244A83EE3E68694904 /* MDCSnackbarMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D1C4015B6347137598F264D6387CCA6 /* MDCSnackbarMessage.m */; };
+		73D4A36BAE65B225B1CBC5EE9A9A802A /* ic_radio_button_unchecked@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D3E267E2C78F75A2831346932CF97F /* ic_radio_button_unchecked@2x.png */; };
+		74F5757E7D5A465C730D2AA937BE785C /* MDCItemBarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 01127A0CE1E1F9D661213AD37AC639FC /* MDCItemBarCell.m */; };
+		75701D93C9E6E0E16551378FB6D15322 /* MDCCollectionStringResources.m in Sources */ = {isa = PBXBuildFile; fileRef = 96E1A962597D9C41D8E7513530EBCD7D /* MDCCollectionStringResources.m */; };
+		75CFCE1AB0C85EEC8F68A664771A0847 /* UIImage+MaterialRTL.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EEA3ACEEB4A63D1DF01A8D3F89BC441 /* UIImage+MaterialRTL.m */; };
+		7673B57A3EAC6E8169C83EA5F68B70E4 /* MDCItemBar.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3068591BFE9A9F8D1B79957A573691 /* MDCItemBar.m */; };
+		76FB19E59FB284927075877B825A67A6 /* UIView+MaterialRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D9BC573FF76C294C05D43278D00B4A6 /* UIView+MaterialRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		79B778A18CC8304044870CCF0AF93C92 /* MDCStatusBarShifter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2543C83779FCB7CA6F63B6E23BA22BDB /* MDCStatusBarShifter.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		7A5C50000FFBA08EB5AEB031CB02508A /* MDCThumbView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CCFBA02AEF1EB2D0EA744C7D87ADB76 /* MDCThumbView.m */; };
+		7B1EB360F18CCF386C0AC46F154F0C9B /* MDCOverlayTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D982B7FBF6D8BFF04DFD915F08E13B0 /* MDCOverlayTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7BC8DF38C236F0C73D8CB5F4D9E8DBAA /* MDCPalettes.m in Sources */ = {isa = PBXBuildFile; fileRef = C9588139AB2E41A105B4F278EF0B01F3 /* MDCPalettes.m */; };
+		7BDC8151577B47E72BCB0F299F6654A8 /* MDCCollectionViewStyler.h in Headers */ = {isa = PBXBuildFile; fileRef = CAA1DC1A670B6F673EE517CD53A4EBD1 /* MDCCollectionViewStyler.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		7BF7E68DCF7F91851687A7D393812EC6 /* MaterialThumbTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D11EB1CC12CA81275669C38699DF58A3 /* MaterialThumbTrack.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7F7F0348C4102A49883CD88C86E122CF /* MaterialIcons+ic_check_circle.m in Sources */ = {isa = PBXBuildFile; fileRef = 443C58797FC89C1F0BDC6BDF82DD1913 /* MaterialIcons+ic_check_circle.m */; };
+		7F86C31F4F88FAD41263B8386772014A /* MDCFeatureHighlightLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0F8786C896495252AF8C693705FE27 /* MDCFeatureHighlightLayer.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		7FAA92CCF3CE42E4265CD84238775669 /* UIImage+MaterialRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ECC1D1D41521DED2581889D20C4D8F9 /* UIImage+MaterialRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		81BAF4596ECCF3B2090CCEB24E981C7E /* MDCOverlayObserverTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DB14C9C7FE14E6BF99957813C38B5BA /* MDCOverlayObserverTransition.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		81F752320FBCB9A12535E3AD2602AA27 /* MDCCollectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 58B3FF2F70B1A1974204F2F8931F665B /* MDCCollectionViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8334A8C5BB14AB374900D9A579A65096 /* MDCSlider_Subclassable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14793E6FDAF9C044D6ED8B67E59C7E75 /* MDCSlider_Subclassable.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		83FE983EC6EEC2C7ACAE955FCABFF518 /* MDCButtonBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 4374B11D22F0FCC5866781A5F08A4D38 /* MDCButtonBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		856224A034BF7897D5745C017D6E26BF /* MDCFeatureHighlightAnimationController.m in Sources */ = {isa = PBXBuildFile; fileRef = D2FFA02DCC45D1EDB5D30FB9CEB3B9BD /* MDCFeatureHighlightAnimationController.m */; };
+		86115CB0ADDFA0C2DA2A6C8A2834A7FD /* MaterialIcons+ic_check_circle.h in Headers */ = {isa = PBXBuildFile; fileRef = 263DB970C3B145399EBC89F15760FB2B /* MaterialIcons+ic_check_circle.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		866CA83566ACE3526AA5FABAB6E08CED /* MDCRaisedButton.h in Headers */ = {isa = PBXBuildFile; fileRef = ABED23378B104A0A25435A6674F29FF5 /* MDCRaisedButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		86ABC77AAAF3BB0E73978E7FD7B371AD /* MDCFontTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = DC384A83912E8C440C7ED70B794A89D2 /* MDCFontTraits.m */; };
+		86CCCDEFFA251A9AB150EDB92E0BDCE4 /* UIFontDescriptor+MaterialTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E5285A7050BE78F06AD6EC2E4BF1A2F /* UIFontDescriptor+MaterialTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		87A2628E58EECA44CEDADB67AE99D7F7 /* MDCSnackbarOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 01C5E9A263A0FBC63B0B1E0D89013529 /* MDCSnackbarOverlayView.m */; };
+		88D4D6C491D0BB280CD6B6D01BDE39B9 /* MDCItemBarStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = C4F53B72FA10D37719F9CB9924A08CBD /* MDCItemBarStyle.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		8A714C7A8F488D84D189041AB5EA984F /* MDCTypography.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A82FF56648D80F9E61096E9A07B06F6 /* MDCTypography.m */; };
+		8B0BD0DC00C8B39EABBBA502C3CC424B /* MaterialOverlayWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = F600563B48E50DAC2BB8C3B23D131DA2 /* MaterialOverlayWindow.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8B9D3A9491A4C5894D9BDB45F75C72EE /* MDCFlexibleHeaderContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 536F8F8CBB3D5593CFA4CBFD765F3BED /* MDCFlexibleHeaderContainerViewController.m */; };
+		91A653669E3851452FCFCA0E2A7CB837 /* MDCInkLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = EA980654C37C923AB926DF64E7E02736 /* MDCInkLayer.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		91EB3409BF51AE8448EC825B00CA7EC8 /* MDCCollectionViewEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = 24C7218ECEE1F60B1B720B21514EE621 /* MDCCollectionViewEditor.m */; };
+		93CA3734266496A1F281BDB7565FA671 /* ic_reorder.png in Resources */ = {isa = PBXBuildFile; fileRef = 403CEE2F8B8AFCD9A8ADAD83045448CB /* ic_reorder.png */; };
+		9424985CFBD9108EAB15C67DE617DDD7 /* MaterialApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F9DCB161F252F8BD0F521356180A57 /* MaterialApplication.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		945823B4D8C6E662F1C2CB08D268A088 /* MaterialIcons+ic_check.h in Headers */ = {isa = PBXBuildFile; fileRef = ACD681F6184F424EE2EAF7600B76F289 /* MaterialIcons+ic_check.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		957F0F86EAB556C7CD058DF04A23F216 /* MDCShadowLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = D8966C5049A9875A33A6802C9840E498 /* MDCShadowLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		95DA110166E184835298E627C35F5B5C /* MDCSnackbarMessageView.h in Headers */ = {isa = PBXBuildFile; fileRef = A3991A36920E062C3E82F61204091F73 /* MDCSnackbarMessageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		96232A06DAC31122E30D7D5724150A83 /* MaterialPageControlStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 94B9A402610F5FCAEE60B7D902780413 /* MaterialPageControlStrings.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		978CE8B98451722A7BCB5F8ECF12F4D5 /* ic_chevron_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D5674E7D4BCC946A30114DBF9DB2F6CA /* ic_chevron_right@2x.png */; };
+		97B175A8C54E8AB93F6A1738A2E8AC32 /* MaterialCollectionsStrings_table.h in Headers */ = {isa = PBXBuildFile; fileRef = BBFB15BBA3F7C53B5BDCBDCEFD66700C /* MaterialCollectionsStrings_table.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		97EE80E12A66CFDC2291192A6D690DA1 /* UIFont+MaterialTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = A8D106719F3F199D438233D94FDF43F5 /* UIFont+MaterialTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		983CC3205216C917F8A2D94E439959F7 /* MDCButtonBar.m in Sources */ = {isa = PBXBuildFile; fileRef = FC8CB7864BDCD9DB97A3711AC446E2B0 /* MDCButtonBar.m */; };
+		9847503FD320C722569D661E21EB0B11 /* MDCAppBarContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D2E69B90D1C23D2FBD5EB175B59364 /* MDCAppBarContainerViewController.m */; };
+		984A454523FEF2464DED49EFB46F4D7D /* MDFTextAccessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 40759EC5DB49E090570D13E76C4CDA94 /* MDFTextAccessibility.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		98FFEDEEDB14192496FB90B75B9CFFB3 /* MDCDialogPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = B9F2A6127E6482F1546297FBA86E9E19 /* MDCDialogPresentationController.m */; };
+		9C71ADED3653D657A6F952A77DA208F7 /* MaterialIcons+ic_reorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B8E69C2D115A0FE03A563709E22B4ED /* MaterialIcons+ic_reorder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9C989E66AB86785F2C11FFAC7EBC30A1 /* MaterialIcons+ic_arrow_back.h in Headers */ = {isa = PBXBuildFile; fileRef = 804D865D3D4D4C65731A550B3D8FC9A5 /* MaterialIcons+ic_arrow_back.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9CEE28601C484B8E43252D783AFF7A05 /* MDCInkTouchController.m in Sources */ = {isa = PBXBuildFile; fileRef = FF7A269A35FCA0697B0E5BD94453D3EF /* MDCInkTouchController.m */; };
+		9D6D3B5FFB61DFD3F80B76195E605784 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */; };
+		9F337AC8E4B3FD0244949450C9FA822B /* UIView+MDCTimingFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5894DCB5AAB8B32C781B6279A0FEF8D9 /* UIView+MDCTimingFunction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A08E58F7C109094B2B88D50771692D44 /* MaterialOverlays.h in Headers */ = {isa = PBXBuildFile; fileRef = B5929610276D0E6D8DD3158FF603C0EC /* MaterialOverlays.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A1799A83EA43D62019EFFEE6D1523F79 /* MDCSnackbarMessageInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 03B0B17771C5E17CCA5515AAC7363532 /* MDCSnackbarMessageInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		A1F9E6ACAA85B87A9D8A087F80530FAF /* ic_info@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5EBBA737C7DEFC62CB07A5607401B086 /* ic_info@3x.png */; };
+		A2CEADFD01F6E59D4D792EFC35289A97 /* UIApplication+AppExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C4F931DA815928A8CA82E5513C6246A /* UIApplication+AppExtensions.m */; };
+		A2EE82AB4435B7F2278B816E9928C1AA /* MDCPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = A683F198135D9329FD62063BFB4B0F9B /* MDCPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A339971188CEF5E30398257AA87216D5 /* MaterialAppBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0C383ECBB30F7ADEB6B1EFF274C298 /* MaterialAppBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A53D190E021C5C1186AC498313F5366A /* MDCShadowLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = B6134FFEBB32CC196B45597FC2948611 /* MDCShadowLayer.m */; };
+		A5847C5D55280D73543922B562E3EE76 /* MDCFeatureHighlightAnimationController.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8039BB5A86167E8DCDB72F46D6388B /* MDCFeatureHighlightAnimationController.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		A5CE5EE5A0CB5AC74A082871D0E4D0E2 /* NSArray+MDFUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 7231A93714A109C83065D36604C9451C /* NSArray+MDFUtils.m */; };
+		A6B49525465146B18DECD9B24AD878DE /* MDFColorCalculations.m in Sources */ = {isa = PBXBuildFile; fileRef = 516E307567E6B1C8060A69B31F20108A /* MDFColorCalculations.m */; };
+		AA10E060FCF509E24CEAEE87D2E80949 /* MDCShadowElevations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E855EBFE6A726985077571DB7E89BD5 /* MDCShadowElevations.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		AA6B9D4E09B8642FE07CA11093EFB762 /* MDCSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 2862A3829BA4649EDB04191EB5D64C4B /* MDCSlider.m */; };
+		AB01C09668E3D82190EAE5DC10E07CAA /* UIView+MaterialRTL.m in Sources */ = {isa = PBXBuildFile; fileRef = 90B29DB14670F66061CFB82DDC68AF49 /* UIView+MaterialRTL.m */; };
+		AB8705EA210EDB911167D97874D360FB /* MDFImageCalculations.m in Sources */ = {isa = PBXBuildFile; fileRef = F68D30CBF1457E3E9AE7D3AE92AC18F0 /* MDFImageCalculations.m */; };
+		ABEC063A0D41BC10143B8DACF1B82237 /* ic_arrow_back.png in Resources */ = {isa = PBXBuildFile; fileRef = 15E9398FCB2DA33C5C08533B1716A7CE /* ic_arrow_back.png */; };
+		ADB5ECE6B1779BB7CCB7C3468BADC052 /* MDCFeatureHighlightView.h in Headers */ = {isa = PBXBuildFile; fileRef = 17B8A83C9148D87712E07EDE938E65E0 /* MDCFeatureHighlightView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		AF01D47F2E21218233A1FF787C75EBE2 /* MDCFlatButton.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCF3D3D2FE3A10C4245EF66AE882178 /* MDCFlatButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B15972456A2F74F579179B9FA24B11A2 /* MaterialPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D8330A4B1BF56B9147CC1FE27AFDFCA /* MaterialPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B20E8D99109D62C4F51394FBE9CB4346 /* MDCInkGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = CAC43F65D5D78A89EAC07A697ACC9837 /* MDCInkGestureRecognizer.m */; };
+		B22A6ACFF10775AFE5312ADF4FB00ECC /* UIFont+MaterialTypographyPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E75C79B7D5289097D15A811F188CED2 /* UIFont+MaterialTypographyPrivate.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		B31AC47ADCCE328A838CCDFB76642B4D /* UIApplication+AppExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 95D1CF13299CEF28BCBAA62F927A3D80 /* UIApplication+AppExtensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B6617FDF0F00EEA0091D859D88DDFD44 /* MDCHeaderStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6929889D615189113913408E3D1B9E /* MDCHeaderStackView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B818D6AEBD75B9F9CDC04357F55DF6EF /* UIFont+MaterialTypography.m in Sources */ = {isa = PBXBuildFile; fileRef = E17A7167DE53F6528C656D4979850FBC /* UIFont+MaterialTypography.m */; };
+		B8A8D97688E58A1C843EE96397D81DF9 /* MaterialPalettes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EC4BB63283347849E4A8B02A60CABC4 /* MaterialPalettes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BB463EFA3C52D5DDFFDAB937345C932F /* MDCNumericValueLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = C660FEA28DDB8CB873D9BCE3DA03F6B3 /* MDCNumericValueLabel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BBD17582B2F80BD702EF29C8B0E5D712 /* MaterialIcons+ic_info.h in Headers */ = {isa = PBXBuildFile; fileRef = FD4ED0BAB173C96E24BFAF538C1A0353 /* MaterialIcons+ic_info.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BCFF786BA8B6010F68220F150D77BC30 /* MDCKeyboardWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4C70E576A2623B72B27F812FA19587 /* MDCKeyboardWatcher.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BD37D976E99C4BF895220E803F0CC41D /* MDCCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D1D4C0D37627D761BB16ECB99105E4A0 /* MDCCollectionViewController.m */; };
+		BE43B4DB418BFA444DEE432B7F329C9C /* MDCStatusBarShifter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D86AB797FE0EAA5C5384DF417BF5346 /* MDCStatusBarShifter.m */; };
+		BF4527E139FB205D0EBD8F54FD8AF18D /* MDCTabBarAlignment.h in Headers */ = {isa = PBXBuildFile; fileRef = B9E2AAB8153882A4590062F569A4D595 /* MDCTabBarAlignment.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BF73F5FFED03E771C41544D7E5AF7AB8 /* MaterialCollections.h in Headers */ = {isa = PBXBuildFile; fileRef = 210894774DFDFBA293E2296F2A30C362 /* MaterialCollections.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BF9A53B148F71E2405838165261131E7 /* MDCFlexibleHeaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EAC67B229E26EFB3FEF38B7164183F0 /* MDCFlexibleHeaderViewController.m */; };
+		BFCDBAD98869A1F1A6BBEAF75E86F926 /* MDCOverlayObserverTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 1509DAD755F448EBE08F87224B5BD8D3 /* MDCOverlayObserverTransition.m */; };
+		C1B17B6540AD304C1A39E0A37E19AE2C /* MDCFlexibleHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BE7789CD2EC0A70DE711AC5A1FEF8D /* MDCFlexibleHeaderView.m */; };
+		C1C7F298EA4326DF2C05351A740E1D8F /* MDCInkView.m in Sources */ = {isa = PBXBuildFile; fileRef = FC7FA8E220EACEBE9FB49B6A6B3732E5 /* MDCInkView.m */; };
+		C212207098B33F8B829CE94A3706DB49 /* MDCNumericValueLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E74B45D4E01DE3821E65C8FEC806B60 /* MDCNumericValueLabel.m */; };
+		C2309CF5EBD904E226161D55F14B950A /* MaterialActivityIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7143C04351DADE6FD07918C99C3BF31E /* MaterialActivityIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C3A59E6F295659D872D65BFEB6832A34 /* MDCRaisedButton.m in Sources */ = {isa = PBXBuildFile; fileRef = B77E7CD1098848AED57761E60382667D /* MDCRaisedButton.m */; };
+		C415FCA0E080D6BDAF30C011F5476604 /* MDCCollectionViewLayoutAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 462854769E2CB8F1B329D4392C79AA61 /* MDCCollectionViewLayoutAttributes.m */; };
+		C77D1E2CEA9AC648CCAE66DD64A12E57 /* MDFTextAccessibility-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E961B158FE9954DDD2B6C09E3462883 /* MDFTextAccessibility-dummy.m */; };
+		C7AC330240BBC7E4EB43FE67062A461B /* MDCCollectionStringResources.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C42FCD2D863F783537F7B84C002801 /* MDCCollectionStringResources.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		C95B219DE3270084C28BE6FDDC86F2D5 /* MaterialTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = D1A37A0287C491DFE2089102146664E8 /* MaterialTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CA4EF6FF105C4B45D26CC12A9F8CA011 /* MaterialSnackbar.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C7E38A7B56C28ED6E56D587A376C3B4 /* MaterialSnackbar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CB57A2838CE91AA87493A967057A9F50 /* ic_reorder@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 47BD4FBE1EC6F6C948B7056DFB3EAE4E /* ic_reorder@2x.png */; };
+		CB68DFA2C9FC1A3435236521B0408CEE /* UIViewController+MaterialDialogs.h in Headers */ = {isa = PBXBuildFile; fileRef = E8C4112E03A439A51F0FBD876DA804E5 /* UIViewController+MaterialDialogs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CC4BC92CDE1AA4B8613AB884E75FB2E4 /* MDCTabBarItemAppearance.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FE6A5198039451C28C172BC4168A03A /* MDCTabBarItemAppearance.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CDAFC1E966DB3C899DE01EC81998EE9C /* MDCCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 29BB55A9B6803B9A3A7A064A6E797A79 /* MDCCollectionViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D053587851EF944EAC99AF4152E5BA75 /* MDCCollectionViewEditor.h in Headers */ = {isa = PBXBuildFile; fileRef = F4C0F26237AA99F43F82CD8B6404A8FF /* MDCCollectionViewEditor.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		D07E00458702FE480F21B32777B0F013 /* MaterialAnimationTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = C075A49AEB6D1C36BA22C458FC6A2801 /* MaterialAnimationTiming.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D143DDFD972B30645F3278852EE20F5B /* MaterialIcons+ic_reorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F9391682535FDA07FBB0AB83B6B96E0 /* MaterialIcons+ic_reorder.m */; };
+		D2C9BED43BB4C6FA2D23424759A4EB2F /* MDCOverlayUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DD35DF5F260987C932CF7B25AD8C22C4 /* MDCOverlayUtilities.m */; };
+		D3BC8C16993BC06EF08B9A0B91B81568 /* MDCOverlayAnimationObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = EB110721FC9D3D6E29D13627A35DFD0E /* MDCOverlayAnimationObserver.m */; };
+		D448A87D1BC2FC2702156E6FE048F9BC /* MaterialButtonBar.h in Headers */ = {isa = PBXBuildFile; fileRef = D14A347A944C556F216B967AFCF766C8 /* MaterialButtonBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D4D362E714758EDDEC809019CC26974C /* MDCNavigationBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CCF1F1AE19AF21CE8869CF3A681CC787 /* MDCNavigationBar.m */; };
+		D6BE450D35006B7F2F83EB19CDC1B473 /* UIFontDescriptor+MaterialTypography.m in Sources */ = {isa = PBXBuildFile; fileRef = D7E1DE48A44A60C2AE808B6D69A73683 /* UIFontDescriptor+MaterialTypography.m */; };
+		D6CEB0B38DC1554A3B1956CB6A11D892 /* MDCAlertController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D28C66D16BE7A01B82F7FD890CA7DBC /* MDCAlertController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D72106583CB3A2A6B758B48F27882B40 /* ic_check_circle.png in Resources */ = {isa = PBXBuildFile; fileRef = 11ED6DF86B1C41582FEF6983B868825F /* ic_check_circle.png */; };
+		D846A62610497F25E2B7A537EA12C757 /* MDCSnackbarMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = D20FE85CECC64B86387F4CA60B86C8C6 /* MDCSnackbarMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DACA2B285CD4608DBB73D72910DDCC3B /* MDCOverlayUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C03DAFCD2FB2199D18A24125D772CB7A /* MDCOverlayUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		DB772D2AC10FA285081B0AD22494A408 /* MDCAppBarContainerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA357A2956B620B50A4CAEFE8F1795B /* MDCAppBarContainerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DBAAB720813BBA54AD2126495BDAA7D2 /* MaterialButtons.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B9EBBBC413F2FB5A96D131DC26FFC36 /* MaterialButtons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DBCD145300C030FCA8C9F1D8C624216B /* MDCThumbTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = 86754C059E8434587187015DC770180B /* MDCThumbTrack.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DC0601BB3966D321FDC30D767B44C37F /* MaterialCollectionsStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 56417D84CA78A113438D534EE4FFC54A /* MaterialCollectionsStrings.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		DC2B567C06EA75C2EF988EE491DB370A /* ic_check@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 49A3FB5A7A3C2EEAAF7C7BD7C72CABBD /* ic_check@3x.png */; };
+		DDD7A57F4148DC9FCC8DB0DAF6866E10 /* ic_arrow_back@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = FE7AE3A31ABEA928F10508D5385C37F8 /* ic_arrow_back@3x.png */; };
+		DEEF35853A0974C2FBE1D5F0DD7AE0BC /* MDCFloatingButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E66CD057FB364E80D5BC3D34A00B42FF /* MDCFloatingButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DF0C93BD3E28121899DB290E32612D14 /* MDCPageControlTrackLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8556079BFB00835D898F480913F78F13 /* MDCPageControlTrackLayer.m */; };
+		E09CE6C566DADA7AB46361EF95F0D4A2 /* MDCInkLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E37F8FD7F722E714E0005FB0C96F9A03 /* MDCInkLayer.m */; };
+		E122D135F905A61F2F2BC12B5E752E8B /* MDCFeatureHighlightViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C27D7602B81556831B0A85A92B4E5A3 /* MDCFeatureHighlightViewController.m */; };
+		E16F8810A88826A00D8AEFEA8382FCE0 /* MaterialIcons+ic_check.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AE915AB74A3A3AA3F3F10C11CD9644 /* MaterialIcons+ic_check.m */; };
+		E21FBFA76EC56E1D06EB0CD35550A7F8 /* MDCAppBarButtonBarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24743DF539FCD29F2B8EF21442F2 /* MDCAppBarButtonBarBuilder.m */; };
+		E4282287703DA962B61A39D1B0D8318D /* MDCCollectionGridBackgroundView.h in Headers */ = {isa = PBXBuildFile; fileRef = 79DCB73AD07EBD187AB62F38B93A8863 /* MDCCollectionGridBackgroundView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		E4452C88A27E46E154E525C9840E1494 /* MDCPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BA4F460E41035D7B0B538CDC2752925D /* MDCPageControl.m */; };
+		E5CA64F5137CB5A48B42C9BB8F8EE127 /* MDCTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D62C2A9C95A969E4AA727F1C8C202C /* MDCTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E7D877B60FFD0FF706FDDFD568088D78 /* MaterialIcons+ic_radio_button_unchecked.h in Headers */ = {isa = PBXBuildFile; fileRef = 97FBECBD5EF590F0A8005F8B94E808FF /* MaterialIcons+ic_radio_button_unchecked.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E88C4953B207850482CE8CAF646EB7F6 /* MDCInkGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0750459EFB95F5CE725C61781848452B /* MDCInkGestureRecognizer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E90F58CF316377AF8434201C85BBEA50 /* MaterialIcons.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4B4B293D1D97D44EA76F8E2DD5595E /* MaterialIcons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E98184F9E8FBA7F587905DDDD0944848 /* CAMediaTimingFunction+MDCAnimationTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 74905502A1DF96D7D84E7714A179E9E9 /* CAMediaTimingFunction+MDCAnimationTiming.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E9FEACB48E266BE82E3F563E89A57E55 /* MDCOverlayImplementor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2506F285EFA1CEF8247B19211C38EF23 /* MDCOverlayImplementor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EA9BE12F0B4EC342AE180CDEAC34F8D3 /* ic_arrow_back@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 11DD5A41B2DA0290521D16D24EEC529D /* ic_arrow_back@2x.png */; };
+		EBB65F826BFB14DC485D1126FA924591 /* MDCFeatureHighlightViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 66E845FD6DDDE254DBD69B4B9FBCA3B8 /* MDCFeatureHighlightViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		ED5BBB6CB14C9E62E7C62DCDD69C727E /* MDCDialogTransitionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0040124427B7D454BC17F95E2C95F1B9 /* MDCDialogTransitionController.m */; };
+		F2AF846BCE456A75743C8A76EFE8AC36 /* MDCPalettes.h in Headers */ = {isa = PBXBuildFile; fileRef = 675F4FE5A00141BDF25CA3589A5DEF88 /* MDCPalettes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F428458129C3701B14F25859C60F6C4A /* MDCDialogShadowedView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F5A046B9A9E9CC97A6C6B6A65F22F53 /* MDCDialogShadowedView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		F43265AC32261E3688370C90941A1C51 /* MDCFontTextStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = CD6BFB0EA4919F07C8AD5F586E34376D /* MDCFontTextStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F5A806B7DF97350385E8C0AF48172DB2 /* MDCIcons.h in Headers */ = {isa = PBXBuildFile; fileRef = 8938D8038B0C55A96B4E161C6661FFC0 /* MDCIcons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F7A7869F8EB0BB5B4F817AE17001B79A /* MaterialComponents-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 13FA3054B67E07E3C004F5E26131FFC5 /* MaterialComponents-dummy.m */; };
+		F81CCFD29E38C4B4669681176C4C53C0 /* MDFColorCalculations.h in Headers */ = {isa = PBXBuildFile; fileRef = 10D3AFAF60EB1088403525BA3DF6BD18 /* MDFColorCalculations.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		F89C9B4B75A51557C4194C373983E7DD /* MDCPageControlTrackLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D57CB474D3A2B64257FE6E21F9BD796 /* MDCPageControlTrackLayer.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		F8E7DFFB95518F5BE25C98ACA633E003 /* MDCNavigationBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B79C689F86C1C48EEBFE41AA191DBE /* MDCNavigationBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FA36A066EE5CF084A61B8E5CE4A50928 /* MDCCollectionViewStyling.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FECD187F5A83C12336BB0C55DD75C6F /* MDCCollectionViewStyling.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FAEBD8461B68C2706F8A208E3E596643 /* MDCCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BEBA1206741596666E53A5291AC6C67D /* MDCCollectionViewCell.m */; };
+		FB0210FF9893437C285475B18A6B25D6 /* MaterialHeaderStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = 702CBDDD852DAA7044CE6BCB5AA2D950 /* MaterialHeaderStackView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FB207298B52DA12C580DA33D926A33CE /* ic_check_circle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 20A374DC73FDF4CF43A4454A86E587F6 /* ic_check_circle@2x.png */; };
+		FCC2DBDF248F8D1B0759647AA9AADBC2 /* MDCFlexibleHeaderViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 24A9F1821AD8EA4BF21E13D87EC6F56D /* MDCFlexibleHeaderViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FD7FA96389A0CB49A6673EFF467DDAA3 /* MDCDialogTransitionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0044FD236D22AB00062FFED53D72ECEF /* MDCDialogTransitionController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FDBD2F6421CA1221915E3E4DE3B98C57 /* MDCRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = 935B6D6F1FAB419F6C7B4129E6A0074F /* MDCRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FF37686F3E3AFF2F94C01E95A9CE2911 /* MDCAppBarButtonBarBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FC2C7E47A0EA56BD6295D82B56F6192 /* MDCAppBarButtonBarBuilder.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		FF82D045067B9F2BE69E2C5772EEBAFE /* MDCTabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D8DE150DA0161A584D8CED87D6DF987 /* MDCTabBar.m */; };
+		FFCED3ABEBE505D648ECFB89C3B5A1DE /* MDCItemBarCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E70A12012C34069A15DAAEF725754A18 /* MDCItemBarCell.h */; settings = {ATTRIBUTES = (Project, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		07B01A307DE976243C53CDA94B27C112 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = EEA5B88E1ACE47BDFFC5FD0BBAA2A28C;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_check";
+		};
+		17BCA1B89A11CC355E43FD3BFCD13C12 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2E72C96C2685FC808D51BA6B9AA64CF4;
+			remoteInfo = MDFTextAccessibility;
+		};
+		26A37A36E1641BBB8CE2EDDFC8616CCD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 063B0E6AFAF8DCF585379E4BCB2C7131;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_chevron_right";
+		};
+		39EA7F91F3A8B4BBE7EDA6E436B1836F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = AFFA60B0A14082D99BC69B83E990917F;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_reorder";
+		};
+		77F3D96E9E9ED94700A1F61B82743FBE /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 16E29731A9C9770DCC25F5A8A3ED71FA;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_info";
+		};
+		79BDE4F2A4F44762925D8ABCC802FDBA /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 827B847BE0C5521773C58E7A599CAD8D;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_arrow_back";
+		};
+		8B33909233E6BAB3ED98C8FEB26CD2E6 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 19634FBF87D1F1FA955FF17A6BB5585E;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+		};
+		94AE73493B374CDBE138E1C8D3A177CB /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 26C4686B7C9E9E7E4E77A332481D6196;
+			remoteInfo = MaterialComponents;
+		};
+		B92E0F607A56686D7F93C4B7757E85F5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = C2EC108B302373D03D5F0A9EB5B55787;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_check_circle";
+		};
+		F34B40D121BBEE584389E4FD1349C927 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2E72C96C2685FC808D51BA6B9AA64CF4;
+			remoteInfo = MDFTextAccessibility;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		0040124427B7D454BC17F95E2C95F1B9 /* MDCDialogTransitionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCDialogTransitionController.m; path = components/Dialogs/src/MDCDialogTransitionController.m; sourceTree = "<group>"; };
+		0044FD236D22AB00062FFED53D72ECEF /* MDCDialogTransitionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCDialogTransitionController.h; path = components/Dialogs/src/MDCDialogTransitionController.h; sourceTree = "<group>"; };
+		01127A0CE1E1F9D661213AD37AC639FC /* MDCItemBarCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCItemBarCell.m; path = components/Tabs/src/private/MDCItemBarCell.m; sourceTree = "<group>"; };
+		01B79C689F86C1C48EEBFE41AA191DBE /* MDCNavigationBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCNavigationBar.h; path = components/NavigationBar/src/MDCNavigationBar.h; sourceTree = "<group>"; };
+		01C5E9A263A0FBC63B0B1E0D89013529 /* MDCSnackbarOverlayView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarOverlayView.m; path = components/Snackbar/src/private/MDCSnackbarOverlayView.m; sourceTree = "<group>"; };
+		029A97895F42B6AB7B7209A3BB20DCA8 /* ic_info@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_info@2x.png"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png"; sourceTree = "<group>"; };
+		02AE1C5FFC5FC596ABEC7C98AEF62DD8 /* Pods-BuildingBeautifulApps.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BuildingBeautifulApps.debug.xcconfig"; sourceTree = "<group>"; };
+		03B0B17771C5E17CCA5515AAC7363532 /* MDCSnackbarMessageInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessageInternal.h; path = components/Snackbar/src/private/MDCSnackbarMessageInternal.h; sourceTree = "<group>"; };
+		03B1990C768D7EBE9880314C80B89B32 /* MDCCollectionInfoBarView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionInfoBarView.m; path = components/Collections/src/private/MDCCollectionInfoBarView.m; sourceTree = "<group>"; };
+		03CE9EF2998E990D7C6C15AC4AEFF20D /* MaterialShadowElevations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialShadowElevations.h; path = components/ShadowElevations/src/MaterialShadowElevations.h; sourceTree = "<group>"; };
+		041B9228D9CF59ABFD7ACB6A1D468715 /* MDCCollectionViewStylingDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewStylingDelegate.h; path = components/Collections/src/MDCCollectionViewStylingDelegate.h; sourceTree = "<group>"; };
+		04BA7B9EA003598360273283129FDE9B /* MaterialCollections.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialCollections.bundle; path = components/Collections/src/MaterialCollections.bundle; sourceTree = "<group>"; };
+		06A99FC5FF2D8E635C719D756C525052 /* MDCKeyboardWatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCKeyboardWatcher.m; path = components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m; sourceTree = "<group>"; };
+		0750459EFB95F5CE725C61781848452B /* MDCInkGestureRecognizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkGestureRecognizer.h; path = components/Ink/src/MDCInkGestureRecognizer.h; sourceTree = "<group>"; };
+		07B2F589B283B574F2B354D14386BBF8 /* MDCFontTraits.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFontTraits.h; path = components/Typography/src/private/MDCFontTraits.h; sourceTree = "<group>"; };
+		09A539046C55C092B1882F2B3101A656 /* libMaterialComponents.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMaterialComponents.a; path = libMaterialComponents.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		0C1F25227166DC67A877DFCA5594F74B /* MaterialTabs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialTabs.h; path = components/Tabs/src/MaterialTabs.h; sourceTree = "<group>"; };
+		0EC4BB63283347849E4A8B02A60CABC4 /* MaterialPalettes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPalettes.h; path = components/Palettes/src/MaterialPalettes.h; sourceTree = "<group>"; };
+		0EEA3ACEEB4A63D1DF01A8D3F89BC441 /* UIImage+MaterialRTL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MaterialRTL.m"; path = "components/private/RTL/src/UIImage+MaterialRTL.m"; sourceTree = "<group>"; };
+		0F8DD7BF09A1359D0C22AD2D99DF9967 /* MDCSlider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSlider.h; path = components/Slider/src/MDCSlider.h; sourceTree = "<group>"; };
+		10B9C9D65FA83AC626EFF1C6A94BA402 /* CAMediaTimingFunction+MDCAnimationTiming.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CAMediaTimingFunction+MDCAnimationTiming.m"; path = "components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m"; sourceTree = "<group>"; };
+		10D3AFAF60EB1088403525BA3DF6BD18 /* MDFColorCalculations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDFColorCalculations.h; path = src/private/MDFColorCalculations.h; sourceTree = "<group>"; };
+		1119E38AD872AC586FC0B36077CBD452 /* MDCProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCProgressView.h; path = components/ProgressView/src/MDCProgressView.h; sourceTree = "<group>"; };
+		11DD5A41B2DA0290521D16D24EEC529D /* ic_arrow_back@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back@2x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png"; sourceTree = "<group>"; };
+		11ED6DF86B1C41582FEF6983B868825F /* ic_check_circle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_check_circle.png; path = components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png; sourceTree = "<group>"; };
+		120CFBE565880C2F4F462AAFCEBB37E5 /* Pods-BuildingBeautifulApps.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BuildingBeautifulApps.release.xcconfig"; sourceTree = "<group>"; };
+		12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		12BE96DCA235623AF7766C60CCFAE1C7 /* MDCButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCButton.h; path = components/Buttons/src/MDCButton.h; sourceTree = "<group>"; };
+		12D62C2A9C95A969E4AA727F1C8C202C /* MDCTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTypography.h; path = components/Typography/src/MDCTypography.h; sourceTree = "<group>"; };
+		13923E685C01C84D742BF61E9A51D084 /* MDCFeatureHighlightView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightView.m; path = components/FeatureHighlight/src/private/MDCFeatureHighlightView.m; sourceTree = "<group>"; };
+		13DBFFD40004CC93DF060411AE7CB49F /* MDFTextAccessibility-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MDFTextAccessibility-prefix.pch"; sourceTree = "<group>"; };
+		13FA3054B67E07E3C004F5E26131FFC5 /* MaterialComponents-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MaterialComponents-dummy.m"; sourceTree = "<group>"; };
+		14793E6FDAF9C044D6ED8B67E59C7E75 /* MDCSlider_Subclassable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSlider_Subclassable.h; path = components/Slider/src/private/MDCSlider_Subclassable.h; sourceTree = "<group>"; };
+		1509DAD755F448EBE08F87224B5BD8D3 /* MDCOverlayObserverTransition.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayObserverTransition.m; path = components/private/Overlay/src/private/MDCOverlayObserverTransition.m; sourceTree = "<group>"; };
+		158DFD17C32FF1158E4896DD754DDC6B /* MDCCollectionViewTextCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewTextCell.m; path = components/CollectionCells/src/MDCCollectionViewTextCell.m; sourceTree = "<group>"; };
+		15E9398FCB2DA33C5C08533B1716A7CE /* ic_arrow_back.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_arrow_back.png; path = components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png; sourceTree = "<group>"; };
+		16C2D56E186EC25B2AD48EF7EC5DB131 /* MDCCollectionViewFlowLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewFlowLayout.h; path = components/Collections/src/MDCCollectionViewFlowLayout.h; sourceTree = "<group>"; };
+		16E650750C1D8383CFF76B265B232D54 /* MDCOverlayObserverOverlay.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayObserverOverlay.h; path = components/private/Overlay/src/private/MDCOverlayObserverOverlay.h; sourceTree = "<group>"; };
+		17AAA691CE308745D666AC354DEBD7D1 /* ic_radio_button_unchecked.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_radio_button_unchecked.png; path = components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png; sourceTree = "<group>"; };
+		17B8A83C9148D87712E07EDE938E65E0 /* MDCFeatureHighlightView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightView.h; path = components/FeatureHighlight/src/private/MDCFeatureHighlightView.h; sourceTree = "<group>"; };
+		193A24743DF539FCD29F2B8EF21442F2 /* MDCAppBarButtonBarBuilder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAppBarButtonBarBuilder.m; path = components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m; sourceTree = "<group>"; };
+		1B3462BC5FFFCC355901DAA536C77A5A /* MDCFeatureHighlightLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightLayer.m; path = components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m; sourceTree = "<group>"; };
+		1C21154B03011C9702C295079DCF65E1 /* MaterialInk.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialInk.h; path = components/Ink/src/MaterialInk.h; sourceTree = "<group>"; };
+		1D1C4015B6347137598F264D6387CCA6 /* MDCSnackbarMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarMessage.m; path = components/Snackbar/src/MDCSnackbarMessage.m; sourceTree = "<group>"; };
+		1D28C66D16BE7A01B82F7FD890CA7DBC /* MDCAlertController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAlertController.h; path = components/Dialogs/src/MDCAlertController.h; sourceTree = "<group>"; };
+		1D570439942906B139B693491F7E71ED /* MDCAppBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAppBar.m; path = components/AppBar/src/MDCAppBar.m; sourceTree = "<group>"; };
+		1D9BC573FF76C294C05D43278D00B4A6 /* UIView+MaterialRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MaterialRTL.h"; path = "components/private/RTL/src/UIView+MaterialRTL.h"; sourceTree = "<group>"; };
+		1E74B45D4E01DE3821E65C8FEC806B60 /* MDCNumericValueLabel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCNumericValueLabel.m; path = components/private/ThumbTrack/src/MDCNumericValueLabel.m; sourceTree = "<group>"; };
+		1F0F8786C896495252AF8C693705FE27 /* MDCFeatureHighlightLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightLayer.h; path = components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h; sourceTree = "<group>"; };
+		1FA357A2956B620B50A4CAEFE8F1795B /* MDCAppBarContainerViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAppBarContainerViewController.h; path = components/AppBar/src/MDCAppBarContainerViewController.h; sourceTree = "<group>"; };
+		206683C2791ADADFAC3B8A5DAA2DA22A /* MaterialComponents-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MaterialComponents-prefix.pch"; sourceTree = "<group>"; };
+		206E1270F7CD7132605A140A429FE475 /* MDCCollectionInfoBarView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionInfoBarView.h; path = components/Collections/src/private/MDCCollectionInfoBarView.h; sourceTree = "<group>"; };
+		20A374DC73FDF4CF43A4454A86E587F6 /* ic_check_circle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check_circle@2x.png"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png"; sourceTree = "<group>"; };
+		210894774DFDFBA293E2296F2A30C362 /* MaterialCollections.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollections.h; path = components/Collections/src/MaterialCollections.h; sourceTree = "<group>"; };
+		24A9F1821AD8EA4BF21E13D87EC6F56D /* MDCFlexibleHeaderViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlexibleHeaderViewController.h; path = components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h; sourceTree = "<group>"; };
+		24C7218ECEE1F60B1B720B21514EE621 /* MDCCollectionViewEditor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewEditor.m; path = components/Collections/src/private/MDCCollectionViewEditor.m; sourceTree = "<group>"; };
+		2506F285EFA1CEF8247B19211C38EF23 /* MDCOverlayImplementor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayImplementor.h; path = components/private/Overlay/src/MDCOverlayImplementor.h; sourceTree = "<group>"; };
+		2543C83779FCB7CA6F63B6E23BA22BDB /* MDCStatusBarShifter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCStatusBarShifter.h; path = components/FlexibleHeader/src/private/MDCStatusBarShifter.h; sourceTree = "<group>"; };
+		25F7B26DAEC96431ECEEC467ADA2CF28 /* MDCSnackbarManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarManager.h; path = components/Snackbar/src/MDCSnackbarManager.h; sourceTree = "<group>"; };
+		263DB970C3B145399EBC89F15760FB2B /* MaterialIcons+ic_check_circle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_check_circle.h"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h"; sourceTree = "<group>"; };
+		2792F28B4CCFEB1DCDCDBB8636947EBC /* MDCItemBarStyle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCItemBarStyle.m; path = components/Tabs/src/private/MDCItemBarStyle.m; sourceTree = "<group>"; };
+		2862A3829BA4649EDB04191EB5D64C4B /* MDCSlider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSlider.m; path = components/Slider/src/MDCSlider.m; sourceTree = "<group>"; };
+		29BB55A9B6803B9A3A7A064A6E797A79 /* MDCCollectionViewCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewCell.h; path = components/CollectionCells/src/MDCCollectionViewCell.h; sourceTree = "<group>"; };
+		2D0C383ECBB30F7ADEB6B1EFF274C298 /* MaterialAppBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialAppBar.h; path = components/AppBar/src/MaterialAppBar.h; sourceTree = "<group>"; };
+		2FE6A5198039451C28C172BC4168A03A /* MDCTabBarItemAppearance.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTabBarItemAppearance.h; path = components/Tabs/src/MDCTabBarItemAppearance.h; sourceTree = "<group>"; };
+		33072B9B16A9B8DAAEDE9D6B449679D2 /* ic_arrow_back_ios@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back_ios@2x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png"; sourceTree = "<group>"; };
+		35901EA242A4B2DE85C2894CC9194C1F /* ic_chevron_right@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_chevron_right@3x.png"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png"; sourceTree = "<group>"; };
+		38A6CB047FC50FA03168F50ACA26C75B /* ic_check_circle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check_circle@3x.png"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png"; sourceTree = "<group>"; };
+		3BF39A7F429701947B09DCBEB4A07F05 /* MDCIcons.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCIcons.m; path = components/private/Icons/src/MDCIcons.m; sourceTree = "<group>"; };
+		3C914D35C46E85C26AA1E246E17CECE5 /* MDCProgressView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCProgressView.m; path = components/ProgressView/src/MDCProgressView.m; sourceTree = "<group>"; };
+		3D8330A4B1BF56B9147CC1FE27AFDFCA /* MaterialPageControl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPageControl.h; path = components/PageControl/src/MaterialPageControl.h; sourceTree = "<group>"; };
+		3F5A046B9A9E9CC97A6C6B6A65F22F53 /* MDCDialogShadowedView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCDialogShadowedView.h; path = components/Dialogs/src/private/MDCDialogShadowedView.h; sourceTree = "<group>"; };
+		3F9391682535FDA07FBB0AB83B6B96E0 /* MaterialIcons+ic_reorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_reorder.m"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m"; sourceTree = "<group>"; };
+		3F9B634EE11CC423F51EE3D659001D14 /* NSArray+MDFUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MDFUtils.h"; path = "src/private/NSArray+MDFUtils.h"; sourceTree = "<group>"; };
+		403CEE2F8B8AFCD9A8ADAD83045448CB /* ic_reorder.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_reorder.png; path = components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png; sourceTree = "<group>"; };
+		40759EC5DB49E090570D13E76C4CDA94 /* MDFTextAccessibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDFTextAccessibility.h; path = src/MDFTextAccessibility.h; sourceTree = "<group>"; };
+		409899CE1143F81E8130E2069D59605B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+		423E686AE21269BCFA30A045BF0D5F96 /* ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist"; sourceTree = "<group>"; };
+		4277E14F56DAC15ABD24D97EDC26ADEA /* UIFont+MaterialTypographyPrivate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIFont+MaterialTypographyPrivate.m"; path = "components/Typography/src/private/UIFont+MaterialTypographyPrivate.m"; sourceTree = "<group>"; };
+		430CFFC6D36F60111CDF22059398251D /* MaterialIcons_ic_check_circle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_check_circle.bundle; path = MaterialIcons_ic_check_circle.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		4374B11D22F0FCC5866781A5F08A4D38 /* MDCButtonBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCButtonBar.h; path = components/ButtonBar/src/MDCButtonBar.h; sourceTree = "<group>"; };
+		443C58797FC89C1F0BDC6BDF82DD1913 /* MaterialIcons+ic_check_circle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_check_circle.m"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m"; sourceTree = "<group>"; };
+		444B921CA054B6ED8B57713242404400 /* MaterialCollectionLayoutAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionLayoutAttributes.h; path = components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h; sourceTree = "<group>"; };
+		45DA800B226D1DE08F69E5BDDC45E203 /* MDCActivityIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCActivityIndicator.m; path = components/ActivityIndicator/src/MDCActivityIndicator.m; sourceTree = "<group>"; };
+		462854769E2CB8F1B329D4392C79AA61 /* MDCCollectionViewLayoutAttributes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewLayoutAttributes.m; path = components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m; sourceTree = "<group>"; };
+		478E465B2E211ABEB0687F1096C92E0C /* ResourceBundle-MaterialIcons_ic_reorder-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_reorder-Info.plist"; sourceTree = "<group>"; };
+		47BD4FBE1EC6F6C948B7056DFB3EAE4E /* ic_reorder@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_reorder@2x.png"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png"; sourceTree = "<group>"; };
+		49A3FB5A7A3C2EEAAF7C7BD7C72CABBD /* ic_check@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check@3x.png"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png"; sourceTree = "<group>"; };
+		4AF4F84748B988E39D513A50701185FC /* MDFTextAccessibility.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDFTextAccessibility.m; path = src/MDFTextAccessibility.m; sourceTree = "<group>"; };
+		4B9EBBBC413F2FB5A96D131DC26FFC36 /* MaterialButtons.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialButtons.h; path = components/Buttons/src/MaterialButtons.h; sourceTree = "<group>"; };
+		4D40D28A97062B1CC07236668DC678AD /* MDFImageCalculations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDFImageCalculations.h; path = src/private/MDFImageCalculations.h; sourceTree = "<group>"; };
+		4F0E678DFEF2B507BAEF2FFD1EF23228 /* MDCFlatButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlatButton.m; path = components/Buttons/src/MDCFlatButton.m; sourceTree = "<group>"; };
+		4FC2C7E47A0EA56BD6295D82B56F6192 /* MDCAppBarButtonBarBuilder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAppBarButtonBarBuilder.h; path = components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h; sourceTree = "<group>"; };
+		4FECD187F5A83C12336BB0C55DD75C6F /* MDCCollectionViewStyling.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewStyling.h; path = components/Collections/src/MDCCollectionViewStyling.h; sourceTree = "<group>"; };
+		506805F39B4A029793221A2B4824A062 /* MDFTextAccessibility-Bridging-Header.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDFTextAccessibility-Bridging-Header.h"; path = "src/MDFTextAccessibility-Bridging-Header.h"; sourceTree = "<group>"; };
+		516E307567E6B1C8060A69B31F20108A /* MDFColorCalculations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDFColorCalculations.m; path = src/private/MDFColorCalculations.m; sourceTree = "<group>"; };
+		51F9DCB161F252F8BD0F521356180A57 /* MaterialApplication.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialApplication.h; path = components/private/Application/src/MaterialApplication.h; sourceTree = "<group>"; };
+		522F0C6B92C308F6D1B7BB497022A769 /* MDCSnackbarMessageViewInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessageViewInternal.h; path = components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h; sourceTree = "<group>"; };
+		523EEB14DB0CEFD241559CCC496E445B /* MDCOverlayObserverOverlay.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayObserverOverlay.m; path = components/private/Overlay/src/private/MDCOverlayObserverOverlay.m; sourceTree = "<group>"; };
+		536F8F8CBB3D5593CFA4CBFD765F3BED /* MDCFlexibleHeaderContainerViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlexibleHeaderContainerViewController.m; path = components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m; sourceTree = "<group>"; };
+		5572DC66A4C3A03942D5656C7DC33A85 /* Pods-BuildingBeautifulApps-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-BuildingBeautifulApps-acknowledgements.markdown"; sourceTree = "<group>"; };
+		56417D84CA78A113438D534EE4FFC54A /* MaterialCollectionsStrings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionsStrings.h; path = components/Collections/src/private/MaterialCollectionsStrings.h; sourceTree = "<group>"; };
+		5677CC19D390C501CCA90EEE390AAE6D /* MDCItemBarAlignment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarAlignment.h; path = components/Tabs/src/private/MDCItemBarAlignment.h; sourceTree = "<group>"; };
+		5894DCB5AAB8B32C781B6279A0FEF8D9 /* UIView+MDCTimingFunction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MDCTimingFunction.h"; path = "components/AnimationTiming/src/UIView+MDCTimingFunction.h"; sourceTree = "<group>"; };
+		58B3FF2F70B1A1974204F2F8931F665B /* MDCCollectionViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewController.h; path = components/Collections/src/MDCCollectionViewController.h; sourceTree = "<group>"; };
+		59D335F07CA6F3AF80A7760B046F9BE3 /* ResourceBundle-MaterialIcons_ic_info-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_info-Info.plist"; sourceTree = "<group>"; };
+		5B8E69C2D115A0FE03A563709E22B4ED /* MaterialIcons+ic_reorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_reorder.h"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h"; sourceTree = "<group>"; };
+		5C27D7602B81556831B0A85A92B4E5A3 /* MDCFeatureHighlightViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightViewController.m; path = components/FeatureHighlight/src/MDCFeatureHighlightViewController.m; sourceTree = "<group>"; };
+		5C4B4B293D1D97D44EA76F8E2DD5595E /* MaterialIcons.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialIcons.h; path = components/private/Icons/src/MaterialIcons.h; sourceTree = "<group>"; };
+		5C4F931DA815928A8CA82E5513C6246A /* UIApplication+AppExtensions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+AppExtensions.m"; path = "components/private/Application/src/UIApplication+AppExtensions.m"; sourceTree = "<group>"; };
+		5D8DE150DA0161A584D8CED87D6DF987 /* MDCTabBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCTabBar.m; path = components/Tabs/src/MDCTabBar.m; sourceTree = "<group>"; };
+		5D982B7FBF6D8BFF04DFD915F08E13B0 /* MDCOverlayTransitioning.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayTransitioning.h; path = components/private/Overlay/src/MDCOverlayTransitioning.h; sourceTree = "<group>"; };
+		5DB14C9C7FE14E6BF99957813C38B5BA /* MDCOverlayObserverTransition.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayObserverTransition.h; path = components/private/Overlay/src/private/MDCOverlayObserverTransition.h; sourceTree = "<group>"; };
+		5EBBA737C7DEFC62CB07A5607401B086 /* ic_info@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_info@3x.png"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png"; sourceTree = "<group>"; };
+		5F7BDB2580B244756CFA046131516EF2 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+		60852389E40D9EF0F70B7BF97E7B998D /* MaterialSlider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialSlider.h; path = components/Slider/src/MaterialSlider.h; sourceTree = "<group>"; };
+		61C0E2BD02828C530EA209D50ED1B519 /* MaterialPageControlStrings_table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPageControlStrings_table.h; path = components/PageControl/src/private/MaterialPageControlStrings_table.h; sourceTree = "<group>"; };
+		62057440CF0144D03DEB925C378645B7 /* ic_radio_button_unchecked@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_radio_button_unchecked@3x.png"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png"; sourceTree = "<group>"; };
+		621F64FAC8A6CDF22ADF8271D04409C6 /* MDCFlexibleHeaderContainerViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlexibleHeaderContainerViewController.h; path = components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h; sourceTree = "<group>"; };
+		654AA469F888FFF8F1CE4AA611FD6B69 /* MaterialIcons+ic_chevron_right.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_chevron_right.m"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m"; sourceTree = "<group>"; };
+		6677BBD93E7A4672F9AEA51236310EDF /* MDCCollectionViewLayoutAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewLayoutAttributes.h; path = components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h; sourceTree = "<group>"; };
+		66E845FD6DDDE254DBD69B4B9FBCA3B8 /* MDCFeatureHighlightViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightViewController.h; path = components/FeatureHighlight/src/MDCFeatureHighlightViewController.h; sourceTree = "<group>"; };
+		675F4FE5A00141BDF25CA3589A5DEF88 /* MDCPalettes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPalettes.h; path = components/Palettes/src/MDCPalettes.h; sourceTree = "<group>"; };
+		67D647688DBDE7C289D22CFAADF4006C /* MDCPaletteExpansions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPaletteExpansions.m; path = components/Palettes/src/private/MDCPaletteExpansions.m; sourceTree = "<group>"; };
+		683A8B83E16F375FE011E9C5AA0221EE /* MDCCollectionGridBackgroundView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionGridBackgroundView.m; path = components/Collections/src/private/MDCCollectionGridBackgroundView.m; sourceTree = "<group>"; };
+		6ADBE2A8BC6E0585880B9137AEDC228D /* Pods-BuildingBeautifulApps-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BuildingBeautifulApps-frameworks.sh"; sourceTree = "<group>"; };
+		6B9A7110EE95FE54D52AC78F8943FF30 /* libPods-BuildingBeautifulApps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-BuildingBeautifulApps.a"; path = "libPods-BuildingBeautifulApps.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		6D3E3C231B7AE692FCE91C1216645EA3 /* UIViewController+MaterialDialogs.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+MaterialDialogs.m"; path = "components/Dialogs/src/UIViewController+MaterialDialogs.m"; sourceTree = "<group>"; };
+		6E75C79B7D5289097D15A811F188CED2 /* UIFont+MaterialTypographyPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIFont+MaterialTypographyPrivate.h"; path = "components/Typography/src/private/UIFont+MaterialTypographyPrivate.h"; sourceTree = "<group>"; };
+		6EAC67B229E26EFB3FEF38B7164183F0 /* MDCFlexibleHeaderViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlexibleHeaderViewController.m; path = components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m; sourceTree = "<group>"; };
+		6ECC1D1D41521DED2581889D20C4D8F9 /* UIImage+MaterialRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MaterialRTL.h"; path = "components/private/RTL/src/UIImage+MaterialRTL.h"; sourceTree = "<group>"; };
+		6EE3924624B8CAFC171FD153BBFC8449 /* MDCFlexibleHeaderView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlexibleHeaderView.h; path = components/FlexibleHeader/src/MDCFlexibleHeaderView.h; sourceTree = "<group>"; };
+		6F9741A397ADB188B83497B96D7D30F5 /* MDCOverlayWindow.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayWindow.m; path = components/OverlayWindow/src/MDCOverlayWindow.m; sourceTree = "<group>"; };
+		702CBDDD852DAA7044CE6BCB5AA2D950 /* MaterialHeaderStackView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialHeaderStackView.h; path = components/HeaderStackView/src/MaterialHeaderStackView.h; sourceTree = "<group>"; };
+		7143C04351DADE6FD07918C99C3BF31E /* MaterialActivityIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialActivityIndicator.h; path = components/ActivityIndicator/src/MaterialActivityIndicator.h; sourceTree = "<group>"; };
+		71BE7789CD2EC0A70DE711AC5A1FEF8D /* MDCFlexibleHeaderView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlexibleHeaderView.m; path = components/FlexibleHeader/src/MDCFlexibleHeaderView.m; sourceTree = "<group>"; };
+		7231A93714A109C83065D36604C9451C /* NSArray+MDFUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MDFUtils.m"; path = "src/private/NSArray+MDFUtils.m"; sourceTree = "<group>"; };
+		74905502A1DF96D7D84E7714A179E9E9 /* CAMediaTimingFunction+MDCAnimationTiming.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CAMediaTimingFunction+MDCAnimationTiming.h"; path = "components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h"; sourceTree = "<group>"; };
+		752EC7F93FEFE96C89367CBBBB8CB32B /* MDCCollectionViewEditing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewEditing.h; path = components/Collections/src/MDCCollectionViewEditing.h; sourceTree = "<group>"; };
+		77C440E4189E05E40980CE67AF6A977D /* MaterialShadowLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialShadowLayer.h; path = components/ShadowLayer/src/MaterialShadowLayer.h; sourceTree = "<group>"; };
+		7941C852DB02A5C5D4BE708004028A52 /* UIView+MDCTimingFunction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MDCTimingFunction.m"; path = "components/AnimationTiming/src/UIView+MDCTimingFunction.m"; sourceTree = "<group>"; };
+		79DCB73AD07EBD187AB62F38B93A8863 /* MDCCollectionGridBackgroundView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionGridBackgroundView.h; path = components/Collections/src/private/MDCCollectionGridBackgroundView.h; sourceTree = "<group>"; };
+		7C5778E1102FA874A7F4F6FFD400C7DE /* ic_check.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_check.png; path = components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png; sourceTree = "<group>"; };
+		7C6135E851D024BF64D3B71654768D9C /* ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist"; sourceTree = "<group>"; };
+		7D86AB797FE0EAA5C5384DF417BF5346 /* MDCStatusBarShifter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCStatusBarShifter.m; path = components/FlexibleHeader/src/private/MDCStatusBarShifter.m; sourceTree = "<group>"; };
+		7E855EBFE6A726985077571DB7E89BD5 /* MDCShadowElevations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCShadowElevations.h; path = components/ShadowElevations/src/MDCShadowElevations.h; sourceTree = "<group>"; };
+		7EBAFD93350BF0CF6E8CE57A39A1FA5D /* ic_chevron_right.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_chevron_right.png; path = components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png; sourceTree = "<group>"; };
+		7F9E8F936B7FA4CE55F6D4A70EDF478C /* ic_arrow_back_ios.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_arrow_back_ios.png; path = components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png; sourceTree = "<group>"; };
+		804D865D3D4D4C65731A550B3D8FC9A5 /* MaterialIcons+ic_arrow_back.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_arrow_back.h"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h"; sourceTree = "<group>"; };
+		81B08B2D4EB2559D2497B7BB8B215DF3 /* MDCOverlayAnimationObserver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayAnimationObserver.h; path = components/private/Overlay/src/private/MDCOverlayAnimationObserver.h; sourceTree = "<group>"; };
+		8272252EDEB9A0A290A95F34B0A4AEBD /* Pods-BuildingBeautifulApps-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-BuildingBeautifulApps-dummy.m"; sourceTree = "<group>"; };
+		84467817302E2399BA95D3A909871AFA /* MaterialDialogs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialDialogs.h; path = components/Dialogs/src/MaterialDialogs.h; sourceTree = "<group>"; };
+		84D3E267E2C78F75A2831346932CF97F /* ic_radio_button_unchecked@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_radio_button_unchecked@2x.png"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png"; sourceTree = "<group>"; };
+		8556079BFB00835D898F480913F78F13 /* MDCPageControlTrackLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPageControlTrackLayer.m; path = components/PageControl/src/private/MDCPageControlTrackLayer.m; sourceTree = "<group>"; };
+		860E1A6AE14CC46812BFD2EECD3DF1B6 /* MaterialIcons_ic_check.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_check.bundle; path = MaterialIcons_ic_check.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		86754C059E8434587187015DC770180B /* MDCThumbTrack.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCThumbTrack.h; path = components/private/ThumbTrack/src/MDCThumbTrack.h; sourceTree = "<group>"; };
+		87D692B9AD07C602ED145B594F3FF7D9 /* ic_reorder@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_reorder@3x.png"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png"; sourceTree = "<group>"; };
+		88AE915AB74A3A3AA3F3F10C11CD9644 /* MaterialIcons+ic_check.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_check.m"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m"; sourceTree = "<group>"; };
+		8917229D3430B609F88F33A180E7063C /* ic_check@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check@2x.png"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png"; sourceTree = "<group>"; };
+		8938D8038B0C55A96B4E161C6661FFC0 /* MDCIcons.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCIcons.h; path = components/private/Icons/src/MDCIcons.h; sourceTree = "<group>"; };
+		8BF097DEAD72714A366668962C25EC9B /* MDCCollectionViewTextCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewTextCell.h; path = components/CollectionCells/src/MDCCollectionViewTextCell.h; sourceTree = "<group>"; };
+		8CCFBA02AEF1EB2D0EA744C7D87ADB76 /* MDCThumbView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCThumbView.m; path = components/private/ThumbTrack/src/MDCThumbView.m; sourceTree = "<group>"; };
+		8E961B158FE9954DDD2B6C09E3462883 /* MDFTextAccessibility-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MDFTextAccessibility-dummy.m"; sourceTree = "<group>"; };
+		90B29DB14670F66061CFB82DDC68AF49 /* UIView+MaterialRTL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MaterialRTL.m"; path = "components/private/RTL/src/UIView+MaterialRTL.m"; sourceTree = "<group>"; };
+		915F12E15D337DE30C909A4C3749EE83 /* MaterialCollectionCells.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialCollectionCells.bundle; path = components/CollectionCells/src/MaterialCollectionCells.bundle; sourceTree = "<group>"; };
+		931A07F6E4357134E2E8449CFE5E056E /* MDCCollectionViewFlowLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewFlowLayout.m; path = components/Collections/src/MDCCollectionViewFlowLayout.m; sourceTree = "<group>"; };
+		935B6D6F1FAB419F6C7B4129E6A0074F /* MDCRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCRTL.h; path = components/private/RTL/src/MDCRTL.h; sourceTree = "<group>"; };
+		93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
+		94294D2C0E41046D41ED4D332EF32E37 /* MaterialTabs.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialTabs.bundle; path = components/Tabs/src/MaterialTabs.bundle; sourceTree = "<group>"; };
+		94B9A402610F5FCAEE60B7D902780413 /* MaterialPageControlStrings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPageControlStrings.h; path = components/PageControl/src/private/MaterialPageControlStrings.h; sourceTree = "<group>"; };
+		95D1CF13299CEF28BCBAA62F927A3D80 /* UIApplication+AppExtensions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIApplication+AppExtensions.h"; path = "components/private/Application/src/UIApplication+AppExtensions.h"; sourceTree = "<group>"; };
+		96E1A962597D9C41D8E7513530EBCD7D /* MDCCollectionStringResources.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionStringResources.m; path = components/Collections/src/private/MDCCollectionStringResources.m; sourceTree = "<group>"; };
+		97262CDCD801553DA99ECC7847E39E98 /* MDCActivityIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCActivityIndicator.h; path = components/ActivityIndicator/src/MDCActivityIndicator.h; sourceTree = "<group>"; };
+		97E9347E0E620A695CA9575055B9A219 /* MDCPageControlIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPageControlIndicator.h; path = components/PageControl/src/private/MDCPageControlIndicator.h; sourceTree = "<group>"; };
+		97FBECBD5EF590F0A8005F8B94E808FF /* MaterialIcons+ic_radio_button_unchecked.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_radio_button_unchecked.h"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h"; sourceTree = "<group>"; };
+		98BE3C2752BDFA411D8AD43231FF4BCC /* MDCSnackbarOverlayView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarOverlayView.h; path = components/Snackbar/src/private/MDCSnackbarOverlayView.h; sourceTree = "<group>"; };
+		98F8E9B6EBCFF521C01B78E4BD1039BD /* MDCPaletteNames.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPaletteNames.m; path = components/Palettes/src/private/MDCPaletteNames.m; sourceTree = "<group>"; };
+		9A7FE223E125A19DB7A772510BF0DEB2 /* MaterialFlexibleHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialFlexibleHeader.h; path = components/FlexibleHeader/src/MaterialFlexibleHeader.h; sourceTree = "<group>"; };
+		9A82FF56648D80F9E61096E9A07B06F6 /* MDCTypography.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCTypography.m; path = components/Typography/src/MDCTypography.m; sourceTree = "<group>"; };
+		9B114982D3918901056DE5DF45AEAC16 /* Pods-BuildingBeautifulApps-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BuildingBeautifulApps-resources.sh"; sourceTree = "<group>"; };
+		9C7E38A7B56C28ED6E56D587A376C3B4 /* MaterialSnackbar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialSnackbar.h; path = components/Snackbar/src/MaterialSnackbar.h; sourceTree = "<group>"; };
+		9CA3D76D548F43BB8F241C55FB9D5656 /* MDCAppBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAppBar.h; path = components/AppBar/src/MDCAppBar.h; sourceTree = "<group>"; };
+		9D57CB474D3A2B64257FE6E21F9BD796 /* MDCPageControlTrackLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPageControlTrackLayer.h; path = components/PageControl/src/private/MDCPageControlTrackLayer.h; sourceTree = "<group>"; };
+		9E05EB6FB230393D92DC9A1584D7DE50 /* MDCThumbTrack.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCThumbTrack.m; path = components/private/ThumbTrack/src/MDCThumbTrack.m; sourceTree = "<group>"; };
+		9E5285A7050BE78F06AD6EC2E4BF1A2F /* UIFontDescriptor+MaterialTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIFontDescriptor+MaterialTypography.h"; path = "components/Typography/src/UIFontDescriptor+MaterialTypography.h"; sourceTree = "<group>"; };
+		9F5AE307F5EF407D47769AC7313B9DCA /* MDCSnackbarManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarManager.m; path = components/Snackbar/src/MDCSnackbarManager.m; sourceTree = "<group>"; };
+		9F8BE2D8847C692FB18FCFEF6F294478 /* MaterialIcons_ic_radio_button_unchecked.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_radio_button_unchecked.bundle; path = MaterialIcons_ic_radio_button_unchecked.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MDFTextAccessibility.xcconfig; sourceTree = "<group>"; };
+		A32E50911D7DB6FBC3E4CC4ECCBA1596 /* MaterialCollectionCells.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionCells.h; path = components/CollectionCells/src/MaterialCollectionCells.h; sourceTree = "<group>"; };
+		A3991A36920E062C3E82F61204091F73 /* MDCSnackbarMessageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessageView.h; path = components/Snackbar/src/MDCSnackbarMessageView.h; sourceTree = "<group>"; };
+		A6219827B685EAAF10C4441241536DD2 /* Pods-BuildingBeautifulApps-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-BuildingBeautifulApps-acknowledgements.plist"; sourceTree = "<group>"; };
+		A683F198135D9329FD62063BFB4B0F9B /* MDCPageControl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPageControl.h; path = components/PageControl/src/MDCPageControl.h; sourceTree = "<group>"; };
+		A8D106719F3F199D438233D94FDF43F5 /* UIFont+MaterialTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIFont+MaterialTypography.h"; path = "components/Typography/src/UIFont+MaterialTypography.h"; sourceTree = "<group>"; };
+		ABED23378B104A0A25435A6674F29FF5 /* MDCRaisedButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCRaisedButton.h; path = components/Buttons/src/MDCRaisedButton.h; sourceTree = "<group>"; };
+		ACCED250D3351A0D22EEA492436EBE80 /* ic_info.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_info.png; path = components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png; sourceTree = "<group>"; };
+		ACD681F6184F424EE2EAF7600B76F289 /* MaterialIcons+ic_check.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_check.h"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h"; sourceTree = "<group>"; };
+		B12139AB4284238F1123EB1E38B230E1 /* MDCRTL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCRTL.m; path = components/private/RTL/src/MDCRTL.m; sourceTree = "<group>"; };
+		B177F408148335CFD14BF2E1C8FADB3F /* ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist"; sourceTree = "<group>"; };
+		B3AB010097D6D3763F9664DCA9A711EB /* MDCDialogShadowedView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCDialogShadowedView.m; path = components/Dialogs/src/private/MDCDialogShadowedView.m; sourceTree = "<group>"; };
+		B4CDE57035DA000166BF394A847F6AE2 /* MDCDialogPresentationController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCDialogPresentationController.h; path = components/Dialogs/src/MDCDialogPresentationController.h; sourceTree = "<group>"; };
+		B52A38C1D2775315C12601204EF0524E /* MaterialIcons+ic_info.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_info.m"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m"; sourceTree = "<group>"; };
+		B56398DA0E3930C91FF640F861706411 /* MDCPageControlIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPageControlIndicator.m; path = components/PageControl/src/private/MDCPageControlIndicator.m; sourceTree = "<group>"; };
+		B5929610276D0E6D8DD3158FF603C0EC /* MaterialOverlays.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialOverlays.h; path = components/private/Overlay/src/MaterialOverlays.h; sourceTree = "<group>"; };
+		B6134FFEBB32CC196B45597FC2948611 /* MDCShadowLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCShadowLayer.m; path = components/ShadowLayer/src/MDCShadowLayer.m; sourceTree = "<group>"; };
+		B6D338FD921EC51C550567AB2D429021 /* libMDFTextAccessibility.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMDFTextAccessibility.a; path = libMDFTextAccessibility.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		B73577CD8AEFE5DA6EB995CC8F2C92A7 /* MaterialNavigationBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialNavigationBar.h; path = components/NavigationBar/src/MaterialNavigationBar.h; sourceTree = "<group>"; };
+		B77E7CD1098848AED57761E60382667D /* MDCRaisedButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCRaisedButton.m; path = components/Buttons/src/MDCRaisedButton.m; sourceTree = "<group>"; };
+		B9E2AAB8153882A4590062F569A4D595 /* MDCTabBarAlignment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTabBarAlignment.h; path = components/Tabs/src/MDCTabBarAlignment.h; sourceTree = "<group>"; };
+		B9F2A6127E6482F1546297FBA86E9E19 /* MDCDialogPresentationController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCDialogPresentationController.m; path = components/Dialogs/src/MDCDialogPresentationController.m; sourceTree = "<group>"; };
+		BA4F460E41035D7B0B538CDC2752925D /* MDCPageControl.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPageControl.m; path = components/PageControl/src/MDCPageControl.m; sourceTree = "<group>"; };
+		BB3068591BFE9A9F8D1B79957A573691 /* MDCItemBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCItemBar.m; path = components/Tabs/src/private/MDCItemBar.m; sourceTree = "<group>"; };
+		BBFB15BBA3F7C53B5BDCBDCEFD66700C /* MaterialCollectionsStrings_table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionsStrings_table.h; path = components/Collections/src/private/MaterialCollectionsStrings_table.h; sourceTree = "<group>"; };
+		BDAF0CDE00CDA3F4B1CE9E7374239490 /* MDCTabBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTabBar.h; path = components/Tabs/src/MDCTabBar.h; sourceTree = "<group>"; };
+		BE257A301C797B8D3C24053EFEF0DB5A /* MDCButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCButton.m; path = components/Buttons/src/MDCButton.m; sourceTree = "<group>"; };
+		BE4C70E576A2623B72B27F812FA19587 /* MDCKeyboardWatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCKeyboardWatcher.h; path = components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h; sourceTree = "<group>"; };
+		BEBA1206741596666E53A5291AC6C67D /* MDCCollectionViewCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewCell.m; path = components/CollectionCells/src/MDCCollectionViewCell.m; sourceTree = "<group>"; };
+		C03DAFCD2FB2199D18A24125D772CB7A /* MDCOverlayUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayUtilities.h; path = components/private/Overlay/src/private/MDCOverlayUtilities.h; sourceTree = "<group>"; };
+		C0499AC785EBF2667F45935055F327A1 /* ResourceBundle-MaterialIcons_ic_check_circle-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_check_circle-Info.plist"; sourceTree = "<group>"; };
+		C075A49AEB6D1C36BA22C458FC6A2801 /* MaterialAnimationTiming.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialAnimationTiming.h; path = components/AnimationTiming/src/MaterialAnimationTiming.h; sourceTree = "<group>"; };
+		C078D453FB972AF56047785185938933 /* MDCPaletteNames.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPaletteNames.h; path = components/Palettes/src/private/MDCPaletteNames.h; sourceTree = "<group>"; };
+		C092C0ED18CF0F6D5A1391571F068348 /* MaterialPageControl.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialPageControl.bundle; path = components/PageControl/src/MaterialPageControl.bundle; sourceTree = "<group>"; };
+		C19F7B7784CFCB4369498613360AA4CB /* MaterialIcons+ic_radio_button_unchecked.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_radio_button_unchecked.m"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m"; sourceTree = "<group>"; };
+		C3CE561D11742D1092438C75CE67C1D4 /* MDCAlertController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAlertController.m; path = components/Dialogs/src/MDCAlertController.m; sourceTree = "<group>"; };
+		C4899C25A4830FCF08B2BB4F8ABC361A /* MDCPaletteExpansions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPaletteExpansions.h; path = components/Palettes/src/private/MDCPaletteExpansions.h; sourceTree = "<group>"; };
+		C4F53B72FA10D37719F9CB9924A08CBD /* MDCItemBarStyle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarStyle.h; path = components/Tabs/src/private/MDCItemBarStyle.h; sourceTree = "<group>"; };
+		C660FEA28DDB8CB873D9BCE3DA03F6B3 /* MDCNumericValueLabel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCNumericValueLabel.h; path = components/private/ThumbTrack/src/MDCNumericValueLabel.h; sourceTree = "<group>"; };
+		C67AC2707AD0B4EC907D6DC6B79DD436 /* MaterialProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialProgressView.h; path = components/ProgressView/src/MaterialProgressView.h; sourceTree = "<group>"; };
+		C70F87D8C5E5F9AEBFA97552A5BCD739 /* ResourceBundle-MaterialIcons_ic_check-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_check-Info.plist"; sourceTree = "<group>"; };
+		C830C5EEEAE60B4A9283F0C2F0A02094 /* MaterialIcons+ic_arrow_back.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_arrow_back.m"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m"; sourceTree = "<group>"; };
+		C9588139AB2E41A105B4F278EF0B01F3 /* MDCPalettes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPalettes.m; path = components/Palettes/src/MDCPalettes.m; sourceTree = "<group>"; };
+		CAA1DC1A670B6F673EE517CD53A4EBD1 /* MDCCollectionViewStyler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewStyler.h; path = components/Collections/src/private/MDCCollectionViewStyler.h; sourceTree = "<group>"; };
+		CAC43F65D5D78A89EAC07A697ACC9837 /* MDCInkGestureRecognizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkGestureRecognizer.m; path = components/Ink/src/MDCInkGestureRecognizer.m; sourceTree = "<group>"; };
+		CADC6B616AB3936666BDBD42A2705DE6 /* MDCItemBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBar.h; path = components/Tabs/src/private/MDCItemBar.h; sourceTree = "<group>"; };
+		CB370B0CFF7E9F249F9A4A4A5C9828C0 /* MaterialIcons_ic_chevron_right.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_chevron_right.bundle; path = MaterialIcons_ic_chevron_right.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		CC56C512FD3A98A296C04156DD8DFEC9 /* MDCShadowElevations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCShadowElevations.m; path = components/ShadowElevations/src/MDCShadowElevations.m; sourceTree = "<group>"; };
+		CCF1F1AE19AF21CE8869CF3A681CC787 /* MDCNavigationBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCNavigationBar.m; path = components/NavigationBar/src/MDCNavigationBar.m; sourceTree = "<group>"; };
+		CD6BFB0EA4919F07C8AD5F586E34376D /* MDCFontTextStyle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFontTextStyle.h; path = components/Typography/src/MDCFontTextStyle.h; sourceTree = "<group>"; };
+		CE6929889D615189113913408E3D1B9E /* MDCHeaderStackView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCHeaderStackView.h; path = components/HeaderStackView/src/MDCHeaderStackView.h; sourceTree = "<group>"; };
+		D100E5E7F62D86CE9CCC97B487779DEC /* MDCOverlayWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayWindow.h; path = components/OverlayWindow/src/MDCOverlayWindow.h; sourceTree = "<group>"; };
+		D11EB1CC12CA81275669C38699DF58A3 /* MaterialThumbTrack.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialThumbTrack.h; path = components/private/ThumbTrack/src/MaterialThumbTrack.h; sourceTree = "<group>"; };
+		D14A347A944C556F216B967AFCF766C8 /* MaterialButtonBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialButtonBar.h; path = components/ButtonBar/src/MaterialButtonBar.h; sourceTree = "<group>"; };
+		D1A37A0287C491DFE2089102146664E8 /* MaterialTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialTypography.h; path = components/Typography/src/MaterialTypography.h; sourceTree = "<group>"; };
+		D1D4C0D37627D761BB16ECB99105E4A0 /* MDCCollectionViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewController.m; path = components/Collections/src/MDCCollectionViewController.m; sourceTree = "<group>"; };
+		D20FE85CECC64B86387F4CA60B86C8C6 /* MDCSnackbarMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessage.h; path = components/Snackbar/src/MDCSnackbarMessage.h; sourceTree = "<group>"; };
+		D2FFA02DCC45D1EDB5D30FB9CEB3B9BD /* MDCFeatureHighlightAnimationController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightAnimationController.m; path = components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m; sourceTree = "<group>"; };
+		D43D8FF7991737DB826BFF92EBF8ADFA /* MaterialIcons_ic_reorder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_reorder.bundle; path = MaterialIcons_ic_reorder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		D49CC986145361BA86D40441881692D8 /* MDCThumbView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCThumbView.h; path = components/private/ThumbTrack/src/MDCThumbView.h; sourceTree = "<group>"; };
+		D5674E7D4BCC946A30114DBF9DB2F6CA /* ic_chevron_right@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_chevron_right@2x.png"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png"; sourceTree = "<group>"; };
+		D79A92B4599903B71AD908CC7E5B0213 /* MDCButtonBar+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDCButtonBar+Private.h"; path = "components/ButtonBar/src/private/MDCButtonBar+Private.h"; sourceTree = "<group>"; };
+		D7E1DE48A44A60C2AE808B6D69A73683 /* UIFontDescriptor+MaterialTypography.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIFontDescriptor+MaterialTypography.m"; path = "components/Typography/src/UIFontDescriptor+MaterialTypography.m"; sourceTree = "<group>"; };
+		D8966C5049A9875A33A6802C9840E498 /* MDCShadowLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCShadowLayer.h; path = components/ShadowLayer/src/MDCShadowLayer.h; sourceTree = "<group>"; };
+		D8C42FCD2D863F783537F7B84C002801 /* MDCCollectionStringResources.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionStringResources.h; path = components/Collections/src/private/MDCCollectionStringResources.h; sourceTree = "<group>"; };
+		D9E396F14C5448B3C15F7B48AFC85B6F /* MDCOverlayObserver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayObserver.h; path = components/private/Overlay/src/MDCOverlayObserver.h; sourceTree = "<group>"; };
+		DBB2727B89FCF4B81EAB1F748F4EE6F7 /* MaterialIcons_ic_info.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_info.bundle; path = MaterialIcons_ic_info.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		DC384A83912E8C440C7ED70B794A89D2 /* MDCFontTraits.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFontTraits.m; path = components/Typography/src/private/MDCFontTraits.m; sourceTree = "<group>"; };
+		DD35DF5F260987C932CF7B25AD8C22C4 /* MDCOverlayUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayUtilities.m; path = components/private/Overlay/src/private/MDCOverlayUtilities.m; sourceTree = "<group>"; };
+		E17A7167DE53F6528C656D4979850FBC /* UIFont+MaterialTypography.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIFont+MaterialTypography.m"; path = "components/Typography/src/UIFont+MaterialTypography.m"; sourceTree = "<group>"; };
+		E22DE5B99BE8057D6452C77B5B4A8D39 /* MDCIcons+BundleLoader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDCIcons+BundleLoader.h"; path = "components/private/Icons/src/MDCIcons+BundleLoader.h"; sourceTree = "<group>"; };
+		E37F8FD7F722E714E0005FB0C96F9A03 /* MDCInkLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkLayer.m; path = components/Ink/src/private/MDCInkLayer.m; sourceTree = "<group>"; };
+		E47ED49AEF9D2FE77E92679C5569563D /* MDCInkTouchController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkTouchController.h; path = components/Ink/src/MDCInkTouchController.h; sourceTree = "<group>"; };
+		E601CD11978BE11A131D16DA1717A354 /* MDCOverlayObserver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayObserver.m; path = components/private/Overlay/src/MDCOverlayObserver.m; sourceTree = "<group>"; };
+		E66CD057FB364E80D5BC3D34A00B42FF /* MDCFloatingButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFloatingButton.h; path = components/Buttons/src/MDCFloatingButton.h; sourceTree = "<group>"; };
+		E70A12012C34069A15DAAEF725754A18 /* MDCItemBarCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarCell.h; path = components/Tabs/src/private/MDCItemBarCell.h; sourceTree = "<group>"; };
+		E88C708F20439859824CDC2F79216421 /* MaterialRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialRTL.h; path = components/private/RTL/src/MaterialRTL.h; sourceTree = "<group>"; };
+		E8C4112E03A439A51F0FBD876DA804E5 /* UIViewController+MaterialDialogs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+MaterialDialogs.h"; path = "components/Dialogs/src/UIViewController+MaterialDialogs.h"; sourceTree = "<group>"; };
+		E95DB580D0830673D87F39AEFDA6EF67 /* ic_arrow_back_ios@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back_ios@3x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png"; sourceTree = "<group>"; };
+		EA980654C37C923AB926DF64E7E02736 /* MDCInkLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkLayer.h; path = components/Ink/src/private/MDCInkLayer.h; sourceTree = "<group>"; };
+		EB110721FC9D3D6E29D13627A35DFD0E /* MDCOverlayAnimationObserver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayAnimationObserver.m; path = components/private/Overlay/src/private/MDCOverlayAnimationObserver.m; sourceTree = "<group>"; };
+		EB1C6A347A3B1B5278B6179E7E7A6C7E /* MDCHeaderStackView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCHeaderStackView.m; path = components/HeaderStackView/src/MDCHeaderStackView.m; sourceTree = "<group>"; };
+		EC8039BB5A86167E8DCDB72F46D6388B /* MDCFeatureHighlightAnimationController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightAnimationController.h; path = components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h; sourceTree = "<group>"; };
+		EDD61B881B917B05AFD9539341F931FD /* MDCItemBarStringConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarStringConstants.h; path = components/Tabs/src/private/MDCItemBarStringConstants.h; sourceTree = "<group>"; };
+		EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MaterialComponents.xcconfig; sourceTree = "<group>"; };
+		EF3D4AABE18C6B0D033BD47108A9156D /* MDCInkView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkView.h; path = components/Ink/src/MDCInkView.h; sourceTree = "<group>"; };
+		EFCF3D3D2FE3A10C4245EF66AE882178 /* MDCFlatButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlatButton.h; path = components/Buttons/src/MDCFlatButton.h; sourceTree = "<group>"; };
+		F14A5EBD4362C79FF3F8A7262FEA2D5B /* MDCCollectionViewEditingDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewEditingDelegate.h; path = components/Collections/src/MDCCollectionViewEditingDelegate.h; sourceTree = "<group>"; };
+		F1E7B70BE2622CF3F81A0AD037E21C47 /* MDCSnackbarMessageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarMessageView.m; path = components/Snackbar/src/MDCSnackbarMessageView.m; sourceTree = "<group>"; };
+		F398E51F9526801442D77BE9612F9C62 /* MaterialIcons+ic_chevron_right.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_chevron_right.h"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h"; sourceTree = "<group>"; };
+		F4C0F26237AA99F43F82CD8B6404A8FF /* MDCCollectionViewEditor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewEditor.h; path = components/Collections/src/private/MDCCollectionViewEditor.h; sourceTree = "<group>"; };
+		F5A94E964BB75BF779F888AE07B3F95C /* MaterialKeyboardWatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialKeyboardWatcher.h; path = components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h; sourceTree = "<group>"; };
+		F5BEB5E003D1847D87CC74803474B2EF /* MaterialFeatureHighlight.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialFeatureHighlight.h; path = components/FeatureHighlight/src/MaterialFeatureHighlight.h; sourceTree = "<group>"; };
+		F5F5CD9392CF68CA57F883CA8A1DA6BE /* MDCCollectionViewStyler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewStyler.m; path = components/Collections/src/private/MDCCollectionViewStyler.m; sourceTree = "<group>"; };
+		F600563B48E50DAC2BB8C3B23D131DA2 /* MaterialOverlayWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialOverlayWindow.h; path = components/OverlayWindow/src/MaterialOverlayWindow.h; sourceTree = "<group>"; };
+		F64F50AD20E83F81710454204053A744 /* MDCFloatingButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFloatingButton.m; path = components/Buttons/src/MDCFloatingButton.m; sourceTree = "<group>"; };
+		F68D30CBF1457E3E9AE7D3AE92AC18F0 /* MDFImageCalculations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDFImageCalculations.m; path = src/private/MDFImageCalculations.m; sourceTree = "<group>"; };
+		F7D2E69B90D1C23D2FBD5EB175B59364 /* MDCAppBarContainerViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAppBarContainerViewController.m; path = components/AppBar/src/MDCAppBarContainerViewController.m; sourceTree = "<group>"; };
+		F82A46DDAA89ACF53DA3C47CC04971EF /* MDCButton+Subclassing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDCButton+Subclassing.h"; path = "components/Buttons/src/private/MDCButton+Subclassing.h"; sourceTree = "<group>"; };
+		FC7FA8E220EACEBE9FB49B6A6B3732E5 /* MDCInkView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkView.m; path = components/Ink/src/MDCInkView.m; sourceTree = "<group>"; };
+		FC8CB7864BDCD9DB97A3711AC446E2B0 /* MDCButtonBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCButtonBar.m; path = components/ButtonBar/src/MDCButtonBar.m; sourceTree = "<group>"; };
+		FD4ED0BAB173C96E24BFAF538C1A0353 /* MaterialIcons+ic_info.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_info.h"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h"; sourceTree = "<group>"; };
+		FE7AE3A31ABEA928F10508D5385C37F8 /* ic_arrow_back@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back@3x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png"; sourceTree = "<group>"; };
+		FF7A269A35FCA0697B0E5BD94453D3EF /* MDCInkTouchController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkTouchController.m; path = components/Ink/src/MDCInkTouchController.m; sourceTree = "<group>"; };
+		FF9E5D282080B168147A56CBC1A20CB3 /* MaterialIcons_ic_arrow_back.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_arrow_back.bundle; path = MaterialIcons_ic_arrow_back.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		0490164F31DF4DFD21CB5B6C0C9C2828 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9D6D3B5FFB61DFD3F80B76195E605784 /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		05A8C2288619671B1A30A7EF4C739D71 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		10CE89D4B6EA0CBA4230B7FA3FE04DE3 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		120E9482EC24B536DE2A5345E8B71E40 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				303E2CEF1A7B2F29A77E3275D5543798 /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		142596A1D8F1283799C634488452D605 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		59F35B6B50BC5A7D99059FEC9B83AFB9 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		68E4BC6B1D0B207D3F9298FC9505A73E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7B63882D2EA962158694D9F4255CD668 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		AA767584440C8D2E1C217BA896C2796A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3584E7D333209DF162223D26DF0E795F /* CoreGraphics.framework in Frameworks */,
+				35BDD24AF246B8AF9D163CF7005C3A27 /* Foundation.framework in Frameworks */,
+				641CD6C953ADD27482B6CDBCCF24CD6A /* QuartzCore.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		AFFB6859E3D5DB059AA62780279F1BFA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		00F05AF39E02FA6994432A4054A60EC2 /* Base */ = {
+			isa = PBXGroup;
+			children = (
+				5C4B4B293D1D97D44EA76F8E2DD5595E /* MaterialIcons.h */,
+				8938D8038B0C55A96B4E161C6661FFC0 /* MDCIcons.h */,
+				3BF39A7F429701947B09DCBEB4A07F05 /* MDCIcons.m */,
+				E22DE5B99BE8057D6452C77B5B4A8D39 /* MDCIcons+BundleLoader.h */,
+			);
+			name = Base;
+			sourceTree = "<group>";
+		};
+		015D80086EA2452E311127664AED6C49 /* Icons */ = {
+			isa = PBXGroup;
+			children = (
+				00F05AF39E02FA6994432A4054A60EC2 /* Base */,
+				7BBBBB41025DA2946E721C6B4CFE9582 /* ic_arrow_back */,
+				199DBEBBD73D20BC3BA7B1F7F655DC2D /* ic_check */,
+				BC22755231123F8970B82180656CBC02 /* ic_check_circle */,
+				C0478CE6F06E1DD40878AE929472991C /* ic_chevron_right */,
+				A8AC6F8EA0BF9331BC3179FC0941D312 /* ic_info */,
+				EC40E103B51AE1755CA03F26C6C066F1 /* ic_radio_button_unchecked */,
+				C8CCC6846666AAD0D3CA32B272E86A7F /* ic_reorder */,
+			);
+			name = Icons;
+			sourceTree = "<group>";
+		};
+		0A0BC298073A7DBD29E89E8AB28AFF89 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				04BA7B9EA003598360273283129FDE9B /* MaterialCollections.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		0F4F0B2885DA4E9FDA72BB907CFEEBA1 /* MDFTextAccessibility */ = {
+			isa = PBXGroup;
+			children = (
+				10D3AFAF60EB1088403525BA3DF6BD18 /* MDFColorCalculations.h */,
+				516E307567E6B1C8060A69B31F20108A /* MDFColorCalculations.m */,
+				4D40D28A97062B1CC07236668DC678AD /* MDFImageCalculations.h */,
+				F68D30CBF1457E3E9AE7D3AE92AC18F0 /* MDFImageCalculations.m */,
+				40759EC5DB49E090570D13E76C4CDA94 /* MDFTextAccessibility.h */,
+				4AF4F84748B988E39D513A50701185FC /* MDFTextAccessibility.m */,
+				506805F39B4A029793221A2B4824A062 /* MDFTextAccessibility-Bridging-Header.h */,
+				3F9B634EE11CC423F51EE3D659001D14 /* NSArray+MDFUtils.h */,
+				7231A93714A109C83065D36604C9451C /* NSArray+MDFUtils.m */,
+				8BBEF3ED9DC53D6F9F554679719F9E66 /* Support Files */,
+			);
+			name = MDFTextAccessibility;
+			path = MDFTextAccessibility;
+			sourceTree = "<group>";
+		};
+		0FFE22ED316D810F07A3CE1804C14671 /* Overlay */ = {
+			isa = PBXGroup;
+			children = (
+				B5929610276D0E6D8DD3158FF603C0EC /* MaterialOverlays.h */,
+				81B08B2D4EB2559D2497B7BB8B215DF3 /* MDCOverlayAnimationObserver.h */,
+				EB110721FC9D3D6E29D13627A35DFD0E /* MDCOverlayAnimationObserver.m */,
+				2506F285EFA1CEF8247B19211C38EF23 /* MDCOverlayImplementor.h */,
+				D9E396F14C5448B3C15F7B48AFC85B6F /* MDCOverlayObserver.h */,
+				E601CD11978BE11A131D16DA1717A354 /* MDCOverlayObserver.m */,
+				16E650750C1D8383CFF76B265B232D54 /* MDCOverlayObserverOverlay.h */,
+				523EEB14DB0CEFD241559CCC496E445B /* MDCOverlayObserverOverlay.m */,
+				5DB14C9C7FE14E6BF99957813C38B5BA /* MDCOverlayObserverTransition.h */,
+				1509DAD755F448EBE08F87224B5BD8D3 /* MDCOverlayObserverTransition.m */,
+				5D982B7FBF6D8BFF04DFD915F08E13B0 /* MDCOverlayTransitioning.h */,
+				C03DAFCD2FB2199D18A24125D772CB7A /* MDCOverlayUtilities.h */,
+				DD35DF5F260987C932CF7B25AD8C22C4 /* MDCOverlayUtilities.m */,
+			);
+			name = Overlay;
+			sourceTree = "<group>";
+		};
+		122DA2E5084A4393C29BE363C764795C /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				5A4DBD434EA75DD3EDD3494C46AE6968 /* iOS */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		14F3093C9EDA04FD806300494FD654F0 /* ProgressView */ = {
+			isa = PBXGroup;
+			children = (
+				C67AC2707AD0B4EC907D6DC6B79DD436 /* MaterialProgressView.h */,
+				1119E38AD872AC586FC0B36077CBD452 /* MDCProgressView.h */,
+				3C914D35C46E85C26AA1E246E17CECE5 /* MDCProgressView.m */,
+			);
+			name = ProgressView;
+			sourceTree = "<group>";
+		};
+		15CB945DCEE15326848DB6EE1185BC50 /* Support Files */ = {
+			isa = PBXGroup;
+			children = (
+				EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */,
+				13FA3054B67E07E3C004F5E26131FFC5 /* MaterialComponents-dummy.m */,
+				206683C2791ADADFAC3B8A5DAA2DA22A /* MaterialComponents-prefix.pch */,
+				B177F408148335CFD14BF2E1C8FADB3F /* ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist */,
+				C70F87D8C5E5F9AEBFA97552A5BCD739 /* ResourceBundle-MaterialIcons_ic_check-Info.plist */,
+				C0499AC785EBF2667F45935055F327A1 /* ResourceBundle-MaterialIcons_ic_check_circle-Info.plist */,
+				7C6135E851D024BF64D3B71654768D9C /* ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist */,
+				59D335F07CA6F3AF80A7760B046F9BE3 /* ResourceBundle-MaterialIcons_ic_info-Info.plist */,
+				423E686AE21269BCFA30A045BF0D5F96 /* ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist */,
+				478E465B2E211ABEB0687F1096C92E0C /* ResourceBundle-MaterialIcons_ic_reorder-Info.plist */,
+			);
+			name = "Support Files";
+			path = "../Target Support Files/MaterialComponents";
+			sourceTree = "<group>";
+		};
+		199DBEBBD73D20BC3BA7B1F7F655DC2D /* ic_check */ = {
+			isa = PBXGroup;
+			children = (
+				ACD681F6184F424EE2EAF7600B76F289 /* MaterialIcons+ic_check.h */,
+				88AE915AB74A3A3AA3F3F10C11CD9644 /* MaterialIcons+ic_check.m */,
+				F7107ECA24205B6455A55C23978D1621 /* Resources */,
+			);
+			name = ic_check;
+			sourceTree = "<group>";
+		};
+		1A51286FBEFC155062FB53A0ADD4D106 /* Snackbar */ = {
+			isa = PBXGroup;
+			children = (
+				9C7E38A7B56C28ED6E56D587A376C3B4 /* MaterialSnackbar.h */,
+				25F7B26DAEC96431ECEEC467ADA2CF28 /* MDCSnackbarManager.h */,
+				9F5AE307F5EF407D47769AC7313B9DCA /* MDCSnackbarManager.m */,
+				D20FE85CECC64B86387F4CA60B86C8C6 /* MDCSnackbarMessage.h */,
+				1D1C4015B6347137598F264D6387CCA6 /* MDCSnackbarMessage.m */,
+				03B0B17771C5E17CCA5515AAC7363532 /* MDCSnackbarMessageInternal.h */,
+				A3991A36920E062C3E82F61204091F73 /* MDCSnackbarMessageView.h */,
+				F1E7B70BE2622CF3F81A0AD037E21C47 /* MDCSnackbarMessageView.m */,
+				522F0C6B92C308F6D1B7BB497022A769 /* MDCSnackbarMessageViewInternal.h */,
+				98BE3C2752BDFA411D8AD43231FF4BCC /* MDCSnackbarOverlayView.h */,
+				01C5E9A263A0FBC63B0B1E0D89013529 /* MDCSnackbarOverlayView.m */,
+			);
+			name = Snackbar;
+			sourceTree = "<group>";
+		};
+		28B6E99744BA88E1C186F28B24BE34DB /* OverlayWindow */ = {
+			isa = PBXGroup;
+			children = (
+				F600563B48E50DAC2BB8C3B23D131DA2 /* MaterialOverlayWindow.h */,
+				D100E5E7F62D86CE9CCC97B487779DEC /* MDCOverlayWindow.h */,
+				6F9741A397ADB188B83497B96D7D30F5 /* MDCOverlayWindow.m */,
+			);
+			name = OverlayWindow;
+			sourceTree = "<group>";
+		};
+		2D236E262784B2E75892C151B31D5BE2 /* Dialogs */ = {
+			isa = PBXGroup;
+			children = (
+				84467817302E2399BA95D3A909871AFA /* MaterialDialogs.h */,
+				1D28C66D16BE7A01B82F7FD890CA7DBC /* MDCAlertController.h */,
+				C3CE561D11742D1092438C75CE67C1D4 /* MDCAlertController.m */,
+				B4CDE57035DA000166BF394A847F6AE2 /* MDCDialogPresentationController.h */,
+				B9F2A6127E6482F1546297FBA86E9E19 /* MDCDialogPresentationController.m */,
+				3F5A046B9A9E9CC97A6C6B6A65F22F53 /* MDCDialogShadowedView.h */,
+				B3AB010097D6D3763F9664DCA9A711EB /* MDCDialogShadowedView.m */,
+				0044FD236D22AB00062FFED53D72ECEF /* MDCDialogTransitionController.h */,
+				0040124427B7D454BC17F95E2C95F1B9 /* MDCDialogTransitionController.m */,
+				E8C4112E03A439A51F0FBD876DA804E5 /* UIViewController+MaterialDialogs.h */,
+				6D3E3C231B7AE692FCE91C1216645EA3 /* UIViewController+MaterialDialogs.m */,
+			);
+			name = Dialogs;
+			sourceTree = "<group>";
+		};
+		3BD889F6E1BD87A35685DC18128AB26A /* Pods-BuildingBeautifulApps */ = {
+			isa = PBXGroup;
+			children = (
+				5572DC66A4C3A03942D5656C7DC33A85 /* Pods-BuildingBeautifulApps-acknowledgements.markdown */,
+				A6219827B685EAAF10C4441241536DD2 /* Pods-BuildingBeautifulApps-acknowledgements.plist */,
+				8272252EDEB9A0A290A95F34B0A4AEBD /* Pods-BuildingBeautifulApps-dummy.m */,
+				6ADBE2A8BC6E0585880B9137AEDC228D /* Pods-BuildingBeautifulApps-frameworks.sh */,
+				9B114982D3918901056DE5DF45AEAC16 /* Pods-BuildingBeautifulApps-resources.sh */,
+				02AE1C5FFC5FC596ABEC7C98AEF62DD8 /* Pods-BuildingBeautifulApps.debug.xcconfig */,
+				120CFBE565880C2F4F462AAFCEBB37E5 /* Pods-BuildingBeautifulApps.release.xcconfig */,
+			);
+			name = "Pods-BuildingBeautifulApps";
+			path = "Target Support Files/Pods-BuildingBeautifulApps";
+			sourceTree = "<group>";
+		};
+		444ED16EF9B93203AFE8059068568CF6 /* PageControl */ = {
+			isa = PBXGroup;
+			children = (
+				3D8330A4B1BF56B9147CC1FE27AFDFCA /* MaterialPageControl.h */,
+				94B9A402610F5FCAEE60B7D902780413 /* MaterialPageControlStrings.h */,
+				61C0E2BD02828C530EA209D50ED1B519 /* MaterialPageControlStrings_table.h */,
+				A683F198135D9329FD62063BFB4B0F9B /* MDCPageControl.h */,
+				BA4F460E41035D7B0B538CDC2752925D /* MDCPageControl.m */,
+				97E9347E0E620A695CA9575055B9A219 /* MDCPageControlIndicator.h */,
+				B56398DA0E3930C91FF640F861706411 /* MDCPageControlIndicator.m */,
+				9D57CB474D3A2B64257FE6E21F9BD796 /* MDCPageControlTrackLayer.h */,
+				8556079BFB00835D898F480913F78F13 /* MDCPageControlTrackLayer.m */,
+				BEB9000A25F7F69AB8A2CE63887588C6 /* Resources */,
+			);
+			name = PageControl;
+			sourceTree = "<group>";
+		};
+		4B0B90B01CFF775D9C7B38D466F294D0 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				17AAA691CE308745D666AC354DEBD7D1 /* ic_radio_button_unchecked.png */,
+				84D3E267E2C78F75A2831346932CF97F /* ic_radio_button_unchecked@2x.png */,
+				62057440CF0144D03DEB925C378645B7 /* ic_radio_button_unchecked@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		4F83E7F2B19DDC28995A33F954D7B750 /* Collections */ = {
+			isa = PBXGroup;
+			children = (
+				210894774DFDFBA293E2296F2A30C362 /* MaterialCollections.h */,
+				56417D84CA78A113438D534EE4FFC54A /* MaterialCollectionsStrings.h */,
+				BBFB15BBA3F7C53B5BDCBDCEFD66700C /* MaterialCollectionsStrings_table.h */,
+				79DCB73AD07EBD187AB62F38B93A8863 /* MDCCollectionGridBackgroundView.h */,
+				683A8B83E16F375FE011E9C5AA0221EE /* MDCCollectionGridBackgroundView.m */,
+				206E1270F7CD7132605A140A429FE475 /* MDCCollectionInfoBarView.h */,
+				03B1990C768D7EBE9880314C80B89B32 /* MDCCollectionInfoBarView.m */,
+				D8C42FCD2D863F783537F7B84C002801 /* MDCCollectionStringResources.h */,
+				96E1A962597D9C41D8E7513530EBCD7D /* MDCCollectionStringResources.m */,
+				58B3FF2F70B1A1974204F2F8931F665B /* MDCCollectionViewController.h */,
+				D1D4C0D37627D761BB16ECB99105E4A0 /* MDCCollectionViewController.m */,
+				752EC7F93FEFE96C89367CBBBB8CB32B /* MDCCollectionViewEditing.h */,
+				F14A5EBD4362C79FF3F8A7262FEA2D5B /* MDCCollectionViewEditingDelegate.h */,
+				F4C0F26237AA99F43F82CD8B6404A8FF /* MDCCollectionViewEditor.h */,
+				24C7218ECEE1F60B1B720B21514EE621 /* MDCCollectionViewEditor.m */,
+				16C2D56E186EC25B2AD48EF7EC5DB131 /* MDCCollectionViewFlowLayout.h */,
+				931A07F6E4357134E2E8449CFE5E056E /* MDCCollectionViewFlowLayout.m */,
+				CAA1DC1A670B6F673EE517CD53A4EBD1 /* MDCCollectionViewStyler.h */,
+				F5F5CD9392CF68CA57F883CA8A1DA6BE /* MDCCollectionViewStyler.m */,
+				4FECD187F5A83C12336BB0C55DD75C6F /* MDCCollectionViewStyling.h */,
+				041B9228D9CF59ABFD7ACB6A1D468715 /* MDCCollectionViewStylingDelegate.h */,
+				0A0BC298073A7DBD29E89E8AB28AFF89 /* Resources */,
+			);
+			name = Collections;
+			sourceTree = "<group>";
+		};
+		53737E6E93B329D96F036A43EAF22646 /* Typography */ = {
+			isa = PBXGroup;
+			children = (
+				D1A37A0287C491DFE2089102146664E8 /* MaterialTypography.h */,
+				CD6BFB0EA4919F07C8AD5F586E34376D /* MDCFontTextStyle.h */,
+				07B2F589B283B574F2B354D14386BBF8 /* MDCFontTraits.h */,
+				DC384A83912E8C440C7ED70B794A89D2 /* MDCFontTraits.m */,
+				12D62C2A9C95A969E4AA727F1C8C202C /* MDCTypography.h */,
+				9A82FF56648D80F9E61096E9A07B06F6 /* MDCTypography.m */,
+				A8D106719F3F199D438233D94FDF43F5 /* UIFont+MaterialTypography.h */,
+				E17A7167DE53F6528C656D4979850FBC /* UIFont+MaterialTypography.m */,
+				6E75C79B7D5289097D15A811F188CED2 /* UIFont+MaterialTypographyPrivate.h */,
+				4277E14F56DAC15ABD24D97EDC26ADEA /* UIFont+MaterialTypographyPrivate.m */,
+				9E5285A7050BE78F06AD6EC2E4BF1A2F /* UIFontDescriptor+MaterialTypography.h */,
+				D7E1DE48A44A60C2AE808B6D69A73683 /* UIFontDescriptor+MaterialTypography.m */,
+			);
+			name = Typography;
+			sourceTree = "<group>";
+		};
+		57B3AC99860520DA3D05E9DCC199382E /* AnimationTiming */ = {
+			isa = PBXGroup;
+			children = (
+				74905502A1DF96D7D84E7714A179E9E9 /* CAMediaTimingFunction+MDCAnimationTiming.h */,
+				10B9C9D65FA83AC626EFF1C6A94BA402 /* CAMediaTimingFunction+MDCAnimationTiming.m */,
+				C075A49AEB6D1C36BA22C458FC6A2801 /* MaterialAnimationTiming.h */,
+				5894DCB5AAB8B32C781B6279A0FEF8D9 /* UIView+MDCTimingFunction.h */,
+				7941C852DB02A5C5D4BE708004028A52 /* UIView+MDCTimingFunction.m */,
+			);
+			name = AnimationTiming;
+			sourceTree = "<group>";
+		};
+		5A4DBD434EA75DD3EDD3494C46AE6968 /* iOS */ = {
+			isa = PBXGroup;
+			children = (
+				409899CE1143F81E8130E2069D59605B /* CoreGraphics.framework */,
+				12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */,
+				5F7BDB2580B244756CFA046131516EF2 /* QuartzCore.framework */,
+			);
+			name = iOS;
+			sourceTree = "<group>";
+		};
+		5B9B9BF255AED07DB6926B6422A71F1B /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				6F352D5A20ECA41E1A995B662456AFC4 /* MaterialComponents */,
+				0F4F0B2885DA4E9FDA72BB907CFEEBA1 /* MDFTextAccessibility */,
+			);
+			name = Pods;
+			sourceTree = "<group>";
+		};
+		5CCDE775C68B760973ABA074B79AA9A9 /* Targets Support Files */ = {
+			isa = PBXGroup;
+			children = (
+				3BD889F6E1BD87A35685DC18128AB26A /* Pods-BuildingBeautifulApps */,
+			);
+			name = "Targets Support Files";
+			sourceTree = "<group>";
+		};
+		5EB185DA3E833BE86F7173AD153ED92B /* CollectionCells */ = {
+			isa = PBXGroup;
+			children = (
+				A32E50911D7DB6FBC3E4CC4ECCBA1596 /* MaterialCollectionCells.h */,
+				29BB55A9B6803B9A3A7A064A6E797A79 /* MDCCollectionViewCell.h */,
+				BEBA1206741596666E53A5291AC6C67D /* MDCCollectionViewCell.m */,
+				8BF097DEAD72714A366668962C25EC9B /* MDCCollectionViewTextCell.h */,
+				158DFD17C32FF1158E4896DD754DDC6B /* MDCCollectionViewTextCell.m */,
+				E92ECD77FAAF62A64A87A141AB207123 /* Resources */,
+			);
+			name = CollectionCells;
+			sourceTree = "<group>";
+		};
+		5FC45D223B2D6C4904ECBE9DDC39C4DA /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				403CEE2F8B8AFCD9A8ADAD83045448CB /* ic_reorder.png */,
+				47BD4FBE1EC6F6C948B7056DFB3EAE4E /* ic_reorder@2x.png */,
+				87D692B9AD07C602ED145B594F3FF7D9 /* ic_reorder@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		635C52F44DD7D619304875A77DEECB7A /* Tabs */ = {
+			isa = PBXGroup;
+			children = (
+				0C1F25227166DC67A877DFCA5594F74B /* MaterialTabs.h */,
+				CADC6B616AB3936666BDBD42A2705DE6 /* MDCItemBar.h */,
+				BB3068591BFE9A9F8D1B79957A573691 /* MDCItemBar.m */,
+				5677CC19D390C501CCA90EEE390AAE6D /* MDCItemBarAlignment.h */,
+				E70A12012C34069A15DAAEF725754A18 /* MDCItemBarCell.h */,
+				01127A0CE1E1F9D661213AD37AC639FC /* MDCItemBarCell.m */,
+				EDD61B881B917B05AFD9539341F931FD /* MDCItemBarStringConstants.h */,
+				C4F53B72FA10D37719F9CB9924A08CBD /* MDCItemBarStyle.h */,
+				2792F28B4CCFEB1DCDCDBB8636947EBC /* MDCItemBarStyle.m */,
+				BDAF0CDE00CDA3F4B1CE9E7374239490 /* MDCTabBar.h */,
+				5D8DE150DA0161A584D8CED87D6DF987 /* MDCTabBar.m */,
+				B9E2AAB8153882A4590062F569A4D595 /* MDCTabBarAlignment.h */,
+				2FE6A5198039451C28C172BC4168A03A /* MDCTabBarItemAppearance.h */,
+				6EF06DBA252DBC3C63E36D49176DFF34 /* Resources */,
+			);
+			name = Tabs;
+			sourceTree = "<group>";
+		};
+		67DEEE835292D3753E9C9C944975A1F1 /* ShadowLayer */ = {
+			isa = PBXGroup;
+			children = (
+				77C440E4189E05E40980CE67AF6A977D /* MaterialShadowLayer.h */,
+				D8966C5049A9875A33A6802C9840E498 /* MDCShadowLayer.h */,
+				B6134FFEBB32CC196B45597FC2948611 /* MDCShadowLayer.m */,
+			);
+			name = ShadowLayer;
+			sourceTree = "<group>";
+		};
+		6906A22C03A392F2D5612B99843C7B16 /* AppBar */ = {
+			isa = PBXGroup;
+			children = (
+				2D0C383ECBB30F7ADEB6B1EFF274C298 /* MaterialAppBar.h */,
+				9CA3D76D548F43BB8F241C55FB9D5656 /* MDCAppBar.h */,
+				1D570439942906B139B693491F7E71ED /* MDCAppBar.m */,
+				1FA357A2956B620B50A4CAEFE8F1795B /* MDCAppBarContainerViewController.h */,
+				F7D2E69B90D1C23D2FBD5EB175B59364 /* MDCAppBarContainerViewController.m */,
+			);
+			name = AppBar;
+			sourceTree = "<group>";
+		};
+		6C7910AF3C49D2EF31AEB30319482C37 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				ACCED250D3351A0D22EEA492436EBE80 /* ic_info.png */,
+				029A97895F42B6AB7B7209A3BB20DCA8 /* ic_info@2x.png */,
+				5EBBA737C7DEFC62CB07A5607401B086 /* ic_info@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		6EF06DBA252DBC3C63E36D49176DFF34 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				94294D2C0E41046D41ED4D332EF32E37 /* MaterialTabs.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		6F352D5A20ECA41E1A995B662456AFC4 /* MaterialComponents */ = {
+			isa = PBXGroup;
+			children = (
+				860FDBF1491FEF45BBDC4B10C7A6029A /* ActivityIndicator */,
+				57B3AC99860520DA3D05E9DCC199382E /* AnimationTiming */,
+				6906A22C03A392F2D5612B99843C7B16 /* AppBar */,
+				DC5320477BAF4A05AE764444E095C05E /* ButtonBar */,
+				8B423F014C2BFE2D485F66E90BE4E37A /* Buttons */,
+				5EB185DA3E833BE86F7173AD153ED92B /* CollectionCells */,
+				9E6ABE4B858C2ADEC3217A48A6B64CD1 /* CollectionLayoutAttributes */,
+				4F83E7F2B19DDC28995A33F954D7B750 /* Collections */,
+				2D236E262784B2E75892C151B31D5BE2 /* Dialogs */,
+				B26BD90E467D23E0105D42B7F1AEC069 /* FeatureHighlight */,
+				7A385EB5D98EE940F9E0187E0DB19C51 /* FlexibleHeader */,
+				7BB4357B73230E3118EC1730397E5F7E /* HeaderStackView */,
+				79A5FC65EED1F300B4FEB2C7BF3792C4 /* Ink */,
+				E1408803AF660D6CADA8F86423AF95B1 /* NavigationBar */,
+				28B6E99744BA88E1C186F28B24BE34DB /* OverlayWindow */,
+				444ED16EF9B93203AFE8059068568CF6 /* PageControl */,
+				FF842A3362760880262DF2AB9BEA82D4 /* Palettes */,
+				BE9FCA4B7CA2E2C7250B24CC35C0564C /* private */,
+				14F3093C9EDA04FD806300494FD654F0 /* ProgressView */,
+				903888289A0980729917B492E52ED941 /* ShadowElevations */,
+				67DEEE835292D3753E9C9C944975A1F1 /* ShadowLayer */,
+				8B047C13A4435E40C995F275E36DE89D /* Slider */,
+				1A51286FBEFC155062FB53A0ADD4D106 /* Snackbar */,
+				15CB945DCEE15326848DB6EE1185BC50 /* Support Files */,
+				635C52F44DD7D619304875A77DEECB7A /* Tabs */,
+				53737E6E93B329D96F036A43EAF22646 /* Typography */,
+			);
+			name = MaterialComponents;
+			path = MaterialComponents;
+			sourceTree = "<group>";
+		};
+		766E4937EA799D9EC8B3869F8CEF6B5D /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				09A539046C55C092B1882F2B3101A656 /* libMaterialComponents.a */,
+				B6D338FD921EC51C550567AB2D429021 /* libMDFTextAccessibility.a */,
+				6B9A7110EE95FE54D52AC78F8943FF30 /* libPods-BuildingBeautifulApps.a */,
+				FF9E5D282080B168147A56CBC1A20CB3 /* MaterialIcons_ic_arrow_back.bundle */,
+				860E1A6AE14CC46812BFD2EECD3DF1B6 /* MaterialIcons_ic_check.bundle */,
+				430CFFC6D36F60111CDF22059398251D /* MaterialIcons_ic_check_circle.bundle */,
+				CB370B0CFF7E9F249F9A4A4A5C9828C0 /* MaterialIcons_ic_chevron_right.bundle */,
+				DBB2727B89FCF4B81EAB1F748F4EE6F7 /* MaterialIcons_ic_info.bundle */,
+				9F8BE2D8847C692FB18FCFEF6F294478 /* MaterialIcons_ic_radio_button_unchecked.bundle */,
+				D43D8FF7991737DB826BFF92EBF8ADFA /* MaterialIcons_ic_reorder.bundle */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		79A5FC65EED1F300B4FEB2C7BF3792C4 /* Ink */ = {
+			isa = PBXGroup;
+			children = (
+				1C21154B03011C9702C295079DCF65E1 /* MaterialInk.h */,
+				0750459EFB95F5CE725C61781848452B /* MDCInkGestureRecognizer.h */,
+				CAC43F65D5D78A89EAC07A697ACC9837 /* MDCInkGestureRecognizer.m */,
+				EA980654C37C923AB926DF64E7E02736 /* MDCInkLayer.h */,
+				E37F8FD7F722E714E0005FB0C96F9A03 /* MDCInkLayer.m */,
+				E47ED49AEF9D2FE77E92679C5569563D /* MDCInkTouchController.h */,
+				FF7A269A35FCA0697B0E5BD94453D3EF /* MDCInkTouchController.m */,
+				EF3D4AABE18C6B0D033BD47108A9156D /* MDCInkView.h */,
+				FC7FA8E220EACEBE9FB49B6A6B3732E5 /* MDCInkView.m */,
+			);
+			name = Ink;
+			sourceTree = "<group>";
+		};
+		7A385EB5D98EE940F9E0187E0DB19C51 /* FlexibleHeader */ = {
+			isa = PBXGroup;
+			children = (
+				9A7FE223E125A19DB7A772510BF0DEB2 /* MaterialFlexibleHeader.h */,
+				621F64FAC8A6CDF22ADF8271D04409C6 /* MDCFlexibleHeaderContainerViewController.h */,
+				536F8F8CBB3D5593CFA4CBFD765F3BED /* MDCFlexibleHeaderContainerViewController.m */,
+				6EE3924624B8CAFC171FD153BBFC8449 /* MDCFlexibleHeaderView.h */,
+				71BE7789CD2EC0A70DE711AC5A1FEF8D /* MDCFlexibleHeaderView.m */,
+				24A9F1821AD8EA4BF21E13D87EC6F56D /* MDCFlexibleHeaderViewController.h */,
+				6EAC67B229E26EFB3FEF38B7164183F0 /* MDCFlexibleHeaderViewController.m */,
+				2543C83779FCB7CA6F63B6E23BA22BDB /* MDCStatusBarShifter.h */,
+				7D86AB797FE0EAA5C5384DF417BF5346 /* MDCStatusBarShifter.m */,
+			);
+			name = FlexibleHeader;
+			sourceTree = "<group>";
+		};
+		7BB4357B73230E3118EC1730397E5F7E /* HeaderStackView */ = {
+			isa = PBXGroup;
+			children = (
+				702CBDDD852DAA7044CE6BCB5AA2D950 /* MaterialHeaderStackView.h */,
+				CE6929889D615189113913408E3D1B9E /* MDCHeaderStackView.h */,
+				EB1C6A347A3B1B5278B6179E7E7A6C7E /* MDCHeaderStackView.m */,
+			);
+			name = HeaderStackView;
+			sourceTree = "<group>";
+		};
+		7BBBBB41025DA2946E721C6B4CFE9582 /* ic_arrow_back */ = {
+			isa = PBXGroup;
+			children = (
+				804D865D3D4D4C65731A550B3D8FC9A5 /* MaterialIcons+ic_arrow_back.h */,
+				C830C5EEEAE60B4A9283F0C2F0A02094 /* MaterialIcons+ic_arrow_back.m */,
+				9F3E1632178E5C2029635BBAE94F3A0A /* Resources */,
+			);
+			name = ic_arrow_back;
+			sourceTree = "<group>";
+		};
+		7DB346D0F39D3F0E887471402A8071AB = {
+			isa = PBXGroup;
+			children = (
+				93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */,
+				122DA2E5084A4393C29BE363C764795C /* Frameworks */,
+				5B9B9BF255AED07DB6926B6422A71F1B /* Pods */,
+				766E4937EA799D9EC8B3869F8CEF6B5D /* Products */,
+				5CCDE775C68B760973ABA074B79AA9A9 /* Targets Support Files */,
+			);
+			sourceTree = "<group>";
+		};
+		860FDBF1491FEF45BBDC4B10C7A6029A /* ActivityIndicator */ = {
+			isa = PBXGroup;
+			children = (
+				7143C04351DADE6FD07918C99C3BF31E /* MaterialActivityIndicator.h */,
+				97262CDCD801553DA99ECC7847E39E98 /* MDCActivityIndicator.h */,
+				45DA800B226D1DE08F69E5BDDC45E203 /* MDCActivityIndicator.m */,
+			);
+			name = ActivityIndicator;
+			sourceTree = "<group>";
+		};
+		87E4ABB0C4383AF0F29468B14112DF80 /* ThumbTrack */ = {
+			isa = PBXGroup;
+			children = (
+				D11EB1CC12CA81275669C38699DF58A3 /* MaterialThumbTrack.h */,
+				C660FEA28DDB8CB873D9BCE3DA03F6B3 /* MDCNumericValueLabel.h */,
+				1E74B45D4E01DE3821E65C8FEC806B60 /* MDCNumericValueLabel.m */,
+				86754C059E8434587187015DC770180B /* MDCThumbTrack.h */,
+				9E05EB6FB230393D92DC9A1584D7DE50 /* MDCThumbTrack.m */,
+				D49CC986145361BA86D40441881692D8 /* MDCThumbView.h */,
+				8CCFBA02AEF1EB2D0EA744C7D87ADB76 /* MDCThumbView.m */,
+			);
+			name = ThumbTrack;
+			sourceTree = "<group>";
+		};
+		8B047C13A4435E40C995F275E36DE89D /* Slider */ = {
+			isa = PBXGroup;
+			children = (
+				60852389E40D9EF0F70B7BF97E7B998D /* MaterialSlider.h */,
+				0F8DD7BF09A1359D0C22AD2D99DF9967 /* MDCSlider.h */,
+				2862A3829BA4649EDB04191EB5D64C4B /* MDCSlider.m */,
+				14793E6FDAF9C044D6ED8B67E59C7E75 /* MDCSlider_Subclassable.h */,
+			);
+			name = Slider;
+			sourceTree = "<group>";
+		};
+		8B423F014C2BFE2D485F66E90BE4E37A /* Buttons */ = {
+			isa = PBXGroup;
+			children = (
+				4B9EBBBC413F2FB5A96D131DC26FFC36 /* MaterialButtons.h */,
+				12BE96DCA235623AF7766C60CCFAE1C7 /* MDCButton.h */,
+				BE257A301C797B8D3C24053EFEF0DB5A /* MDCButton.m */,
+				F82A46DDAA89ACF53DA3C47CC04971EF /* MDCButton+Subclassing.h */,
+				EFCF3D3D2FE3A10C4245EF66AE882178 /* MDCFlatButton.h */,
+				4F0E678DFEF2B507BAEF2FFD1EF23228 /* MDCFlatButton.m */,
+				E66CD057FB364E80D5BC3D34A00B42FF /* MDCFloatingButton.h */,
+				F64F50AD20E83F81710454204053A744 /* MDCFloatingButton.m */,
+				ABED23378B104A0A25435A6674F29FF5 /* MDCRaisedButton.h */,
+				B77E7CD1098848AED57761E60382667D /* MDCRaisedButton.m */,
+			);
+			name = Buttons;
+			sourceTree = "<group>";
+		};
+		8BBEF3ED9DC53D6F9F554679719F9E66 /* Support Files */ = {
+			isa = PBXGroup;
+			children = (
+				A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */,
+				8E961B158FE9954DDD2B6C09E3462883 /* MDFTextAccessibility-dummy.m */,
+				13DBFFD40004CC93DF060411AE7CB49F /* MDFTextAccessibility-prefix.pch */,
+			);
+			name = "Support Files";
+			path = "../Target Support Files/MDFTextAccessibility";
+			sourceTree = "<group>";
+		};
+		903888289A0980729917B492E52ED941 /* ShadowElevations */ = {
+			isa = PBXGroup;
+			children = (
+				03CE9EF2998E990D7C6C15AC4AEFF20D /* MaterialShadowElevations.h */,
+				7E855EBFE6A726985077571DB7E89BD5 /* MDCShadowElevations.h */,
+				CC56C512FD3A98A296C04156DD8DFEC9 /* MDCShadowElevations.m */,
+			);
+			name = ShadowElevations;
+			sourceTree = "<group>";
+		};
+		9E6ABE4B858C2ADEC3217A48A6B64CD1 /* CollectionLayoutAttributes */ = {
+			isa = PBXGroup;
+			children = (
+				444B921CA054B6ED8B57713242404400 /* MaterialCollectionLayoutAttributes.h */,
+				6677BBD93E7A4672F9AEA51236310EDF /* MDCCollectionViewLayoutAttributes.h */,
+				462854769E2CB8F1B329D4392C79AA61 /* MDCCollectionViewLayoutAttributes.m */,
+			);
+			name = CollectionLayoutAttributes;
+			sourceTree = "<group>";
+		};
+		9EC1DD96659E9FFC62849C078CDEDE6E /* Application */ = {
+			isa = PBXGroup;
+			children = (
+				51F9DCB161F252F8BD0F521356180A57 /* MaterialApplication.h */,
+				95D1CF13299CEF28BCBAA62F927A3D80 /* UIApplication+AppExtensions.h */,
+				5C4F931DA815928A8CA82E5513C6246A /* UIApplication+AppExtensions.m */,
+			);
+			name = Application;
+			sourceTree = "<group>";
+		};
+		9F3E1632178E5C2029635BBAE94F3A0A /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				15E9398FCB2DA33C5C08533B1716A7CE /* ic_arrow_back.png */,
+				11DD5A41B2DA0290521D16D24EEC529D /* ic_arrow_back@2x.png */,
+				FE7AE3A31ABEA928F10508D5385C37F8 /* ic_arrow_back@3x.png */,
+				7F9E8F936B7FA4CE55F6D4A70EDF478C /* ic_arrow_back_ios.png */,
+				33072B9B16A9B8DAAEDE9D6B449679D2 /* ic_arrow_back_ios@2x.png */,
+				E95DB580D0830673D87F39AEFDA6EF67 /* ic_arrow_back_ios@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		A8AC6F8EA0BF9331BC3179FC0941D312 /* ic_info */ = {
+			isa = PBXGroup;
+			children = (
+				FD4ED0BAB173C96E24BFAF538C1A0353 /* MaterialIcons+ic_info.h */,
+				B52A38C1D2775315C12601204EF0524E /* MaterialIcons+ic_info.m */,
+				6C7910AF3C49D2EF31AEB30319482C37 /* Resources */,
+			);
+			name = ic_info;
+			sourceTree = "<group>";
+		};
+		AF25FF466DBA2941E997767B393643DA /* RTL */ = {
+			isa = PBXGroup;
+			children = (
+				E88C708F20439859824CDC2F79216421 /* MaterialRTL.h */,
+				935B6D6F1FAB419F6C7B4129E6A0074F /* MDCRTL.h */,
+				B12139AB4284238F1123EB1E38B230E1 /* MDCRTL.m */,
+				6ECC1D1D41521DED2581889D20C4D8F9 /* UIImage+MaterialRTL.h */,
+				0EEA3ACEEB4A63D1DF01A8D3F89BC441 /* UIImage+MaterialRTL.m */,
+				1D9BC573FF76C294C05D43278D00B4A6 /* UIView+MaterialRTL.h */,
+				90B29DB14670F66061CFB82DDC68AF49 /* UIView+MaterialRTL.m */,
+			);
+			name = RTL;
+			sourceTree = "<group>";
+		};
+		B26BD90E467D23E0105D42B7F1AEC069 /* FeatureHighlight */ = {
+			isa = PBXGroup;
+			children = (
+				F5BEB5E003D1847D87CC74803474B2EF /* MaterialFeatureHighlight.h */,
+				EC8039BB5A86167E8DCDB72F46D6388B /* MDCFeatureHighlightAnimationController.h */,
+				D2FFA02DCC45D1EDB5D30FB9CEB3B9BD /* MDCFeatureHighlightAnimationController.m */,
+				1F0F8786C896495252AF8C693705FE27 /* MDCFeatureHighlightLayer.h */,
+				1B3462BC5FFFCC355901DAA536C77A5A /* MDCFeatureHighlightLayer.m */,
+				17B8A83C9148D87712E07EDE938E65E0 /* MDCFeatureHighlightView.h */,
+				13923E685C01C84D742BF61E9A51D084 /* MDCFeatureHighlightView.m */,
+				66E845FD6DDDE254DBD69B4B9FBCA3B8 /* MDCFeatureHighlightViewController.h */,
+				5C27D7602B81556831B0A85A92B4E5A3 /* MDCFeatureHighlightViewController.m */,
+			);
+			name = FeatureHighlight;
+			sourceTree = "<group>";
+		};
+		BC22755231123F8970B82180656CBC02 /* ic_check_circle */ = {
+			isa = PBXGroup;
+			children = (
+				263DB970C3B145399EBC89F15760FB2B /* MaterialIcons+ic_check_circle.h */,
+				443C58797FC89C1F0BDC6BDF82DD1913 /* MaterialIcons+ic_check_circle.m */,
+				CC9F919EA99C89421B37019CDB0A409E /* Resources */,
+			);
+			name = ic_check_circle;
+			sourceTree = "<group>";
+		};
+		BE9FCA4B7CA2E2C7250B24CC35C0564C /* private */ = {
+			isa = PBXGroup;
+			children = (
+				9EC1DD96659E9FFC62849C078CDEDE6E /* Application */,
+				015D80086EA2452E311127664AED6C49 /* Icons */,
+				FBD6A87FCC2224358E3A0DFA22CEEF3A /* KeyboardWatcher */,
+				0FFE22ED316D810F07A3CE1804C14671 /* Overlay */,
+				AF25FF466DBA2941E997767B393643DA /* RTL */,
+				87E4ABB0C4383AF0F29468B14112DF80 /* ThumbTrack */,
+			);
+			name = private;
+			sourceTree = "<group>";
+		};
+		BEB9000A25F7F69AB8A2CE63887588C6 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				C092C0ED18CF0F6D5A1391571F068348 /* MaterialPageControl.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		C0478CE6F06E1DD40878AE929472991C /* ic_chevron_right */ = {
+			isa = PBXGroup;
+			children = (
+				F398E51F9526801442D77BE9612F9C62 /* MaterialIcons+ic_chevron_right.h */,
+				654AA469F888FFF8F1CE4AA611FD6B69 /* MaterialIcons+ic_chevron_right.m */,
+				D046EF7CC52EAC0CA7A571CF2A25FC45 /* Resources */,
+			);
+			name = ic_chevron_right;
+			sourceTree = "<group>";
+		};
+		C8CCC6846666AAD0D3CA32B272E86A7F /* ic_reorder */ = {
+			isa = PBXGroup;
+			children = (
+				5B8E69C2D115A0FE03A563709E22B4ED /* MaterialIcons+ic_reorder.h */,
+				3F9391682535FDA07FBB0AB83B6B96E0 /* MaterialIcons+ic_reorder.m */,
+				5FC45D223B2D6C4904ECBE9DDC39C4DA /* Resources */,
+			);
+			name = ic_reorder;
+			sourceTree = "<group>";
+		};
+		CC9F919EA99C89421B37019CDB0A409E /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				11ED6DF86B1C41582FEF6983B868825F /* ic_check_circle.png */,
+				20A374DC73FDF4CF43A4454A86E587F6 /* ic_check_circle@2x.png */,
+				38A6CB047FC50FA03168F50ACA26C75B /* ic_check_circle@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		D046EF7CC52EAC0CA7A571CF2A25FC45 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				7EBAFD93350BF0CF6E8CE57A39A1FA5D /* ic_chevron_right.png */,
+				D5674E7D4BCC946A30114DBF9DB2F6CA /* ic_chevron_right@2x.png */,
+				35901EA242A4B2DE85C2894CC9194C1F /* ic_chevron_right@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		DC5320477BAF4A05AE764444E095C05E /* ButtonBar */ = {
+			isa = PBXGroup;
+			children = (
+				D14A347A944C556F216B967AFCF766C8 /* MaterialButtonBar.h */,
+				4FC2C7E47A0EA56BD6295D82B56F6192 /* MDCAppBarButtonBarBuilder.h */,
+				193A24743DF539FCD29F2B8EF21442F2 /* MDCAppBarButtonBarBuilder.m */,
+				4374B11D22F0FCC5866781A5F08A4D38 /* MDCButtonBar.h */,
+				FC8CB7864BDCD9DB97A3711AC446E2B0 /* MDCButtonBar.m */,
+				D79A92B4599903B71AD908CC7E5B0213 /* MDCButtonBar+Private.h */,
+			);
+			name = ButtonBar;
+			sourceTree = "<group>";
+		};
+		E1408803AF660D6CADA8F86423AF95B1 /* NavigationBar */ = {
+			isa = PBXGroup;
+			children = (
+				B73577CD8AEFE5DA6EB995CC8F2C92A7 /* MaterialNavigationBar.h */,
+				01B79C689F86C1C48EEBFE41AA191DBE /* MDCNavigationBar.h */,
+				CCF1F1AE19AF21CE8869CF3A681CC787 /* MDCNavigationBar.m */,
+			);
+			name = NavigationBar;
+			sourceTree = "<group>";
+		};
+		E92ECD77FAAF62A64A87A141AB207123 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				915F12E15D337DE30C909A4C3749EE83 /* MaterialCollectionCells.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		EC40E103B51AE1755CA03F26C6C066F1 /* ic_radio_button_unchecked */ = {
+			isa = PBXGroup;
+			children = (
+				97FBECBD5EF590F0A8005F8B94E808FF /* MaterialIcons+ic_radio_button_unchecked.h */,
+				C19F7B7784CFCB4369498613360AA4CB /* MaterialIcons+ic_radio_button_unchecked.m */,
+				4B0B90B01CFF775D9C7B38D466F294D0 /* Resources */,
+			);
+			name = ic_radio_button_unchecked;
+			sourceTree = "<group>";
+		};
+		F7107ECA24205B6455A55C23978D1621 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				7C5778E1102FA874A7F4F6FFD400C7DE /* ic_check.png */,
+				8917229D3430B609F88F33A180E7063C /* ic_check@2x.png */,
+				49A3FB5A7A3C2EEAAF7C7BD7C72CABBD /* ic_check@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		FBD6A87FCC2224358E3A0DFA22CEEF3A /* KeyboardWatcher */ = {
+			isa = PBXGroup;
+			children = (
+				F5A94E964BB75BF779F888AE07B3F95C /* MaterialKeyboardWatcher.h */,
+				BE4C70E576A2623B72B27F812FA19587 /* MDCKeyboardWatcher.h */,
+				06A99FC5FF2D8E635C719D756C525052 /* MDCKeyboardWatcher.m */,
+			);
+			name = KeyboardWatcher;
+			sourceTree = "<group>";
+		};
+		FF842A3362760880262DF2AB9BEA82D4 /* Palettes */ = {
+			isa = PBXGroup;
+			children = (
+				0EC4BB63283347849E4A8B02A60CABC4 /* MaterialPalettes.h */,
+				C4899C25A4830FCF08B2BB4F8ABC361A /* MDCPaletteExpansions.h */,
+				67D647688DBDE7C289D22CFAADF4006C /* MDCPaletteExpansions.m */,
+				C078D453FB972AF56047785185938933 /* MDCPaletteNames.h */,
+				98F8E9B6EBCFF521C01B78E4BD1039BD /* MDCPaletteNames.m */,
+				675F4FE5A00141BDF25CA3589A5DEF88 /* MDCPalettes.h */,
+				C9588139AB2E41A105B4F278EF0B01F3 /* MDCPalettes.m */,
+			);
+			name = Palettes;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		1BF21BF58E4EBE29C297FBEF774B04F0 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F81CCFD29E38C4B4669681176C4C53C0 /* MDFColorCalculations.h in Headers */,
+				421078E41926305DF11196F6FB28AD42 /* MDFImageCalculations.h in Headers */,
+				3109CBFCFA85CBFA88B4F9FA1F3A16D1 /* MDFTextAccessibility-Bridging-Header.h in Headers */,
+				984A454523FEF2464DED49EFB46F4D7D /* MDFTextAccessibility.h in Headers */,
+				1A0003B88CFC06F475A1A7D437E14A27 /* NSArray+MDFUtils.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		BD0D3F935DD310043B1C382E24090D3C /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E98184F9E8FBA7F587905DDDD0944848 /* CAMediaTimingFunction+MDCAnimationTiming.h in Headers */,
+				C2309CF5EBD904E226161D55F14B950A /* MaterialActivityIndicator.h in Headers */,
+				D07E00458702FE480F21B32777B0F013 /* MaterialAnimationTiming.h in Headers */,
+				A339971188CEF5E30398257AA87216D5 /* MaterialAppBar.h in Headers */,
+				9424985CFBD9108EAB15C67DE617DDD7 /* MaterialApplication.h in Headers */,
+				D448A87D1BC2FC2702156E6FE048F9BC /* MaterialButtonBar.h in Headers */,
+				DBAAB720813BBA54AD2126495BDAA7D2 /* MaterialButtons.h in Headers */,
+				47C39E63B795E98E36A83BBAC82BF86F /* MaterialCollectionCells.h in Headers */,
+				0D20BD182D66DBDD7E4D6CB7F77CF9F3 /* MaterialCollectionLayoutAttributes.h in Headers */,
+				BF73F5FFED03E771C41544D7E5AF7AB8 /* MaterialCollections.h in Headers */,
+				DC0601BB3966D321FDC30D767B44C37F /* MaterialCollectionsStrings.h in Headers */,
+				97B175A8C54E8AB93F6A1738A2E8AC32 /* MaterialCollectionsStrings_table.h in Headers */,
+				3D2BB082025D1252507C363E4714C625 /* MaterialDialogs.h in Headers */,
+				52C9FD65F3A7015BF99A651500F2D24C /* MaterialFeatureHighlight.h in Headers */,
+				48887AC621143DD5D40DBFE5A4E23883 /* MaterialFlexibleHeader.h in Headers */,
+				FB0210FF9893437C285475B18A6B25D6 /* MaterialHeaderStackView.h in Headers */,
+				9C989E66AB86785F2C11FFAC7EBC30A1 /* MaterialIcons+ic_arrow_back.h in Headers */,
+				945823B4D8C6E662F1C2CB08D268A088 /* MaterialIcons+ic_check.h in Headers */,
+				86115CB0ADDFA0C2DA2A6C8A2834A7FD /* MaterialIcons+ic_check_circle.h in Headers */,
+				3019DD7715B81601126A4182935F7DA9 /* MaterialIcons+ic_chevron_right.h in Headers */,
+				BBD17582B2F80BD702EF29C8B0E5D712 /* MaterialIcons+ic_info.h in Headers */,
+				E7D877B60FFD0FF706FDDFD568088D78 /* MaterialIcons+ic_radio_button_unchecked.h in Headers */,
+				9C71ADED3653D657A6F952A77DA208F7 /* MaterialIcons+ic_reorder.h in Headers */,
+				E90F58CF316377AF8434201C85BBEA50 /* MaterialIcons.h in Headers */,
+				0E47C9B2997E679B24FA498EE2363228 /* MaterialInk.h in Headers */,
+				4C2B4BA673669811FBFF71DF09D6F550 /* MaterialKeyboardWatcher.h in Headers */,
+				1C4083843A8D6038A7EAA2DD85FDC174 /* MaterialNavigationBar.h in Headers */,
+				A08E58F7C109094B2B88D50771692D44 /* MaterialOverlays.h in Headers */,
+				8B0BD0DC00C8B39EABBBA502C3CC424B /* MaterialOverlayWindow.h in Headers */,
+				B15972456A2F74F579179B9FA24B11A2 /* MaterialPageControl.h in Headers */,
+				96232A06DAC31122E30D7D5724150A83 /* MaterialPageControlStrings.h in Headers */,
+				3A2F4061FB79B93EA5C9B8DA9094EED5 /* MaterialPageControlStrings_table.h in Headers */,
+				B8A8D97688E58A1C843EE96397D81DF9 /* MaterialPalettes.h in Headers */,
+				3516A50767315A26E2D625A823474101 /* MaterialProgressView.h in Headers */,
+				7339A37AFA0F1A69B86239CE639CC15D /* MaterialRTL.h in Headers */,
+				173E8E625D765B2536A2145C9F528898 /* MaterialShadowElevations.h in Headers */,
+				7321A0DEBC74D9ED66E36F9A27FF0CCD /* MaterialShadowLayer.h in Headers */,
+				0617544187F62EC4C98A6BEE1428C5D6 /* MaterialSlider.h in Headers */,
+				CA4EF6FF105C4B45D26CC12A9F8CA011 /* MaterialSnackbar.h in Headers */,
+				04EC8CBF409C803BF749B2F9E8E38E0B /* MaterialTabs.h in Headers */,
+				7BF7E68DCF7F91851687A7D393812EC6 /* MaterialThumbTrack.h in Headers */,
+				C95B219DE3270084C28BE6FDDC86F2D5 /* MaterialTypography.h in Headers */,
+				1D8C9CF5687E222D0C1919213AA0116A /* MDCActivityIndicator.h in Headers */,
+				D6CEB0B38DC1554A3B1956CB6A11D892 /* MDCAlertController.h in Headers */,
+				1274CD4A2DD52C98C966921502C57446 /* MDCAppBar.h in Headers */,
+				FF37686F3E3AFF2F94C01E95A9CE2911 /* MDCAppBarButtonBarBuilder.h in Headers */,
+				DB772D2AC10FA285081B0AD22494A408 /* MDCAppBarContainerViewController.h in Headers */,
+				5685049F462A3F846BF0EA56103E153C /* MDCButton+Subclassing.h in Headers */,
+				4E8DA5386F2879E77B2E23D0E03C4A9B /* MDCButton.h in Headers */,
+				69CD5189E440D7767EE5B771A9FEE03D /* MDCButtonBar+Private.h in Headers */,
+				83FE983EC6EEC2C7ACAE955FCABFF518 /* MDCButtonBar.h in Headers */,
+				E4282287703DA962B61A39D1B0D8318D /* MDCCollectionGridBackgroundView.h in Headers */,
+				3BFFD555516224FB8FF319A087BCA29F /* MDCCollectionInfoBarView.h in Headers */,
+				C7AC330240BBC7E4EB43FE67062A461B /* MDCCollectionStringResources.h in Headers */,
+				CDAFC1E966DB3C899DE01EC81998EE9C /* MDCCollectionViewCell.h in Headers */,
+				81F752320FBCB9A12535E3AD2602AA27 /* MDCCollectionViewController.h in Headers */,
+				49C5DD0A16846BF2E4806A9510D2998D /* MDCCollectionViewEditing.h in Headers */,
+				4717C3070FA97344C11B65BACF2DDF3C /* MDCCollectionViewEditingDelegate.h in Headers */,
+				D053587851EF944EAC99AF4152E5BA75 /* MDCCollectionViewEditor.h in Headers */,
+				24CD705DC0032088FFF4C5DF861B0099 /* MDCCollectionViewFlowLayout.h in Headers */,
+				54BB836815554D4144AC9824136B8FA9 /* MDCCollectionViewLayoutAttributes.h in Headers */,
+				7BDC8151577B47E72BCB0F299F6654A8 /* MDCCollectionViewStyler.h in Headers */,
+				FA36A066EE5CF084A61B8E5CE4A50928 /* MDCCollectionViewStyling.h in Headers */,
+				67E00C690CF9CFB20C51270B46B6A1CB /* MDCCollectionViewStylingDelegate.h in Headers */,
+				451AD57BB35CAD3C692F082E93B99BF3 /* MDCCollectionViewTextCell.h in Headers */,
+				46CB2D9B298AA3F30C5D42BC04F39E94 /* MDCDialogPresentationController.h in Headers */,
+				F428458129C3701B14F25859C60F6C4A /* MDCDialogShadowedView.h in Headers */,
+				FD7FA96389A0CB49A6673EFF467DDAA3 /* MDCDialogTransitionController.h in Headers */,
+				A5847C5D55280D73543922B562E3EE76 /* MDCFeatureHighlightAnimationController.h in Headers */,
+				7F86C31F4F88FAD41263B8386772014A /* MDCFeatureHighlightLayer.h in Headers */,
+				ADB5ECE6B1779BB7CCB7C3468BADC052 /* MDCFeatureHighlightView.h in Headers */,
+				EBB65F826BFB14DC485D1126FA924591 /* MDCFeatureHighlightViewController.h in Headers */,
+				AF01D47F2E21218233A1FF787C75EBE2 /* MDCFlatButton.h in Headers */,
+				0B0FE5E1667FA17C1026EF1F92C1A63F /* MDCFlexibleHeaderContainerViewController.h in Headers */,
+				25160F444E7DF39397B6D6AFC4F07141 /* MDCFlexibleHeaderView.h in Headers */,
+				FCC2DBDF248F8D1B0759647AA9AADBC2 /* MDCFlexibleHeaderViewController.h in Headers */,
+				DEEF35853A0974C2FBE1D5F0DD7AE0BC /* MDCFloatingButton.h in Headers */,
+				F43265AC32261E3688370C90941A1C51 /* MDCFontTextStyle.h in Headers */,
+				67ED336DA6AA8B8497F1539842808631 /* MDCFontTraits.h in Headers */,
+				B6617FDF0F00EEA0091D859D88DDFD44 /* MDCHeaderStackView.h in Headers */,
+				610644D23738415ACB073C8B072244BB /* MDCIcons+BundleLoader.h in Headers */,
+				F5A806B7DF97350385E8C0AF48172DB2 /* MDCIcons.h in Headers */,
+				E88C4953B207850482CE8CAF646EB7F6 /* MDCInkGestureRecognizer.h in Headers */,
+				91A653669E3851452FCFCA0E2A7CB837 /* MDCInkLayer.h in Headers */,
+				6FBA9C40C2CC499C9E549022E8CC48A9 /* MDCInkTouchController.h in Headers */,
+				373D05814A0C88B4A0635C5A79FF822B /* MDCInkView.h in Headers */,
+				5CEE44CB5B97F207D902E967A7A28542 /* MDCItemBar.h in Headers */,
+				28D9B87B12B0ADC9D2B6D6A0DCADC59A /* MDCItemBarAlignment.h in Headers */,
+				FFCED3ABEBE505D648ECFB89C3B5A1DE /* MDCItemBarCell.h in Headers */,
+				274573598F1BA1A5256CA32D7689462A /* MDCItemBarStringConstants.h in Headers */,
+				88D4D6C491D0BB280CD6B6D01BDE39B9 /* MDCItemBarStyle.h in Headers */,
+				BCFF786BA8B6010F68220F150D77BC30 /* MDCKeyboardWatcher.h in Headers */,
+				F8E7DFFB95518F5BE25C98ACA633E003 /* MDCNavigationBar.h in Headers */,
+				BB463EFA3C52D5DDFFDAB937345C932F /* MDCNumericValueLabel.h in Headers */,
+				520EC00A1A0B6B3827DA1F4A7E655C0A /* MDCOverlayAnimationObserver.h in Headers */,
+				E9FEACB48E266BE82E3F563E89A57E55 /* MDCOverlayImplementor.h in Headers */,
+				624BA0196EC0BA2C9AAE7D4DE3AB068A /* MDCOverlayObserver.h in Headers */,
+				140D1BAA0F86861FA7A3A788F41C2DAC /* MDCOverlayObserverOverlay.h in Headers */,
+				81BAF4596ECCF3B2090CCEB24E981C7E /* MDCOverlayObserverTransition.h in Headers */,
+				7B1EB360F18CCF386C0AC46F154F0C9B /* MDCOverlayTransitioning.h in Headers */,
+				DACA2B285CD4608DBB73D72910DDCC3B /* MDCOverlayUtilities.h in Headers */,
+				218A5004AD1E67EDB82023BF74D6E81D /* MDCOverlayWindow.h in Headers */,
+				A2EE82AB4435B7F2278B816E9928C1AA /* MDCPageControl.h in Headers */,
+				5E944DEC856408844CB086300051AD03 /* MDCPageControlIndicator.h in Headers */,
+				F89C9B4B75A51557C4194C373983E7DD /* MDCPageControlTrackLayer.h in Headers */,
+				0E3515A7AE66C29F70F654BA2B8EA7BA /* MDCPaletteExpansions.h in Headers */,
+				4AC16280803615380CABD4379AA69D65 /* MDCPaletteNames.h in Headers */,
+				F2AF846BCE456A75743C8A76EFE8AC36 /* MDCPalettes.h in Headers */,
+				29508FF7916F5B95D6F4F940601AC975 /* MDCProgressView.h in Headers */,
+				866CA83566ACE3526AA5FABAB6E08CED /* MDCRaisedButton.h in Headers */,
+				FDBD2F6421CA1221915E3E4DE3B98C57 /* MDCRTL.h in Headers */,
+				AA10E060FCF509E24CEAEE87D2E80949 /* MDCShadowElevations.h in Headers */,
+				957F0F86EAB556C7CD058DF04A23F216 /* MDCShadowLayer.h in Headers */,
+				63793D388D09869517A2472AE9C612B3 /* MDCSlider.h in Headers */,
+				8334A8C5BB14AB374900D9A579A65096 /* MDCSlider_Subclassable.h in Headers */,
+				40FECE7BF976712334BCAD110F2E2051 /* MDCSnackbarManager.h in Headers */,
+				D846A62610497F25E2B7A537EA12C757 /* MDCSnackbarMessage.h in Headers */,
+				A1799A83EA43D62019EFFEE6D1523F79 /* MDCSnackbarMessageInternal.h in Headers */,
+				95DA110166E184835298E627C35F5B5C /* MDCSnackbarMessageView.h in Headers */,
+				6CE23956E33CA9B2981055C2A5541077 /* MDCSnackbarMessageViewInternal.h in Headers */,
+				293557804A5EBF6C30C51757363B057B /* MDCSnackbarOverlayView.h in Headers */,
+				79B778A18CC8304044870CCF0AF93C92 /* MDCStatusBarShifter.h in Headers */,
+				6E5609D839CCD3390C33DFDEC3502382 /* MDCTabBar.h in Headers */,
+				BF4527E139FB205D0EBD8F54FD8AF18D /* MDCTabBarAlignment.h in Headers */,
+				CC4BC92CDE1AA4B8613AB884E75FB2E4 /* MDCTabBarItemAppearance.h in Headers */,
+				DBCD145300C030FCA8C9F1D8C624216B /* MDCThumbTrack.h in Headers */,
+				2EB0AB22EC4D7AB16E9074A5013DD61C /* MDCThumbView.h in Headers */,
+				E5CA64F5137CB5A48B42C9BB8F8EE127 /* MDCTypography.h in Headers */,
+				B31AC47ADCCE328A838CCDFB76642B4D /* UIApplication+AppExtensions.h in Headers */,
+				97EE80E12A66CFDC2291192A6D690DA1 /* UIFont+MaterialTypography.h in Headers */,
+				B22A6ACFF10775AFE5312ADF4FB00ECC /* UIFont+MaterialTypographyPrivate.h in Headers */,
+				86CCCDEFFA251A9AB150EDB92E0BDCE4 /* UIFontDescriptor+MaterialTypography.h in Headers */,
+				7FAA92CCF3CE42E4265CD84238775669 /* UIImage+MaterialRTL.h in Headers */,
+				76FB19E59FB284927075877B825A67A6 /* UIView+MaterialRTL.h in Headers */,
+				9F337AC8E4B3FD0244949450C9FA822B /* UIView+MDCTimingFunction.h in Headers */,
+				CB68DFA2C9FC1A3435236521B0408CEE /* UIViewController+MaterialDialogs.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		063B0E6AFAF8DCF585379E4BCB2C7131 /* MaterialComponents-MaterialIcons_ic_chevron_right */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 3F7ABC9117313216EB86A842D3A56458 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_chevron_right" */;
+			buildPhases = (
+				D5CA2F82A40A254095FF9B7C0C6E6ED0 /* Sources */,
+				10CE89D4B6EA0CBA4230B7FA3FE04DE3 /* Frameworks */,
+				EE98E09657FE54D511C889A907255B98 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_chevron_right";
+			productName = "MaterialComponents-MaterialIcons_ic_chevron_right";
+			productReference = CB370B0CFF7E9F249F9A4A4A5C9828C0 /* MaterialIcons_ic_chevron_right.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		16E29731A9C9770DCC25F5A8A3ED71FA /* MaterialComponents-MaterialIcons_ic_info */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = A4FFB75C138E4CDA3F5386C74BF54FB1 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_info" */;
+			buildPhases = (
+				C3553527CE24E57E85CC0B99B45CBB69 /* Sources */,
+				142596A1D8F1283799C634488452D605 /* Frameworks */,
+				839CBB62A84B07725AEA9935C8274456 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_info";
+			productName = "MaterialComponents-MaterialIcons_ic_info";
+			productReference = DBB2727B89FCF4B81EAB1F748F4EE6F7 /* MaterialIcons_ic_info.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		19634FBF87D1F1FA955FF17A6BB5585E /* MaterialComponents-MaterialIcons_ic_radio_button_unchecked */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 5651E00E66CAF6F1E79453DD35C3FB00 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_radio_button_unchecked" */;
+			buildPhases = (
+				B604D0992F6963FF641E919D03F37519 /* Sources */,
+				68E4BC6B1D0B207D3F9298FC9505A73E /* Frameworks */,
+				876EC345CD610EAAF80C1868DBC537AA /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+			productName = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+			productReference = 9F8BE2D8847C692FB18FCFEF6F294478 /* MaterialIcons_ic_radio_button_unchecked.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		26C4686B7C9E9E7E4E77A332481D6196 /* MaterialComponents */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7B14FE9889C0D696F704111E1F0E9C6F /* Build configuration list for PBXNativeTarget "MaterialComponents" */;
+			buildPhases = (
+				825931AD29BDE0F7AF200E156A2C33EA /* Sources */,
+				AA767584440C8D2E1C217BA896C2796A /* Frameworks */,
+				BD0D3F935DD310043B1C382E24090D3C /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				32F900408371178EB800134DE248AAA8 /* PBXTargetDependency */,
+				632625506E7B6EC59E5961BBEA8854DA /* PBXTargetDependency */,
+				898FE7AC319E3ED34052F71E9D0BE37D /* PBXTargetDependency */,
+				8D9AC5C7FEE2D6B171694687487F3701 /* PBXTargetDependency */,
+				3CE4BDD049C05CBBB86987FA04F5D8E7 /* PBXTargetDependency */,
+				2A0C3ADA41D941D838232940BDE2076B /* PBXTargetDependency */,
+				A2732BABC5F45114656C696C61B9E7C1 /* PBXTargetDependency */,
+				5FCFFDFE6ED996AD11CC566808C07447 /* PBXTargetDependency */,
+			);
+			name = MaterialComponents;
+			productName = MaterialComponents;
+			productReference = 09A539046C55C092B1882F2B3101A656 /* libMaterialComponents.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 524F6DEAF1626D3D3F38300C46E2E942 /* Build configuration list for PBXNativeTarget "MDFTextAccessibility" */;
+			buildPhases = (
+				7F4D7723BB12E0EC91AEBC6B23CC8CD5 /* Sources */,
+				0490164F31DF4DFD21CB5B6C0C9C2828 /* Frameworks */,
+				1BF21BF58E4EBE29C297FBEF774B04F0 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = MDFTextAccessibility;
+			productName = MDFTextAccessibility;
+			productReference = B6D338FD921EC51C550567AB2D429021 /* libMDFTextAccessibility.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		827B847BE0C5521773C58E7A599CAD8D /* MaterialComponents-MaterialIcons_ic_arrow_back */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CC7BE8C55AE7F464F23B6EBDA2A73DA8 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_arrow_back" */;
+			buildPhases = (
+				EA618F0B994D2DD0B72131F1055443A0 /* Sources */,
+				7B63882D2EA962158694D9F4255CD668 /* Frameworks */,
+				7EDA433322A6D744439989E189CC6023 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_arrow_back";
+			productName = "MaterialComponents-MaterialIcons_ic_arrow_back";
+			productReference = FF9E5D282080B168147A56CBC1A20CB3 /* MaterialIcons_ic_arrow_back.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		AFFA60B0A14082D99BC69B83E990917F /* MaterialComponents-MaterialIcons_ic_reorder */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 892D4ECEBD307A77824E601B91911F7E /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_reorder" */;
+			buildPhases = (
+				33704B71CC0F5E694015731B788D1ED9 /* Sources */,
+				AFFB6859E3D5DB059AA62780279F1BFA /* Frameworks */,
+				F00F50DDE4719D170DB52573A8F0C4F1 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_reorder";
+			productName = "MaterialComponents-MaterialIcons_ic_reorder";
+			productReference = D43D8FF7991737DB826BFF92EBF8ADFA /* MaterialIcons_ic_reorder.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		C2EC108B302373D03D5F0A9EB5B55787 /* MaterialComponents-MaterialIcons_ic_check_circle */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = EAC712836DA82097060BEA2911374AE6 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check_circle" */;
+			buildPhases = (
+				E7B5F4908CD3AA75538A82DF89CF8899 /* Sources */,
+				05A8C2288619671B1A30A7EF4C739D71 /* Frameworks */,
+				1F0BEAADFE445C4F493876E5175E917F /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_check_circle";
+			productName = "MaterialComponents-MaterialIcons_ic_check_circle";
+			productReference = 430CFFC6D36F60111CDF22059398251D /* MaterialIcons_ic_check_circle.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		CC81BAB345F2D13D67703EDBFE5DFEFE /* Pods-BuildingBeautifulApps */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = C644C7353E6F78383A06A7910789EF03 /* Build configuration list for PBXNativeTarget "Pods-BuildingBeautifulApps" */;
+			buildPhases = (
+				A71B5F92A81592C0CDCFA1B721CDD4BD /* Sources */,
+				120E9482EC24B536DE2A5345E8B71E40 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				314C50DFC3461E84B3EA7B21D6AF6986 /* PBXTargetDependency */,
+				B18A9A072ED45E647C7FD129E60E231F /* PBXTargetDependency */,
+			);
+			name = "Pods-BuildingBeautifulApps";
+			productName = "Pods-BuildingBeautifulApps";
+			productReference = 6B9A7110EE95FE54D52AC78F8943FF30 /* libPods-BuildingBeautifulApps.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		EEA5B88E1ACE47BDFFC5FD0BBAA2A28C /* MaterialComponents-MaterialIcons_ic_check */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = EC5DC1C972130F562B5702C94306D164 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check" */;
+			buildPhases = (
+				0FF20C6B6E2BE811475F118AE5F72055 /* Sources */,
+				59F35B6B50BC5A7D99059FEC9B83AFB9 /* Frameworks */,
+				02106D26B2898B8D12579C4037186994 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_check";
+			productName = "MaterialComponents-MaterialIcons_ic_check";
+			productReference = 860E1A6AE14CC46812BFD2EECD3DF1B6 /* MaterialIcons_ic_check.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		D41D8CD98F00B204E9800998ECF8427E /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0830;
+				LastUpgradeCheck = 0700;
+			};
+			buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 7DB346D0F39D3F0E887471402A8071AB;
+			productRefGroup = 766E4937EA799D9EC8B3869F8CEF6B5D /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				26C4686B7C9E9E7E4E77A332481D6196 /* MaterialComponents */,
+				827B847BE0C5521773C58E7A599CAD8D /* MaterialComponents-MaterialIcons_ic_arrow_back */,
+				EEA5B88E1ACE47BDFFC5FD0BBAA2A28C /* MaterialComponents-MaterialIcons_ic_check */,
+				C2EC108B302373D03D5F0A9EB5B55787 /* MaterialComponents-MaterialIcons_ic_check_circle */,
+				063B0E6AFAF8DCF585379E4BCB2C7131 /* MaterialComponents-MaterialIcons_ic_chevron_right */,
+				16E29731A9C9770DCC25F5A8A3ED71FA /* MaterialComponents-MaterialIcons_ic_info */,
+				19634FBF87D1F1FA955FF17A6BB5585E /* MaterialComponents-MaterialIcons_ic_radio_button_unchecked */,
+				AFFA60B0A14082D99BC69B83E990917F /* MaterialComponents-MaterialIcons_ic_reorder */,
+				2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */,
+				CC81BAB345F2D13D67703EDBFE5DFEFE /* Pods-BuildingBeautifulApps */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		02106D26B2898B8D12579C4037186994 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				64BD87D6A0EE900D83D40B3A793CB98B /* ic_check.png in Resources */,
+				4C9D6933282639AAEDFCE3760D663370 /* ic_check@2x.png in Resources */,
+				DC2B567C06EA75C2EF988EE491DB370A /* ic_check@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		1F0BEAADFE445C4F493876E5175E917F /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D72106583CB3A2A6B758B48F27882B40 /* ic_check_circle.png in Resources */,
+				FB207298B52DA12C580DA33D926A33CE /* ic_check_circle@2x.png in Resources */,
+				2DE4DA16A223502BDAE19CB16707EA25 /* ic_check_circle@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7EDA433322A6D744439989E189CC6023 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				ABEC063A0D41BC10143B8DACF1B82237 /* ic_arrow_back.png in Resources */,
+				EA9BE12F0B4EC342AE180CDEAC34F8D3 /* ic_arrow_back@2x.png in Resources */,
+				DDD7A57F4148DC9FCC8DB0DAF6866E10 /* ic_arrow_back@3x.png in Resources */,
+				4211DA431C07D51F55AB2D9000F745DB /* ic_arrow_back_ios.png in Resources */,
+				2AA0B61EABF1D62E39ABB6309B1E93CB /* ic_arrow_back_ios@2x.png in Resources */,
+				4CBD21241E82CCBA918B0E72FF122FF7 /* ic_arrow_back_ios@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		839CBB62A84B07725AEA9935C8274456 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				24900323EF8B3538F240F4824D3BC843 /* ic_info.png in Resources */,
+				45002548D32FF2E02C25B5EA30BBCA89 /* ic_info@2x.png in Resources */,
+				A1F9E6ACAA85B87A9D8A087F80530FAF /* ic_info@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		876EC345CD610EAAF80C1868DBC537AA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				59F2E39B0B51CF3480C2FE2A1B3B0CBA /* ic_radio_button_unchecked.png in Resources */,
+				73D4A36BAE65B225B1CBC5EE9A9A802A /* ic_radio_button_unchecked@2x.png in Resources */,
+				091A8578BC600F0579CD4CB9A119DCD8 /* ic_radio_button_unchecked@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EE98E09657FE54D511C889A907255B98 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				54AC6E6DC67C3C418A85ED4983EC39D5 /* ic_chevron_right.png in Resources */,
+				978CE8B98451722A7BCB5F8ECF12F4D5 /* ic_chevron_right@2x.png in Resources */,
+				3C9EA68F25AD2F27CE9EA4F444C56FA6 /* ic_chevron_right@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F00F50DDE4719D170DB52573A8F0C4F1 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				93CA3734266496A1F281BDB7565FA671 /* ic_reorder.png in Resources */,
+				CB57A2838CE91AA87493A967057A9F50 /* ic_reorder@2x.png in Resources */,
+				051B40934BCB60C81579E65ED35CD7A0 /* ic_reorder@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		0FF20C6B6E2BE811475F118AE5F72055 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		33704B71CC0F5E694015731B788D1ED9 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F4D7723BB12E0EC91AEBC6B23CC8CD5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A6B49525465146B18DECD9B24AD878DE /* MDFColorCalculations.m in Sources */,
+				AB8705EA210EDB911167D97874D360FB /* MDFImageCalculations.m in Sources */,
+				C77D1E2CEA9AC648CCAE66DD64A12E57 /* MDFTextAccessibility-dummy.m in Sources */,
+				6C84F71A1D807C4CB432B7B933F4FF6F /* MDFTextAccessibility.m in Sources */,
+				A5CE5EE5A0CB5AC74A082871D0E4D0E2 /* NSArray+MDFUtils.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		825931AD29BDE0F7AF200E156A2C33EA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				63188636F2C3E07CE98221656B929588 /* CAMediaTimingFunction+MDCAnimationTiming.m in Sources */,
+				F7A7869F8EB0BB5B4F817AE17001B79A /* MaterialComponents-dummy.m in Sources */,
+				0EBDEC7917FC21DD3AD7979621EA2307 /* MaterialIcons+ic_arrow_back.m in Sources */,
+				E16F8810A88826A00D8AEFEA8382FCE0 /* MaterialIcons+ic_check.m in Sources */,
+				7F7F0348C4102A49883CD88C86E122CF /* MaterialIcons+ic_check_circle.m in Sources */,
+				3D2B20D0F1D2DF6518A6E97129778190 /* MaterialIcons+ic_chevron_right.m in Sources */,
+				203C4032B594FAEFC8C97B3AFB740B1D /* MaterialIcons+ic_info.m in Sources */,
+				14612015079E6E117DED63E2337F4346 /* MaterialIcons+ic_radio_button_unchecked.m in Sources */,
+				D143DDFD972B30645F3278852EE20F5B /* MaterialIcons+ic_reorder.m in Sources */,
+				6FE4364F0DE10004ECF20D68071F4739 /* MDCActivityIndicator.m in Sources */,
+				65E9B44BBB842E8838653E605F87B3CD /* MDCAlertController.m in Sources */,
+				677A054DB9F431CF6C98E570A8223F50 /* MDCAppBar.m in Sources */,
+				E21FBFA76EC56E1D06EB0CD35550A7F8 /* MDCAppBarButtonBarBuilder.m in Sources */,
+				9847503FD320C722569D661E21EB0B11 /* MDCAppBarContainerViewController.m in Sources */,
+				02B3889D3E871468F88E5DBE7E9C5E21 /* MDCButton.m in Sources */,
+				983CC3205216C917F8A2D94E439959F7 /* MDCButtonBar.m in Sources */,
+				5A23C9982240753826D25F3648BE3915 /* MDCCollectionGridBackgroundView.m in Sources */,
+				601F6E1396EAC24AD0DF4FC09872F769 /* MDCCollectionInfoBarView.m in Sources */,
+				75701D93C9E6E0E16551378FB6D15322 /* MDCCollectionStringResources.m in Sources */,
+				FAEBD8461B68C2706F8A208E3E596643 /* MDCCollectionViewCell.m in Sources */,
+				BD37D976E99C4BF895220E803F0CC41D /* MDCCollectionViewController.m in Sources */,
+				91EB3409BF51AE8448EC825B00CA7EC8 /* MDCCollectionViewEditor.m in Sources */,
+				2AB6A1D688CF1EA0FA6345D547CF931D /* MDCCollectionViewFlowLayout.m in Sources */,
+				C415FCA0E080D6BDAF30C011F5476604 /* MDCCollectionViewLayoutAttributes.m in Sources */,
+				53BB396FE274D0FB6F22F98138F0A130 /* MDCCollectionViewStyler.m in Sources */,
+				1B25CFC33E70C55ADB21117C2E0BC425 /* MDCCollectionViewTextCell.m in Sources */,
+				98FFEDEEDB14192496FB90B75B9CFFB3 /* MDCDialogPresentationController.m in Sources */,
+				3998D3B0FBE92AB251C8FE66F7214BF9 /* MDCDialogShadowedView.m in Sources */,
+				ED5BBB6CB14C9E62E7C62DCDD69C727E /* MDCDialogTransitionController.m in Sources */,
+				856224A034BF7897D5745C017D6E26BF /* MDCFeatureHighlightAnimationController.m in Sources */,
+				71FF2344ED69DD4EC1BD52B6334C79EE /* MDCFeatureHighlightLayer.m in Sources */,
+				701A7F5C929096A5A4AAD770AA8CC8A1 /* MDCFeatureHighlightView.m in Sources */,
+				E122D135F905A61F2F2BC12B5E752E8B /* MDCFeatureHighlightViewController.m in Sources */,
+				5EBEA9BE9A76AE4BA005EF74784B9739 /* MDCFlatButton.m in Sources */,
+				8B9D3A9491A4C5894D9BDB45F75C72EE /* MDCFlexibleHeaderContainerViewController.m in Sources */,
+				C1B17B6540AD304C1A39E0A37E19AE2C /* MDCFlexibleHeaderView.m in Sources */,
+				BF9A53B148F71E2405838165261131E7 /* MDCFlexibleHeaderViewController.m in Sources */,
+				68E150F63885364AA7143698177876C6 /* MDCFloatingButton.m in Sources */,
+				86ABC77AAAF3BB0E73978E7FD7B371AD /* MDCFontTraits.m in Sources */,
+				4A9EFA8C13DFEB3A8EF9E7AB8802A3D1 /* MDCHeaderStackView.m in Sources */,
+				05E5A4ADDD5472838AAB9FFF46AF2137 /* MDCIcons.m in Sources */,
+				B20E8D99109D62C4F51394FBE9CB4346 /* MDCInkGestureRecognizer.m in Sources */,
+				E09CE6C566DADA7AB46361EF95F0D4A2 /* MDCInkLayer.m in Sources */,
+				9CEE28601C484B8E43252D783AFF7A05 /* MDCInkTouchController.m in Sources */,
+				C1C7F298EA4326DF2C05351A740E1D8F /* MDCInkView.m in Sources */,
+				7673B57A3EAC6E8169C83EA5F68B70E4 /* MDCItemBar.m in Sources */,
+				74F5757E7D5A465C730D2AA937BE785C /* MDCItemBarCell.m in Sources */,
+				723E8EEE2D1B59FC03F6158CCF391D2C /* MDCItemBarStyle.m in Sources */,
+				5C146662CCCE2C78543F8A049B696E66 /* MDCKeyboardWatcher.m in Sources */,
+				D4D362E714758EDDEC809019CC26974C /* MDCNavigationBar.m in Sources */,
+				C212207098B33F8B829CE94A3706DB49 /* MDCNumericValueLabel.m in Sources */,
+				D3BC8C16993BC06EF08B9A0B91B81568 /* MDCOverlayAnimationObserver.m in Sources */,
+				6BA617C860537C13AE7EA0AF05DF96FA /* MDCOverlayObserver.m in Sources */,
+				704742BFFD1D9BAE18AC34F964C43044 /* MDCOverlayObserverOverlay.m in Sources */,
+				BFCDBAD98869A1F1A6BBEAF75E86F926 /* MDCOverlayObserverTransition.m in Sources */,
+				D2C9BED43BB4C6FA2D23424759A4EB2F /* MDCOverlayUtilities.m in Sources */,
+				34FBD1D58C8BD1C74A876169FB1C15CA /* MDCOverlayWindow.m in Sources */,
+				E4452C88A27E46E154E525C9840E1494 /* MDCPageControl.m in Sources */,
+				07484E38806037944055D0BF76806FA4 /* MDCPageControlIndicator.m in Sources */,
+				DF0C93BD3E28121899DB290E32612D14 /* MDCPageControlTrackLayer.m in Sources */,
+				195B84DD18A2352DA5EDEC2F347F0985 /* MDCPaletteExpansions.m in Sources */,
+				5180979CE3EEB34F06466107253D6BB1 /* MDCPaletteNames.m in Sources */,
+				7BC8DF38C236F0C73D8CB5F4D9E8DBAA /* MDCPalettes.m in Sources */,
+				0CD124B11142B650BF877996F9F0E07A /* MDCProgressView.m in Sources */,
+				C3A59E6F295659D872D65BFEB6832A34 /* MDCRaisedButton.m in Sources */,
+				2A316D54A91DA5CD37F5231CC2E36978 /* MDCRTL.m in Sources */,
+				10B1D8ED7E2CF740C124B7C74CDBB74E /* MDCShadowElevations.m in Sources */,
+				A53D190E021C5C1186AC498313F5366A /* MDCShadowLayer.m in Sources */,
+				AA6B9D4E09B8642FE07CA11093EFB762 /* MDCSlider.m in Sources */,
+				586B689107644E8DFF068DC9A1E927D6 /* MDCSnackbarManager.m in Sources */,
+				73A9FEFF284BE8244A83EE3E68694904 /* MDCSnackbarMessage.m in Sources */,
+				58FB26F7D268DF6E49DE32787ECF53B3 /* MDCSnackbarMessageView.m in Sources */,
+				87A2628E58EECA44CEDADB67AE99D7F7 /* MDCSnackbarOverlayView.m in Sources */,
+				BE43B4DB418BFA444DEE432B7F329C9C /* MDCStatusBarShifter.m in Sources */,
+				FF82D045067B9F2BE69E2C5772EEBAFE /* MDCTabBar.m in Sources */,
+				299DD5695C130C8315A9E5FA786ECEAB /* MDCThumbTrack.m in Sources */,
+				7A5C50000FFBA08EB5AEB031CB02508A /* MDCThumbView.m in Sources */,
+				8A714C7A8F488D84D189041AB5EA984F /* MDCTypography.m in Sources */,
+				A2CEADFD01F6E59D4D792EFC35289A97 /* UIApplication+AppExtensions.m in Sources */,
+				B818D6AEBD75B9F9CDC04357F55DF6EF /* UIFont+MaterialTypography.m in Sources */,
+				69EA046EE6873743400E09466C970A14 /* UIFont+MaterialTypographyPrivate.m in Sources */,
+				D6BE450D35006B7F2F83EB19CDC1B473 /* UIFontDescriptor+MaterialTypography.m in Sources */,
+				75CFCE1AB0C85EEC8F68A664771A0847 /* UIImage+MaterialRTL.m in Sources */,
+				AB01C09668E3D82190EAE5DC10E07CAA /* UIView+MaterialRTL.m in Sources */,
+				05FF239C8670278A10D7BD58DD5260E1 /* UIView+MDCTimingFunction.m in Sources */,
+				14D517DDB1CB758C5FAA1B5963590CDF /* UIViewController+MaterialDialogs.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		A71B5F92A81592C0CDCFA1B721CDD4BD /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5C20F66911408C3E193E604D21F47677 /* Pods-BuildingBeautifulApps-dummy.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		B604D0992F6963FF641E919D03F37519 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		C3553527CE24E57E85CC0B99B45CBB69 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D5CA2F82A40A254095FF9B7C0C6E6ED0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		E7B5F4908CD3AA75538A82DF89CF8899 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EA618F0B994D2DD0B72131F1055443A0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		2A0C3ADA41D941D838232940BDE2076B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_info";
+			target = 16E29731A9C9770DCC25F5A8A3ED71FA /* MaterialComponents-MaterialIcons_ic_info */;
+			targetProxy = 77F3D96E9E9ED94700A1F61B82743FBE /* PBXContainerItemProxy */;
+		};
+		314C50DFC3461E84B3EA7B21D6AF6986 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MDFTextAccessibility;
+			target = 2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */;
+			targetProxy = 17BCA1B89A11CC355E43FD3BFCD13C12 /* PBXContainerItemProxy */;
+		};
+		32F900408371178EB800134DE248AAA8 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MDFTextAccessibility;
+			target = 2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */;
+			targetProxy = F34B40D121BBEE584389E4FD1349C927 /* PBXContainerItemProxy */;
+		};
+		3CE4BDD049C05CBBB86987FA04F5D8E7 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_chevron_right";
+			target = 063B0E6AFAF8DCF585379E4BCB2C7131 /* MaterialComponents-MaterialIcons_ic_chevron_right */;
+			targetProxy = 26A37A36E1641BBB8CE2EDDFC8616CCD /* PBXContainerItemProxy */;
+		};
+		5FCFFDFE6ED996AD11CC566808C07447 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_reorder";
+			target = AFFA60B0A14082D99BC69B83E990917F /* MaterialComponents-MaterialIcons_ic_reorder */;
+			targetProxy = 39EA7F91F3A8B4BBE7EDA6E436B1836F /* PBXContainerItemProxy */;
+		};
+		632625506E7B6EC59E5961BBEA8854DA /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_arrow_back";
+			target = 827B847BE0C5521773C58E7A599CAD8D /* MaterialComponents-MaterialIcons_ic_arrow_back */;
+			targetProxy = 79BDE4F2A4F44762925D8ABCC802FDBA /* PBXContainerItemProxy */;
+		};
+		898FE7AC319E3ED34052F71E9D0BE37D /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_check";
+			target = EEA5B88E1ACE47BDFFC5FD0BBAA2A28C /* MaterialComponents-MaterialIcons_ic_check */;
+			targetProxy = 07B01A307DE976243C53CDA94B27C112 /* PBXContainerItemProxy */;
+		};
+		8D9AC5C7FEE2D6B171694687487F3701 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_check_circle";
+			target = C2EC108B302373D03D5F0A9EB5B55787 /* MaterialComponents-MaterialIcons_ic_check_circle */;
+			targetProxy = B92E0F607A56686D7F93C4B7757E85F5 /* PBXContainerItemProxy */;
+		};
+		A2732BABC5F45114656C696C61B9E7C1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+			target = 19634FBF87D1F1FA955FF17A6BB5585E /* MaterialComponents-MaterialIcons_ic_radio_button_unchecked */;
+			targetProxy = 8B33909233E6BAB3ED98C8FEB26CD2E6 /* PBXContainerItemProxy */;
+		};
+		B18A9A072ED45E647C7FD129E60E231F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MaterialComponents;
+			target = 26C4686B7C9E9E7E4E77A332481D6196 /* MaterialComponents */;
+			targetProxy = 94AE73493B374CDBE138E1C8D3A177CB /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		26A41178C802A87FA1AD4A3956B6AE95 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 120CFBE565880C2F4F462AAFCEBB37E5 /* Pods-BuildingBeautifulApps.release.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				MACH_O_TYPE = staticlib;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PODS_ROOT = "$(SRCROOT)";
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		287CBD65CDB3E73D2A9EA687E99A5751 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		2A7F72C933E47CDA496240F2DB012CCC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_arrow_back;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		2E3057527561F89CCF7C36156EA42661 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_info;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		31EACB913B5F8E3A5C01AFA41C7D6289 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		42F4DA7BA113F8850E6E6467FECD7C52 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_radio_button_unchecked;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		4E292B5527D60C961400A6DAD7DC288B /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_arrow_back;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		4E487F173E6C9664F4E9E26B9635D23C /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				COPY_PHASE_STRIP = NO;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"POD_CONFIGURATION_DEBUG=1",
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				ONLY_ACTIVE_ARCH = YES;
+				PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
+				STRIP_INSTALLED_PRODUCT = NO;
+				SYMROOT = "${SRCROOT}/../build";
+			};
+			name = Debug;
+		};
+		5DC26BFB28032F299B56B7044BC93363 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_reorder;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		65F909AC31A48502DA9CDC7270A6D92F /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_info;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		6C32666A141D43FD834C6383A3836F88 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MaterialComponents/MaterialComponents-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		6F0457C9499D58F5CAA67923DCDB19F1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_reorder;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		78467EE81EF50258F8C619B09A659B4F /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check_circle;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		82B23D2232C7A01F1938A674A4665348 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_chevron_right;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		9BBC2037B7A2FA8F55E4C50B43624CC9 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		9C5B0D020E4C763E746EE2589F8D88DD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 02AE1C5FFC5FC596ABEC7C98AEF62DD8 /* Pods-BuildingBeautifulApps.debug.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				MACH_O_TYPE = staticlib;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PODS_ROOT = "$(SRCROOT)";
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		AE5C6E7CD6F75A92598D888038A66873 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check_circle;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		BDD0139D6EB93FA375F887ABD62DAB2E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"POD_CONFIGURATION_RELEASE=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
+				STRIP_INSTALLED_PRODUCT = NO;
+				SYMROOT = "${SRCROOT}/../build";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		E490E9C2F965850E4BA4D30EC78FB5F8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_chevron_right;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		EE8AED0DB82801B10AD5298ABA16D730 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MaterialComponents/MaterialComponents-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		F6EF1039304C9649537A65ED79C81CC1 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_radio_button_unchecked;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		F82ACD5AEAD83427020470C7DA4A22E1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4E487F173E6C9664F4E9E26B9635D23C /* Debug */,
+				BDD0139D6EB93FA375F887ABD62DAB2E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		3F7ABC9117313216EB86A842D3A56458 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_chevron_right" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				82B23D2232C7A01F1938A674A4665348 /* Debug */,
+				E490E9C2F965850E4BA4D30EC78FB5F8 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		524F6DEAF1626D3D3F38300C46E2E942 /* Build configuration list for PBXNativeTarget "MDFTextAccessibility" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9BBC2037B7A2FA8F55E4C50B43624CC9 /* Debug */,
+				287CBD65CDB3E73D2A9EA687E99A5751 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		5651E00E66CAF6F1E79453DD35C3FB00 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_radio_button_unchecked" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F6EF1039304C9649537A65ED79C81CC1 /* Debug */,
+				42F4DA7BA113F8850E6E6467FECD7C52 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7B14FE9889C0D696F704111E1F0E9C6F /* Build configuration list for PBXNativeTarget "MaterialComponents" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				EE8AED0DB82801B10AD5298ABA16D730 /* Debug */,
+				6C32666A141D43FD834C6383A3836F88 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		892D4ECEBD307A77824E601B91911F7E /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_reorder" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				5DC26BFB28032F299B56B7044BC93363 /* Debug */,
+				6F0457C9499D58F5CAA67923DCDB19F1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		A4FFB75C138E4CDA3F5386C74BF54FB1 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_info" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				65F909AC31A48502DA9CDC7270A6D92F /* Debug */,
+				2E3057527561F89CCF7C36156EA42661 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C644C7353E6F78383A06A7910789EF03 /* Build configuration list for PBXNativeTarget "Pods-BuildingBeautifulApps" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9C5B0D020E4C763E746EE2589F8D88DD /* Debug */,
+				26A41178C802A87FA1AD4A3956B6AE95 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CC7BE8C55AE7F464F23B6EBDA2A73DA8 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_arrow_back" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2A7F72C933E47CDA496240F2DB012CCC /* Debug */,
+				4E292B5527D60C961400A6DAD7DC288B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		EAC712836DA82097060BEA2911374AE6 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check_circle" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				AE5C6E7CD6F75A92598D888038A66873 /* Debug */,
+				78467EE81EF50258F8C619B09A659B4F /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		EC5DC1C972130F562B5702C94306D164 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				31EACB913B5F8E3A5C01AFA41C7D6289 /* Debug */,
+				F82ACD5AEAD83427020470C7DA4A22E1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MDFTextAccessibility.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MDFTextAccessibility.xcscheme
new file mode 100644
index 0000000..18c0c00
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MDFTextAccessibility.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '2E72C96C2685FC808D51BA6B9AA64CF4'
+               BlueprintName = 'MDFTextAccessibility'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'libMDFTextAccessibility.a'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme
new file mode 100644
index 0000000..01458fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '827B847BE0C5521773C58E7A599CAD8D'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_arrow_back'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_arrow_back.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check.xcscheme
new file mode 100644
index 0000000..fd44e2a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'EEA5B88E1ACE47BDFFC5FD0BBAA2A28C'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_check'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_check.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check_circle.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check_circle.xcscheme
new file mode 100644
index 0000000..99be795
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check_circle.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'C2EC108B302373D03D5F0A9EB5B55787'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_check_circle'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_check_circle.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme
new file mode 100644
index 0000000..dcc3b83
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '063B0E6AFAF8DCF585379E4BCB2C7131'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_chevron_right'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_chevron_right.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_info.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_info.xcscheme
new file mode 100644
index 0000000..0ad6725
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_info.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '16E29731A9C9770DCC25F5A8A3ED71FA'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_info'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_info.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme
new file mode 100644
index 0000000..95e4dcc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '19634FBF87D1F1FA955FF17A6BB5585E'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_radio_button_unchecked'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_radio_button_unchecked.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_reorder.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_reorder.xcscheme
new file mode 100644
index 0000000..dda74d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_reorder.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'AFFA60B0A14082D99BC69B83E990917F'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_reorder'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_reorder.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents.xcscheme
new file mode 100644
index 0000000..fedc528
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '26C4686B7C9E9E7E4E77A332481D6196'
+               BlueprintName = 'MaterialComponents'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'libMaterialComponents.a'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/Pods-BuildingBeautifulApps.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/Pods-BuildingBeautifulApps.xcscheme
new file mode 100644
index 0000000..eceb195
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/Pods-BuildingBeautifulApps.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'CC81BAB345F2D13D67703EDBFE5DFEFE'
+               BlueprintName = 'Pods-BuildingBeautifulApps'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'libPods-BuildingBeautifulApps.a'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/xcschememanagement.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..99cc136
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>MDFTextAccessibility.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>8</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>1</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_check.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>2</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_check_circle.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>3</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>4</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_info.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>5</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>6</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_reorder.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>7</integer>
+		</dict>
+		<key>MaterialComponents.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+		<key>Pods-BuildingBeautifulApps.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>9</integer>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>063B0E6AFAF8DCF585379E4BCB2C7131</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>16E29731A9C9770DCC25F5A8A3ED71FA</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>19634FBF87D1F1FA955FF17A6BB5585E</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>26C4686B7C9E9E7E4E77A332481D6196</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>2E72C96C2685FC808D51BA6B9AA64CF4</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>827B847BE0C5521773C58E7A599CAD8D</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>AFFA60B0A14082D99BC69B83E990917F</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>C2EC108B302373D03D5F0A9EB5B55787</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>CC81BAB345F2D13D67703EDBFE5DFEFE</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>EEA5B88E1ACE47BDFFC5FD0BBAA2A28C</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-dummy.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-dummy.m
new file mode 100644
index 0000000..1c4041a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_MDFTextAccessibility : NSObject
+@end
+@implementation PodsDummy_MDFTextAccessibility
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch
new file mode 100644
index 0000000..beb2a24
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch
@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility.xcconfig
new file mode 100644
index 0000000..40ebbb7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility.xcconfig
@@ -0,0 +1,9 @@
+CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/MDFTextAccessibility
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents-dummy.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents-dummy.m
new file mode 100644
index 0000000..6ba91fd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_MaterialComponents : NSObject
+@end
+@implementation PodsDummy_MaterialComponents
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents-prefix.pch b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents-prefix.pch
new file mode 100644
index 0000000..beb2a24
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents-prefix.pch
@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents.xcconfig
new file mode 100644
index 0000000..cf0750c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/MaterialComponents.xcconfig
@@ -0,0 +1,11 @@
+CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/MaterialComponents
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MaterialComponents" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility"
+OTHER_LDFLAGS = -framework "CoreGraphics" -framework "QuartzCore"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/MaterialComponents
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.markdown b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.markdown
new file mode 100644
index 0000000..488d4d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.markdown
@@ -0,0 +1,415 @@
+# Acknowledgements
+This application makes use of the following third party libraries:
+
+## MDFTextAccessibility
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+## MaterialComponents
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+Generated by CocoaPods - https://cocoapods.org
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.plist
new file mode 100644
index 0000000..3707be8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.plist
@@ -0,0 +1,453 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>PreferenceSpecifiers</key>
+	<array>
+		<dict>
+			<key>FooterText</key>
+			<string>This application makes use of the following third party libraries:</string>
+			<key>Title</key>
+			<string>Acknowledgements</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+</string>
+			<key>License</key>
+			<string>Apache License, Version 2.0</string>
+			<key>Title</key>
+			<string>MDFTextAccessibility</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+</string>
+			<key>License</key>
+			<string>Apache 2.0</string>
+			<key>Title</key>
+			<string>MaterialComponents</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>Generated by CocoaPods - https://cocoapods.org</string>
+			<key>Title</key>
+			<string></string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+	</array>
+	<key>StringsTable</key>
+	<string>Acknowledgements</string>
+	<key>Title</key>
+	<string>Acknowledgements</string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-dummy.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-dummy.m
new file mode 100644
index 0000000..7efe4e0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_BuildingBeautifulApps : NSObject
+@end
+@implementation PodsDummy_Pods_BuildingBeautifulApps
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh
new file mode 100755
index 0000000..0f29f13
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+set -e
+
+echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+
+SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
+
+install_framework()
+{
+  if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
+    local source="${BUILT_PRODUCTS_DIR}/$1"
+  elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
+    local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
+  elif [ -r "$1" ]; then
+    local source="$1"
+  fi
+
+  local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+
+  if [ -L "${source}" ]; then
+      echo "Symlinked..."
+      source="$(readlink "${source}")"
+  fi
+
+  # use filter instead of exclude so missing patterns dont' throw errors
+  echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
+  rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
+
+  local basename
+  basename="$(basename -s .framework "$1")"
+  binary="${destination}/${basename}.framework/${basename}"
+  if ! [ -r "$binary" ]; then
+    binary="${destination}/${basename}"
+  fi
+
+  # Strip invalid architectures so "fat" simulator / device frameworks work on device
+  if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
+    strip_invalid_archs "$binary"
+  fi
+
+  # Resign the code if required by the build settings to avoid unstable apps
+  code_sign_if_enabled "${destination}/$(basename "$1")"
+
+  # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
+  if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
+    local swift_runtime_libs
+    swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u  && exit ${PIPESTATUS[0]})
+    for lib in $swift_runtime_libs; do
+      echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
+      rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
+      code_sign_if_enabled "${destination}/${lib}"
+    done
+  fi
+}
+
+# Signs a framework with the provided identity
+code_sign_if_enabled() {
+  if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
+    # Use the current code_sign_identitiy
+    echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
+    local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
+
+    if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
+      code_sign_cmd="$code_sign_cmd &"
+    fi
+    echo "$code_sign_cmd"
+    eval "$code_sign_cmd"
+  fi
+}
+
+# Strip invalid architectures
+strip_invalid_archs() {
+  binary="$1"
+  # Get architectures for current file
+  archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
+  stripped=""
+  for arch in $archs; do
+    if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
+      # Strip non-valid architectures in-place
+      lipo -remove "$arch" -output "$binary" "$binary" || exit 1
+      stripped="$stripped $arch"
+    fi
+  done
+  if [[ "$stripped" ]]; then
+    echo "Stripped $binary of architectures:$stripped"
+  fi
+}
+
+if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
+  wait
+fi
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh
new file mode 100755
index 0000000..41487d8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+set -e
+
+mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+
+RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
+> "$RESOURCES_TO_COPY"
+
+XCASSET_FILES=()
+
+case "${TARGETED_DEVICE_FAMILY}" in
+  1,2)
+    TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
+    ;;
+  1)
+    TARGET_DEVICE_ARGS="--target-device iphone"
+    ;;
+  2)
+    TARGET_DEVICE_ARGS="--target-device ipad"
+    ;;
+  3)
+    TARGET_DEVICE_ARGS="--target-device tv"
+    ;;
+  4)
+    TARGET_DEVICE_ARGS="--target-device watch"
+    ;;
+  *)
+    TARGET_DEVICE_ARGS="--target-device mac"
+    ;;
+esac
+
+install_resource()
+{
+  if [[ "$1" = /* ]] ; then
+    RESOURCE_PATH="$1"
+  else
+    RESOURCE_PATH="${PODS_ROOT}/$1"
+  fi
+  if [[ ! -e "$RESOURCE_PATH" ]] ; then
+    cat << EOM
+error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
+EOM
+    exit 1
+  fi
+  case $RESOURCE_PATH in
+    *.storyboard)
+      echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
+      ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
+      ;;
+    *.xib)
+      echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
+      ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
+      ;;
+    *.framework)
+      echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      ;;
+    *.xcdatamodel)
+      echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
+      xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
+      ;;
+    *.xcdatamodeld)
+      echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
+      xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
+      ;;
+    *.xcmappingmodel)
+      echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
+      xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
+      ;;
+    *.xcassets)
+      ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
+      XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
+      ;;
+    *)
+      echo "$RESOURCE_PATH"
+      echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
+      ;;
+  esac
+}
+if [[ "$CONFIGURATION" == "Debug" ]]; then
+  install_resource "MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle"
+  install_resource "MaterialComponents/components/Collections/src/MaterialCollections.bundle"
+  install_resource "MaterialComponents/components/PageControl/src/MaterialPageControl.bundle"
+  install_resource "MaterialComponents/components/Tabs/src/MaterialTabs.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_arrow_back.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check_circle.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_chevron_right.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_info.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_radio_button_unchecked.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_reorder.bundle"
+fi
+if [[ "$CONFIGURATION" == "Release" ]]; then
+  install_resource "MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle"
+  install_resource "MaterialComponents/components/Collections/src/MaterialCollections.bundle"
+  install_resource "MaterialComponents/components/PageControl/src/MaterialPageControl.bundle"
+  install_resource "MaterialComponents/components/Tabs/src/MaterialTabs.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_arrow_back.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check_circle.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_chevron_right.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_info.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_radio_button_unchecked.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_reorder.bundle"
+fi
+
+mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
+  mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+  rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
+rm -f "$RESOURCES_TO_COPY"
+
+if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
+then
+  # Find all other xcassets (this unfortunately includes those of path pods and other targets).
+  OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
+  while read line; do
+    if [[ $line != "${PODS_ROOT}*" ]]; then
+      XCASSET_FILES+=("$line")
+    fi
+  done <<<"$OTHER_XCASSETS"
+
+  printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig
new file mode 100644
index 0000000..9efe4c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig
@@ -0,0 +1,9 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility" "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" -isystem "${PODS_ROOT}/Headers/Public/MaterialComponents"
+OTHER_LDFLAGS = $(inherited) -ObjC -l"MDFTextAccessibility" -l"MaterialComponents" -framework "CoreGraphics" -framework "QuartzCore"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
+PODS_ROOT = ${SRCROOT}/Pods
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig
new file mode 100644
index 0000000..9efe4c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Complete/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig
@@ -0,0 +1,9 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility" "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" -isystem "${PODS_ROOT}/Headers/Public/MaterialComponents"
+OTHER_LDFLAGS = $(inherited) -ObjC -l"MDFTextAccessibility" -l"MaterialComponents" -framework "CoreGraphics" -framework "QuartzCore"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
+PODS_ROOT = ${SRCROOT}/Pods
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/AppDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/AppDelegate.h
new file mode 100644
index 0000000..52e80c4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/AppDelegate.h
@@ -0,0 +1,24 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@end
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/AppDelegate.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/AppDelegate.m
new file mode 100644
index 0000000..0a1c30b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/AppDelegate.m
@@ -0,0 +1,63 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "AppDelegate.h"
+#import "ProductGridViewController.h"
+#import "ProductStorageHelper.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+
+  // Instantiate a UITabBarController with 3 ProductGridViewControllers
+  NSString *const mainStoryboardName = @"ProductGrid";
+  ProductGridViewController *home = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil].instantiateInitialViewController;
+  home.isHome = YES;
+  home.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -4);
+  home.tabBarItem.title = @"Home";
+  home.tabBarItem.image = [UIImage imageNamed:@"Diamond"];
+  home.products = productsFor(ProductCategoryHome);
+
+  ProductGridViewController *clothing = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil].instantiateInitialViewController;
+  clothing.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -4);
+  clothing.tabBarItem.title = @"Clothing";
+  clothing.tabBarItem.image = [UIImage imageNamed:@"HeartFull"];
+  clothing.products = productsFor(ProductCategoryClothing);
+
+  ProductGridViewController *popsicles = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil].instantiateInitialViewController;
+  popsicles.tabBarItem.titlePositionAdjustment = UIOffsetMake(0, -4);
+  popsicles.tabBarItem.title = @"Popsicles";
+  popsicles.tabBarItem.image = [UIImage imageNamed:@"Cart"];
+  popsicles.products = productsFor(ProductCategoryPopsicles);
+
+  UITabBarController *tabBarController = [[UITabBarController alloc] init];
+  tabBarController.viewControllers = @[ clothing, home, popsicles ];
+  tabBarController.tabBar.tintColor = [UIColor colorWithRed:96/255.0 green:125/255.0 blue:139/255.0 alpha:1];
+  tabBarController.selectedIndex = 1;
+
+  // Make the UITabBarController the main interface of the app
+  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+  self.window.rootViewController = tabBarController;
+  [self.window makeKeyAndVisible];
+
+  return YES;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..e21c852
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,98 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "logo2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "logo3x.png",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "logo_76.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "logo_76_2x.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "83.5x83.5",
+      "idiom" : "ipad",
+      "filename" : "logo_167.png",
+      "scale" : "2x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo2x.png
new file mode 100644
index 0000000..c72c0c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo3x.png
new file mode 100644
index 0000000..01a53b6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_167.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_167.png
new file mode 100644
index 0000000..8843740
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_167.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76.png
new file mode 100644
index 0000000..b55437f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76_2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76_2x.png
new file mode 100644
index 0000000..d36c2e4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/AppIcon.appiconset/logo_76_2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart.png
new file mode 100644
index 0000000..4eec7bb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@2x.png
new file mode 100644
index 0000000..c92dc6e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@3x.png
new file mode 100644
index 0000000..fc24519
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Cart@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Contents.json
new file mode 100644
index 0000000..f8c76ae
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Cart.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "Cart.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Cart@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Cart@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..da4a164
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Contents.json
new file mode 100644
index 0000000..08bad59
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "Diamond.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Diamond@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "Diamond@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond.png
new file mode 100644
index 0000000..bf00e92
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@2x.png
new file mode 100644
index 0000000..ac2cd5a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@3x.png
new file mode 100644
index 0000000..d3c667e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/Diamond.imageset/Diamond@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/Contents.json
new file mode 100644
index 0000000..fa1c88e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "HeartEmpty.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartEmpty@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartEmpty@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty.png
new file mode 100644
index 0000000..97115f7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@2x.png
new file mode 100644
index 0000000..85b0f2b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@3x.png
new file mode 100644
index 0000000..11ee824
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartEmpty.imageset/HeartEmpty@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/Contents.json
new file mode 100644
index 0000000..bce9af1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "HeartOpaque.png",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartOpaque@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "HeartOpaque@3x.png",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque.png
new file mode 100644
index 0000000..37796f8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@2x.png
new file mode 100644
index 0000000..5b7d16e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@3x.png
new file mode 100644
index 0000000..78b13e6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/HeartFull.imageset/HeartOpaque@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Contents.json
new file mode 100644
index 0000000..9978607
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "Shrine_logo_launchscreen.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Shrine_logo_launchscreen.pdf b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Shrine_logo_launchscreen.pdf
new file mode 100644
index 0000000..beb3e1e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLaunchLogo.imageset/Shrine_logo_launchscreen.pdf
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/Contents.json
new file mode 100644
index 0000000..2d8fc36
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "shrine_logo_withicon.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/shrine_logo_withicon.pdf b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/shrine_logo_withicon.pdf
new file mode 100644
index 0000000..a16bede
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineLogo.imageset/shrine_logo_withicon.pdf
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/Contents.json b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/Contents.json
new file mode 100644
index 0000000..35488c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/Contents.json
@@ -0,0 +1,12 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "filename" : "shrine_text_logo.pdf"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/shrine_text_logo.pdf b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/shrine_text_logo.pdf
new file mode 100644
index 0000000..4842ea2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Assets.xcassets/ShrineTextLogo.imageset/shrine_text_logo.pdf
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Base.lproj/LaunchScreen.storyboard b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..fdf3f97
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
+                        <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Base.lproj/ProductGrid.storyboard b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Base.lproj/ProductGrid.storyboard
new file mode 100644
index 0000000..042ad8a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Base.lproj/ProductGrid.storyboard
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="a5o-Vp-6qw">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+        <capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--Product Grid View Controller-->
+        <scene sceneID="Lyg-Jc-kew">
+            <objects>
+                <collectionViewController id="a5o-Vp-6qw" customClass="ProductGridViewController" sceneMemberID="viewController">
+                    <collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="KFO-tS-zxM">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="U4F-Lr-tIB">
+                            <size key="itemSize" width="157" height="191"/>
+                            <size key="headerReferenceSize" width="0.0" height="0.0"/>
+                            <size key="footerReferenceSize" width="0.0" height="0.0"/>
+                            <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
+                        </collectionViewFlowLayout>
+                        <cells>
+                            <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="cell" id="Cs7-hN-5ih" customClass="ProductCollectionViewCell">
+                                <rect key="frame" x="0.0" y="0.0" width="157" height="191"/>
+                                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                                    <rect key="frame" x="0.0" y="0.0" width="157" height="191"/>
+                                    <autoresizingMask key="autoresizingMask"/>
+                                    <subviews>
+                                        <imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ujR-N6-x2H">
+                                            <rect key="frame" x="4" y="4" width="149" height="149"/>
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" secondItem="ujR-N6-x2H" secondAttribute="height" id="Jsg-SG-uqa"/>
+                                            </constraints>
+                                        </imageView>
+                                        <button opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="vRd-OH-xYh" customClass="MDCFlatButton">
+                                            <rect key="frame" x="119" y="153" width="38" height="38"/>
+                                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" secondItem="vRd-OH-xYh" secondAttribute="height" id="9NK-Of-LLD"/>
+                                                <constraint firstAttribute="width" constant="38" id="Yu0-Un-EAx"/>
+                                            </constraints>
+                                            <color key="tintColor" red="0.0" green="0.0" blue="0.0" alpha="0.54000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <state key="normal" image="HeartEmpty"/>
+                                            <state key="selected" image="HeartFull"/>
+                                        </button>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="$XX" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aNr-ue-aFb">
+                                            <rect key="frame" x="115" y="8" width="34" height="21"/>
+                                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
+                                            <color key="textColor" red="0.035294117647058823" green="0.19215686274509802" blue="0.25882352941176467" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                    </subviews>
+                                </view>
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                                <constraints>
+                                    <constraint firstAttribute="trailing" secondItem="aNr-ue-aFb" secondAttribute="trailing" constant="8" id="6v7-id-quN"/>
+                                    <constraint firstAttribute="trailing" secondItem="ujR-N6-x2H" secondAttribute="trailing" constant="4" id="EXQ-Gu-gxF"/>
+                                    <constraint firstAttribute="bottom" secondItem="vRd-OH-xYh" secondAttribute="bottom" id="GU2-mP-pdc"/>
+                                    <constraint firstItem="ujR-N6-x2H" firstAttribute="leading" secondItem="Cs7-hN-5ih" secondAttribute="leading" constant="4" id="eZb-A2-2J0"/>
+                                    <constraint firstAttribute="trailing" secondItem="vRd-OH-xYh" secondAttribute="trailing" id="l5g-6E-n42"/>
+                                    <constraint firstItem="ujR-N6-x2H" firstAttribute="top" secondItem="Cs7-hN-5ih" secondAttribute="top" constant="4" id="qNY-Y8-cuL"/>
+                                    <constraint firstItem="aNr-ue-aFb" firstAttribute="top" secondItem="Cs7-hN-5ih" secondAttribute="top" constant="8" id="vYS-Gb-pED"/>
+                                </constraints>
+                                <connections>
+                                    <outlet property="favoriteButton" destination="vRd-OH-xYh" id="y7v-5O-akJ"/>
+                                    <outlet property="imageView" destination="ujR-N6-x2H" id="LYp-6N-Kxm"/>
+                                    <outlet property="priceLabel" destination="aNr-ue-aFb" id="bQh-HB-Rbd"/>
+                                </connections>
+                            </collectionViewCell>
+                        </cells>
+                        <connections>
+                            <outlet property="dataSource" destination="a5o-Vp-6qw" id="Fmh-r6-bYu"/>
+                            <outlet property="delegate" destination="a5o-Vp-6qw" id="5Wf-zl-fAA"/>
+                        </connections>
+                    </collectionView>
+                    <connections>
+                        <outlet property="headerContentView" destination="Wgr-bd-yYT" id="GOd-dQ-Wb2"/>
+                        <outlet property="shrineLogo" destination="664-A7-GNa" id="9ob-Jw-aKp"/>
+                    </connections>
+                </collectionViewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Bum-ch-p73" userLabel="First Responder" sceneMemberID="firstResponder"/>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ShrineLogo" id="664-A7-GNa">
+                    <rect key="frame" x="0.0" y="0.0" width="136" height="52"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                </imageView>
+                <view contentMode="scaleToFill" id="Wgr-bd-yYT" userLabel="HeaderContentView" customClass="HomeHeaderView">
+                    <rect key="frame" x="0.0" y="0.0" width="320" height="420"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="fishbowl.png" translatesAutoresizingMaskIntoConstraints="NO" id="dJV-WH-exb">
+                            <rect key="frame" x="-70" y="0.0" width="320" height="420"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="420" id="IhW-sV-TVC"/>
+                            </constraints>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Best Gift for Teen Girls" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="78U-jz-TLC">
+                            <rect key="frame" x="131" y="186" width="189" height="81.5"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="189" id="svA-re-Txy"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="34"/>
+                            <color key="textColor" red="0.035294117647058823" green="0.19215686274509802" blue="0.25882352941176467" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Choose fun, exciting, and unique gifts every girl will love." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="i9y-di-e68">
+                            <rect key="frame" x="133" y="272.5" width="187" height="29"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                            <color key="textColor" red="0.035294117647058823" green="0.19215686274509802" blue="0.25882352941176467" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ShrineTextLogo" translatesAutoresizingMaskIntoConstraints="NO" id="abA-kk-gjn">
+                            <rect key="frame" x="131" y="169" width="89" height="17"/>
+                        </imageView>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="78U-jz-TLC" secondAttribute="trailing" id="G05-qm-bnJ"/>
+                        <constraint firstItem="78U-jz-TLC" firstAttribute="leading" secondItem="abA-kk-gjn" secondAttribute="leading" id="LwH-zL-HId"/>
+                        <constraint firstItem="dJV-WH-exb" firstAttribute="leading" secondItem="Wgr-bd-yYT" secondAttribute="leading" constant="-70" id="QHB-jn-Yck"/>
+                        <constraint firstAttribute="bottom" secondItem="dJV-WH-exb" secondAttribute="bottom" id="Rzm-wk-8i1"/>
+                        <constraint firstAttribute="trailing" secondItem="i9y-di-e68" secondAttribute="trailing" id="hjZ-oC-zI1"/>
+                        <constraint firstItem="78U-jz-TLC" firstAttribute="top" secondItem="abA-kk-gjn" secondAttribute="bottom" id="kct-lJ-PSa"/>
+                        <constraint firstItem="i9y-di-e68" firstAttribute="top" secondItem="78U-jz-TLC" secondAttribute="bottom" constant="5" id="q8S-am-z3h"/>
+                        <constraint firstAttribute="trailing" secondItem="dJV-WH-exb" secondAttribute="trailing" constant="70" id="qjz-2J-hIJ"/>
+                        <constraint firstAttribute="bottom" secondItem="i9y-di-e68" secondAttribute="bottom" constant="118.5" id="yc3-UC-Skv"/>
+                        <constraint firstItem="i9y-di-e68" firstAttribute="leading" secondItem="78U-jz-TLC" secondAttribute="leading" constant="2" id="z0J-BQ-Up7"/>
+                    </constraints>
+                    <connections>
+                        <outlet property="backgroundImage" destination="dJV-WH-exb" id="M37-lX-kJy"/>
+                        <outlet property="descLabel" destination="i9y-di-e68" id="vLN-Z0-XeX"/>
+                        <outlet property="textLogo" destination="abA-kk-gjn" id="LoF-SO-j4N"/>
+                        <outlet property="titleLabel" destination="78U-jz-TLC" id="3gR-7M-u3W"/>
+                    </connections>
+                </view>
+            </objects>
+            <point key="canvasLocation" x="584.79999999999995" y="389.95502248875567"/>
+        </scene>
+    </scenes>
+    <resources>
+        <image name="HeartEmpty" width="20" height="18"/>
+        <image name="HeartFull" width="20" height="18"/>
+        <image name="ShrineLogo" width="100" height="30"/>
+        <image name="ShrineTextLogo" width="89" height="17"/>
+        <image name="fishbowl.png" width="1000" height="1000"/>
+    </resources>
+</document>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Info.plist
new file mode 100644
index 0000000..0482c40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Info.plist
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>$(EXECUTABLE_NAME)</string>
+	<key>CFBundleIdentifier</key>
+	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>$(PRODUCT_NAME)</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSRequiresIPhoneOS</key>
+	<true/>
+	<key>UILaunchStoryboardName</key>
+	<string>LaunchScreen</string>
+	<key>UIRequiredDeviceCapabilities</key>
+	<array>
+		<string>armv7</string>
+	</array>
+	<key>UIStatusBarTintParameters</key>
+	<dict>
+		<key>UINavigationBar</key>
+		<dict>
+			<key>Style</key>
+			<string>UIBarStyleDefault</string>
+			<key>Translucent</key>
+			<false/>
+		</dict>
+	</dict>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/ProductGridViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/ProductGridViewController.h
new file mode 100644
index 0000000..f197111
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/ProductGridViewController.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+#import "MaterialCollections.h"
+
+@class Product;
+
+@interface ProductGridViewController : MDCCollectionViewController
+
+@property(nonatomic) BOOL isHome;
+@property(nonatomic) NSArray <Product *> *products;
+
+@end
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/ProductGridViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/ProductGridViewController.m
new file mode 100644
index 0000000..d0367a0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/ProductGridViewController.m
@@ -0,0 +1,86 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "ProductGridViewController.h"
+#import "ProductCollectionViewCell.h"
+#import "Product.h"
+#import "HomeHeaderView.h"
+
+#import "MaterialButtons.h"
+
+@interface ProductGridViewController ()
+
+@property(nonatomic) IBOutlet HomeHeaderView *headerContentView;
+@property(nonatomic) IBOutlet UIImageView *shrineLogo;
+
+@end
+
+@implementation ProductGridViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  self.collectionView.contentInset = UIEdgeInsetsMake(0, 0, self.tabBarController.tabBar.bounds.size.height, 0);
+
+  self.styler.cellStyle = MDCCollectionViewCellStyleCard;
+  self.styler.cellLayoutType = MDCCollectionViewCellLayoutTypeGrid;
+  self.styler.gridPadding = 8;
+  [self updateLayout];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+  [self updateLayout];
+}
+
+- (void)updateLayout {
+  self.styler.gridColumnCount = 1;
+
+  [self.collectionView.collectionViewLayout invalidateLayout];
+}
+
+#pragma mark - Target / Action
+
+- (void)favoriteButtonDidTouch:(UIButton *)sender {
+  Product *product = self.products[sender.tag];
+  product.isFavorite = !product.isFavorite;
+  [self.collectionView reloadItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:sender.tag inSection:0]]];
+}
+
+#pragma mark - CollectionView DataSource
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  ProductCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
+  cell.product = self.products[indexPath.item];
+
+  cell.favoriteButton.tag = indexPath.item;
+  if (![cell.favoriteButton.allTargets containsObject:self]) {
+    [cell.favoriteButton addTarget:self action:@selector(favoriteButtonDidTouch:) forControlEvents:UIControlEventTouchUpInside];
+  }
+
+  return cell;
+}
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+  return self.products.count;
+}
+
+#pragma mark - MDCCollectionViewStylingDelegate
+
+- (CGFloat)collectionView:(UICollectionView *)collectionView cellHeightAtIndexPath:(NSIndexPath *)indexPath {
+  return (collectionView.bounds.size.width - (self.styler.gridColumnCount + 1) * self.styler.gridColumnCount) * 5/4.f / self.styler.gridColumnCount;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/backpack.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/backpack.png
new file mode 100644
index 0000000..c6d3c11
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/backpack.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/binoculars.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/binoculars.png
new file mode 100644
index 0000000..c759674
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/binoculars.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/chucks.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/chucks.png
new file mode 100755
index 0000000..9a893f6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/chucks.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/flippers.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/flippers.png
new file mode 100755
index 0000000..f9acb2e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/flippers.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/heels.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/heels.png
new file mode 100755
index 0000000..cbdbb56
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/heels.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/helmet.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/helmet.png
new file mode 100755
index 0000000..b39a8c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/helmet.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/lipstick.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/lipstick.png
new file mode 100755
index 0000000..eab0c25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/lipstick.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/shoes.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/shoes.png
new file mode 100755
index 0000000..92030a8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/shoes.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/sunnies.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/sunnies.png
new file mode 100755
index 0000000..771c609
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/sunnies.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/umbrella.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/umbrella.png
new file mode 100755
index 0000000..c778e2c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Clothing/umbrella.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/beachball.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/beachball.png
new file mode 100755
index 0000000..22248fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/beachball.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/brush.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/brush.png
new file mode 100755
index 0000000..9ab9dbc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/brush.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/chair.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/chair.png
new file mode 100755
index 0000000..038fd42
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/chair.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/clock.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/clock.png
new file mode 100755
index 0000000..3fb14fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/clock.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/fishbowl.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/fishbowl.png
new file mode 100755
index 0000000..34d22f4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/fishbowl.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/lamp.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/lamp.png
new file mode 100755
index 0000000..fab2ffc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/lamp.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/lawnchair.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/lawnchair.png
new file mode 100755
index 0000000..bae60d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/lawnchair.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/pen.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/pen.png
new file mode 100755
index 0000000..7e35d40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/pen.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/radio.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/radio.png
new file mode 100755
index 0000000..e724064
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/radio.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/surfboard.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/surfboard.png
new file mode 100755
index 0000000..5eaf34d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/surfboard.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/teapot.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/teapot.png
new file mode 100755
index 0000000..5bdb62d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/teapot.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/tools.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/tools.png
new file mode 100755
index 0000000..f9b9383
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/tools.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/typewriter.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/typewriter.png
new file mode 100755
index 0000000..d2790bf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Home/typewriter.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/HomeHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/HomeHeaderView.h
new file mode 100644
index 0000000..4b4c7b3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/HomeHeaderView.h
@@ -0,0 +1,26 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface HomeHeaderView : UIView
+
+@property (weak, nonatomic) IBOutlet UIImageView *backgroundImage;
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
+@property (weak, nonatomic) IBOutlet UIImageView *textLogo;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/HomeHeaderView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/HomeHeaderView.m
new file mode 100644
index 0000000..209540b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/HomeHeaderView.m
@@ -0,0 +1,21 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "HomeHeaderView.h"
+
+@implementation HomeHeaderView
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Images/fishbowl.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Images/fishbowl.png
new file mode 100755
index 0000000..34d22f4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Images/fishbowl.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Images/popsicle.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Images/popsicle.png
new file mode 100755
index 0000000..e35e8a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Images/popsicle.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Product.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Product.h
new file mode 100644
index 0000000..0dee839
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Product.h
@@ -0,0 +1,25 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@interface Product : NSObject
+
+@property(nonatomic) NSString *imagePath;
+@property(nonatomic) NSString *price;
+@property(nonatomic) BOOL isFavorite;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Product.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Product.m
new file mode 100644
index 0000000..592cf20
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/Product.m
@@ -0,0 +1,38 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "Product.h"
+
+@implementation Product
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    // Random price
+    int price = arc4random() % 100;
+    self.price = [NSString stringWithFormat:@"$%d", price];
+  }
+  return self;
+}
+
+- (BOOL)isEqual:(id)object {
+  return [object isMemberOfClass:[self class]] &&
+  [((Product*)object).price isEqualToString:self.price] &&
+  [((Product*)object).imagePath isEqualToString:self.imagePath] &&
+  ((Product*)object).isFavorite == self.isFavorite;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.h
new file mode 100644
index 0000000..bf17633
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class Product;
+@class MDCButton;
+
+@interface ProductCollectionViewCell : UICollectionViewCell
+
+@property(nonatomic) Product *product;
+@property(nonatomic) IBOutlet MDCButton *favoriteButton;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.m
new file mode 100644
index 0000000..c96644f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductCollectionViewCell.m
@@ -0,0 +1,51 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "ProductCollectionViewCell.h"
+#import "Product.h"
+
+#import "MaterialButtons.h"
+
+@interface ProductCollectionViewCell ()
+
+@property(nonatomic) IBOutlet UIImageView *imageView;
+@property(nonatomic) IBOutlet UILabel *priceLabel;
+
+@end
+
+@implementation ProductCollectionViewCell
+
+- (void)awakeFromNib {
+  [super awakeFromNib];
+  self.favoriteButton.contentEdgeInsets = UIEdgeInsetsZero;
+  UIImage *image = [[self.favoriteButton imageForState:UIControlStateNormal] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  [self.favoriteButton setImage:image forState:UIControlStateNormal];
+
+  image = [[self.favoriteButton imageForState:UIControlStateSelected] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  [self.favoriteButton setImage:image forState:UIControlStateSelected];
+}
+
+- (void)setProduct:(Product *)product {
+  if (![_product isEqual:product]) {
+    _product = product;
+
+    self.imageView.image = [UIImage imageWithContentsOfFile:product.imagePath];
+    self.priceLabel.text = product.price;
+    self.favoriteButton.selected = product.isFavorite;
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductStorageHelper.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductStorageHelper.h
new file mode 100644
index 0000000..3c476f7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/Supplemental/ProductStorageHelper.h
@@ -0,0 +1,62 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import "Product.h"
+
+@class Product;
+
+typedef NS_ENUM(NSUInteger, ProductCategory) {
+  ProductCategoryHome,
+  ProductCategoryClothing,
+  ProductCategoryPopsicles,
+};
+
+static inline NSArray <Product *> *productsFor(ProductCategory category) {
+  NSString *const pngExtension = @"png";
+  NSString *folderPath;
+  NSMutableArray <NSString *> *files = [NSMutableArray array];
+
+  switch (category) {
+    case ProductCategoryPopsicles: {
+      // 16 popsicles
+      for (int i = 0; i < 16; ++i) {
+        [files addObject:[[NSBundle mainBundle] pathForResource:@"popsicle" ofType:pngExtension]];
+      }
+    }
+      break;
+    case ProductCategoryClothing:
+      folderPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Clothing"];
+      // Fallthru
+    case ProductCategoryHome:
+      folderPath = folderPath ?: [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Home"];
+      
+      NSError *error;
+      NSArray *fileNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error];
+      for (NSString *fileName in fileNames) {
+        [files addObject:[folderPath stringByAppendingPathComponent:fileName]];
+      }
+      break;
+  }
+
+  NSMutableArray *mutableProducts = [NSMutableArray array];
+  for (NSString *path in files) {
+    Product *product = [[Product alloc] init];
+    product.imagePath = path;
+    [mutableProducts addObject:product];
+  }
+  return [NSArray arrayWithArray:mutableProducts];
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/main.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/main.m
new file mode 100644
index 0000000..9028428
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulApps/main.m
@@ -0,0 +1,16 @@
+//
+//  main.m
+//  ShrineCodelabObjc
+//
+//  Created by Will Larche on 4/19/17.
+//  Copyright © 2017 Will Larche. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+  @autoreleasepool {
+      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+  }
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/project.pbxproj b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..74f9434
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/project.pbxproj
@@ -0,0 +1,462 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		36625A771EA869DA00A0E2AD /* HomeHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 36625A761EA869DA00A0E2AD /* HomeHeaderView.m */; };
+		36625A791EA86D3200A0E2AD /* fishbowl.png in Resources */ = {isa = PBXBuildFile; fileRef = 36625A781EA86D3200A0E2AD /* fishbowl.png */; };
+		36DABBA51EA7F0E700906586 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBA41EA7F0E700906586 /* main.m */; };
+		36DABBA81EA7F0E700906586 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBA71EA7F0E700906586 /* AppDelegate.m */; };
+		36DABBAB1EA7F0E700906586 /* ProductGridViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBAA1EA7F0E700906586 /* ProductGridViewController.m */; };
+		36DABBB11EA7F0E700906586 /* ProductGrid.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBAF1EA7F0E700906586 /* ProductGrid.storyboard */; };
+		36DABBB31EA7F0E700906586 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBB21EA7F0E700906586 /* Assets.xcassets */; };
+		36DABBB61EA7F0E700906586 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBB41EA7F0E700906586 /* LaunchScreen.storyboard */; };
+		36DABBBF1EA812B200906586 /* ProductCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBBE1EA812B200906586 /* ProductCollectionViewCell.m */; };
+		36DABBC21EA8166200906586 /* Product.m in Sources */ = {isa = PBXBuildFile; fileRef = 36DABBC11EA8166200906586 /* Product.m */; };
+		36DABBF91EA82E5800906586 /* popsicle.png in Resources */ = {isa = PBXBuildFile; fileRef = 36DABBE11EA82E5800906586 /* popsicle.png */; };
+		36DABC301EA833A700906586 /* Clothing in Resources */ = {isa = PBXBuildFile; fileRef = 36DABC2E1EA833A700906586 /* Clothing */; };
+		36DABC311EA833A700906586 /* Home in Resources */ = {isa = PBXBuildFile; fileRef = 36DABC2F1EA833A700906586 /* Home */; };
+		EB711BFCEEE7BF2237D99896 /* libPods-BuildingBeautifulApps.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D967962C61FD651D0BC490A2 /* libPods-BuildingBeautifulApps.a */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		14F6B115B062FC99E50F1F41 /* Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulAppsObjcComplete/Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig"; sourceTree = "<group>"; };
+		1E77988AD077916A17CF5F2D /* libPods-ShrineCodelabObjc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ShrineCodelabObjc.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		26364F6243F3061661E5BB6A /* Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulAppsObjcComplete/Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig"; sourceTree = "<group>"; };
+		36625A751EA869DA00A0E2AD /* HomeHeaderView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HomeHeaderView.h; path = ../Supplemental/HomeHeaderView.h; sourceTree = "<group>"; };
+		36625A761EA869DA00A0E2AD /* HomeHeaderView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HomeHeaderView.m; path = ../Supplemental/HomeHeaderView.m; sourceTree = "<group>"; };
+		36625A781EA86D3200A0E2AD /* fishbowl.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fishbowl.png; sourceTree = "<group>"; };
+		36DABBA01EA7F0E700906586 /* BuildingBeautifulApps.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BuildingBeautifulApps.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		36DABBA41EA7F0E700906586 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
+		36DABBA61EA7F0E700906586 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
+		36DABBA71EA7F0E700906586 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
+		36DABBA91EA7F0E700906586 /* ProductGridViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProductGridViewController.h; sourceTree = "<group>"; };
+		36DABBAA1EA7F0E700906586 /* ProductGridViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ProductGridViewController.m; sourceTree = "<group>"; };
+		36DABBB01EA7F0E700906586 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/ProductGrid.storyboard; sourceTree = "<group>"; };
+		36DABBB21EA7F0E700906586 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
+		36DABBB51EA7F0E700906586 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
+		36DABBB71EA7F0E700906586 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		36DABBBD1EA812B200906586 /* ProductCollectionViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductCollectionViewCell.h; sourceTree = "<group>"; };
+		36DABBBE1EA812B200906586 /* ProductCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProductCollectionViewCell.m; sourceTree = "<group>"; };
+		36DABBC01EA8166200906586 /* Product.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Product.h; sourceTree = "<group>"; };
+		36DABBC11EA8166200906586 /* Product.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Product.m; sourceTree = "<group>"; };
+		36DABBC41EA8194900906586 /* ProductStorageHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProductStorageHelper.h; sourceTree = "<group>"; };
+		36DABBE11EA82E5800906586 /* popsicle.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = popsicle.png; sourceTree = "<group>"; };
+		36DABC2E1EA833A700906586 /* Clothing */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Clothing; sourceTree = "<group>"; };
+		36DABC2F1EA833A700906586 /* Home */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Home; sourceTree = "<group>"; };
+		475C1BCD7153021C09BABEA7 /* Pods-BuildingBeautifulApps.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulApps.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig"; sourceTree = "<group>"; };
+		5FF09E137DA3C50D9A38C1C3 /* libPods-BuildingBeautifulAppsObjcComplete.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BuildingBeautifulAppsObjcComplete.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		84F26C556113B9B6F06AE5E0 /* Pods-BuildingBeautifulApps.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BuildingBeautifulApps.release.xcconfig"; path = "Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig"; sourceTree = "<group>"; };
+		9D1E5807E130C987D54DAE15 /* Pods-ShrineCodelabObjc.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShrineCodelabObjc.release.xcconfig"; path = "Pods/Target Support Files/Pods-ShrineCodelabObjc/Pods-ShrineCodelabObjc.release.xcconfig"; sourceTree = "<group>"; };
+		D967962C61FD651D0BC490A2 /* libPods-BuildingBeautifulApps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BuildingBeautifulApps.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		F0B0363E04251F4B2787BD47 /* Pods-ShrineCodelabObjc.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShrineCodelabObjc.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ShrineCodelabObjc/Pods-ShrineCodelabObjc.debug.xcconfig"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		36DABB9D1EA7F0E700906586 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				EB711BFCEEE7BF2237D99896 /* libPods-BuildingBeautifulApps.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		1EB15273881A22502C68AA78 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				1E77988AD077916A17CF5F2D /* libPods-ShrineCodelabObjc.a */,
+				5FF09E137DA3C50D9A38C1C3 /* libPods-BuildingBeautifulAppsObjcComplete.a */,
+				D967962C61FD651D0BC490A2 /* libPods-BuildingBeautifulApps.a */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		36DABB971EA7F0E700906586 = {
+			isa = PBXGroup;
+			children = (
+				36DABBA21EA7F0E700906586 /* BuildingBeautifulApps */,
+				36DABBA11EA7F0E700906586 /* Products */,
+				80F36927416F68DD55EC31B8 /* Pods */,
+				1EB15273881A22502C68AA78 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		36DABBA11EA7F0E700906586 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				36DABBA01EA7F0E700906586 /* BuildingBeautifulApps.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		36DABBA21EA7F0E700906586 /* BuildingBeautifulApps */ = {
+			isa = PBXGroup;
+			children = (
+				36DABBA61EA7F0E700906586 /* AppDelegate.h */,
+				36DABBA71EA7F0E700906586 /* AppDelegate.m */,
+				36DABBA91EA7F0E700906586 /* ProductGridViewController.h */,
+				36DABBAA1EA7F0E700906586 /* ProductGridViewController.m */,
+				36DABBAF1EA7F0E700906586 /* ProductGrid.storyboard */,
+				36DABBC31EA8169C00906586 /* Supplemental */,
+				36DABBB21EA7F0E700906586 /* Assets.xcassets */,
+				36DABBB41EA7F0E700906586 /* LaunchScreen.storyboard */,
+				36DABBB71EA7F0E700906586 /* Info.plist */,
+				36DABBA31EA7F0E700906586 /* Supporting Files */,
+			);
+			path = BuildingBeautifulApps;
+			sourceTree = "<group>";
+		};
+		36DABBA31EA7F0E700906586 /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				36DABBA41EA7F0E700906586 /* main.m */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		36DABBC31EA8169C00906586 /* Supplemental */ = {
+			isa = PBXGroup;
+			children = (
+				36DABC2E1EA833A700906586 /* Clothing */,
+				36DABC2F1EA833A700906586 /* Home */,
+				36DABBC71EA82E5800906586 /* Images */,
+				36DABBC01EA8166200906586 /* Product.h */,
+				36DABBC11EA8166200906586 /* Product.m */,
+				36DABBBD1EA812B200906586 /* ProductCollectionViewCell.h */,
+				36DABBBE1EA812B200906586 /* ProductCollectionViewCell.m */,
+				36625A751EA869DA00A0E2AD /* HomeHeaderView.h */,
+				36625A761EA869DA00A0E2AD /* HomeHeaderView.m */,
+				36DABBC41EA8194900906586 /* ProductStorageHelper.h */,
+			);
+			path = Supplemental;
+			sourceTree = "<group>";
+		};
+		36DABBC71EA82E5800906586 /* Images */ = {
+			isa = PBXGroup;
+			children = (
+				36625A781EA86D3200A0E2AD /* fishbowl.png */,
+				36DABBE11EA82E5800906586 /* popsicle.png */,
+			);
+			path = Images;
+			sourceTree = "<group>";
+		};
+		80F36927416F68DD55EC31B8 /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				F0B0363E04251F4B2787BD47 /* Pods-ShrineCodelabObjc.debug.xcconfig */,
+				9D1E5807E130C987D54DAE15 /* Pods-ShrineCodelabObjc.release.xcconfig */,
+				14F6B115B062FC99E50F1F41 /* Pods-BuildingBeautifulAppsObjcComplete.debug.xcconfig */,
+				26364F6243F3061661E5BB6A /* Pods-BuildingBeautifulAppsObjcComplete.release.xcconfig */,
+				475C1BCD7153021C09BABEA7 /* Pods-BuildingBeautifulApps.debug.xcconfig */,
+				84F26C556113B9B6F06AE5E0 /* Pods-BuildingBeautifulApps.release.xcconfig */,
+			);
+			name = Pods;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		36DABB9F1EA7F0E700906586 /* BuildingBeautifulApps */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 36DABBBA1EA7F0E700906586 /* Build configuration list for PBXNativeTarget "BuildingBeautifulApps" */;
+			buildPhases = (
+				2ED5460D364563253D57F229 /* [CP] Check Pods Manifest.lock */,
+				36DABB9C1EA7F0E700906586 /* Sources */,
+				36DABB9D1EA7F0E700906586 /* Frameworks */,
+				36DABB9E1EA7F0E700906586 /* Resources */,
+				749A29FFDF664C69E2CF0C41 /* [CP] Embed Pods Frameworks */,
+				8D73756F76B06B68032DC382 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = BuildingBeautifulApps;
+			productName = ShrineCodelabObjc;
+			productReference = 36DABBA01EA7F0E700906586 /* BuildingBeautifulApps.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		36DABB981EA7F0E700906586 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0830;
+				ORGANIZATIONNAME = "Will Larche";
+				TargetAttributes = {
+					36DABB9F1EA7F0E700906586 = {
+						CreatedOnToolsVersion = 8.3.2;
+						ProvisioningStyle = Automatic;
+					};
+				};
+			};
+			buildConfigurationList = 36DABB9B1EA7F0E700906586 /* Build configuration list for PBXProject "BuildingBeautifulAppsObjcStarter" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 36DABB971EA7F0E700906586;
+			productRefGroup = 36DABBA11EA7F0E700906586 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				36DABB9F1EA7F0E700906586 /* BuildingBeautifulApps */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		36DABB9E1EA7F0E700906586 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				36DABBB61EA7F0E700906586 /* LaunchScreen.storyboard in Resources */,
+				36DABBB31EA7F0E700906586 /* Assets.xcassets in Resources */,
+				36625A791EA86D3200A0E2AD /* fishbowl.png in Resources */,
+				36DABBF91EA82E5800906586 /* popsicle.png in Resources */,
+				36DABBB11EA7F0E700906586 /* ProductGrid.storyboard in Resources */,
+				36DABC301EA833A700906586 /* Clothing in Resources */,
+				36DABC311EA833A700906586 /* Home in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		2ED5460D364563253D57F229 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n";
+			showEnvVarsInLog = 0;
+		};
+		749A29FFDF664C69E2CF0C41 /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		8D73756F76B06B68032DC382 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Copy Pods Resources";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		36DABB9C1EA7F0E700906586 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				36DABBA81EA7F0E700906586 /* AppDelegate.m in Sources */,
+				36DABBC21EA8166200906586 /* Product.m in Sources */,
+				36625A771EA869DA00A0E2AD /* HomeHeaderView.m in Sources */,
+				36DABBAB1EA7F0E700906586 /* ProductGridViewController.m in Sources */,
+				36DABBBF1EA812B200906586 /* ProductCollectionViewCell.m in Sources */,
+				36DABBA51EA7F0E700906586 /* main.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		36DABBAF1EA7F0E700906586 /* ProductGrid.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				36DABBB01EA7F0E700906586 /* Base */,
+			);
+			name = ProductGrid.storyboard;
+			sourceTree = "<group>";
+		};
+		36DABBB41EA7F0E700906586 /* LaunchScreen.storyboard */ = {
+			isa = PBXVariantGroup;
+			children = (
+				36DABBB51EA7F0E700906586 /* Base */,
+			);
+			name = LaunchScreen.storyboard;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		36DABBB81EA7F0E700906586 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		36DABBB91EA7F0E700906586 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 10.3;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		36DABBBB1EA7F0E700906586 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 475C1BCD7153021C09BABEA7 /* Pods-BuildingBeautifulApps.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				DEVELOPMENT_TEAM = "";
+				INFOPLIST_FILE = "$(SRCROOT)/BuildingBeautifulApps/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.mux.ShrineCodelabObjc;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		36DABBBC1EA7F0E700906586 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 84F26C556113B9B6F06AE5E0 /* Pods-BuildingBeautifulApps.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				DEVELOPMENT_TEAM = "";
+				INFOPLIST_FILE = "$(SRCROOT)/BuildingBeautifulApps/Info.plist";
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.mux.ShrineCodelabObjc;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		36DABB9B1EA7F0E700906586 /* Build configuration list for PBXProject "BuildingBeautifulAppsObjcStarter" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				36DABBB81EA7F0E700906586 /* Debug */,
+				36DABBB91EA7F0E700906586 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		36DABBBA1EA7F0E700906586 /* Build configuration list for PBXNativeTarget "BuildingBeautifulApps" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				36DABBBB1EA7F0E700906586 /* Debug */,
+				36DABBBC1EA7F0E700906586 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 36DABB981EA7F0E700906586 /* Project object */;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..b5c5dd2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:ShrineCodelabObjc.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/xcshareddata/xcschemes/BuildingBeautifulAppsObjcStarter.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/xcshareddata/xcschemes/BuildingBeautifulAppsObjcStarter.xcscheme
new file mode 100644
index 0000000..b6d66cd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj/xcshareddata/xcschemes/BuildingBeautifulAppsObjcStarter.xcscheme
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0830"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+               BuildableName = "BuildingBeautifulApps.app"
+               BlueprintName = "BuildingBeautifulApps"
+               ReferencedContainer = "container:BuildingBeautifulAppsObjcStarter.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+            BuildableName = "BuildingBeautifulApps.app"
+            BlueprintName = "BuildingBeautifulApps"
+            ReferencedContainer = "container:BuildingBeautifulAppsObjcStarter.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+            BuildableName = "BuildingBeautifulApps.app"
+            BlueprintName = "BuildingBeautifulApps"
+            ReferencedContainer = "container:BuildingBeautifulAppsObjcStarter.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "36DABB9F1EA7F0E700906586"
+            BuildableName = "BuildingBeautifulApps.app"
+            BlueprintName = "BuildingBeautifulApps"
+            ReferencedContainer = "container:BuildingBeautifulAppsObjcStarter.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcworkspace/contents.xcworkspacedata b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..59e095d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:/Users/larche/Documents/iOS/material-components-ios/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/BuildingBeautifulAppsObjcStarter.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:BuildingBeautifulAppsObjcStarter.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Podfile b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Podfile
new file mode 100644
index 0000000..5528ac1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Podfile
@@ -0,0 +1,10 @@
+# Uncomment the next line to define a global platform for your project
+platform :ios, '9.0'
+
+target 'BuildingBeautifulApps' do
+  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
+  # use_frameworks!
+
+  # Pods for ShrineCodelabObjc
+  pod 'MaterialComponents'
+end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Podfile.lock b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Podfile.lock
new file mode 100644
index 0000000..c2ab666
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Podfile.lock
@@ -0,0 +1,166 @@
+PODS:
+  - MaterialComponents (23.0.1):
+    - MaterialComponents/ActivityIndicator (= 23.0.1)
+    - MaterialComponents/AnimationTiming (= 23.0.1)
+    - MaterialComponents/AppBar (= 23.0.1)
+    - MaterialComponents/ButtonBar (= 23.0.1)
+    - MaterialComponents/Buttons (= 23.0.1)
+    - MaterialComponents/CollectionCells (= 23.0.1)
+    - MaterialComponents/CollectionLayoutAttributes (= 23.0.1)
+    - MaterialComponents/Collections (= 23.0.1)
+    - MaterialComponents/Dialogs (= 23.0.1)
+    - MaterialComponents/FeatureHighlight (= 23.0.1)
+    - MaterialComponents/FlexibleHeader (= 23.0.1)
+    - MaterialComponents/HeaderStackView (= 23.0.1)
+    - MaterialComponents/Ink (= 23.0.1)
+    - MaterialComponents/NavigationBar (= 23.0.1)
+    - MaterialComponents/OverlayWindow (= 23.0.1)
+    - MaterialComponents/PageControl (= 23.0.1)
+    - MaterialComponents/Palettes (= 23.0.1)
+    - MaterialComponents/private (= 23.0.1)
+    - MaterialComponents/ProgressView (= 23.0.1)
+    - MaterialComponents/ShadowElevations (= 23.0.1)
+    - MaterialComponents/ShadowLayer (= 23.0.1)
+    - MaterialComponents/Slider (= 23.0.1)
+    - MaterialComponents/Snackbar (= 23.0.1)
+    - MaterialComponents/Tabs (= 23.0.1)
+    - MaterialComponents/Typography (= 23.0.1)
+  - MaterialComponents/ActivityIndicator (23.0.1):
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/RTL
+  - MaterialComponents/AnimationTiming (23.0.1)
+  - MaterialComponents/AppBar (23.0.1):
+    - MaterialComponents/FlexibleHeader
+    - MaterialComponents/HeaderStackView
+    - MaterialComponents/NavigationBar
+    - MaterialComponents/private/Icons/ic_arrow_back
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ButtonBar (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/RTL
+  - MaterialComponents/Buttons (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/CollectionCells (23.0.1):
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/private/Icons/ic_check
+    - MaterialComponents/private/Icons/ic_check_circle
+    - MaterialComponents/private/Icons/ic_chevron_right
+    - MaterialComponents/private/Icons/ic_info
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked
+    - MaterialComponents/private/Icons/ic_reorder
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/CollectionLayoutAttributes (23.0.1)
+  - MaterialComponents/Collections (23.0.1):
+    - MaterialComponents/CollectionCells
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/Dialogs (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+  - MaterialComponents/FeatureHighlight (23.0.1):
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/FlexibleHeader (23.0.1):
+    - MaterialComponents/private/Application
+    - MDFTextAccessibility
+  - MaterialComponents/HeaderStackView (23.0.1)
+  - MaterialComponents/Ink (23.0.1)
+  - MaterialComponents/NavigationBar (23.0.1):
+    - MaterialComponents/ButtonBar
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/OverlayWindow (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/PageControl (23.0.1)
+  - MaterialComponents/Palettes (23.0.1)
+  - MaterialComponents/private (23.0.1):
+    - MaterialComponents/private/Application (= 23.0.1)
+    - MaterialComponents/private/Icons (= 23.0.1)
+    - MaterialComponents/private/KeyboardWatcher (= 23.0.1)
+    - MaterialComponents/private/Overlay (= 23.0.1)
+    - MaterialComponents/private/RTL (= 23.0.1)
+    - MaterialComponents/private/ThumbTrack (= 23.0.1)
+  - MaterialComponents/private/Application (23.0.1)
+  - MaterialComponents/private/Icons (23.0.1):
+    - MaterialComponents/private/Icons/Base (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_arrow_back (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check_circle (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_chevron_right (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_info (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_reorder (= 23.0.1)
+  - MaterialComponents/private/Icons/Base (23.0.1)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check_circle (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_chevron_right (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_info (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_reorder (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/KeyboardWatcher (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/private/Overlay (23.0.1)
+  - MaterialComponents/private/RTL (23.0.1)
+  - MaterialComponents/private/ThumbTrack (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ProgressView (23.0.1):
+    - MaterialComponents/private/RTL
+  - MaterialComponents/ShadowElevations (23.0.1)
+  - MaterialComponents/ShadowLayer (23.0.1)
+  - MaterialComponents/Slider (23.0.1):
+    - MaterialComponents/private/ThumbTrack
+  - MaterialComponents/Snackbar (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Buttons
+    - MaterialComponents/OverlayWindow
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/Overlay
+    - MaterialComponents/Typography
+  - MaterialComponents/Tabs (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/Typography (23.0.1):
+    - MaterialComponents/private/Application
+  - MDFTextAccessibility (1.2.0)
+
+DEPENDENCIES:
+  - MaterialComponents
+
+SPEC CHECKSUMS:
+  MaterialComponents: 8666bde1128660f2a3525d03d6b460d2bc34dc3b
+  MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
+
+PODFILE CHECKSUM: abed8eea0ed77b9de5377b2d8f0b9fd29abd1705
+
+COCOAPODS: 1.2.1
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/.DS_Store b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/.DS_Store
new file mode 100644
index 0000000..18e6565
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/.DS_Store
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFColorCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFColorCalculations.h
new file mode 120000
index 0000000..fa89574
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFColorCalculations.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/private/MDFColorCalculations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFImageCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFImageCalculations.h
new file mode 120000
index 0000000..474b2cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFImageCalculations.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/private/MDFImageCalculations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility-Bridging-Header.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility-Bridging-Header.h
new file mode 120000
index 0000000..d562af0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility-Bridging-Header.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
new file mode 120000
index 0000000..6bf2534
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/MDFTextAccessibility.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/NSArray+MDFUtils.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/NSArray+MDFUtils.h
new file mode 120000
index 0000000..32c1020
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MDFTextAccessibility/MDFTextAccessibility/NSArray+MDFUtils.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/private/NSArray+MDFUtils.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
new file mode 120000
index 0000000..20d501f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCActivityIndicator.h
new file mode 120000
index 0000000..44abaed
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAlertController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAlertController.h
new file mode 120000
index 0000000..aaf6589
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAlertController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCAlertController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBar.h
new file mode 120000
index 0000000..6bc15b0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBarButtonBarBuilder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBarButtonBarBuilder.h
new file mode 120000
index 0000000..83435f4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBarButtonBarBuilder.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBarContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBarContainerViewController.h
new file mode 120000
index 0000000..90f2e9c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCAppBarContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButton+Subclassing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButton+Subclassing.h
new file mode 120000
index 0000000..a1eafff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButton+Subclassing.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButton.h
new file mode 120000
index 0000000..35e4667
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButtonBar+Private.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButtonBar+Private.h
new file mode 120000
index 0000000..6246a17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButtonBar+Private.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButtonBar.h
new file mode 120000
index 0000000..433abfb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionGridBackgroundView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionGridBackgroundView.h
new file mode 120000
index 0000000..16b703f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionGridBackgroundView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionInfoBarView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionInfoBarView.h
new file mode 120000
index 0000000..315c699
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionInfoBarView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionStringResources.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionStringResources.h
new file mode 120000
index 0000000..284d457
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionStringResources.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewCell.h
new file mode 120000
index 0000000..f8b8942
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewController.h
new file mode 120000
index 0000000..17318d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditing.h
new file mode 120000
index 0000000..f822353
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditing.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditingDelegate.h
new file mode 120000
index 0000000..36cda64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditor.h
new file mode 120000
index 0000000..a59328f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewEditor.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewFlowLayout.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewFlowLayout.h
new file mode 120000
index 0000000..1259cc1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewFlowLayout.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewLayoutAttributes.h
new file mode 120000
index 0000000..7e572fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyler.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyler.h
new file mode 120000
index 0000000..c38fd37
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyler.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyling.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyling.h
new file mode 120000
index 0000000..afe2a2d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStyling.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStylingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStylingDelegate.h
new file mode 120000
index 0000000..7e7a85c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewStylingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewTextCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewTextCell.h
new file mode 120000
index 0000000..36307b4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCCollectionViewTextCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogPresentationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogPresentationController.h
new file mode 120000
index 0000000..c8812b5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogPresentationController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogShadowedView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogShadowedView.h
new file mode 120000
index 0000000..e559378
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogShadowedView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogTransitionController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogTransitionController.h
new file mode 120000
index 0000000..3510b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCDialogTransitionController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightAnimationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightAnimationController.h
new file mode 120000
index 0000000..ff58aa3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightAnimationController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightLayer.h
new file mode 120000
index 0000000..b91ac22
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightView.h
new file mode 120000
index 0000000..c9d7a09
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightViewController.h
new file mode 120000
index 0000000..80dfbbc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFeatureHighlightViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlatButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlatButton.h
new file mode 120000
index 0000000..a706599
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlatButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFlatButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
new file mode 120000
index 0000000..2f397d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderView.h
new file mode 120000
index 0000000..8bf8ccd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderViewController.h
new file mode 120000
index 0000000..49ebdb2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFlexibleHeaderViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFloatingButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFloatingButton.h
new file mode 120000
index 0000000..53cd131
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFloatingButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFloatingButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFontTextStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFontTextStyle.h
new file mode 120000
index 0000000..28be954
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFontTextStyle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCFontTextStyle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFontTraits.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFontTraits.h
new file mode 120000
index 0000000..18f8a54
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCFontTraits.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/private/MDCFontTraits.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCHeaderStackView.h
new file mode 120000
index 0000000..098d7a2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCIcons+BundleLoader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCIcons+BundleLoader.h
new file mode 120000
index 0000000..83bb369
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCIcons+BundleLoader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCIcons.h
new file mode 120000
index 0000000..f64284e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkGestureRecognizer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkGestureRecognizer.h
new file mode 120000
index 0000000..41c61fe
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkGestureRecognizer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkLayer.h
new file mode 120000
index 0000000..ed548c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/private/MDCInkLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkTouchController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkTouchController.h
new file mode 120000
index 0000000..deff05c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkTouchController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkTouchController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkView.h
new file mode 120000
index 0000000..71f0259
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCInkView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBar.h
new file mode 120000
index 0000000..01beb92
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarAlignment.h
new file mode 120000
index 0000000..41ea67b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarAlignment.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarCell.h
new file mode 120000
index 0000000..e864dbb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarStringConstants.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarStringConstants.h
new file mode 120000
index 0000000..2857d7b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarStringConstants.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarStyle.h
new file mode 120000
index 0000000..1e9aea6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCItemBarStyle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCKeyboardWatcher.h
new file mode 120000
index 0000000..6748571
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCNavigationBar.h
new file mode 120000
index 0000000..be1e2df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCNumericValueLabel.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCNumericValueLabel.h
new file mode 120000
index 0000000..05fc677
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCNumericValueLabel.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayAnimationObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayAnimationObserver.h
new file mode 120000
index 0000000..8aef920
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayAnimationObserver.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayImplementor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayImplementor.h
new file mode 120000
index 0000000..dd6c72c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayImplementor.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserver.h
new file mode 120000
index 0000000..734f36b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserver.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverOverlay.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverOverlay.h
new file mode 120000
index 0000000..d4afb1a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverOverlay.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverTransition.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverTransition.h
new file mode 120000
index 0000000..f8b8b7f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayObserverTransition.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayTransitioning.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayTransitioning.h
new file mode 120000
index 0000000..d819f9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayTransitioning.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayUtilities.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayUtilities.h
new file mode 120000
index 0000000..61dd343
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayUtilities.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayWindow.h
new file mode 120000
index 0000000..b4f521f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControl.h
new file mode 120000
index 0000000..436f689
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MDCPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControlIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControlIndicator.h
new file mode 120000
index 0000000..86ca489
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControlIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControlTrackLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControlTrackLayer.h
new file mode 120000
index 0000000..70b335d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPageControlTrackLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPaletteExpansions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPaletteExpansions.h
new file mode 120000
index 0000000..bb723ea
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPaletteExpansions.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPaletteNames.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPaletteNames.h
new file mode 120000
index 0000000..b14ada4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPaletteNames.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPalettes.h
new file mode 120000
index 0000000..9fbd2c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MDCPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCProgressView.h
new file mode 120000
index 0000000..355e6bc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MDCProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCRTL.h
new file mode 120000
index 0000000..0f5cb64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MDCRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCRaisedButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCRaisedButton.h
new file mode 120000
index 0000000..ccef7c0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCRaisedButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCRaisedButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCShadowElevations.h
new file mode 120000
index 0000000..884db2c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCShadowLayer.h
new file mode 120000
index 0000000..662ce66
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSlider.h
new file mode 120000
index 0000000..c6d28f3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MDCSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSlider_Subclassable.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSlider_Subclassable.h
new file mode 120000
index 0000000..de1e86e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSlider_Subclassable.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarManager.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarManager.h
new file mode 120000
index 0000000..bd47604
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarManager.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessage.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessage.h
new file mode 120000
index 0000000..ca85673
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessage.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageInternal.h
new file mode 120000
index 0000000..8c946d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageInternal.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageView.h
new file mode 120000
index 0000000..bd504ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageViewInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageViewInternal.h
new file mode 120000
index 0000000..88ee640
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarMessageViewInternal.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarOverlayView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarOverlayView.h
new file mode 120000
index 0000000..8db1860
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCSnackbarOverlayView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCStatusBarShifter.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCStatusBarShifter.h
new file mode 120000
index 0000000..b56f8eb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCStatusBarShifter.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBar.h
new file mode 120000
index 0000000..1ae3c01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBarAlignment.h
new file mode 120000
index 0000000..0837a68
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBarAlignment.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBarItemAppearance.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBarItemAppearance.h
new file mode 120000
index 0000000..25eda76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTabBarItemAppearance.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCThumbTrack.h
new file mode 120000
index 0000000..d562391
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCThumbView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCThumbView.h
new file mode 120000
index 0000000..f268b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCThumbView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTypography.h
new file mode 120000
index 0000000..92f1672
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MDCTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialActivityIndicator.h
new file mode 120000
index 0000000..cdc04d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialAnimationTiming.h
new file mode 120000
index 0000000..47c524c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialAppBar.h
new file mode 120000
index 0000000..9b9b359
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MaterialAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialApplication.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialApplication.h
new file mode 120000
index 0000000..84d4230
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialApplication.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/MaterialApplication.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialButtonBar.h
new file mode 120000
index 0000000..03f519d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialButtons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialButtons.h
new file mode 120000
index 0000000..e201bb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialButtons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MaterialButtons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionCells.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionCells.h
new file mode 120000
index 0000000..fcebe0b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionCells.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionLayoutAttributes.h
new file mode 120000
index 0000000..12203fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollections.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollections.h
new file mode 120000
index 0000000..c651483
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollections.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MaterialCollections.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings.h
new file mode 120000
index 0000000..470ca4d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings_table.h
new file mode 120000
index 0000000..b3f6e7c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialCollectionsStrings_table.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialDialogs.h
new file mode 120000
index 0000000..9fa87cb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialFeatureHighlight.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialFeatureHighlight.h
new file mode 120000
index 0000000..408b3da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialFeatureHighlight.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialFlexibleHeader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialFlexibleHeader.h
new file mode 120000
index 0000000..a0ff5eb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialFlexibleHeader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialHeaderStackView.h
new file mode 120000
index 0000000..e489f50
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_arrow_back.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_arrow_back.h
new file mode 120000
index 0000000..d217414
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_arrow_back.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check.h
new file mode 120000
index 0000000..2ed904e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check_circle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check_circle.h
new file mode 120000
index 0000000..ca1cb59
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_check_circle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_chevron_right.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_chevron_right.h
new file mode 120000
index 0000000..c5e2145
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_chevron_right.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_info.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_info.h
new file mode 120000
index 0000000..8f6a835
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_info.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
new file mode 120000
index 0000000..5bef137
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_reorder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_reorder.h
new file mode 120000
index 0000000..414fed9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons+ic_reorder.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons.h
new file mode 120000
index 0000000..a5fd2c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MaterialIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialInk.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialInk.h
new file mode 120000
index 0000000..d342e27
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialInk.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MaterialInk.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialKeyboardWatcher.h
new file mode 120000
index 0000000..4d746e2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialNavigationBar.h
new file mode 120000
index 0000000..4d955df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialOverlayWindow.h
new file mode 120000
index 0000000..91896d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialOverlays.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialOverlays.h
new file mode 120000
index 0000000..29fe249
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialOverlays.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControl.h
new file mode 120000
index 0000000..7803abc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MaterialPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings.h
new file mode 120000
index 0000000..cd39ffa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings_table.h
new file mode 120000
index 0000000..434acfa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPageControlStrings_table.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPalettes.h
new file mode 120000
index 0000000..592e442
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MaterialPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialProgressView.h
new file mode 120000
index 0000000..2bf7929
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MaterialProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialRTL.h
new file mode 120000
index 0000000..e146eb8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialShadowElevations.h
new file mode 120000
index 0000000..fae8446
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialShadowLayer.h
new file mode 120000
index 0000000..9b2b29d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialSlider.h
new file mode 120000
index 0000000..c5876b7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MaterialSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialSnackbar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialSnackbar.h
new file mode 120000
index 0000000..dbfbe01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialSnackbar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialTabs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialTabs.h
new file mode 120000
index 0000000..4268edf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialTabs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MaterialTabs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialThumbTrack.h
new file mode 120000
index 0000000..dd6979f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialTypography.h
new file mode 120000
index 0000000..19f03c3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIApplication+AppExtensions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIApplication+AppExtensions.h
new file mode 120000
index 0000000..7de802f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIApplication+AppExtensions.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypography.h
new file mode 120000
index 0000000..1459935
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypographyPrivate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypographyPrivate.h
new file mode 120000
index 0000000..153aa0a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFont+MaterialTypographyPrivate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFontDescriptor+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFontDescriptor+MaterialTypography.h
new file mode 120000
index 0000000..58f36cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIFontDescriptor+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIImage+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIImage+MaterialRTL.h
new file mode 120000
index 0000000..fe3b980
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIImage+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIView+MDCTimingFunction.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIView+MDCTimingFunction.h
new file mode 120000
index 0000000..1c20698
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIView+MDCTimingFunction.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIView+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIView+MaterialRTL.h
new file mode 120000
index 0000000..b45713a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIView+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIViewController+MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIViewController+MaterialDialogs.h
new file mode 120000
index 0000000..0e65c76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Private/MaterialComponents/UIViewController+MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
new file mode 120000
index 0000000..6bf2534
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MDFTextAccessibility/MDFTextAccessibility/MDFTextAccessibility.h
@@ -0,0 +1 @@
+../../../../MDFTextAccessibility/src/MDFTextAccessibility.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
new file mode 120000
index 0000000..20d501f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/CAMediaTimingFunction+MDCAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCActivityIndicator.h
new file mode 120000
index 0000000..44abaed
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAlertController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAlertController.h
new file mode 120000
index 0000000..aaf6589
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAlertController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCAlertController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAppBar.h
new file mode 120000
index 0000000..6bc15b0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAppBarContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAppBarContainerViewController.h
new file mode 120000
index 0000000..90f2e9c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCAppBarContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCButton.h
new file mode 120000
index 0000000..35e4667
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCButtonBar.h
new file mode 120000
index 0000000..433abfb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewCell.h
new file mode 120000
index 0000000..f8b8942
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewController.h
new file mode 120000
index 0000000..17318d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditing.h
new file mode 120000
index 0000000..f822353
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditing.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditingDelegate.h
new file mode 120000
index 0000000..36cda64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewEditingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewFlowLayout.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewFlowLayout.h
new file mode 120000
index 0000000..1259cc1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewFlowLayout.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewLayoutAttributes.h
new file mode 120000
index 0000000..7e572fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStyling.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStyling.h
new file mode 120000
index 0000000..afe2a2d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStyling.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStylingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStylingDelegate.h
new file mode 120000
index 0000000..7e7a85c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewStylingDelegate.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewTextCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewTextCell.h
new file mode 120000
index 0000000..36307b4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCCollectionViewTextCell.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCDialogPresentationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCDialogPresentationController.h
new file mode 120000
index 0000000..c8812b5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCDialogPresentationController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCDialogTransitionController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCDialogTransitionController.h
new file mode 120000
index 0000000..3510b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCDialogTransitionController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFeatureHighlightViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFeatureHighlightViewController.h
new file mode 120000
index 0000000..80dfbbc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFeatureHighlightViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlatButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlatButton.h
new file mode 120000
index 0000000..a706599
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlatButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFlatButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
new file mode 120000
index 0000000..2f397d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderContainerViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderView.h
new file mode 120000
index 0000000..8bf8ccd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderViewController.h
new file mode 120000
index 0000000..49ebdb2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFlexibleHeaderViewController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFloatingButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFloatingButton.h
new file mode 120000
index 0000000..53cd131
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFloatingButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCFloatingButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFontTextStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFontTextStyle.h
new file mode 120000
index 0000000..28be954
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCFontTextStyle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCFontTextStyle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCHeaderStackView.h
new file mode 120000
index 0000000..098d7a2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCIcons+BundleLoader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCIcons+BundleLoader.h
new file mode 120000
index 0000000..83bb369
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCIcons+BundleLoader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCIcons.h
new file mode 120000
index 0000000..f64284e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MDCIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkGestureRecognizer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkGestureRecognizer.h
new file mode 120000
index 0000000..41c61fe
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkGestureRecognizer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkTouchController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkTouchController.h
new file mode 120000
index 0000000..deff05c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkTouchController.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkTouchController.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkView.h
new file mode 120000
index 0000000..71f0259
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCInkView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MDCInkView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCKeyboardWatcher.h
new file mode 120000
index 0000000..6748571
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCNavigationBar.h
new file mode 120000
index 0000000..be1e2df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCNumericValueLabel.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCNumericValueLabel.h
new file mode 120000
index 0000000..05fc677
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCNumericValueLabel.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayImplementor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayImplementor.h
new file mode 120000
index 0000000..dd6c72c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayImplementor.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayObserver.h
new file mode 120000
index 0000000..734f36b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayObserver.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayTransitioning.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayTransitioning.h
new file mode 120000
index 0000000..d819f9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayTransitioning.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayWindow.h
new file mode 120000
index 0000000..b4f521f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCPageControl.h
new file mode 120000
index 0000000..436f689
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MDCPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCPalettes.h
new file mode 120000
index 0000000..9fbd2c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MDCPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCProgressView.h
new file mode 120000
index 0000000..355e6bc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MDCProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCRTL.h
new file mode 120000
index 0000000..0f5cb64
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MDCRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCRaisedButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCRaisedButton.h
new file mode 120000
index 0000000..ccef7c0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCRaisedButton.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MDCRaisedButton.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCShadowElevations.h
new file mode 120000
index 0000000..884db2c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCShadowLayer.h
new file mode 120000
index 0000000..662ce66
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSlider.h
new file mode 120000
index 0000000..c6d28f3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MDCSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarManager.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarManager.h
new file mode 120000
index 0000000..bd47604
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarManager.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessage.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessage.h
new file mode 120000
index 0000000..ca85673
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessage.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessageView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessageView.h
new file mode 120000
index 0000000..bd504ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCSnackbarMessageView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBar.h
new file mode 120000
index 0000000..1ae3c01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBarAlignment.h
new file mode 120000
index 0000000..0837a68
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBarAlignment.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBarItemAppearance.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBarItemAppearance.h
new file mode 120000
index 0000000..25eda76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTabBarItemAppearance.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCThumbTrack.h
new file mode 120000
index 0000000..d562391
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCThumbView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCThumbView.h
new file mode 120000
index 0000000..f268b7d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCThumbView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTypography.h
new file mode 120000
index 0000000..92f1672
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MDCTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MDCTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialActivityIndicator.h
new file mode 120000
index 0000000..cdc04d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialActivityIndicator.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialAnimationTiming.h
new file mode 120000
index 0000000..47c524c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialAnimationTiming.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialAppBar.h
new file mode 120000
index 0000000..9b9b359
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialAppBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AppBar/src/MaterialAppBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialApplication.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialApplication.h
new file mode 120000
index 0000000..84d4230
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialApplication.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/MaterialApplication.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialButtonBar.h
new file mode 120000
index 0000000..03f519d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialButtonBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialButtons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialButtons.h
new file mode 120000
index 0000000..e201bb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialButtons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Buttons/src/MaterialButtons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollectionCells.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollectionCells.h
new file mode 120000
index 0000000..fcebe0b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollectionCells.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollectionLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollectionLayoutAttributes.h
new file mode 120000
index 0000000..12203fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollectionLayoutAttributes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollections.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollections.h
new file mode 120000
index 0000000..c651483
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialCollections.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Collections/src/MaterialCollections.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialDialogs.h
new file mode 120000
index 0000000..9fa87cb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialFeatureHighlight.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialFeatureHighlight.h
new file mode 120000
index 0000000..408b3da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialFeatureHighlight.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialFlexibleHeader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialFlexibleHeader.h
new file mode 120000
index 0000000..a0ff5eb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialFlexibleHeader.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialHeaderStackView.h
new file mode 120000
index 0000000..e489f50
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialHeaderStackView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_arrow_back.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_arrow_back.h
new file mode 120000
index 0000000..d217414
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_arrow_back.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check.h
new file mode 120000
index 0000000..2ed904e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check_circle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check_circle.h
new file mode 120000
index 0000000..ca1cb59
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_check_circle.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_chevron_right.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_chevron_right.h
new file mode 120000
index 0000000..c5e2145
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_chevron_right.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_info.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_info.h
new file mode 120000
index 0000000..8f6a835
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_info.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
new file mode 120000
index 0000000..5bef137
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_radio_button_unchecked.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_reorder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_reorder.h
new file mode 120000
index 0000000..414fed9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons+ic_reorder.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons.h
new file mode 120000
index 0000000..a5fd2c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialIcons.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Icons/src/MaterialIcons.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialInk.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialInk.h
new file mode 120000
index 0000000..d342e27
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialInk.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Ink/src/MaterialInk.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialKeyboardWatcher.h
new file mode 120000
index 0000000..4d746e2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialKeyboardWatcher.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialNavigationBar.h
new file mode 120000
index 0000000..4d955df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialNavigationBar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialOverlayWindow.h
new file mode 120000
index 0000000..91896d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialOverlayWindow.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialOverlays.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialOverlays.h
new file mode 120000
index 0000000..29fe249
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialOverlays.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialPageControl.h
new file mode 120000
index 0000000..7803abc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialPageControl.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/PageControl/src/MaterialPageControl.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialPalettes.h
new file mode 120000
index 0000000..592e442
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialPalettes.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Palettes/src/MaterialPalettes.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialProgressView.h
new file mode 120000
index 0000000..2bf7929
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialProgressView.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ProgressView/src/MaterialProgressView.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialRTL.h
new file mode 120000
index 0000000..e146eb8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialShadowElevations.h
new file mode 120000
index 0000000..fae8446
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialShadowElevations.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialShadowLayer.h
new file mode 120000
index 0000000..9b2b29d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialShadowLayer.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialSlider.h
new file mode 120000
index 0000000..c5876b7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialSlider.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Slider/src/MaterialSlider.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialSnackbar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialSnackbar.h
new file mode 120000
index 0000000..dbfbe01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialSnackbar.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialTabs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialTabs.h
new file mode 120000
index 0000000..4268edf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialTabs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Tabs/src/MaterialTabs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialThumbTrack.h
new file mode 120000
index 0000000..dd6979f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialThumbTrack.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialTypography.h
new file mode 120000
index 0000000..19f03c3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIApplication+AppExtensions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIApplication+AppExtensions.h
new file mode 120000
index 0000000..7de802f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIApplication+AppExtensions.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIFont+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIFont+MaterialTypography.h
new file mode 120000
index 0000000..1459935
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIFont+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIFontDescriptor+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIFontDescriptor+MaterialTypography.h
new file mode 120000
index 0000000..58f36cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIFontDescriptor+MaterialTypography.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIImage+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIImage+MaterialRTL.h
new file mode 120000
index 0000000..fe3b980
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIImage+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIView+MDCTimingFunction.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIView+MDCTimingFunction.h
new file mode 120000
index 0000000..1c20698
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIView+MDCTimingFunction.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIView+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIView+MaterialRTL.h
new file mode 120000
index 0000000..b45713a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIView+MaterialRTL.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIViewController+MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIViewController+MaterialDialogs.h
new file mode 120000
index 0000000..0e65c76
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Headers/Public/MaterialComponents/UIViewController+MaterialDialogs.h
@@ -0,0 +1 @@
+../../../MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
\ No newline at end of file
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/LICENSE b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/README.md b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/README.md
new file mode 100644
index 0000000..6010bea
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/README.md
@@ -0,0 +1,106 @@
+MDFTextAccessibility assists in selecting text colors that will meet the
+[W3C standards for accessibility](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html).
+
+[![Build Status](https://travis-ci.org/material-foundation/material-text-accessibility-ios.svg?branch=develop)](https://travis-ci.org/material-foundation/material-text-accessibility-ios)
+[![Code Coverage](http://codecov.io/github/material-foundation/material-text-accessibility-ios/coverage.svg?branch=develop)](http://codecov.io/github/material-foundation/material-text-accessibility-ios?branch=develop)
+
+*May 24, 2016: We're still staging MDFTextAccessibility, feel free to poke
+around, but non-code things like CocoaPods support and continuous integration
+testing will be ramping up over the next few weeks. The API is relatively stable
+at this point.*
+
+## Accessibility of text
+
+Apps created for the widest range of users should ensure that users can read
+text presented over any background. While the legibility of text depends on many
+things, a great start is to provide a sufficiently large *contrast ratio*
+between foreground text colors and their background colors. The contrast ratio
+of two colors is a measurement of how much the brightness of two colors differ.
+For example, white on dark grey might have a contrast ratio of 9:1, while white
+on medium grey might only have a contrast ratio of 4:1. In general, larger
+contrast ratios are better and will ensure the widest range of users can easily
+read the text in your app.
+
+The [W3C](https://www.w3.org)'s
+[Web Content Accessibility Guidelines](https://www.w3.org/TR/WCAG/#visual-audio-contrast)
+contains two recommendations for text contrast ratios:
+
+1. Minimum contrast: text should have a contrast ratio of at least 4.5:1,
+   except for "large" text, which can have a contrast ratio of 3:1.
+2. Enhanced contrast: text should have a contrast ratio of at least 7:1, except
+   for large text, which can have a contrast ratio of 4.5:1.
+
+"Large" text is nominally defined as at least 18pt in a normal font face or at
+least 14pt in a bold font face. For more information (including some important
+exceptions), see the
+[Guidelines](https://www.w3.org/TR/WCAG/#visual-audio-contrast).
+
+## Computing contrast ratios
+
+Computing acceptable contrast ratios involves the foreground color, the
+background color, the text size, and the transparency of the foreground color,
+if any. MDFTextAccessibility provides convenient access to colors that will
+automatically give acceptable contrast ratios.
+
+For methods that return a UIColor, the color along with its alpha is guaranteed
+to provide a contrast ratio meeting the minimum ratios recommended by the W3C.
+The returned alpha may be greater than the requested alpha to ensure acceptable
+contrast ratios, that is, the returned color may be more opaque than requested
+to ensure that the text remains legible.
+
+## Legible text on images
+
+Displaying text legibly on arbitrary images is difficult because the image
+content can conflict with the text. Images with smooth gradients or blurred
+regions are likely to result in more legible text; images with many details and
+high contrast are less likely to result in legible text.
+
+MDFTextAccessibility provides methods that attempt to select a good color for
+displaying text on a particular image, but the quality of the results will
+depend on the contents of the image. If the content of the image is not known
+(for example, when images provided by the user), then consider using a
+semi-transparent shim between the image and the text to increase contrast.
+
+## Usage
+
+### Basic usage
+
+The simplest usage is to select between black and white text depending on the
+background color, irrespective of the font:
+
+```objective-c
+label.textColor = [MDFTextAccessibility textColorOnBackgroundColor:label.backgroundColor
+                                                         textAlpha:1
+                                                              font:nil];
+```
+
+Many design standards for user interfaces use text colors that are not fully
+opaque. However, transparent text can reduce legibility, so you can request a
+color that is as close as possible to a particular alpha value while still being
+legible:
+
+```objective-c
+label.textColor = [MDFTextAccessibility textColorOnBackgroundColor:label.backgroundColor
+                                                   targetTextAlpha:0.85
+                                                              font:nil];
+```
+
+Since the W3C recommends different contrast ratios for "normal" and "large"
+text, including the font can result in a text color closer to your target alpha
+when appropriate:
+
+```objective-c
+label.textColor = [MDFTextAccessibility textColorOnBackgroundColor:label.backgroundColor
+                                                         textAlpha:0.85
+                                                              font:label.font];
+```
+
+### Advanced usage
+
+For more advanced usage, such as selecting from a set of colors other than white
+and black, see MDFTextAccessibility's
+`textColorFromChoices:onBackgroundColor:options:`.
+
+## License
+
+MDFTextAccessiblity is licensed under the [Apache License Version 2.0](LICENSE).
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h
new file mode 100644
index 0000000..ea88e56
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility-Bridging-Header.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFTextAccessibility.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility.h
new file mode 100644
index 0000000..34a13d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility.h
@@ -0,0 +1,199 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Options for selecting text colors that provide acceptable contrast ratios. */
+typedef NS_OPTIONS(NSUInteger, MDFTextAccessibilityOptions) {
+  /** No options. */
+  MDFTextAccessibilityOptionsNone = 0,
+
+  /** Font size is at least 14pt bold or 18pt normal. */
+  MDFTextAccessibilityOptionsLargeFont = 1 << 0,
+
+  /** Do not modify alpha values to find good colors. */
+  MDFTextAccessibilityOptionsPreserveAlpha = 1 << 1,
+
+  /** Prefer darker colors to lighter colors. */
+  MDFTextAccessibilityOptionsPreferDarker = 1 << 2,
+
+  /** Prefer lighter colors to darker colors. */
+  MDFTextAccessibilityOptionsPreferLighter = 1 << 3,
+
+  /** Use enhanced contrast ratios (level AAA) instead of minimum ratios (level AA). */
+  MDFTextAccessibilityOptionsEnhancedContrast = 1 << 4,
+};
+
+/**
+ MDFTextAccessiblity provides methods to compute accessible text colors.
+ */
+@interface MDFTextAccessibility : NSObject
+
+/**
+ An optionally transparent text color suitable for displaying on a background color with a
+ particular font.
+
+ The color returned will be white or black with an alpha value of targetTextAlpha, unless the
+ contrast ratio is insufficient, in which case the alpha is increased (made more opaque).
+
+ If the passed font is nil, then a conservative guess is used.
+
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param targetTextAlpha The target alpha of the text.
+ @param font The font the text will use or nil.
+ @return A color with acceptable contrast ratio for displaying text on |color|.
+ */
++ (nonnull UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                targetTextAlpha:(CGFloat)targetTextAlpha
+                                           font:(nullable UIFont *)font;
+
+/**
+ An optionally transparent text color suitable for displaying on a background image with a
+ particular font.
+
+ The color returned will be white or black with an alpha value of targetTextAlpha, unless the
+ contrast ratio is insufficient, in which case the alpha is increased (made more opaque).
+
+ If the passed font is nil, then a conservative guess is used.
+
+ The content of the background image is simply averaged to make an average color, which is then used
+ as if it were the background color of the text. Depending on the contents of the image, this
+ approximation may or may not result in legible text.
+
+ The supplied image region will be intersected with the image's bounds. If the resulting region is
+ null or empty then this method returns nil.
+
+ @param backgroundImage The opaque background image the text will be displayed on.
+ @param region The region in which the text will be displayed. Can be conservatively large.
+ @param targetTextAlpha The target alpha of the text.
+ @param font The font to be used to display the text. Can be nil.
+ @return A color with acceptable contrast ratio, or nil if the region is out of bounds of the image.
+ */
++ (nullable UIColor *)textColorOnBackgroundImage:(nonnull UIImage *)backgroundImage
+                                        inRegion:(CGRect)region
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                            font:(nullable UIFont *)font;
+
+#pragma mark Advanced methods
+
+/**
+ An optionally transparent text color suitable for displaying text on a given opaque background
+ color.
+
+ This method calls textColorFromChoices:onColor:options: with the choices [white, black], both
+ with their alpha set to targetTextAlpha.
+
+ If MDFTextAccessibilityOptionsPreserveAlpha is included in the options, then the algorithm will not
+ modify the alpha values, which may result in no color being returned at all.
+
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param targetTextAlpha The target alpha of the text.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return A color with acceptable contrast ratio or nil if no such color exists.
+ */
++ (nullable UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                         options:(MDFTextAccessibilityOptions)options;
+
+/**
+ A color selected from a set which is suitable for displaying text on a given opaque background
+ color.
+
+ Since the minimum ratio for "large" text is less stringent, set
+ the MDFTextAccessibilityOptionsLargeFont bit if the font size will be greater than or
+ equal to 18pt normal or 14pt bold. If in doubt or if the text size can vary, be conservative and do
+ not specify MDFTextAccessibilityOptionsLargeFont in the options.
+
+ By default, the first acceptable color in |choices| will be returned. If
+ MDFTextAccessibilityOptionsPreferLighter is set, then the lightest acceptable color will be
+ returned, and if MDFTextAccessibilityOptionsPreferDarker is set, then the darkest acceptable color
+ will be returned. This allows for a standard set of text colors to be used in different situations.
+
+ By default, the algorithm will attempt to modify the alpha value of colors in |choices| instead
+ of switching to an alternate color, under the assumption that text with slightly different
+ alpha values is less noticible than, for example, black text where white text is usually used.
+ If MDFTextAccessibilityOptionsPreserveAlpha is included in the options, then the algorithm will not
+ modify the alpha values, which may result in no color being returned at all.
+
+ @param choices An array of text color UIColor objects with optional alpha values.
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return A color with acceptable contrast ratio or nil if no such color exists.
+ */
++ (nullable UIColor *)textColorFromChoices:(nonnull NSArray<UIColor *> *)choices
+                         onBackgroundColor:(nonnull UIColor *)backgroundColor
+                                   options:(MDFTextAccessibilityOptions)options;
+
+/**
+ The minimum alpha that text can have and still have an acceptable contrast ratio. Depending on
+ color combinations, the minimum useable alpha can vary.
+
+ Since the minimum ratio for "large" text is less stringent, set
+ the MDFTextAccessibilityOptionsLargeFont bit if the font size will be greater than or
+ equal to 18pt normal or 14pt bold. If in doubt or if the text size can vary, be conservative and do
+ not specify MDFTextAccessibilityOptionsLargeFont in the options.
+
+ @note There are some color combinations (white on white) for which an acceptable alpha value
+ doesn't exist.
+
+ @param textColor The text color (alpha is ignored).
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return The minimum alpha value to use in this situation, or -1 if there is no such alpha.
+ */
++ (CGFloat)minAlphaOfTextColor:(nonnull UIColor *)textColor
+             onBackgroundColor:(nonnull UIColor *)backgroundColor
+                       options:(MDFTextAccessibilityOptions)options;
+
+/**
+ The contrast ratio of a text color when displayed on an opaque background color.
+
+ @param textColor A text color with optional transparency.
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @return The contrast ratio of the text color on the background color.
+ */
++ (CGFloat)contrastRatioForTextColor:(nonnull UIColor *)textColor
+                   onBackgroundColor:(nonnull UIColor *)backgroundColor;
+
+/**
+ Whether a text color passes accessibility standards when displayed on an opaque background color.
+
+ MDFTextAccessibilityOptionsLargeFont and MDFTextAccessibilityOptionsEnhancedContrast are relevant
+ options for this method.
+
+ @param textColor A text color with optional transparency.
+ @param backgroundColor The opaque background color the text will be displayed on.
+ @param options A combination of MDFTextAccessibilityOptions values.
+ @return YES if the text color would meet accessibility standards.
+ */
++ (BOOL)textColor:(nonnull UIColor *)textColor
+    passesOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                    options:(MDFTextAccessibilityOptions)options;
+
+/**
+ Whether a particular font would be considered "large" for the purposes of calculating
+ contrast ratios.
+
+ Large fonts are defined as greater than 18pt normal or 14pt bold. If the passed font is nil, then
+ this method returns NO.
+ For more see: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
+
+ @param font The font to examine, or nil.
+ @return YES if the font is non-nil and is considered "large".
+ */
++ (BOOL)isLargeForContrastRatios:(nullable UIFont *)font;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility.m
new file mode 100644
index 0000000..5e10ddf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/MDFTextAccessibility.m
@@ -0,0 +1,185 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFTextAccessibility.h"
+
+#import "private/MDFColorCalculations.h"
+#import "private/MDFImageCalculations.h"
+#import "private/NSArray+MDFUtils.h"
+
+static const CGFloat kMinContrastRatioNormalText = 4.5f;
+static const CGFloat kMinContrastRatioLargeText = 3.0f;
+static const CGFloat kMinContrastRatioNormalTextEnhanced = 7.0f;
+static const CGFloat kMinContrastRatioLargeTextEnhanced = 4.5f;
+
+@implementation MDFTextAccessibility
+
++ (nonnull UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                targetTextAlpha:(CGFloat)targetTextAlpha
+                                           font:(nullable UIFont *)font {
+  MDFTextAccessibilityOptions options = 0;
+  if ([self isLargeForContrastRatios:font]) {
+    options |= MDFTextAccessibilityOptionsLargeFont;
+  }
+  return [self textColorOnBackgroundColor:backgroundColor
+                          targetTextAlpha:targetTextAlpha
+                                  options:options];
+}
+
++ (nullable UIColor *)textColorOnBackgroundImage:(nonnull UIImage *)backgroundImage
+                                        inRegion:(CGRect)region
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                            font:(nullable UIFont *)font {
+  UIColor *backgroundColor = MDFAverageColorOfOpaqueImage(backgroundImage, region);
+  if (!backgroundColor) {
+    return nil;
+  }
+
+  return
+      [self textColorOnBackgroundColor:backgroundColor targetTextAlpha:targetTextAlpha font:font];
+}
+
++ (nullable UIColor *)textColorOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                                 targetTextAlpha:(CGFloat)targetTextAlpha
+                                         options:(MDFTextAccessibilityOptions)options {
+  NSArray *colors = @[
+    [UIColor colorWithWhite:1 alpha:targetTextAlpha],
+    [UIColor colorWithWhite:0 alpha:targetTextAlpha]
+  ];
+  UIColor *textColor =
+      [self textColorFromChoices:colors onBackgroundColor:backgroundColor options:options];
+  return textColor;
+}
+
++ (nullable UIColor *)textColorFromChoices:(nonnull NSArray<UIColor *> *)choices
+                         onBackgroundColor:(nonnull UIColor *)backgroundColor
+                                   options:(MDFTextAccessibilityOptions)options {
+  [choices enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+    NSAssert([obj isKindOfClass:[UIColor class]], @"Choices must be UIColors.");
+  }];
+
+  // Sort by luminance if requested.
+  if ((options & MDFTextAccessibilityOptionsPreferLighter) ||
+      (options & MDFTextAccessibilityOptionsPreferDarker)) {
+    NSArray *luminances = [choices mdf_arrayByMappingObjects:^id(id object) {
+      return @([self luminanceOfColor:object]);
+    }];
+
+    BOOL inverse = (options & MDFTextAccessibilityOptionsPreferDarker) ? YES : NO;
+    choices = [luminances mdf_sortArray:choices
+                        usingComparator:^NSComparisonResult(id obj1, id obj2) {
+                          float first = inverse ? [obj1 floatValue] : [obj2 floatValue];
+                          float second = inverse ? [obj2 floatValue] : [obj1 floatValue];
+
+                          if (first < second) {
+                            return NSOrderedAscending;
+                          } else if (first > second) {
+                            return NSOrderedDescending;
+                          } else {
+                            return NSOrderedSame;
+                          }
+                        }];
+  }
+
+  // Search the array for a color that can be used, adjusting alpha values upwards if requested.
+  // The first acceptable color (adjusted or not) is returned.
+  BOOL adjustAlphas = (options & MDFTextAccessibilityOptionsPreserveAlpha) ? NO : YES;
+  for (UIColor *choice in choices) {
+    if ([self textColor:choice passesOnBackgroundColor:backgroundColor options:options]) {
+      return choice;
+    }
+
+    if (!adjustAlphas) {
+      continue;
+    }
+
+    CGFloat alpha = CGColorGetAlpha(choice.CGColor);
+    CGFloat minAlpha =
+        [self minAlphaOfTextColor:choice onBackgroundColor:backgroundColor options:options];
+    if (minAlpha > 0) {
+      if (alpha > minAlpha) {
+        NSAssert(NO,
+                 @"Logic error: computed an acceptable minimum alpha (%f) that is *less* than the "
+                 @"unacceptable current alpha (%f).",
+                 minAlpha, alpha);
+        continue;
+      }
+      return [choice colorWithAlphaComponent:minAlpha];
+    }
+  }
+
+  return nil;
+}
+
++ (CGFloat)minAlphaOfTextColor:(nonnull UIColor *)textColor
+             onBackgroundColor:(nonnull UIColor *)backgroundColor
+                       options:(MDFTextAccessibilityOptions)options {
+  CGFloat minContrastRatio = [self minContrastRatioForOptions:options];
+  return MDFMinAlphaOfColorOnBackgroundColor(textColor, backgroundColor, minContrastRatio);
+}
+
++ (CGFloat)contrastRatioForTextColor:(UIColor *)textColor
+                   onBackgroundColor:(UIColor *)backgroundColor {
+  CGFloat colorComponents[4];
+  CGFloat backgroundColorComponents[4];
+  MDFCopyRGBAComponents(textColor.CGColor, colorComponents);
+  MDFCopyRGBAComponents(backgroundColor.CGColor, backgroundColorComponents);
+
+  NSAssert(backgroundColorComponents[3] == 1,
+           @"Background color %@ must be opaque for a valid contrast ratio calculation.",
+           backgroundColor);
+  backgroundColorComponents[3] = 1;
+
+  return MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+}
+
++ (BOOL)textColor:(nonnull UIColor *)textColor
+    passesOnBackgroundColor:(nonnull UIColor *)backgroundColor
+                    options:(MDFTextAccessibilityOptions)options {
+  CGFloat minContrastRatio = [self minContrastRatioForOptions:options];
+  CGFloat ratio = [self contrastRatioForTextColor:textColor onBackgroundColor:backgroundColor];
+  return ratio >= minContrastRatio ? YES : NO;
+}
+
++ (BOOL)isLargeForContrastRatios:(nullable UIFont *)font {
+  UIFontDescriptor *fontDescriptor = font.fontDescriptor;
+  BOOL isBold =
+      (fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold;
+  return font.pointSize >= 18 || (isBold && font.pointSize >= 14);
+}
+
+#pragma mark - Private methods
+
++ (CGFloat)luminanceOfColor:(UIColor *)color {
+  CGFloat colorComponents[4];
+  MDFCopyRGBAComponents(color.CGColor, colorComponents);
+  return MDFRelativeLuminanceOfRGBComponents(colorComponents);
+}
+
++ (CGFloat)minContrastRatioForOptions:(MDFTextAccessibilityOptions)options {
+  BOOL isLarge =
+      (options & MDFTextAccessibilityOptionsLargeFont) == MDFTextAccessibilityOptionsLargeFont;
+  BOOL isEnhanced = (options & MDFTextAccessibilityOptionsEnhancedContrast) ==
+                    MDFTextAccessibilityOptionsEnhancedContrast;
+
+  if (isEnhanced) {
+    return isLarge ? kMinContrastRatioLargeTextEnhanced : kMinContrastRatioNormalTextEnhanced;
+  } else {
+    return isLarge ? kMinContrastRatioLargeText : kMinContrastRatioNormalText;
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.h
new file mode 100644
index 0000000..3e2f78f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.h
@@ -0,0 +1,70 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Copies the RGBA components of color, expanding greyscale colors out to RGBA if necessary.
+
+ @param color The color to extract the components from.
+ @param rgbaComponents A pointer to four CGFloat values.
+ */
+void MDFCopyRGBAComponents(CGColorRef color, CGFloat *rgbaComponents);
+
+/**
+ Returns the contrast ratio of a foreground color blended on top of a background color.
+
+ @param foregroundColorComponents A pointer to four RGBA CGFloats of the foreground color.
+ @param backgroundColorComponents A pointer to four RGBA CGFloats of the background color.
+ @return The contrast ratio of the two colors after blending.
+ */
+CGFloat MDFContrastRatioOfRGBAComponents(const CGFloat *foregroundColorComponents,
+                                         const CGFloat *backgroundColorComponents);
+
+/**
+ Calculates the relative luminance of a sRGB color from its components (ignores alpha).
+ @see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+
+ @param components A pointer to three RGB CGFloat values of the color.
+ @return The relative luminance of the color.
+ */
+CGFloat MDFRelativeLuminanceOfRGBComponents(const CGFloat *components);
+
+/**
+ Calculates the minimum alpha that a foreground color can have such that, when it's blended on top
+ of an opaque background color, the resulting contrast ratio is higher than a minimum contrast
+ ratio.
+
+ If there is no such acceptable contrast ratio, then -1 is returned. This is the case when even a
+ completely opaque foreground color can't produce a high enough contrast ratio. For example, light
+ grey on white will have a low contrast ratio for any alpha value assigned to the light grey.
+
+ @param color The foreground color (alpha ignored).
+ @param backgroundColor The background color (assumed to be opaque).
+ @param minContrastRatio The minimum allowable contrast ratio.
+ @return The minimum acceptable alpha of the foreground color, or -1 if no such alpha exists.
+ */
+CGFloat MDFMinAlphaOfColorOnBackgroundColor(UIColor *color,
+                                            UIColor *backgroundColor,
+                                            CGFloat minContrastRatio);
+
+#if defined __cplusplus
+}  // extern "C"
+#endif
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.m
new file mode 100644
index 0000000..a804fbd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFColorCalculations.m
@@ -0,0 +1,185 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFColorCalculations.h"
+
+/**
+ The number of iterations required to find the minimum acceptable alpha is
+ ceil(log2(1/kMinAlphaSearchPrecision)), or 7 for a precision of 0.01. If you adjust the precision
+ then also adjust the max iterations, which is used as a safety check.
+ */
+static const CGFloat kMinAlphaSearchPrecision = 0.01f;
+static const NSUInteger kMinAlphaSearchMaxIterations = 10;
+
+/** Returns value raised to exponent. */
+static inline CGFloat MDFPow(CGFloat value, CGFloat exponent) {
+#if CGFLOAT_IS_DOUBLE
+  return pow(value, exponent);
+#else
+  return powf(value, exponent);
+#endif
+}
+
+/**
+ Calculate a linear RGB component from a sRGB component for calculating luminance.
+ @see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ */
+static inline CGFloat LinearRGBComponent(CGFloat component) {
+  if (component <= 0.03928f) {
+    return component / 12.92f;
+  } else {
+    return MDFPow(((component + 0.055f) / 1.055f), 2.4f);
+  }
+}
+
+/**
+ Blend a foreground color with alpha on a opaque background color.
+ @note The background color must be opaque for this to be valid.
+ @see http://en.wikipedia.org/wiki/Alpha_compositing
+ */
+static inline void BlendColorOnOpaqueBackground(const CGFloat *foregroundColor,
+                                                const CGFloat *backgroundColor,
+                                                CGFloat *blendedColor) {
+  for (int i = 0; i < 3; ++i) {
+    blendedColor[i] =
+        foregroundColor[i] * foregroundColor[3] + backgroundColor[i] * (1 - foregroundColor[3]);
+  }
+  blendedColor[3] = 1.0f;
+}
+
+static inline CGFloat ContrastRatioOfRGBComponents(const CGFloat *firstComponents,
+                                                   const CGFloat *secondComponents) {
+  CGFloat firstLuminance = MDFRelativeLuminanceOfRGBComponents(firstComponents);
+  CGFloat secondLuminance = MDFRelativeLuminanceOfRGBComponents(secondComponents);
+
+  if (secondLuminance > firstLuminance) {
+    CGFloat temp = firstLuminance;
+    firstLuminance = secondLuminance;
+    secondLuminance = temp;
+  }
+
+  return (firstLuminance + 0.05f) / (secondLuminance + 0.05f);
+}
+
+CGFloat MDFContrastRatioOfRGBAComponents(const CGFloat *foregroundColorComponents,
+                                         const CGFloat *backgroundColorComponents) {
+  CGFloat blendedColor[4];
+  BlendColorOnOpaqueBackground(foregroundColorComponents, backgroundColorComponents, blendedColor);
+  return ContrastRatioOfRGBComponents(blendedColor, backgroundColorComponents);
+}
+
+void MDFCopyRGBAComponents(CGColorRef color, CGFloat *rgbaComponents) {
+  CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(CGColorGetColorSpace(color));
+  if (!(colorSpaceModel == kCGColorSpaceModelRGB ||
+        colorSpaceModel == kCGColorSpaceModelMonochrome)) {
+    NSCAssert(NO, @"Can't compute luminance for non-RGB color space model %i.", colorSpaceModel);
+    for (int i = 0; i < 4; ++i) {
+      rgbaComponents[i] = 0;
+    }
+    return;
+  }
+
+  size_t numComponents = CGColorGetNumberOfComponents(color);
+  const CGFloat *components = CGColorGetComponents(color);
+  switch (numComponents) {
+    // Greyscale + alpha
+    case 2:
+      for (int i = 0; i < 3; ++i) {
+        rgbaComponents[i] = components[0];
+      }
+      rgbaComponents[3] = components[1];
+      break;
+
+    // RGB + alpha
+    case 4:
+      for (int i = 0; i < 4; ++i) {
+        rgbaComponents[i] = components[i];
+      }
+      break;
+
+    default:
+      NSCAssert(NO, @"Unexpected number of color components: %zu.", numComponents);
+  }
+}
+
+CGFloat MDFRelativeLuminanceOfRGBComponents(const CGFloat *components) {
+  CGFloat linearRGB[3];
+  for (int i = 0; i < 3; ++i) {
+    linearRGB[i] = LinearRGBComponent(components[i]);
+  }
+  return 0.2126f * linearRGB[0] + 0.7152f * linearRGB[1] + 0.0722f * linearRGB[2];
+}
+
+CGFloat MDFMinAlphaOfColorOnBackgroundColor(UIColor *color,
+                                            UIColor *backgroundColor,
+                                            CGFloat minContrastRatio) {
+  CGFloat colorComponents[4];
+  CGFloat backgroundColorComponents[4];
+  MDFCopyRGBAComponents(color.CGColor, colorComponents);
+  MDFCopyRGBAComponents(backgroundColor.CGColor, backgroundColorComponents);
+
+  NSCAssert(backgroundColorComponents[3] == 1,
+            @"Background color %@ must be opaque for a valid contrast ratio calculation.",
+            backgroundColor);
+  backgroundColorComponents[3] = 1;
+
+  NSCAssert(minContrastRatio > 0, @"Invalid min contrast ratio %g.", (double)minContrastRatio);
+  CGFloat minAlpha = 0;
+  CGFloat maxAlpha = 1;
+
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+  colorComponents[3] = minAlpha;
+  CGFloat minAlphaRatio =
+      MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+  NSCAssert(minAlphaRatio < minContrastRatio, @"Transparent color cannot be a valid color.");
+#endif  // !defined(NS_BLOCK_ASSERTIONS)
+
+  // maxAlphaRatio is the best contrast ratio we can acheive by modifying the alpha of this color.
+  // If it's not good enough, then return now and inform the caller.
+  colorComponents[3] = maxAlpha;
+  CGFloat maxAlphaRatio =
+      MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+  if (maxAlphaRatio < minContrastRatio) {
+    return -1;
+  }
+
+  // Classic binary search of a range.
+  NSUInteger numIterations = 0;
+  while (numIterations <= kMinAlphaSearchMaxIterations &&
+         (maxAlpha - minAlpha) > kMinAlphaSearchPrecision) {
+    CGFloat testAlpha = (minAlpha + maxAlpha) / 2;
+    colorComponents[3] = testAlpha;
+    CGFloat testRatio =
+        MDFContrastRatioOfRGBAComponents(colorComponents, backgroundColorComponents);
+
+    if (testRatio < minContrastRatio) {
+      minAlpha = testAlpha;
+    } else {
+      maxAlpha = testAlpha;
+    }
+
+    ++numIterations;
+  }
+
+  if (numIterations > kMinAlphaSearchMaxIterations) {
+    NSCAssert(NO, @"Too many iterations (%i) while finding min alpha of text color %@ on %@.",
+              (int)numIterations, color, backgroundColor);
+    return -1;
+  }
+
+  // Conservatively return the max of the range of possible alphas, which is known to pass.
+  return maxAlpha;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.h
new file mode 100644
index 0000000..7cdb664
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ Return the average color of an image in a particular region.
+
+ The region will be intersected with the image's bounds. If the resulting region is empty (or the
+ input region was null) then this function returns nil.
+
+ @param image The image to examine.
+ @param region The region of the image to average, or CGRectInfinite for the entire image.
+ @return The average color, or nil if the region was invalid.
+ */
+UIColor *MDFAverageColorOfOpaqueImage(UIImage *image, CGRect region);
+
+#if defined __cplusplus
+}  // extern "C"
+#endif
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.m
new file mode 100644
index 0000000..0f11f3d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/MDFImageCalculations.m
@@ -0,0 +1,52 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDFImageCalculations.h"
+
+UIColor *MDFAverageColorOfOpaqueImage(UIImage *image, CGRect region) {
+  CGImageRef imageRef = image.CGImage;
+  CGImageRef cropped = CGImageCreateWithImageInRect(imageRef, region);
+
+  // Empty/null regions will cause cropped to be nil.
+  if (!cropped) {
+    return nil;
+  }
+
+  UIGraphicsBeginImageContext(CGSizeMake(1, 1));
+
+  uint8_t argb[4];
+  CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
+  CGContextRef context =
+      CGBitmapContextCreate(argb,  // data
+                            1,     // width
+                            1,     // height
+                            8,     // Bits per component
+                            4,     // Bytes per row
+                            colorspace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Big);
+  CGColorSpaceRelease(colorspace);
+  CGContextSetInterpolationQuality(context, kCGInterpolationMedium);
+  CGContextSetBlendMode(context, kCGBlendModeCopy);
+  CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), cropped);
+  CGContextRelease(context);
+  CGImageRelease(cropped);
+
+  CGFloat alpha = argb[0] / (CGFloat)255;
+  CGFloat scale = alpha > 0 ? 1 / (alpha * 255) : 0;
+  UIColor *color =
+      [UIColor colorWithRed:scale * argb[1] green:scale * argb[2] blue:scale * argb[3] alpha:alpha];
+  UIGraphicsEndImageContext();
+  return color;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.h
new file mode 100644
index 0000000..57784b3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.h
@@ -0,0 +1,53 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+typedef id (^MDFMappingFunction)(id object);
+
+/** Functional extensions to NSArray. */
+@interface NSArray (MDFUtils)
+
+/**
+ * Returns an array consisting of applying |function| to each element of self in order.
+ *
+ * @param function A block mapping an input element to an output element.
+ * @return An array of the same size as self containing elements mapped through the function.
+ */
+- (NSArray *)mdf_arrayByMappingObjects:(MDFMappingFunction)function;
+
+/**
+ * Returns a sorted version of |array| by using the passed comparator on self.
+ *
+ * @note The comparator acts of elements of self, @em not |array|.
+ *
+ * Example:
+ * @code
+ * NSArray *weights = @[ 100, 200, 50 ];
+ * NSArray *dogs = @[ @"Bruno", @"Tiger", @"Spot" ];
+ * NSComparator *ascending = ... NSString comparator ...
+ * NSArray *sortedDogs = [weights mdf_sortArray:dogs
+ *                              usingComparator:ascending];
+ * // sortedDogs is @[ @"Spot", @"Bruno", @"Tiger" ].
+ * @endcode
+ *
+ * @param array The array to sort.
+ * @param comparator A comparator acting on elements of self.
+ * @return A sorted copy of |array|.
+ */
+- (NSArray *)mdf_sortArray:(NSArray *)array usingComparator:(NSComparator)comparator;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.m
new file mode 100644
index 0000000..9758611
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MDFTextAccessibility/src/private/NSArray+MDFUtils.m
@@ -0,0 +1,68 @@
+/*
+ Copyright 2016-present Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "NSArray+MDFUtils.h"
+
+@implementation NSArray (MDFUtils)
+
+- (NSArray *)mdf_arrayByMappingObjects:(MDFMappingFunction)function {
+  NSAssert(function, @"Mapping block must not be NULL.");
+  NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:[self count]];
+  [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+    [array addObject:function(obj)];
+  }];
+  return [array copy];
+}
+
+- (BOOL)mdf_anyObjectPassesTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
+  NSIndexSet *indices = [self indexesOfObjectsPassingTest:predicate];
+  return [indices count] > 0;
+}
+
+- (BOOL)mdf_allObjectsPassTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate {
+  NSIndexSet *indices = [self indexesOfObjectsPassingTest:predicate];
+  return [indices count] == [self count];
+}
+
+- (NSArray *)mdf_sortArray:(NSArray *)array usingComparator:(NSComparator)comparator {
+  NSAssert(comparator, @"Comparator block must not be NULL.");
+
+  NSUInteger numElements = [self count];
+  NSAssert([array count] == numElements, @"Array %@ must have length %lu.", array,
+           (unsigned long)numElements);
+
+  // Create a permutation array by sorting self with comparator.
+  NSMutableArray *permutation = [[NSMutableArray alloc] initWithCapacity:numElements];
+  for (NSUInteger i = 0; i < numElements; ++i) {
+    [permutation addObject:@(i)];
+  }
+
+  NSArray *sortedPermutation = [permutation sortedArrayUsingComparator:^(id a, id b) {
+    NSUInteger firstIndex = [a unsignedIntegerValue];
+    NSUInteger secondIndex = [b unsignedIntegerValue];
+    return comparator(self[firstIndex], self[secondIndex]);
+  }];
+
+  // Permute array into order.
+  NSMutableArray *sorted = [[NSMutableArray alloc] initWithCapacity:numElements];
+  for (NSUInteger i = 0; i < numElements; ++i) {
+    NSUInteger index = [sortedPermutation[i] unsignedIntegerValue];
+    [sorted addObject:array[index]];
+  }
+  return [sorted copy];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Manifest.lock b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Manifest.lock
new file mode 100644
index 0000000..c2ab666
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Manifest.lock
@@ -0,0 +1,166 @@
+PODS:
+  - MaterialComponents (23.0.1):
+    - MaterialComponents/ActivityIndicator (= 23.0.1)
+    - MaterialComponents/AnimationTiming (= 23.0.1)
+    - MaterialComponents/AppBar (= 23.0.1)
+    - MaterialComponents/ButtonBar (= 23.0.1)
+    - MaterialComponents/Buttons (= 23.0.1)
+    - MaterialComponents/CollectionCells (= 23.0.1)
+    - MaterialComponents/CollectionLayoutAttributes (= 23.0.1)
+    - MaterialComponents/Collections (= 23.0.1)
+    - MaterialComponents/Dialogs (= 23.0.1)
+    - MaterialComponents/FeatureHighlight (= 23.0.1)
+    - MaterialComponents/FlexibleHeader (= 23.0.1)
+    - MaterialComponents/HeaderStackView (= 23.0.1)
+    - MaterialComponents/Ink (= 23.0.1)
+    - MaterialComponents/NavigationBar (= 23.0.1)
+    - MaterialComponents/OverlayWindow (= 23.0.1)
+    - MaterialComponents/PageControl (= 23.0.1)
+    - MaterialComponents/Palettes (= 23.0.1)
+    - MaterialComponents/private (= 23.0.1)
+    - MaterialComponents/ProgressView (= 23.0.1)
+    - MaterialComponents/ShadowElevations (= 23.0.1)
+    - MaterialComponents/ShadowLayer (= 23.0.1)
+    - MaterialComponents/Slider (= 23.0.1)
+    - MaterialComponents/Snackbar (= 23.0.1)
+    - MaterialComponents/Tabs (= 23.0.1)
+    - MaterialComponents/Typography (= 23.0.1)
+  - MaterialComponents/ActivityIndicator (23.0.1):
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/RTL
+  - MaterialComponents/AnimationTiming (23.0.1)
+  - MaterialComponents/AppBar (23.0.1):
+    - MaterialComponents/FlexibleHeader
+    - MaterialComponents/HeaderStackView
+    - MaterialComponents/NavigationBar
+    - MaterialComponents/private/Icons/ic_arrow_back
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ButtonBar (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/RTL
+  - MaterialComponents/Buttons (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/CollectionCells (23.0.1):
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/private/Icons/ic_check
+    - MaterialComponents/private/Icons/ic_check_circle
+    - MaterialComponents/private/Icons/ic_chevron_right
+    - MaterialComponents/private/Icons/ic_info
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked
+    - MaterialComponents/private/Icons/ic_reorder
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/CollectionLayoutAttributes (23.0.1)
+  - MaterialComponents/Collections (23.0.1):
+    - MaterialComponents/CollectionCells
+    - MaterialComponents/CollectionLayoutAttributes
+    - MaterialComponents/Ink
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/Dialogs (23.0.1):
+    - MaterialComponents/Buttons
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+  - MaterialComponents/FeatureHighlight (23.0.1):
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/FlexibleHeader (23.0.1):
+    - MaterialComponents/private/Application
+    - MDFTextAccessibility
+  - MaterialComponents/HeaderStackView (23.0.1)
+  - MaterialComponents/Ink (23.0.1)
+  - MaterialComponents/NavigationBar (23.0.1):
+    - MaterialComponents/ButtonBar
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+    - MDFTextAccessibility
+  - MaterialComponents/OverlayWindow (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/PageControl (23.0.1)
+  - MaterialComponents/Palettes (23.0.1)
+  - MaterialComponents/private (23.0.1):
+    - MaterialComponents/private/Application (= 23.0.1)
+    - MaterialComponents/private/Icons (= 23.0.1)
+    - MaterialComponents/private/KeyboardWatcher (= 23.0.1)
+    - MaterialComponents/private/Overlay (= 23.0.1)
+    - MaterialComponents/private/RTL (= 23.0.1)
+    - MaterialComponents/private/ThumbTrack (= 23.0.1)
+  - MaterialComponents/private/Application (23.0.1)
+  - MaterialComponents/private/Icons (23.0.1):
+    - MaterialComponents/private/Icons/Base (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_arrow_back (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_check_circle (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_chevron_right (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_info (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_radio_button_unchecked (= 23.0.1)
+    - MaterialComponents/private/Icons/ic_reorder (= 23.0.1)
+  - MaterialComponents/private/Icons/Base (23.0.1)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_check_circle (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_chevron_right (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_info (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/Icons/ic_reorder (23.0.1):
+    - MaterialComponents/private/Icons/Base
+  - MaterialComponents/private/KeyboardWatcher (23.0.1):
+    - MaterialComponents/private/Application
+  - MaterialComponents/private/Overlay (23.0.1)
+  - MaterialComponents/private/RTL (23.0.1)
+  - MaterialComponents/private/ThumbTrack (23.0.1):
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/ShadowElevations
+    - MaterialComponents/ShadowLayer
+    - MaterialComponents/Typography
+  - MaterialComponents/ProgressView (23.0.1):
+    - MaterialComponents/private/RTL
+  - MaterialComponents/ShadowElevations (23.0.1)
+  - MaterialComponents/ShadowLayer (23.0.1)
+  - MaterialComponents/Slider (23.0.1):
+    - MaterialComponents/private/ThumbTrack
+  - MaterialComponents/Snackbar (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Buttons
+    - MaterialComponents/OverlayWindow
+    - MaterialComponents/private/Application
+    - MaterialComponents/private/KeyboardWatcher
+    - MaterialComponents/private/Overlay
+    - MaterialComponents/Typography
+  - MaterialComponents/Tabs (23.0.1):
+    - MaterialComponents/AnimationTiming
+    - MaterialComponents/Ink
+    - MaterialComponents/private/RTL
+    - MaterialComponents/Typography
+  - MaterialComponents/Typography (23.0.1):
+    - MaterialComponents/private/Application
+  - MDFTextAccessibility (1.2.0)
+
+DEPENDENCIES:
+  - MaterialComponents
+
+SPEC CHECKSUMS:
+  MaterialComponents: 8666bde1128660f2a3525d03d6b460d2bc34dc3b
+  MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
+
+PODFILE CHECKSUM: abed8eea0ed77b9de5377b2d8f0b9fd29abd1705
+
+COCOAPODS: 1.2.1
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/LICENSE b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/README.md b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/README.md
new file mode 100644
index 0000000..5df3c30
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/README.md
@@ -0,0 +1,160 @@
+# Material Components for iOS
+
+<img align="right" src="mdc_hero.png" width="300px">
+
+[![Build Status](https://travis-ci.org/material-components/material-components-ios.svg?branch=develop)](https://travis-ci.org/material-components/material-components-ios)
+[![Code coverage](https://img.shields.io/codecov/c/github/material-components/material-components-ios/develop.svg)](https://codecov.io/gh/material-components/material-components-ios/branch/develop)
+
+Material Components for iOS (MDC-iOS) helps developers execute [Material Design](https://www.material.io). Developed by a core team of engineers and UX designers at Google, these components enable a reliable development workflow to build beautiful and functional iOS apps. Learn more about how Material Design supports design and usability best practices across platforms in the  [Material Design Platform Adaptation guidelines](https://material.io/guidelines/platforms/platform-adaptation.html).
+
+Material Components for iOS are written in Objective-C and support Swift and Interface Builder.
+
+## Useful Links
+
+- [How To Use MDC-iOS](howto/)
+- [All Components](components/)
+- [Demo Apps](demos/)
+- [Contributing](contributing/)
+- [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
+- [Material.io](https://www.material.io) (external site)
+- [Material Design Guidelines](https://material.google.com) (external site)
+
+## Trying out Material Components
+
+Our [catalog](catalog/) showcases Material Components. You can use the `pod try` command from anywhere on your machine to try the components, even if you haven't checked out the repo yet:
+
+~~~ bash
+pod try MaterialComponents
+~~~
+
+In case you have already checked out the repo, run the following command:
+
+~~~ bash
+pod install --project-directory=catalog/
+~~~
+
+If you want to take a look at the implementation of the components, you can find the code inside the `Development Pods` folder.
+Use `cmd-1` to open the project navigator within Xcode. Peal open the `Pods` project and inside the `Development Pods` folder you will find the component source code.
+
+## Installation
+
+### Getting Started with a New Project
+
+Check out our [tutorial](howto/tutorial) for a step-by-step guide to setting up a new project using Material Components.
+
+### Adding Material Components to an Existing Project
+
+[CocoaPods](https://cocoapods.org/) is the easiest way to get started (if you're new to CocoaPods,
+check out their [getting started documentation](https://guides.cocoapods.org/using/getting-started.html).)
+
+To install CocoaPods, run the following commands:
+
+~~~ bash
+sudo gem install cocoapods
+~~~
+
+To integrate Material Components in your existing application, first create a new Podfile:
+
+~~~ bash
+cd your-project-directory
+pod init
+~~~
+
+Next, add the
+[Material Components for iOS pod](https://cocoapods.org/pods/MaterialComponentsIOS)
+to your target in your Podfile:
+
+~~~ ruby
+target "MyApp" do
+  ...
+  pod 'MaterialComponents'
+end
+~~~
+
+If you are using Swift, don’t forget to uncomment the `use_frameworks!` line
+at the top of your Podfile.
+
+Then run the command:
+
+~~~ bash
+pod install
+~~~
+
+Now you're ready to get started in Xcode. Don't forget to open the workspace Cocoapods created for you instead of the original project:
+
+~~~ bash
+open your-project.xcworkspace
+~~~
+
+### Usage
+
+The components are built upon familiar UIKit classes and can be added to a view with just a couple of lines. Simply import the Material Components header for the component you're interested in, and add it to your view.
+
+#### Swift
+
+~~~ swift
+import MaterialComponents.MaterialButtons
+
+class ViewController: UIViewController {
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        let raiseButton = MDCRaisedButton.init();
+        raiseButton.setTitle("Raised Button", forState: .Normal);
+        raiseButton.sizeToFit();
+        raiseButton.addTarget(self, action: #selector(tapped), forControlEvents: .TouchUpInside);
+        self.view.addSubview(raiseButton);
+    }
+
+    func tapped(sender: UIButton!){
+        NSLog("Button was tapped!");
+    }
+
+}
+~~~
+
+#### Objective-C
+
+~~~ objc
+#import "MaterialButtons.h"
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  MDCRaisedButton *raisedButton = [MDCRaisedButton new];
+  [raisedButton setTitle:@"Raised Button" forState:UIControlStateNormal];
+  [raisedButton sizeToFit];
+  [raisedButton addTarget:self
+                   action:@selector(tapped:)
+         forControlEvents:UIControlEventTouchUpInside];
+
+  [self.view addSubview:raisedButton];
+}
+
+- (void)tapped:(id)sender {
+  NSLog(@"Button was tapped!");
+}
+
+@end
+~~~
+
+## Attributions
+
+Material Components for iOS uses
+[Material Design icons](https://github.com/google/material-design-icons),
+copyright Google Inc. and licensed under
+[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
+
+Several components use
+[MDFTextAccessibility](https://github.com/material-foundation/material-text-accessibility-ios),
+copyright Google Inc. and licensed under
+[Apache 2.0](https://github.com/material-foundation/material-text-accessibility-ios/blob/master/LICENSE)
+without a NOTICE file.
+
+MDCCatalog uses the
+[Roboto font](https://github.com/google/fonts/tree/master/apache/roboto),
+copyright 2011 Google Inc. and licensed under
+[Apache 2.0](https://github.com/google/fonts/blob/master/apache/roboto/LICENSE.txt)
+without a NOTICE file.
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
new file mode 100644
index 0000000..db0b8b0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.h
@@ -0,0 +1,132 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCActivityIndicatorDelegate;
+
+/**
+ Different operating modes for the activity indicator.
+
+ This component can be used as a determinate progress indicator or an indeterminate activity
+ indicator.
+
+ Default value is MDCActivityIndicatorModeIndeterminate.
+ */
+typedef NS_ENUM(NSInteger, MDCActivityIndicatorMode) {
+  /** Indeterminate indicators visualize an unspecified wait time. */
+  MDCActivityIndicatorModeIndeterminate,
+  /** Determinate indicators display how long an operation will take. */
+  MDCActivityIndicatorModeDeterminate,
+};
+
+/**
+ A Material Design activity indicator.
+
+ The activity indicator is a circular spinner that shows progress of an operation. By default the
+ activity indicator assumes indeterminate progress of an unspecified length of time. In contrast to
+ a standard UIActivityIndicator, MDCActivityIndicator supports showing determinate progress and uses
+ custom Material Design animation for indeterminate progress.
+
+ See https://www.google.com/design/spec/components/progress-activity.html
+ */
+IB_DESIGNABLE
+@interface MDCActivityIndicator : UIView
+
+/**
+ The callback delegate. See @c MDCActivityIndicatorDelegate.
+ */
+@property(nonatomic, weak, nullable) id<MDCActivityIndicatorDelegate> delegate;
+
+/**
+ Whether or not the activity indicator is currently animating.
+ */
+@property(nonatomic, assign, getter=isAnimating) BOOL animating;
+
+/**
+ Spinner radius width. Defaults to 12dp (24x24dp circle), constrained to range [8dp, 72dp]. The
+ spinner is centered in the view's bounds. If the bounds are smaller than the diameter of the
+ spinner, the spinner may be clipped when clipToBounds is true.
+ */
+@property(nonatomic, assign) CGFloat radius UI_APPEARANCE_SELECTOR;
+
+/**
+ Spinner stroke width. Defaults to 2dp.
+ */
+@property(nonatomic, assign) CGFloat strokeWidth UI_APPEARANCE_SELECTOR;
+
+/**
+ Show a faint ink track along the path of the indicator. Should be enabled when the activity
+ indicator wraps around another circular element, such as an avatar or a FAB. Defaults to NO.
+ */
+@property(nonatomic, assign) IBInspectable BOOL trackEnabled;
+
+/**
+ The mode of the activity indicator. Default is MDCActivityIndicatorModeIndeterminate. If
+ currently animating, it will animate the transition between the current mode to the new mode.
+ */
+@property(nonatomic, assign) IBInspectable MDCActivityIndicatorMode indicatorMode;
+
+/**
+ Set the mode of the activity indicator. If currently animating, it will animate the transition
+ between the current mode to the new mode. Default is MDCActivityIndicatorModeIndeterminate with no
+ animation.
+ */
+- (void)setIndicatorMode:(MDCActivityIndicatorMode)mode animated:(BOOL)animated;
+
+/**
+ Progress is the extent to which the activity indicator circle is drawn to completion when
+ indicatorMode is MDCActivityIndicatorModeDeterminate. Progress is drawn clockwise to complete a
+ circle. Valid range is between [0-1]. Default is zero. 0.5 progress is half the circle. The
+ transitions between progress levels are animated.
+ */
+@property(nonatomic, assign) IBInspectable float progress;
+
+/**
+ The array of colors that are cycled through when animating the spinner. Populated with default
+ colors of blue, red, yellow and green on initialization. An empty array results in a blue spinner
+ with no color cycling.
+ */
+@property(nonatomic, copy, nonnull) NSArray<UIColor *> *cycleColors UI_APPEARANCE_SELECTOR;
+
+/**
+ Starts the animated activity indicator. Does nothing if the spinner is already animating.
+ */
+- (void)startAnimating;
+
+/**
+ Stops the animated activity indicator with a short opacity and stroke width animation. Does nothing
+ if the spinner is not animating.
+ */
+- (void)stopAnimating;
+
+@end
+
+/**
+ Delegate protocol for the MDCActivityIndicator.
+ */
+@protocol MDCActivityIndicatorDelegate <NSObject>
+
+@optional
+/**
+ When stop is called, the spinner gracefully animates out using opacity and stroke width.
+ This method is called after that fade-out animation completes.
+
+ @param activityIndicator Caller
+ */
+- (void)activityIndicatorAnimationDidFinish:(nonnull MDCActivityIndicator *)activityIndicator;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.m
new file mode 100644
index 0000000..58d3d23
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MDCActivityIndicator.m
@@ -0,0 +1,798 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCActivityIndicator.h"
+
+#import "MaterialRTL.h"
+#import "UIApplication+AppExtensions.h"
+
+static const NSInteger kMDCActivityIndicatorTotalDetentCount = 5;
+static const NSTimeInterval kMDCActivityIndicatorAnimateOutDuration = 0.1f;
+static const NSTimeInterval kMDCActivityIndicatorPointCycleDuration = 4.0f / 3.0f;
+static const NSTimeInterval kMDCActivityIndicatorPointCycleMinimumVariableDuration =
+    kMDCActivityIndicatorPointCycleDuration / 8;
+static const CGFloat kCycleRotation = 3.0f / 2.0f;
+static const CGFloat kOuterRotationIncrement =
+    (1.0f / kMDCActivityIndicatorTotalDetentCount) * (CGFloat)M_PI;
+static const CGFloat kSpinnerRadius = 12.f;
+static const CGFloat kStrokeLength = 0.75f;
+
+/**
+ Total rotation (outer rotation + stroke rotation) per _cycleCount. One turn is 2.0f.
+ */
+static const CGFloat kSingleCycleRotation =
+    2 * kStrokeLength + kCycleRotation + 1.0f / kMDCActivityIndicatorTotalDetentCount;
+
+/*
+ States for the internal state machine. The states represent the last animation completed.
+ It provides information required to select the next animation.
+ */
+typedef NS_ENUM(NSInteger, MDCActivityIndicatorState) {
+  MDCActivityIndicatorStateIndeterminate,
+  MDCActivityIndicatorStateTransitionToDeterminate,
+  MDCActivityIndicatorStateDeterminate,
+  MDCActivityIndicatorStateTransitionToIndeterminate,
+};
+
+@interface MDCActivityIndicator ()
+
+/**
+ The minimum stroke difference to use when collapsing the stroke to a dot. Based on current
+ radius and stroke width.
+ */
+@property(nonatomic, assign, readonly) CGFloat minStrokeDifference;
+
+/**
+ The current color count for the spinner. Subclasses can change this value to start the spinner at
+ a different color.
+ */
+@property(nonatomic, assign) NSUInteger currentColorCount;
+
+/**
+ The current cycle count.
+ */
+@property(nonatomic, assign, readonly) NSInteger cycleCount;
+
+/**
+ The cycle index at which to start the activity spinner animation. Default is 0, which corresponds
+ to the top of the spinner (12 o'clock position). Spinner cycle indices are based on a 5-point
+ star.
+ */
+@property(nonatomic, assign) NSInteger cycleStartIndex;
+
+/**
+ The outer layer that handles cycle rotations and houses the stroke layer.
+ */
+@property(nonatomic, strong, readonly, nullable) CALayer *outerRotationLayer;
+
+/**
+ The shape layer that handles the animating stroke.
+ */
+@property(nonatomic, strong, readonly, nullable) CAShapeLayer *strokeLayer;
+
+/**
+ The shape layer that shows a faint, circular track along the path of the stroke layer. Enabled
+ via the trackEnabled property.
+ */
+@property(nonatomic, strong, readonly, nullable) CAShapeLayer *trackLayer;
+
+@end
+
+@implementation MDCActivityIndicator {
+  BOOL _animatingOut;
+  BOOL _animationsAdded;
+  BOOL _animationInProgress;
+  BOOL _backgrounded;
+  BOOL _cycleInProgress;
+  CGFloat _currentProgress;
+  CGFloat _lastProgress;
+}
+
+#pragma mark - Init
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCActivityIndicatorInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder {
+  self = [super initWithCoder:coder];
+  if (self) {
+    [self commonMDCActivityIndicatorInit];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self applyPropertiesWithoutAnimation:^{
+    // Resize and recenter rotation layer.
+    _outerRotationLayer.bounds = self.bounds;
+    _outerRotationLayer.position =
+        CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
+
+    _strokeLayer.bounds = _outerRotationLayer.bounds;
+    _strokeLayer.position = _outerRotationLayer.position;
+
+    [self updateStrokePath];
+  }];
+}
+
+- (void)commonMDCActivityIndicatorInit {
+  // Register notifications for foreground and background if needed.
+  [self registerForegroundAndBackgroundNotificationObserversIfNeeded];
+
+  // The activity indicator reflects the passage of time (a spatial semantic context) and so
+  // will not be mirrored in RTL languages.
+  self.mdc_semanticContentAttribute = UISemanticContentAttributeSpatial;
+
+  _cycleStartIndex = 0;
+  _indicatorMode = MDCActivityIndicatorModeIndeterminate;
+
+  // Property defaults.
+  _radius = kSpinnerRadius;
+  _strokeWidth = 2.0f;
+
+  // Colors.
+  _cycleColors = [MDCActivityIndicator defaultColors];
+  _currentColorCount = 0;
+
+  // Track layer.
+  _trackLayer = [CAShapeLayer layer];
+  _trackLayer.lineWidth = _strokeWidth;
+  _trackLayer.fillColor = [UIColor clearColor].CGColor;
+  [self.layer addSublayer:_trackLayer];
+  _trackLayer.hidden = YES;
+
+  // Rotation layer.
+  _outerRotationLayer = [CALayer layer];
+  [self.layer addSublayer:_outerRotationLayer];
+
+  // Stroke layer.
+  _strokeLayer = [CAShapeLayer layer];
+  _strokeLayer.lineWidth = _strokeWidth;
+  _strokeLayer.fillColor = [UIColor clearColor].CGColor;
+  _strokeLayer.strokeStart = 0;
+  _strokeLayer.strokeEnd = 0;
+  [_outerRotationLayer addSublayer:_strokeLayer];
+}
+
+#pragma mark - UIView
+
+- (void)willMoveToWindow:(UIWindow *)newWindow {
+  // If the activity indicator is removed from the window, we should
+  // immediately stop animating, otherwise it will start chewing up CPU.
+  if (!newWindow) {
+    [self actuallyStopAnimating];
+  } else if (_animating && !_backgrounded) {
+    [self actuallyStartAnimating];
+  }
+}
+
+- (CGSize)intrinsicContentSize {
+  CGFloat edge = 2 * _radius + _strokeWidth;
+  return CGSizeMake(edge, edge);
+}
+
+#pragma mark - Public methods
+
+- (void)startAnimating {
+  if (_animatingOut) {
+    [self removeAnimations];
+  }
+
+  if (_animating) {
+    return;
+  }
+
+  _animating = YES;
+
+  if (self.window && !_backgrounded) {
+    [self actuallyStartAnimating];
+  }
+}
+
+- (void)stopAnimating {
+  if (!_animating) {
+    return;
+  }
+
+  _animating = NO;
+
+  [self animateOut];
+}
+
+- (void)stopAnimatingImmediately {
+  if (!_animating) {
+    return;
+  }
+
+  _animating = NO;
+
+  [self actuallyStopAnimating];
+
+  if ([_delegate respondsToSelector:@selector(activityIndicatorAnimationDidFinish:)]) {
+    [_delegate activityIndicatorAnimationDidFinish:self];
+  }
+}
+
+- (void)resetStrokeColor {
+  _currentColorCount = 0;
+
+  [self updateStrokeColor];
+}
+
+- (void)setStrokeColor:(UIColor *)strokeColor {
+  _strokeLayer.strokeColor = strokeColor.CGColor;
+  _trackLayer.strokeColor = [strokeColor colorWithAlphaComponent:0.3f].CGColor;
+}
+
+- (void)setIndicatorMode:(MDCActivityIndicatorMode)indicatorMode {
+  if (_indicatorMode == indicatorMode) {
+    return;
+  }
+  _indicatorMode = indicatorMode;
+  if (_animating && !_animationInProgress) {
+    switch (indicatorMode) {
+      case MDCActivityIndicatorModeDeterminate:
+        [self addTransitionToDeterminateCycle];
+        break;
+      case MDCActivityIndicatorModeIndeterminate:
+        [self addTransitionToIndeterminateCycle];
+        break;
+    }
+  }
+}
+
+- (void)setIndicatorMode:(MDCActivityIndicatorMode)mode animated:(BOOL)animated {
+  [self setIndicatorMode:mode];
+}
+
+- (void)setProgress:(float)progress {
+  _progress = MAX(0.0f, MIN(progress, 1.0f));
+  if (_progress == _currentProgress) {
+    return;
+  }
+  if (_animating && !_animationInProgress) {
+    switch (_indicatorMode) {
+      case MDCActivityIndicatorModeDeterminate:
+        // Currently animating the determinate mode but no animation queued.
+        [self addProgressAnimation];
+        break;
+      case MDCActivityIndicatorModeIndeterminate:
+        break;
+    }
+  }
+}
+
+#pragma mark - Properties
+
+- (void)setStrokeWidth:(CGFloat)strokeWidth {
+  _strokeWidth = strokeWidth;
+  _strokeLayer.lineWidth = _strokeWidth;
+  _trackLayer.lineWidth = _strokeWidth;
+
+  [self updateStrokePath];
+}
+
+- (void)setRadius:(CGFloat)radius {
+  _radius = MIN(MAX(radius, 5.0f), 72.0f);
+
+  [self updateStrokePath];
+}
+
+- (void)setTrackEnabled:(BOOL)trackEnabled {
+  _trackEnabled = trackEnabled;
+
+  _trackLayer.hidden = !_trackEnabled;
+}
+
+#pragma mark - Private methods
+
+/**
+ If this class is not being run in an extension, register for foreground changes and initialize
+ the app background state in case UI is created when the app is backgrounded. (Extensions always
+ return UIApplicationStateBackground for |[UIApplication sharedApplication].applicationState|.)
+ */
+- (void)registerForegroundAndBackgroundNotificationObserversIfNeeded {
+  if ([UIApplication mdc_isAppExtension]) {
+    return;
+  }
+
+  _backgrounded =
+      [UIApplication mdc_safeSharedApplication].applicationState == UIApplicationStateBackground;
+  NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+  [notificationCenter addObserver:self
+                         selector:@selector(controlAnimatingOnForegroundChange:)
+                             name:UIApplicationWillEnterForegroundNotification
+                           object:nil];
+  [notificationCenter addObserver:self
+                         selector:@selector(controlAnimatingOnForegroundChange:)
+                             name:UIApplicationDidEnterBackgroundNotification
+                           object:nil];
+}
+
+- (void)controlAnimatingOnForegroundChange:(NSNotification *)notification {
+  // Stop or restart animating if the app has a foreground change.
+  _backgrounded = [notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification];
+  if (_animating) {
+    if (_backgrounded) {
+      [self actuallyStopAnimating];
+    } else if (self.window) {
+      [self actuallyStartAnimating];
+    }
+  }
+}
+
+- (void)actuallyStartAnimating {
+  if (_animationsAdded) {
+    return;
+  }
+  _animationsAdded = YES;
+  _cycleCount = _cycleStartIndex;
+
+  [self applyPropertiesWithoutAnimation:^{
+    _strokeLayer.strokeStart = 0.0f;
+    _strokeLayer.strokeEnd = 0.001f;
+    _strokeLayer.lineWidth = _strokeWidth;
+    _trackLayer.lineWidth = _strokeWidth;
+
+    [self resetStrokeColor];
+    [self updateStrokePath];
+  }];
+
+  switch (_indicatorMode) {
+    case MDCActivityIndicatorModeIndeterminate:
+      [self addStrokeRotationCycle];
+      break;
+    case MDCActivityIndicatorModeDeterminate:
+      [self addProgressAnimation];
+      break;
+  }
+}
+
+- (void)actuallyStopAnimating {
+  if (!_animationsAdded) {
+    return;
+  }
+
+  [self removeAnimations];
+  [self applyPropertiesWithoutAnimation:^{
+    _strokeLayer.strokeStart = 0.0f;
+    _strokeLayer.strokeEnd = 0.0f;
+  }];
+}
+
+- (void)updateStrokePath {
+  CGFloat offsetRadius = _radius - _strokeLayer.lineWidth / 2.0f;
+  UIBezierPath *strokePath = [UIBezierPath bezierPathWithArcCenter:_strokeLayer.position
+                                                            radius:offsetRadius
+                                                        startAngle:-1.0f * (CGFloat)M_PI_2
+                                                          endAngle:3.0f * (CGFloat)M_PI_2
+                                                         clockwise:YES];
+  _strokeLayer.path = strokePath.CGPath;
+  _trackLayer.path = strokePath.CGPath;
+
+  _minStrokeDifference = _strokeLayer.lineWidth / ((CGFloat)M_PI * 2 * _radius);
+}
+
+- (void)updateStrokeColor {
+  if (_cycleColors.count > 0) {
+    [self setStrokeColor:_cycleColors[_currentColorCount]];
+  } else {
+    [self setStrokeColor:[MDCActivityIndicator defaultColors][0]];
+  }
+}
+
+- (void)addStrokeRotationCycle {
+  if (_animationInProgress) {
+    return;
+  }
+
+  [CATransaction begin];
+  {
+    [CATransaction setCompletionBlock:^{
+      [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateIndeterminate];
+    }];
+
+    // Outer 5-point star detent rotation.
+    CABasicAnimation *outerRotationAnimation =
+        [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+    outerRotationAnimation.duration = kMDCActivityIndicatorPointCycleDuration;
+    outerRotationAnimation.fromValue = @(kOuterRotationIncrement * _cycleCount);
+    outerRotationAnimation.toValue = @(kOuterRotationIncrement * (_cycleCount + 1));
+    outerRotationAnimation.fillMode = kCAFillModeForwards;
+    outerRotationAnimation.removedOnCompletion = NO;
+    [_outerRotationLayer addAnimation:outerRotationAnimation forKey:@"transform.rotation.z"];
+
+    // Stroke rotation.
+    CGFloat startRotation = _cycleCount * (CGFloat)M_PI;
+    CGFloat endRotation = startRotation + kCycleRotation * (CGFloat)M_PI;
+
+    CABasicAnimation *strokeRotationAnimation =
+        [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+    strokeRotationAnimation.duration = kMDCActivityIndicatorPointCycleDuration;
+    strokeRotationAnimation.fromValue = @(startRotation);
+    strokeRotationAnimation.toValue = @(endRotation);
+    strokeRotationAnimation.fillMode = kCAFillModeForwards;
+    strokeRotationAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeRotationAnimation forKey:@"transform.rotation.z"];
+
+    // Stroke start.
+    CABasicAnimation *strokeStartPathAnimation =
+        [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+    strokeStartPathAnimation.duration = kMDCActivityIndicatorPointCycleDuration / 2;
+    // It is always critical to convertTime:fromLayer: for animations, since changes to layer.speed
+    // on this layer or parent layers will alter the offset of beginTime.
+    CFTimeInterval currentTime = [_strokeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
+    strokeStartPathAnimation.beginTime = currentTime + kMDCActivityIndicatorPointCycleDuration / 2;
+    strokeStartPathAnimation.fromValue = @(0.0f);
+    strokeStartPathAnimation.toValue = @(kStrokeLength);
+    strokeStartPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeStartPathAnimation.fillMode = kCAFillModeBoth;
+    strokeStartPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeStartPathAnimation forKey:@"strokeStart"];
+
+    // Stroke end.
+    CABasicAnimation *strokeEndPathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+    strokeEndPathAnimation.duration =
+        kMDCActivityIndicatorPointCycleDuration * ABS(_lastProgress - _currentProgress);
+    // Ensure the stroke never completely disappears on start by animating from non-zero start and
+    // to a value slightly larger than the strokeStart's final value.
+    strokeEndPathAnimation.fromValue = @(_minStrokeDifference);
+    strokeEndPathAnimation.toValue = @(kStrokeLength + _minStrokeDifference);
+    strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+    strokeEndPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+  }
+  [CATransaction commit];
+
+  _animationInProgress = YES;
+}
+
+- (void)addTransitionToIndeterminateCycle {
+  if (_animationInProgress) {
+    return;
+  }
+  // Find the nearest cycle to transition through.
+  NSInteger nearestCycle = 0;
+  CGFloat nearestDistance = CGFLOAT_MAX;
+  const CGFloat normalizedProgress = MAX(_lastProgress - _minStrokeDifference, 0.0f);
+  for (NSInteger cycle = 0; cycle < kMDCActivityIndicatorTotalDetentCount; cycle++) {
+    const CGFloat currentRotation = [self normalizedRotationForCycle:cycle];
+    if (currentRotation >= normalizedProgress) {
+      if (nearestDistance >= (currentRotation - normalizedProgress)) {
+        nearestDistance = currentRotation - normalizedProgress;
+        nearestCycle = cycle;
+      }
+    }
+  }
+
+  if (nearestCycle == 0 && _lastProgress <= _minStrokeDifference) {
+    // Special case for 0% progress.
+    _cycleCount = nearestCycle;
+    [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToIndeterminate];
+    return;
+  }
+
+  _cycleCount = nearestCycle;
+
+  CGFloat targetRotation = [self normalizedRotationForCycle:nearestCycle];
+  if (targetRotation <= 0.001f) {
+    targetRotation = 1.0f;
+  }
+  CGFloat normalizedDuration = 2 * (targetRotation + _currentProgress) / kSingleCycleRotation *
+                               (CGFloat)kMDCActivityIndicatorPointCycleDuration;
+  CGFloat strokeEndTravelDistance = targetRotation - _currentProgress + _minStrokeDifference;
+  CGFloat totalDistance = targetRotation + strokeEndTravelDistance;
+  CGFloat strokeStartDuration =
+      MAX(normalizedDuration * targetRotation / totalDistance,
+          (CGFloat)kMDCActivityIndicatorPointCycleMinimumVariableDuration);
+  CGFloat strokeEndDuration = MAX(normalizedDuration * strokeEndTravelDistance / totalDistance,
+                                  (CGFloat)kMDCActivityIndicatorPointCycleMinimumVariableDuration);
+
+  [CATransaction begin];
+  {
+    [CATransaction setCompletionBlock:^{
+      [self
+          strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToIndeterminate];
+    }];
+
+    // Stroke start.
+    CABasicAnimation *strokeStartPathAnimation =
+        [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+    strokeStartPathAnimation.duration = strokeStartDuration;
+    CFTimeInterval currentTime = [_strokeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
+    strokeStartPathAnimation.beginTime = currentTime + strokeEndDuration;
+    strokeStartPathAnimation.fromValue = @(0.0f);
+    strokeStartPathAnimation.toValue = @(targetRotation);
+    strokeStartPathAnimation.timingFunction = [self materialEaseInOut];
+    ;
+    strokeStartPathAnimation.fillMode = kCAFillModeBoth;
+    strokeStartPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeStartPathAnimation forKey:@"strokeStart"];
+
+    // Stroke end.
+    CABasicAnimation *strokeEndPathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+    strokeEndPathAnimation.duration = strokeEndDuration;
+    // Ensure the stroke never completely disappears on start by animating from non-zero start and
+    // to a value slightly larger than the strokeStart's final value.
+    strokeEndPathAnimation.fromValue = @(_currentProgress);
+    strokeEndPathAnimation.toValue = @(targetRotation + _minStrokeDifference);
+    strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+    strokeEndPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+  }
+  [CATransaction commit];
+
+  _animationInProgress = YES;
+}
+
+- (void)addTransitionToDeterminateCycle {
+  if (_animationInProgress) {
+    return;
+  }
+  if (!_cycleCount) {
+    // The animation period is complete: no need for transition.
+    [_strokeLayer removeAllAnimations];
+    [_outerRotationLayer removeAllAnimations];
+    // Necessary for transition from indeterminate to determinate when cycle == 0.
+    _currentProgress = 0.0f;
+    _lastProgress = _currentProgress;
+    [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToDeterminate];
+  } else {
+    _currentProgress = MAX(_progress, _minStrokeDifference);
+
+    CGFloat rotationDelta = 1.0f - [self normalizedRotationForCycle:_cycleCount];
+
+    // Change the duration relative to the distance in order to keep same relative speed.
+    CGFloat duration = 2.0f * (rotationDelta + _currentProgress) / kSingleCycleRotation *
+                       (CGFloat)kMDCActivityIndicatorPointCycleDuration;
+
+    duration = MAX(duration, (CGFloat)kMDCActivityIndicatorPointCycleMinimumVariableDuration);
+    [CATransaction begin];
+    {
+      [CATransaction setCompletionBlock:^{
+        [self
+            strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateTransitionToDeterminate];
+      }];
+
+      // Outer 5-point star detent rotation. Required for passing from transitionToIndeterminate to
+      // transitionToDeterminate.
+      CABasicAnimation *outerRotationAnimation =
+          [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+      outerRotationAnimation.duration = duration;
+      outerRotationAnimation.fromValue = @(kOuterRotationIncrement * _cycleCount);
+      outerRotationAnimation.toValue = @(kOuterRotationIncrement * _cycleCount);
+      outerRotationAnimation.fillMode = kCAFillModeForwards;
+      outerRotationAnimation.removedOnCompletion = NO;
+      [_outerRotationLayer addAnimation:outerRotationAnimation forKey:@"transform.rotation.z"];
+
+      // Stroke rotation.
+      CGFloat startRotation = _cycleCount * (CGFloat)M_PI;
+      CGFloat endRotation = startRotation + rotationDelta * 2.0f * (CGFloat)M_PI;
+
+      CABasicAnimation *strokeRotationAnimation =
+          [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+      strokeRotationAnimation.duration = duration;
+      strokeRotationAnimation.fromValue = @(startRotation);
+      strokeRotationAnimation.toValue = @(endRotation);
+      strokeRotationAnimation.fillMode = kCAFillModeForwards;
+      strokeRotationAnimation.removedOnCompletion = NO;
+      [_strokeLayer addAnimation:strokeRotationAnimation forKey:@"transform.rotation.z"];
+
+      // Stroke start.
+      CABasicAnimation *strokeStartPathAnimation =
+          [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+      strokeStartPathAnimation.duration = duration;
+      // It is always critical to convertTime:fromLayer: for animations, since changes to
+      // layer.speed on this layer or parent layers will alter the offset of beginTime.
+      CFTimeInterval currentTime = [_strokeLayer convertTime:CACurrentMediaTime() fromLayer:nil];
+      strokeStartPathAnimation.beginTime = currentTime;
+      strokeStartPathAnimation.fromValue = @(0.0f);
+      strokeStartPathAnimation.toValue = @(0.0f);
+      strokeStartPathAnimation.timingFunction = [self materialEaseInOut];
+      strokeStartPathAnimation.fillMode = kCAFillModeBoth;
+      strokeStartPathAnimation.removedOnCompletion = NO;
+      [_strokeLayer addAnimation:strokeStartPathAnimation forKey:@"strokeStart"];
+
+      // Stroke end.
+      CABasicAnimation *strokeEndPathAnimation =
+          [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+      strokeEndPathAnimation.duration = duration;
+      // Ensure the stroke never completely disappears on start by animating from non-zero start and
+      // to a value slightly larger than the strokeStart's final value.
+      strokeEndPathAnimation.fromValue = @(_minStrokeDifference);
+      strokeEndPathAnimation.toValue = @(_currentProgress);
+      strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+      strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+      strokeEndPathAnimation.removedOnCompletion = NO;
+      [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+    }
+    [CATransaction commit];
+
+    _animationInProgress = YES;
+    _lastProgress = _currentProgress;
+  }
+}
+
+- (CAMediaTimingFunction *)materialEaseInOut {
+  // This curve is slow both at the beginning and end.
+  // Visualization of curve  http://cubic-bezier.com/#.4,0,.2,1
+  return [[CAMediaTimingFunction alloc] initWithControlPoints:0.4f:0.0f:0.2f:1.0f];
+}
+
+- (void)addProgressAnimation {
+  if (_animationInProgress) {
+    return;
+  }
+
+  _currentProgress = MAX(_progress, _minStrokeDifference);
+
+  [CATransaction begin];
+  {
+    [CATransaction setCompletionBlock:^{
+      [self strokeRotationCycleFinishedFromState:MDCActivityIndicatorStateDeterminate];
+    }];
+
+    // Stroke end.
+    CABasicAnimation *strokeEndPathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+    strokeEndPathAnimation.duration = kMDCActivityIndicatorPointCycleDuration / 2;
+    strokeEndPathAnimation.fromValue = @(_lastProgress);
+    strokeEndPathAnimation.toValue = @(_currentProgress);
+    strokeEndPathAnimation.timingFunction = [self materialEaseInOut];
+    strokeEndPathAnimation.fillMode = kCAFillModeBoth;
+    strokeEndPathAnimation.removedOnCompletion = NO;
+    [_strokeLayer addAnimation:strokeEndPathAnimation forKey:@"strokeEnd"];
+  }
+
+  [CATransaction commit];
+
+  _lastProgress = _currentProgress;
+  _animationInProgress = YES;
+}
+
+- (void)strokeRotationCycleFinishedFromState:(MDCActivityIndicatorState)state {
+  _animationInProgress = NO;
+
+  if (!_animationsAdded) {
+    return;
+  }
+  if (state == MDCActivityIndicatorStateIndeterminate) {
+    if (_cycleColors.count > 0) {
+      _currentColorCount = (_currentColorCount + 1) % _cycleColors.count;
+      [self updateStrokeColor];
+    }
+    _cycleCount = (_cycleCount + 1) % kMDCActivityIndicatorTotalDetentCount;
+  }
+
+  switch (_indicatorMode) {
+    case MDCActivityIndicatorModeDeterminate:
+      switch (state) {
+        case MDCActivityIndicatorStateDeterminate:
+        case MDCActivityIndicatorStateTransitionToDeterminate:
+          [self addProgressAnimationIfRequired];
+          break;
+        case MDCActivityIndicatorStateIndeterminate:
+        case MDCActivityIndicatorStateTransitionToIndeterminate:
+          [self addTransitionToDeterminateCycle];
+          break;
+      }
+      break;
+    case MDCActivityIndicatorModeIndeterminate:
+      switch (state) {
+        case MDCActivityIndicatorStateDeterminate:
+        case MDCActivityIndicatorStateTransitionToDeterminate:
+          [self addTransitionToIndeterminateCycle];
+          break;
+        case MDCActivityIndicatorStateIndeterminate:
+        case MDCActivityIndicatorStateTransitionToIndeterminate:
+          [self addStrokeRotationCycle];
+          break;
+      }
+      break;
+  }
+}
+
+- (void)addProgressAnimationIfRequired {
+  if (_indicatorMode == MDCActivityIndicatorModeDeterminate) {
+    if (MAX(_progress, _minStrokeDifference) != _currentProgress) {
+      // The values were changes in the while animating or animation is starting.
+      [self addProgressAnimation];
+    }
+  }
+}
+
+/**
+ Rotation that a given cycle has. Represented between 0.0f (cycle has no rotation) and 1.0f.
+ */
+- (CGFloat)normalizedRotationForCycle:(NSInteger)cycle {
+  CGFloat cycleRotation = cycle * kSingleCycleRotation / 2.0f;
+  return cycleRotation - ((NSInteger)cycleRotation);
+}
+
+- (void)animateOut {
+  _animatingOut = YES;
+
+  [CATransaction begin];
+
+  [CATransaction setCompletionBlock:^{
+    if (_animatingOut) {
+      [self removeAnimations];
+      if ([_delegate respondsToSelector:@selector(activityIndicatorAnimationDidFinish:)]) {
+        [_delegate activityIndicatorAnimationDidFinish:self];
+      }
+    }
+  }];
+  [CATransaction setAnimationDuration:kMDCActivityIndicatorAnimateOutDuration];
+
+  _strokeLayer.lineWidth = 0;
+  _trackLayer.lineWidth = 0;
+
+  [CATransaction commit];
+}
+
+- (void)removeAnimations {
+  _animationsAdded = NO;
+  _animatingOut = NO;
+  [_strokeLayer removeAllAnimations];
+  [_outerRotationLayer removeAllAnimations];
+
+  // Reset cycle count to 0 rather than cycleStart to reflect default starting position (top).
+  _cycleCount = 0;
+  // However _animationInProgress represents the CATransaction that hasn't finished, so we leave it
+  // alone here.
+}
+
++ (CGFloat)defaultHeight {
+  return kSpinnerRadius * 2.f;
+}
+
+- (void)applyPropertiesWithoutAnimation:(void (^)(void))setPropBlock {
+  [CATransaction begin];
+
+  // Disable implicit CALayer animations
+  [CATransaction setDisableActions:YES];
+  setPropBlock();
+
+  [CATransaction commit];
+}
+
++ (NSArray<UIColor *> *)defaultColors {
+  static NSArray *defaultColors;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    defaultColors = @[
+      [[UIColor alloc] initWithRed:0.129f green:0.588f blue:0.953f alpha:1],
+      [[UIColor alloc] initWithRed:0.957f green:0.263f blue:0.212f alpha:1],
+      [[UIColor alloc] initWithRed:1.0f green:0.922f blue:0.231f alpha:1],
+      [[UIColor alloc] initWithRed:0.298f green:0.686f blue:0.314f alpha:1]
+    ];
+  });
+  return defaultColors;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
new file mode 100644
index 0000000..0273f25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ActivityIndicator/src/MaterialActivityIndicator.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCActivityIndicator.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
new file mode 100644
index 0000000..18b9c05
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h
@@ -0,0 +1,70 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+/**
+ Material Design easing curve animation values.
+
+ Use these easing curves to create smooth and consistent motion that conforms to Material Design.
+ */
+typedef NS_ENUM(NSUInteger, MDCAnimationTimingFunction) {
+  /**
+   This is the most frequently used interpolation curve for Material Design animations. This curve
+   is slow both at the beginning and end. It has similar characteristics to the system's EaseInOut.
+   This is known as FastOutSlowIn in the Material Design spec.
+   */
+  MDCAnimationTimingFunctionEaseInOut,
+
+  /**
+   This curve should be used for motion when entering frame or when fading in from 0% opacity. This
+   curve is slow at the end. It has similar characteristics to the system's EaseOut. This is known
+   as LinearOutSlowIn in the Material Design spec.
+   */
+  MDCAnimationTimingFunctionEaseOut,
+
+  /**
+   This curve should be used for motion when exiting frame or when fading out to 0% opacity. This
+   curve is slow at the beginning. It has similar characteristics to the system's EaseIn. This
+   is known as FastOutLinearIn in the Material Design spec.
+   */
+  MDCAnimationTimingFunctionEaseIn,
+
+  /**
+   Aliases for various specific timing curve recommendations.
+   */
+  MDCAnimationTimingFunctionTranslate = MDCAnimationTimingFunctionEaseInOut,
+  MDCAnimationTimingFunctionTranslateOnScreen = MDCAnimationTimingFunctionEaseOut,
+  MDCAnimationTimingFunctionTranslateOffScreen = MDCAnimationTimingFunctionEaseIn,
+  MDCAnimationTimingFunctionFadeIn = MDCAnimationTimingFunctionEaseOut,
+  MDCAnimationTimingFunctionFadeOut = MDCAnimationTimingFunctionEaseIn,
+};
+
+/**
+ Material Design animation curves.
+ */
+@interface CAMediaTimingFunction (MDCAnimationTiming)
+
+/**
+ Returns the corresponding CAMediaTimingFunction for the given curve specified by an enum. The most
+ common curve is MDCAnimationTimingFunctionEaseInOut.
+
+ @param type A Material Design media timing function.
+ */
++ (CAMediaTimingFunction *)mdc_functionWithType:(MDCAnimationTimingFunction)type;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m
new file mode 100644
index 0000000..b3fc894
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m
@@ -0,0 +1,35 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "CAMediaTimingFunction+MDCAnimationTiming.h"
+
+@implementation CAMediaTimingFunction (MDCAnimationTiming)
+
++ (CAMediaTimingFunction *)mdc_functionWithType:(MDCAnimationTimingFunction)type {
+  switch (type) {
+    case MDCAnimationTimingFunctionEaseInOut:
+      return [[CAMediaTimingFunction alloc] initWithControlPoints:0.4f:0.0f:0.2f:1.0f];
+    case MDCAnimationTimingFunctionEaseOut:
+      return [[CAMediaTimingFunction alloc] initWithControlPoints:0.0f:0.0f:0.2f:1.0f];
+    case MDCAnimationTimingFunctionEaseIn:
+      return [[CAMediaTimingFunction alloc] initWithControlPoints:0.4f:0.0f:1.0f:1.0f];
+  }
+  NSAssert(NO, @"Invalid MDCAnimationTimingFunction value %i.", (int)type);
+  // Reasonable default to use in Release mode for garbage input.
+  return nil;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
new file mode 100644
index 0000000..70431dc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/MaterialAnimationTiming.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "CAMediaTimingFunction+MDCAnimationTiming.h"
+#import "UIView+MDCTimingFunction.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
new file mode 100644
index 0000000..8002488
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.h
@@ -0,0 +1,39 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+@interface UIView (MDCTimingFunction)
+
+/**
+ A convienence method for applying a timing function to animations.
+
+ @param timingFunction A timing function for the easing curve animation.
+ @param duration The time the animation takes.
+ @param delay The time to wait before the animation begins.
+ @param options Configuration options for the timing function.
+ @param animations Animations to which the timing function will apply.
+ @param completion A completion block fired after the animations complete.
+ */
++ (void)mdc_animateWithTimingFunction:(CAMediaTimingFunction *)timingFunction
+                             duration:(NSTimeInterval)duration
+                                delay:(NSTimeInterval)delay
+                              options:(UIViewAnimationOptions)options
+                           animations:(void (^)(void))animations
+                           completion:(void (^)(BOOL finished))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.m
new file mode 100644
index 0000000..5d4f393
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AnimationTiming/src/UIView+MDCTimingFunction.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIView+MDCTimingFunction.h"
+
+@implementation UIView (MDCTimingFunction)
+
++ (void)mdc_animateWithTimingFunction:(CAMediaTimingFunction *)timingFunction
+                             duration:(NSTimeInterval)duration
+                                delay:(NSTimeInterval)delay
+                              options:(UIViewAnimationOptions)options
+                           animations:(void (^)(void))animations
+                           completion:(void (^)(BOOL finished))completion {
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:timingFunction];
+  [UIView animateWithDuration:duration
+                        delay:delay
+                      options:options
+                   animations:animations
+                   completion:completion];
+  [CATransaction commit];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.h
new file mode 100644
index 0000000..c4260c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.h
@@ -0,0 +1,55 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MaterialFlexibleHeader.h"
+#import "MaterialHeaderStackView.h"
+#import "MaterialNavigationBar.h"
+
+/**
+ The MDCAppBar class creates and configures the constellation of components required to represent a
+ Material App Bar.
+
+ A Material App Bar consists of a Flexible View with a shadow, a Navigation Bar, and space for
+ flexible content such as a photo.
+
+ Learn more at the [Material
+ spec](https://www.google.com/design/spec/patterns/scrolling-techniques.html)
+
+ ### Dependencies
+
+ AppBar depends on the FlexibleHeader, HeaderStackView, and NavigationBar Material Components.
+ */
+@interface MDCAppBar : NSObject
+
+/**
+ Adds headerViewController.view to headerViewController.parentViewController.view and registers
+ navigationItem observation on headerViewController.parentViewController.
+ */
+- (void)addSubviewsToParent;
+
+/** The header view controller instance manages the App Bar's flexible header view behavior. */
+@property(nonatomic, strong, nonnull, readonly)
+    MDCFlexibleHeaderViewController *headerViewController;
+
+/** The navigation bar. */
+@property(nonatomic, strong, nonnull, readonly) MDCNavigationBar *navigationBar;
+
+/**
+ The header stack view that owns the navigationBar (as the top bar) and an optional bottom bar.
+ */
+@property(nonatomic, strong, nonnull, readonly) MDCHeaderStackView *headerStackView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.m
new file mode 100644
index 0000000..785a34a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBar.m
@@ -0,0 +1,286 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBar.h"
+
+#import "MDCAppBarContainerViewController.h"
+
+#import "MaterialFlexibleHeader.h"
+#import "MaterialIcons+ic_arrow_back.h"
+#import "MaterialRTL.h"
+#import "MaterialShadowElevations.h"
+#import "MaterialShadowLayer.h"
+#import "MaterialTypography.h"
+
+static NSString *const kBarStackKey = @"barStack";
+static NSString *const kStatusBarHeightKey = @"statusBarHeight";
+static NSString *const MDCAppBarHeaderViewControllerKey = @"MDCAppBarHeaderViewControllerKey";
+static NSString *const MDCAppBarNavigationBarKey = @"MDCAppBarNavigationBarKey";
+static NSString *const MDCAppBarHeaderStackViewKey = @"MDCAppBarHeaderStackViewKey";
+static const CGFloat kStatusBarHeight = 20;
+
+@class MDCAppBarViewController;
+
+@interface MDCAppBar ()
+
+@property(nonatomic, strong) MDCAppBarViewController *appBarController;
+
+@end
+
+@interface MDCAppBarViewController : UIViewController
+
+@property(nonatomic, strong) MDCHeaderStackView *headerStackView;
+@property(nonatomic, strong) MDCNavigationBar *navigationBar;
+
+@end
+
+@implementation MDCAppBar
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    [self commonMDCAppBarInit];
+    [self commonMDCAppBarViewSetup];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super init];
+  if (self) {
+    [self commonMDCAppBarInit];
+    if ([aDecoder containsValueForKey:MDCAppBarHeaderViewControllerKey]) {
+      _headerViewController = [aDecoder decodeObjectForKey:MDCAppBarHeaderViewControllerKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCAppBarNavigationBarKey]) {
+      _navigationBar = [aDecoder decodeObjectForKey:MDCAppBarNavigationBarKey];
+      _appBarController.navigationBar = _navigationBar;
+    }
+
+    if ([aDecoder containsValueForKey:MDCAppBarHeaderStackViewKey]) {
+      _headerStackView = [aDecoder decodeObjectForKey:MDCAppBarHeaderStackViewKey];
+      _appBarController.headerStackView = _headerStackView;
+    }
+
+    [self commonMDCAppBarViewSetup];
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [aCoder encodeObject:self.headerViewController forKey:MDCAppBarHeaderViewControllerKey];
+  [aCoder encodeObject:self.navigationBar forKey:MDCAppBarNavigationBarKey];
+  [aCoder encodeObject:self.headerStackView forKey:MDCAppBarHeaderStackViewKey];
+}
+
+- (void)commonMDCAppBarInit {
+  _headerViewController = [[MDCFlexibleHeaderViewController alloc] init];
+
+  // Shadow layer
+  MDCFlexibleHeaderView *headerView = _headerViewController.headerView;
+  MDCFlexibleHeaderShadowIntensityChangeBlock intensityBlock =
+      ^(CALayer *_Nonnull shadowLayer, CGFloat intensity) {
+        CGFloat elevation = MDCShadowElevationAppBar * intensity;
+        [(MDCShadowLayer *)shadowLayer setElevation:elevation];
+      };
+  [headerView setShadowLayer:[MDCShadowLayer layer] intensityDidChangeBlock:intensityBlock];
+  _appBarController = [[MDCAppBarViewController alloc] init];
+  _headerStackView = _appBarController.headerStackView;
+  _navigationBar = _appBarController.navigationBar;
+}
+
+- (void)commonMDCAppBarViewSetup {
+  [_headerViewController addChildViewController:_appBarController];
+  _appBarController.view.frame = _headerViewController.view.bounds;
+  [_headerViewController.view addSubview:_appBarController.view];
+  [_appBarController didMoveToParentViewController:_headerViewController];
+
+  [_headerViewController.headerView forwardTouchEventsForView:_appBarController.headerStackView];
+  [_headerViewController.headerView forwardTouchEventsForView:_appBarController.navigationBar];
+}
+
+- (void)addHeaderViewControllerToParentViewController:
+        (nonnull UIViewController *)parentViewController {
+  [parentViewController addChildViewController:_headerViewController];
+}
+
+- (void)addSubviewsToParent {
+  MDCFlexibleHeaderViewController *fhvc = self.headerViewController;
+  NSAssert(fhvc.parentViewController,
+           @"headerViewController does not have a parentViewController. "
+           @"Use [self addChildViewController:appBar.headerViewController]. "
+           @"This warning only appears in DEBUG builds");
+  if (fhvc.view.superview == fhvc.parentViewController.view) {
+    return;
+  }
+
+  // Enforce the header's desire to fully cover the width of its parent view.
+  CGRect frame = fhvc.view.frame;
+  frame.origin.x = 0;
+  frame.size.width = fhvc.parentViewController.view.bounds.size.width;
+  fhvc.view.frame = frame;
+
+  [fhvc.parentViewController.view addSubview:fhvc.view];
+  [fhvc didMoveToParentViewController:fhvc.parentViewController];
+
+  [self.navigationBar observeNavigationItem:fhvc.parentViewController.navigationItem];
+}
+
+@end
+
+@implementation MDCAppBarViewController
+
+- (MDCHeaderStackView *)headerStackView {
+  // Removed call to loadView here as we should never be calling it manually.
+  // It previously replaced loadViewIfNeeded call that is only iOS 9.0+ to
+  // make backwards compatible.
+  // Underlying issue is you need view loaded before accessing. Below change will accomplish that
+  // by calling for view.bounds initializing the stack view
+  if (!_headerStackView) {
+    _headerStackView = [[MDCHeaderStackView alloc] initWithFrame:CGRectZero];
+  }
+  return _headerStackView;
+}
+
+- (MDCNavigationBar *)navigationBar {
+  if (!_navigationBar) {
+    _navigationBar = [[MDCNavigationBar alloc] init];
+  }
+  return _navigationBar;
+}
+
+- (UIViewController *)flexibleHeaderParentViewController {
+  NSAssert([self.parentViewController isKindOfClass:[MDCFlexibleHeaderViewController class]],
+           @"Expected the parent of %@ to be a type of %@", NSStringFromClass([self class]),
+           NSStringFromClass([MDCFlexibleHeaderViewController class]));
+  return self.parentViewController.parentViewController;
+}
+
+- (UIBarButtonItem *)backButtonItem {
+  UIViewController *fhvParent = self.flexibleHeaderParentViewController;
+  UINavigationController *navigationController = fhvParent.navigationController;
+
+  NSArray<UIViewController *> *viewControllerStack = navigationController.viewControllers;
+
+  // This will be zero if there is no navigation controller, so a view controller which is not
+  // inside a navigation controller will be treated the same as a view controller at the root of a
+  // navigation controller
+  NSUInteger index = [viewControllerStack indexOfObject:fhvParent];
+
+  UIViewController *iterator = fhvParent;
+
+  // In complex cases it might actually be a parent of @c fhvParent which is on the nav stack.
+  while (index == NSNotFound && iterator && ![iterator isEqual:navigationController]) {
+    iterator = iterator.parentViewController;
+    index = [viewControllerStack indexOfObject:iterator];
+  }
+
+  if (index == NSNotFound) {
+    NSCAssert(NO, @"View controller not present in its own navigation controller.");
+    // This is not something which should ever happen, but just in case.
+    return nil;
+  }
+  if (index == 0) {
+    // The view controller is at the root of a navigation stack (or not in one).
+    return nil;
+  }
+  UIViewController *previousViewControler = navigationController.viewControllers[index - 1];
+  if ([previousViewControler isKindOfClass:[MDCAppBarContainerViewController class]]) {
+    // Special case: if the previous view controller is a container controller, use its content
+    // view controller.
+    MDCAppBarContainerViewController *chvc =
+        (MDCAppBarContainerViewController *)previousViewControler;
+    previousViewControler = chvc.contentViewController;
+  }
+  UIBarButtonItem *backBarButtonItem = previousViewControler.navigationItem.backBarButtonItem;
+  if (!backBarButtonItem) {
+    UIImage *backButtonImage = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_arrow_back]];
+    backButtonImage = [backButtonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+    if (self.navigationBar.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      backButtonImage = [backButtonImage mdc_imageFlippedForRightToLeftLayoutDirection];
+    }
+    backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:backButtonImage
+                                                         style:UIBarButtonItemStyleDone
+                                                        target:self
+                                                        action:@selector(didTapBackButton:)];
+  }
+  backBarButtonItem.accessibilityIdentifier = @"back_bar_button";
+  return backBarButtonItem;
+}
+
++ (NSBundle *)baseBundle {
+  static NSBundle *bundle = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    // We may not be included by the main bundle, but rather by an embedded framework, so figure out
+    // to which bundle our code is compiled, and use that as the starting point for bundle loading.
+    bundle = [NSBundle bundleForClass:[self class]];
+  });
+
+  return bundle;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.headerStackView.translatesAutoresizingMaskIntoConstraints = NO;
+  self.headerStackView.topBar = self.navigationBar;
+
+  [self.view addSubview:self.headerStackView];
+
+  // Bar stack expands vertically, but has a margin above it for the status bar.
+
+  NSArray<NSLayoutConstraint *> *horizontalConstraints = [NSLayoutConstraint
+      constraintsWithVisualFormat:[NSString stringWithFormat:@"H:|[%@]|", kBarStackKey]
+                          options:0
+                          metrics:nil
+                            views:@{kBarStackKey : self.headerStackView}];
+  [self.view addConstraints:horizontalConstraints];
+
+  NSArray<NSLayoutConstraint *> *verticalConstraints = [NSLayoutConstraint
+      constraintsWithVisualFormat:[NSString stringWithFormat:@"V:|-%@-[%@]|", kStatusBarHeightKey,
+                                                             kBarStackKey]
+                          options:0
+                          metrics:@{
+                            kStatusBarHeightKey : @(kStatusBarHeight)
+                          }
+                            views:@{kBarStackKey : self.headerStackView}];
+  [self.view addConstraints:verticalConstraints];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+
+  UIBarButtonItem *backBarButtonItem = [self backButtonItem];
+  if (backBarButtonItem && !self.navigationBar.backItem) {
+    self.navigationBar.backItem = backBarButtonItem;
+  }
+}
+
+#pragma mark User actions
+
+- (void)didTapBackButton:(id)sender {
+  UIViewController *pvc = self.flexibleHeaderParentViewController;
+  if (pvc.navigationController && pvc.navigationController.viewControllers.count > 1) {
+    [pvc.navigationController popViewControllerAnimated:YES];
+  } else {
+    [pvc dismissViewControllerAnimated:YES completion:nil];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
new file mode 100644
index 0000000..cdbd53a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.h
@@ -0,0 +1,63 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCAppBar;
+@class MDCFlexibleHeaderViewController;
+
+/**
+ The MDCAppBarContainerViewController controller provides an interface for placing a
+ UIViewController behind an App Bar.
+
+ The MDCAppBarContainerViewController class is commonly referred to as the "wrapper API" for the
+ Material App Bar. This contrasts with the "injection" APIs as represented by the APIs in
+ MDCAppBar.h.
+
+ Use the MDCAppBarContainerViewController class when you do not own and cannot alter a view
+ controller to which you want to add an App Bar. If you do own and can modify a view controller
+ it is recommended that you use the MDCAppBar.h APIs instead.
+
+ ### Why we recommend using the MDCAppBar.h APIs over this one
+
+ Wrapping a view controller affects your app code in a variety of not-so-nice ways.
+
+ 1. Wrapped view controllers often need to be unwrapped in a variety of settings.
+ 2. The wrapped view controller's parentViewController is now a level of indirection from its
+    previous parent.
+ 3. Wrapping a view controller can affect things like "isMovingToParentViewController" in
+    wonderfully subtle ways.
+ */
+@interface MDCAppBarContainerViewController : UIViewController
+
+/**
+ Initializes an App Bar container view controller instance with the given content view controller.
+ */
+- (nonnull instancetype)initWithContentViewController:
+        (nonnull UIViewController *)contentViewController NS_DESIGNATED_INITIALIZER;
+
+- (nonnull instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
+                                 bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/** The App Bar views that will be presented in front of the contentViewController's view. */
+@property(nonatomic, strong, nonnull, readonly) MDCAppBar *appBar;
+
+/** The content view controller to be displayed behind the header. */
+@property(nonatomic, strong, nonnull, readonly) UIViewController *contentViewController;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.m
new file mode 100644
index 0000000..966e9c5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MDCAppBarContainerViewController.m
@@ -0,0 +1,76 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBarContainerViewController.h"
+
+#import "MDCAppBar.h"
+
+#import "MaterialFlexibleHeader.h"
+
+@implementation MDCAppBarContainerViewController {
+  MDCAppBar *_appBar;
+}
+
+- (instancetype)initWithContentViewController:(UIViewController *)contentViewController {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _appBar = [[MDCAppBar alloc] init];
+
+    [self addChildViewController:_appBar.headerViewController];
+
+    _contentViewController = contentViewController;
+    [self addChildViewController:contentViewController];
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  [self.view addSubview:self.contentViewController.view];
+  [self.contentViewController didMoveToParentViewController:self];
+
+  [_appBar addSubviewsToParent];
+
+  [_appBar.navigationBar observeNavigationItem:_contentViewController.navigationItem];
+}
+
+- (void)viewWillLayoutSubviews {
+  [super viewWillLayoutSubviews];
+  [_appBar.headerViewController updateTopLayoutGuide];
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return self.appBar.headerViewController.prefersStatusBarHidden;
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  return self.appBar.headerViewController.preferredStatusBarStyle;
+}
+
+- (BOOL)shouldAutorotate {
+  return self.contentViewController.shouldAutorotate;
+}
+
+- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
+  return self.contentViewController.supportedInterfaceOrientations;
+}
+
+- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
+  return self.contentViewController.preferredInterfaceOrientationForPresentation;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MaterialAppBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MaterialAppBar.h
new file mode 100644
index 0000000..04904d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/AppBar/src/MaterialAppBar.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBar.h"
+#import "MDCAppBarContainerViewController.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
new file mode 100644
index 0000000..a95f186
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.h
@@ -0,0 +1,147 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The position of the button bar, typically aligned with the leading or trailing edge of the screen.
+
+ Default: MDCBarButtonLayoutPositionNone
+ */
+typedef NS_OPTIONS(NSUInteger, MDCButtonBarLayoutPosition) {
+  MDCButtonBarLayoutPositionNone = 0,
+
+  /** The button bar is on the leading side of the screen. */
+  MDCButtonBarLayoutPositionLeading = 1 << 0,
+  MDCButtonBarLayoutPositionLeft = MDCButtonBarLayoutPositionLeading,
+
+  /** The button bar is on the trailing side of the screen. */
+  MDCButtonBarLayoutPositionTrailing = 1 << 1,
+  MDCButtonBarLayoutPositionRight = MDCButtonBarLayoutPositionTrailing,
+};
+
+@protocol MDCButtonBarDelegate;
+
+/**
+ The MDCButtonBar class provides a view comprised of a horizontal list of buttons.
+
+ This view will register KVO listeners on the provided button items for the following properties:
+
+ - enabled
+ - title
+ - image
+
+ If any of the above properties change, the MDCButtonBar will immediately reflect the change
+ in the visible UIButton instance.
+ */
+IB_DESIGNABLE
+@interface MDCButtonBar : UIView
+
+#pragma mark Button Items
+
+/**
+ An array of UIBarButtonItem objects that will be used to populate the button views in this bar.
+
+ Setting a new array of items will result in immediate recreation of the button views.
+
+ Once set, changes made to the UIBarButtonItem properties will be observed and applied to the
+ created button views.
+
+ ### Item target/action method signature
+
+ The complete action method signature is:
+
+ - (void)didTap:(UIBarButtonItem *)item event:(UIEvent *)event button:(UIButton *)button;
+
+ Each argument can be optionally-specified. E.g. @selector(didTap) is an acceptable action.
+
+ ### iPad popover support
+
+ MDCButtonBar is not able to associate UIBarButtonItem instances with their corresponding UIButton
+ instance, so certain UIKit methods that accept a UIBarButtonItem cannot be used. This includes,
+ but may not be limited to:
+
+ - UIPopoverController::presentPopoverFromBarButtonItem:permittedArrowDirections:animated:
+ - UIPrinterPickerController::presentFromBarButtonItem:animated:completionHandler:
+ - UIPrintInteractionController::presentFromBarButtonItem:animated:completionHandler:
+ - UIDocumentInteractionController::presentOptionsMenuFromBarButtonItem:animated:
+ - UIDocumentInteractionController::presentOpenInMenuFromBarButtonItem:animated:
+
+ Instead, you must use the related -FromRect: variant which requires a CGRect and view. You can
+ use the provided UIButton by implementing the complete action method signature:
+
+ - (void)didTap:(UIBarButtonItem *)item event:(UIEvent *)event button:(UIButton *)button;
+ */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *items;
+
+/**
+ If greater than zero, will ensure that any UIButton with a title is aligned to the provided
+ baseline.
+
+ The baseline is expressed in number of points from the top edge of the receiver’s
+ bounds.
+
+ Default: 0
+ */
+@property(nonatomic) CGFloat buttonTitleBaseline;
+
+/**
+ The position of the button bar, usually positioned on the leading or trailing edge of the screen.
+
+ Default: MDCBarButtonLayoutPositionNone
+ */
+@property(nonatomic) MDCButtonBarLayoutPosition layoutPosition;
+
+/**
+ Returns a height adhering to the Material spec for Bars and a width that is able to accommodate
+ every item present in the `items` property. The provided size is ignored.
+ */
+- (CGSize)sizeThatFits:(CGSize)size;
+
+@end
+
+typedef NS_OPTIONS(NSUInteger, MDCBarButtonItemLayoutHints) {
+  MDCBarButtonItemLayoutHintsNone = 0,
+
+  /** Whether or not this bar button item is the first button in the list. */
+  MDCBarButtonItemLayoutHintsIsFirstButton = 1 << 0,
+
+  /** Whether or not this bar button item is the last button in the list. */
+  MDCBarButtonItemLayoutHintsIsLastButton = 1 << 1,
+};
+
+/**
+ The MDCButtonBarDelegate protocol defines the means by which MDCButtonBar can request that a
+ view be created for a bar button item.
+
+ An object that conforms to this protocol must forward UIControlEventTouchUpInside events to the
+ button bar's didTapButton:event: method signature in order to pass the correct UIBarButtonItem
+ argument to the item's target/action invocation. This method signature is made available by
+ importing the MDCAppBarButtonBarBuilder.h header. The MDCAppBarButtonBarBuilder.h header should
+ *only* be
+ imported in files that implement objects conforming to MDCButtonBarDelegate.
+
+ @seealso MDCBarButtonItemLayoutHints
+ */
+@protocol MDCButtonBarDelegate <NSObject>
+@required
+
+/** Asks the receiver to return a view that represents the given bar button item. */
+- (nonnull UIView *)buttonBar:(nonnull MDCButtonBar *)buttonBar
+                  viewForItem:(nonnull UIBarButtonItem *)barButtonItem
+                  layoutHints:(MDCBarButtonItemLayoutHints)layoutHints;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.m
new file mode 100644
index 0000000..5a888e9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MDCButtonBar.m
@@ -0,0 +1,392 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButtonBar.h"
+#import "MDCButton.h"
+
+#import "MaterialRTL.h"
+#import "private/MDCAppBarButtonBarBuilder.h"
+
+static const CGFloat kDefaultHeight = 56;
+static const CGFloat kDefaultPadHeight = 64;
+
+// KVO contexts
+static char *const kKVOContextMDCButtonBar = "kKVOContextMDCButtonBar";
+
+// This is required because @selector(enabled) throws a compiler warning of unrecognized selector.
+static NSString *const kEnabledSelector = @"enabled";
+
+static NSString *const MDCButtonBarItemsKey = @"MDCButtonBarItemsKey";
+static NSString *const MDCButtonBarButtonTitleBaselineKey = @"MDCButtonBarButtonTitleBaselineKey";
+static NSString *const MDCButtonBarButtonLayoutPositionKey = @"MDCButtonBarButtonLayoutPositionKey";
+
+@implementation MDCButtonBar {
+  id _buttonItemsLock;
+  NSArray<__kindof UIView *> *_buttonViews;
+
+  MDCAppBarButtonBarBuilder *_defaultBuilder;
+}
+
+- (void)dealloc {
+  self.items = nil;
+}
+
+- (void)commonMDCButtonBarInit {
+  _buttonItemsLock = [[NSObject alloc] init];
+  _layoutPosition = MDCButtonBarLayoutPositionNone;
+
+  _defaultBuilder = [[MDCAppBarButtonBarBuilder alloc] init];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCButtonBarInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder {
+  self = [super initWithCoder:coder];
+  if (self) {
+    [self commonMDCButtonBarInit];
+    if ([coder containsValueForKey:MDCButtonBarItemsKey]) {
+      _items = [coder decodeObjectForKey:MDCButtonBarItemsKey];
+    }
+
+    if ([coder containsValueForKey:MDCButtonBarButtonTitleBaselineKey]) {
+      _buttonTitleBaseline = (CGFloat)[coder decodeDoubleForKey:MDCButtonBarButtonTitleBaselineKey];
+    }
+
+    if ([coder containsValueForKey:MDCButtonBarButtonLayoutPositionKey]) {
+      _layoutPosition = [coder decodeIntegerForKey:MDCButtonBarButtonLayoutPositionKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  if (self.items && self.items.count > 0) {
+    [aCoder encodeObject:self.items forKey:MDCButtonBarItemsKey];
+  }
+  [aCoder encodeDouble:self.buttonTitleBaseline forKey:MDCButtonBarButtonTitleBaselineKey];
+  [aCoder encodeInteger:self.layoutPosition forKey:MDCButtonBarButtonLayoutPositionKey];
+}
+
+- (void)alignButtonBaseline:(UIButton *)button {
+  CGRect contentRect = [button contentRectForBounds:button.bounds];
+  CGRect titleRect = [button titleRectForContentRect:contentRect];
+
+  // Calculate baseline information based on frame that the title text appears in.
+  CGFloat baseline = CGRectGetMaxY(titleRect) + button.titleLabel.font.descender;
+  CGFloat buttonBaseline = button.frame.origin.y + baseline;
+
+  // When modifying insets, be sure to add/subtract equal amounts on opposite sides.
+  UIEdgeInsets insets = button.titleEdgeInsets;
+  CGFloat baselineOffset = _buttonTitleBaseline - buttonBaseline;
+
+  insets.top += baselineOffset;
+  insets.bottom -= baselineOffset;
+  button.titleEdgeInsets = insets;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size shouldLayout:(BOOL)shouldLayout {
+  CGFloat totalWidth = 0;
+
+  CGFloat edge;
+  switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      edge = 0;
+      break;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      edge = size.width;
+      break;
+  }
+
+  BOOL shouldAlignBaselines = _buttonTitleBaseline > 0;
+
+  NSEnumerator<__kindof UIView *> *positionedButtonViews =
+      self.layoutPosition == MDCButtonBarLayoutPositionTrailing
+          ? [_buttonViews reverseObjectEnumerator]
+          : [_buttonViews objectEnumerator];
+
+  for (UIView *view in positionedButtonViews) {
+    CGFloat width = view.frame.size.width;
+    switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+      case UIUserInterfaceLayoutDirectionLeftToRight:
+        break;
+      case UIUserInterfaceLayoutDirectionRightToLeft:
+        edge -= width;
+        break;
+    }
+    if (shouldLayout) {
+      view.frame = CGRectMake(edge, 0, width, size.height);
+
+      if (shouldAlignBaselines && [view isKindOfClass:[UIButton class]]) {
+        if ([(UIButton *)view titleForState:UIControlStateNormal].length > 0) {
+          [self alignButtonBaseline:(UIButton *)view];
+        }
+      }
+    }
+    switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+      case UIUserInterfaceLayoutDirectionLeftToRight:
+        edge += width;
+        break;
+      case UIUserInterfaceLayoutDirectionRightToLeft:
+        break;
+    }
+    totalWidth += width;
+  }
+  // TODO(featherless): Take into account compact/regular sizes rather than the device idiom.
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+  CGFloat height = isPad ? kDefaultPadHeight : kDefaultHeight;
+  return CGSizeMake(totalWidth, height);
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return [self sizeThatFits:size shouldLayout:NO];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self sizeThatFits:self.bounds.size shouldLayout:YES];
+}
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  _defaultBuilder.buttonTitleColor = self.tintColor;
+  [self updateButtonTitleColors];
+}
+
+#pragma mark - Private
+
+- (void)updateButtonTitleColors {
+  for (UIView *viewObj in _buttonViews) {
+    if ([viewObj isKindOfClass:[MDCButton class]]) {
+      MDCButton *buttonView = (MDCButton *)viewObj;
+      buttonView.customTitleColor = self.tintColor;
+    }
+  }
+}
+
+- (NSArray<UIView *> *)viewsForItems:(NSArray<UIBarButtonItem *> *)barButtonItems {
+  if (![barButtonItems count]) {
+    return nil;
+  }
+  id<MDCButtonBarDelegate> delegate = _defaultBuilder;
+
+  NSMutableArray<UIView *> *views = [NSMutableArray array];
+  [barButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem *item, NSUInteger idx, BOOL *stop) {
+    MDCBarButtonItemLayoutHints hints = MDCBarButtonItemLayoutHintsNone;
+    if (idx == 0) {
+      hints |= MDCBarButtonItemLayoutHintsIsFirstButton;
+    }
+    if (idx == [barButtonItems count] - 1) {
+      hints |= MDCBarButtonItemLayoutHintsIsLastButton;
+    }
+    UIView *view = [delegate buttonBar:self viewForItem:item layoutHints:hints];
+    if (!view) {
+      return;
+    }
+
+    [view sizeToFit];
+    if (item.width > 0) {
+      CGRect frame = view.frame;
+      frame.size.width = item.width;
+      view.frame = frame;
+    }
+
+    [self addSubview:view];
+    [views addObject:view];
+  }];
+  return views;
+}
+
+#pragma mark - KVO
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context {
+  if (context == kKVOContextMDCButtonBar) {
+    void (^mainThreadWork)(void) = ^{
+      @synchronized(_buttonItemsLock) {
+        NSUInteger itemIndex = [_items indexOfObject:object];
+        if (itemIndex == NSNotFound || itemIndex > [_buttonViews count]) {
+          return;
+        }
+        UIButton *button = _buttonViews[itemIndex];
+
+        id newValue = [object valueForKey:keyPath];
+        if (newValue == [NSNull null]) {
+          newValue = nil;
+        }
+
+        if ([keyPath isEqualToString:kEnabledSelector]) {
+          if ([button respondsToSelector:@selector(setEnabled:)]) {
+            [button setValue:newValue forKey:keyPath];
+          }
+
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(title))]) {
+          [button setTitle:newValue forState:UIControlStateNormal];
+
+        } else if ([keyPath isEqualToString:NSStringFromSelector(@selector(image))]) {
+          [button setImage:newValue forState:UIControlStateNormal];
+
+        } else {
+          NSLog(@"Unknown key path notification received by %@ for %@.",
+                NSStringFromClass([self class]), keyPath);
+        }
+      }
+    };
+
+    // Ensure that UIKit modifications occur on the main thread.
+    if ([NSThread isMainThread]) {
+      mainThreadWork();
+    } else {
+      [[NSOperationQueue mainQueue] addOperationWithBlock:mainThreadWork];
+    }
+
+  } else {
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+  }
+}
+
+#pragma mark - Button target selector
+
+- (void)didTapButton:(UIButton *)button event:(UIEvent *)event {
+  NSUInteger buttonIndex = [_buttonViews indexOfObject:button];
+  if (buttonIndex == NSNotFound || buttonIndex > [self.buttonItems count]) {
+    return;
+  }
+
+  UIBarButtonItem *item = self.buttonItems[buttonIndex];
+
+  if (item.action == nil) {
+    return;
+  }
+
+  id target = item.target;
+
+  // As per Apple's documentation on UIBarButtonItem:
+  // https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIBarButtonItem_Class/#//apple_ref/occ/instp/UIBarButtonItem/action
+  // "If nil, the action message is passed up the responder chain where it may be handled by any
+  // object implementing a method corresponding to the selector held by the action property."
+  if (target == nil && [self respondsToSelector:@selector(targetForAction:withSender:)]) {
+    // iOS 7 and up.
+    target = [self targetForAction:item.action withSender:self];
+  }
+
+  // If we ultimately couldn't find a target, bail out.
+  if (!target) {
+    return;
+  }
+
+  if (![target respondsToSelector:item.action]) {
+    return;
+  }
+
+  NSMethodSignature *signature = [target methodSignatureForSelector:item.action];
+  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+  invocation.selector = item.action;
+
+  if ([invocation.methodSignature numberOfArguments] > 2) {
+    [invocation setArgument:&item atIndex:2];
+  }
+  if ([invocation.methodSignature numberOfArguments] > 3) {
+    [invocation setArgument:&event atIndex:3];
+  }
+
+  // UIKit methods that present from a UIBarButtonItem will not work with our items because we
+  // can't set the necessary private ivars that associate the item with the button. So we pass the
+  // button as well so that clients can present from the button's frame instead.
+  // This is not part of the standard UIKit method signature.
+  if ([invocation.methodSignature numberOfArguments] > 4) {
+    [invocation setArgument:&button atIndex:4];
+  }
+
+  [invocation invokeWithTarget:target];
+}
+
+#pragma mark - Public
+
+- (NSArray<UIBarButtonItem *> *)buttonItems {
+  return self.items;
+}
+
+- (void)setButtonItems:(NSArray<UIBarButtonItem *> *)buttonItems {
+  self.items = buttonItems;
+}
+
+- (void)setItems:(NSArray<UIBarButtonItem *> *)items {
+  @synchronized(_buttonItemsLock) {
+    if (_items == items || [_items isEqualToArray:items]) {
+      return;
+    }
+
+    NSArray<NSString *> *keyPaths = @[
+      kEnabledSelector, NSStringFromSelector(@selector(title)),
+      NSStringFromSelector(@selector(image))
+    ];
+
+    // Remove old observers
+    for (UIBarButtonItem *item in _items) {
+      for (NSString *keyPath in keyPaths) {
+        [item removeObserver:self forKeyPath:keyPath context:kKVOContextMDCButtonBar];
+      }
+    }
+
+    _items = [items copy];
+
+    // Register new observers
+    for (UIBarButtonItem *item in _items) {
+      for (NSString *keyPath in keyPaths) {
+        [item addObserver:self
+               forKeyPath:keyPath
+                  options:NSKeyValueObservingOptionNew
+                  context:kKVOContextMDCButtonBar];
+      }
+    }
+
+    [self reloadButtonViews];
+  }
+}
+
+- (void)mdc_setSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute {
+  [super mdc_setSemanticContentAttribute:semanticContentAttribute];
+  [self reloadButtonViews];
+}
+
+- (void)setButtonTitleBaseline:(CGFloat)buttonTitleBaseline {
+  _buttonTitleBaseline = buttonTitleBaseline;
+
+  [self setNeedsLayout];
+}
+
+- (void)reloadButtonViews {
+  // TODO(featherless): Recycle buttons.
+  for (UIView *view in _buttonViews) {
+    [view removeFromSuperview];
+  }
+  _buttonViews = [self viewsForItems:_items];
+
+  [self setNeedsLayout];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
new file mode 100644
index 0000000..f870aa1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/MaterialButtonBar.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButtonBar.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h
new file mode 100644
index 0000000..587a11e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MaterialButtonBar.h"
+
+/** MDCBarButtonItemBuilder is an implementation of a Material button item factory. */
+@interface MDCAppBarButtonBarBuilder : NSObject <MDCButtonBarDelegate>
+
+/** The title color for the bar button items. */
+@property(nonatomic, strong) UIColor *buttonTitleColor;
+
+/** The underlying color for the bar button items. */
+@property(nonatomic, strong) UIColor *buttonUnderlyingColor;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m
new file mode 100644
index 0000000..166fe4f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m
@@ -0,0 +1,304 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAppBarButtonBarBuilder.h"
+
+#import "MDCButtonBar+Private.h"
+#import "MaterialButtons.h"
+#import "MaterialRTL.h"
+
+#import <objc/runtime.h>
+
+#define IS_FLAG_SET(value, flag) (((value) & (flag)) == (flag))
+
+static const CGFloat kMinimumItemWidth = 36.f;
+
+// The padding around button contents.
+static const CGFloat kButtonPaddingHorizontal = 12.f;
+
+// Additional insets for the left-most or right-most items, primarily for image buttons.
+static const CGFloat kEdgeButtonAdditionalMarginPhone = 4.f;
+static const CGFloat kEdgeButtonAdditionalMarginPad = 12.f;
+
+// The default MDCButton's alpha for display state is 0.1f which in the context of bar buttons
+// makes it practically invisible. Setting button to a higher opacity is closer to what the
+// button should look like when it is disabled.
+static const CGFloat kDisabledButtonAlpha = 0.45f;
+
+// Content insets for text-only buttons.
+static const UIEdgeInsets kTextOnlyButtonInset = {0, 24.f, 0, 24.f};
+
+// Content insets for image-only buttons.
+static const UIEdgeInsets kImageOnlyButtonInset = {0, 12.0f, 0, 12.0f};
+
+// Indiana Jones style placeholder view for UINavigationBar. Ownership of UIBarButtonItem.customView
+// and UINavigationItem.titleView are normally transferred to UINavigationController but we plan to
+// steal them away. In order to avoid crashing during KVO updates, we steal the view away and
+// replace it with a sandbag view.
+@interface MDCButtonBarSandbagView : UIView
+@end
+
+@interface MDCButtonBarButton : MDCFlatButton
+
+// Content padding for the button.
+@property(nonatomic) UIEdgeInsets contentPadding;
+
+@end
+
+@interface UIBarButtonItem (MDCHeaderInternal)
+
+// Internal version of the standard -customView property. When an item is pushed onto a
+// UINavigationController stack, any -customView object is moved over to this property. This
+// prevents UINavigationController from adding the customView to its own view hierarchy.
+@property(nonatomic, strong, setter=mdc_setCustomView:) UIView *mdc_customView;
+
+@end
+
+@implementation MDCAppBarButtonBarBuilder
+
+#pragma mark - MDCBarButtonItemBuilding
+
+- (UIView *)buttonBar:(MDCButtonBar *)buttonBar
+          viewForItem:(UIBarButtonItem *)buttonItem
+          layoutHints:(MDCBarButtonItemLayoutHints)layoutHints {
+  if (buttonItem == nil) {
+    return nil;
+  }
+
+  // Transfer custom view ownership if necessary.
+  [self transferCustomViewOwnershipForBarButtonItem:buttonItem];
+
+  // Take the real custom view if it exists instead of sandbag view.
+  UIView *customView = buttonItem.mdc_customView ?: buttonItem.customView;
+  if (customView) {
+    return customView;
+  }
+
+// NOTE: This assertion does not occur in release builds because it is accessing a private api.
+#if DEBUG
+  NSAssert(![[buttonItem valueForKey:@"isSystemItem"] boolValue],
+           @"Instances of %@ must not be initialized with %@ when working with %@."
+           @" This is because we cannot extract the system item type from the item.",
+           NSStringFromClass([buttonItem class]),
+           NSStringFromSelector(@selector(initWithBarButtonSystemItem:target:action:)),
+           NSStringFromClass([MDCButtonBar class]));
+#endif
+
+  MDCButtonBarButton *button = [[MDCButtonBarButton alloc] init];
+  [button setBackgroundColor:[UIColor clearColor] forState:UIControlStateNormal];
+  button.disabledAlpha = kDisabledButtonAlpha;
+
+  button.exclusiveTouch = YES;
+  if (buttonItem.title != nil) {
+    [button setTitle:buttonItem.title forState:UIControlStateNormal];
+  }
+  if (buttonItem.image != nil) {
+    [button setImage:buttonItem.image forState:UIControlStateNormal];
+  }
+  if (buttonItem.tintColor != nil) {
+    button.tintColor = buttonItem.tintColor;
+  }
+
+  if (buttonItem.title) {
+    button.inkStyle = MDCInkStyleBounded;
+  } else {
+    button.inkStyle = MDCInkStyleUnbounded;
+  }
+
+  button.tag = buttonItem.tag;
+
+  button.customTitleColor = self.buttonTitleColor;
+  [button setUnderlyingColorHint:self.buttonUnderlyingColor];
+
+  [self updateButton:button withItem:buttonItem barMetrics:UIBarMetricsDefault];
+
+  // Contrary to intuition, UIKit provides the UIBarButtonItem as the action's first argument when
+  // bar buttons are tapped, NOT the button itself. Simply adding the item's target/action to the
+  // button does not allow us to pass the expected argument to the target.
+  //
+  // MDCButtonBar provides didTapButton:event: to which we can pass button events
+  // so that the correct argument is ultimately passed along.
+  [button addTarget:buttonBar
+                action:@selector(didTapButton:event:)
+      forControlEvents:UIControlEventTouchUpInside];
+
+  UIEdgeInsets contentInsets = UIEdgeInsetsZero;
+
+  UIEdgeInsets (^addInsets)(UIEdgeInsets, UIEdgeInsets) = ^(UIEdgeInsets i1, UIEdgeInsets i2) {
+    UIEdgeInsets sum = i1;
+    sum.left += i2.left;
+    sum.top += i2.top;
+    sum.right += i2.right;
+    sum.bottom += i2.bottom;
+    return sum;
+  };
+
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+
+  if ([[button currentTitle] length]) {  // Text-only buttons.
+    contentInsets = addInsets(contentInsets, kTextOnlyButtonInset);
+
+  } else if ([button currentImage]) {  // Image-only buttons.
+    contentInsets = addInsets(contentInsets, kImageOnlyButtonInset);
+
+    if (IS_FLAG_SET(layoutHints, MDCBarButtonItemLayoutHintsIsFirstButton)) {
+      CGFloat additionalInset =
+          (isPad ? kEdgeButtonAdditionalMarginPad : kEdgeButtonAdditionalMarginPhone);
+
+      if (buttonBar.mdc_effectiveUserInterfaceLayoutDirection ==
+          UIUserInterfaceLayoutDirectionLeftToRight) {
+        contentInsets.left += additionalInset;
+      } else {
+        contentInsets.right += additionalInset;
+      }
+    }
+
+    if (IS_FLAG_SET(layoutHints, MDCBarButtonItemLayoutHintsIsLastButton)) {
+      CGFloat additionalInset =
+          (isPad ? kEdgeButtonAdditionalMarginPad : kEdgeButtonAdditionalMarginPhone);
+
+      if (buttonBar.mdc_effectiveUserInterfaceLayoutDirection ==
+          UIUserInterfaceLayoutDirectionLeftToRight) {
+        contentInsets.right += additionalInset;
+      } else {
+        contentInsets.left += additionalInset;
+      }
+    }
+
+  } else {
+    NSAssert(0, @"No button title or image");
+  }
+
+  // Only add padding to the first item of the button bar.
+  if (layoutHints == MDCBarButtonItemLayoutHintsIsFirstButton) {
+    switch (buttonBar.layoutPosition) {
+      case MDCButtonBarLayoutPositionLeading:
+        button.contentPadding =
+            UIEdgeInsetsMake(0, contentInsets.left - kButtonPaddingHorizontal, 0, 0);
+        break;
+      case MDCButtonBarLayoutPositionTrailing:
+        button.contentPadding =
+            UIEdgeInsetsMake(0, 0, 0, contentInsets.right - kButtonPaddingHorizontal);
+      default:
+        break;
+    }
+  }
+
+  button.contentEdgeInsets = contentInsets;
+  button.enabled = buttonItem.enabled;
+  button.accessibilityLabel = buttonItem.accessibilityLabel;
+  button.accessibilityHint = buttonItem.accessibilityHint;
+  button.accessibilityValue = buttonItem.accessibilityValue;
+  button.accessibilityIdentifier = buttonItem.accessibilityIdentifier;
+
+  return button;
+}
+
+#pragma mark - Private
+
+- (void)updateButton:(UIButton *)button
+            withItem:(UIBarButtonItem *)item
+          barMetrics:(UIBarMetrics)barMetrics {
+  [self updateButton:button withItem:item forState:UIControlStateNormal barMetrics:barMetrics];
+  [self updateButton:button withItem:item forState:UIControlStateHighlighted barMetrics:barMetrics];
+  [self updateButton:button withItem:item forState:UIControlStateDisabled barMetrics:barMetrics];
+}
+
+- (void)updateButton:(UIButton *)button
+            withItem:(UIBarButtonItem *)item
+            forState:(UIControlState)state
+          barMetrics:(UIBarMetrics)barMetrics {
+  NSString *title = item.title ?: @"";
+  if ([UIButton instancesRespondToSelector:@selector(setAttributedTitle:forState:)]) {
+    NSMutableDictionary<NSString *, id> *attributes = [NSMutableDictionary dictionary];
+
+    // UIBarButtonItem's appearance proxy values don't appear to come "for free" like they do with
+    // typical UIView instances, so we're attempting to recreate the behavior here.
+    NSArray *appearanceProxies = @[ [item.class appearance] ];
+    for (UIBarButtonItem *appearance in appearanceProxies) {
+      [attributes addEntriesFromDictionary:[appearance titleTextAttributesForState:state]];
+    }
+    [attributes addEntriesFromDictionary:[item titleTextAttributesForState:state]];
+    if ([attributes count] > 0) {
+      [button
+          setAttributedTitle:[[NSAttributedString alloc] initWithString:title attributes:attributes]
+                    forState:state];
+    }
+  } else {
+    [button setTitle:title forState:state];
+  }
+
+  UIImage *backgroundImage = [item backgroundImageForState:state barMetrics:barMetrics];
+  if (backgroundImage) {
+    [button setBackgroundImage:backgroundImage forState:state];
+  }
+}
+
+- (void)transferCustomViewOwnershipForBarButtonItem:(UIBarButtonItem *)barButtonItem {
+  UIView *customView = barButtonItem.customView;
+  if (customView && ![customView isKindOfClass:[MDCButtonBarSandbagView class]]) {
+    // Transfer ownership of any UIBarButtonItem.customView to the internal property
+    // so that UINavigationController won't steal the view from us.
+    barButtonItem.mdc_customView = customView;
+    barButtonItem.customView = [[MDCButtonBarSandbagView alloc] init];
+  }
+}
+
+@end
+
+@implementation MDCButtonBarSandbagView
+@end
+
+@implementation MDCButtonBarButton
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  CGSize fitSize = [super sizeThatFits:size];
+  fitSize.height =
+      self.contentPadding.top + MAX(kMinimumItemWidth, fitSize.height) + self.contentPadding.bottom;
+  fitSize.width =
+      self.contentPadding.left + MAX(kMinimumItemWidth, fitSize.width) + self.contentPadding.right;
+
+  return fitSize;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // TODO(featherless): Remove this conditional and always set the max ripple radius once
+  // https://github.com/material-components/material-components-ios/issues/329 lands.
+  if (self.inkStyle == MDCInkStyleUnbounded) {
+    self.inkMaxRippleRadius = MIN(self.bounds.size.width, self.bounds.size.height) / 2;
+  } else {
+    self.inkMaxRippleRadius = 0;
+  }
+}
+
+@end
+
+@implementation UIBarButtonItem (MDCHeaderInternal)
+
+@dynamic mdc_customView;
+
+- (UIView *)mdc_customView {
+  return objc_getAssociatedObject(self, _cmd);
+}
+
+- (void)mdc_setCustomView:(UIView *)customView {
+  objc_setAssociatedObject(self, @selector(mdc_customView), customView,
+                           OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h
new file mode 100644
index 0000000..a82b951
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ButtonBar/src/private/MDCButtonBar+Private.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButtonBar.h"
+
+@interface MDCButtonBar (Builder)
+
+/**
+ Finds the corresponding UIBarButtonItem and calls its target/action with the item as the first
+ parameter.
+ */
+- (void)didTapButton:(UIButton *)button event:(UIEvent *)event;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCButton.h
new file mode 100644
index 0000000..c3532b9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCButton.h
@@ -0,0 +1,186 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <CoreGraphics/CoreGraphics.h>
+#import <UIKit/UIKit.h>
+
+#import "MaterialInk.h"
+
+/**
+ A Material flat, raised or floating button.
+
+ All buttons display animated ink splashes when the user interacts with the button.
+
+ The title color of the button set to have an accessible contrast ratio with the button's
+ background color. To ensure this works for flat buttons (with transparent background), the caller
+ is responsible for setting (and updating, if necessary) the button's underlyingColor property.
+
+ All buttons set the exclusiveTouch property to YES by default, which prevents users from
+ simultaneously interacting with a button and other UI elements.
+
+ @see http://www.google.com/design/spec/components/buttons.html
+ */
+@interface MDCButton : UIButton
+
+/**
+ A color used as the button's @c backgroundColor for @c state.
+
+ @param state The state.
+ @return The background color.
+ */
+- (nullable UIColor *)backgroundColorForState:(UIControlState)state;
+
+/**
+ A color used as the button's @c backgroundColor.
+
+ If left unset or reset to nil for a given state, then a default blue color is used.
+
+ @param backgroundColor The background color.
+ @param state The state.
+ */
+- (void)setBackgroundColor:(nullable UIColor *)backgroundColor forState:(UIControlState)state;
+
+/** The ink style of the button. */
+@property(nonatomic, assign) MDCInkStyle inkStyle;
+
+/** The ink color of the button. */
+@property(nonatomic, strong, null_resettable) UIColor *inkColor;
+
+/*
+ Maximum radius of the button's ink. If the radius <= 0 then half the length of the diagonal of
+ self.bounds is used. This value is ignored if button's @c inkStyle is set to |MDCInkStyleBounded|.
+ */
+@property(nonatomic, assign) CGFloat inkMaxRippleRadius;
+
+/**
+ A custom title color for the non-disabled states. The default is nil, which means that the button
+ chooses its title color automatically based on @c underlyingColor, whether the button is opaque,
+ its current background color, etc.
+
+ Setting this to a non-nil color overrides that logic, and the caller is responsible for ensuring
+ that the title color/background color combination meets the accessibility requirements.
+ */
+@property(nonatomic, strong, nullable) UIColor *customTitleColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The alpha value that will be applied when the button is disabled. Most clients can leave this as
+ the default value to get a semi-transparent button automatically.
+ */
+@property(nonatomic) CGFloat disabledAlpha;
+
+/**
+ If true, converts the button title to uppercase. Changing this property to NO will not update the
+ current title string.
+
+ Default is YES and is recommended whenever possible.
+ */
+@property(nonatomic, getter=isUppercaseTitle) BOOL uppercaseTitle;
+
+/**
+ Insets to apply to the button’s hit area.
+
+ Allows the button to detect touches outside of its bounds. A negative value indicates an
+ extension past the bounds.
+
+ Default is UIEdgeInsetsZero.
+ */
+@property(nonatomic) UIEdgeInsets hitAreaInsets;
+
+/**
+ The apparent background color as seen by the user, i.e. the color of the view behind the button.
+
+ The underlying color hint is used by buttons to calculate accessible title text colors when in
+ states with transparent background colors. The hint is used whenever the button changes state such
+ that the background color changes, for example, setting the background color or disabling the
+ button.
+
+ For flat buttons, this is the color of both the surrounding area and the button's background.
+ For raised and floating buttons, this is the color of view underneath the button.
+
+ The default is nil.  If left unset, buttons will likely have an incorrect appearance when
+ disabled. Additionally, flat buttons might have text colors with low accessibility.
+ */
+@property(nonatomic, strong, nullable) UIColor *underlyingColorHint;
+
+/** Sets the enabled state with optional animation. */
+- (void)setEnabled:(BOOL)enabled animated:(BOOL)animated;
+
+/**
+ Returns the elevation for a particular control state.
+
+ The default values depend on the kind of button, for example, flat buttons in the
+ UIControlStateNormal state have zero elevation.
+
+ @param state The control state to retrieve the elevation.
+ @return The elevation for the requested state.
+ */
+- (CGFloat)elevationForState:(UIControlState)state;
+
+/**
+ Sets the elevation for a particular control state.
+
+ Use resetElevationForState: to reset the button's behavior to the default for a particular state.
+
+ @param elevation The elevation to set.
+ @param state The state to set.
+ */
+- (void)setElevation:(CGFloat)elevation forState:(UIControlState)state;
+
+/**
+ Resets the elevation for a particular control state back to the button's default behavior.
+
+ @param state The control state to reset the elevation.
+ */
+- (void)resetElevationForState:(UIControlState)state;
+
+/*
+ Indicates whether the button should automatically update its font when the device’s
+ UIContentSizeCategory is changed.
+
+ This property is modeled after the adjustsFontForContentSizeCategory property in the
+ UIConnectSizeCategoryAdjusting protocol added by Apple in iOS 10.0.
+
+ If set to YES, this button will base its text font on MDCFontTextStyleButton.
+
+ Defaults value is NO.
+ */
+@property(nonatomic, readwrite, setter=mdc_setAdjustsFontForContentSizeCategory:)
+    BOOL mdc_adjustsFontForContentSizeCategory UI_APPEARANCE_SELECTOR;
+
+#pragma mark - UIButton changes
+
+/**
+ From UIButton's documentation: "If you subclass UIButton, this method does not return an instance
+ of your subclass. If you want to create an instance of a specific subclass, you must alloc/init
+ the button directly."
+ */
++ (nonnull instancetype)buttonWithType:(UIButtonType)buttonType NS_UNAVAILABLE;
+
+#pragma mark - Deprecated
+
+/** Use setBackgroundColor:forState: instead. */
+- (void)setBackgroundColor:(nullable UIColor *)backgroundColor NS_UNAVAILABLE;
+
+@property(nonatomic)
+    BOOL shouldRaiseOnTouch __deprecated_msg("Use MDCFlatButton instead of shouldRaiseOnTouch = NO")
+        ;
+
+@property(nonatomic) BOOL shouldCapitalizeTitle __deprecated_msg("Use uppercaseTitle instead.");
+
+@property(nonatomic, strong, nullable)
+    UIColor *underlyingColor __deprecated_msg("Use underlyingColorHint instead.");
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCButton.m
new file mode 100644
index 0000000..ec37444
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCButton.m
@@ -0,0 +1,729 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+
+#import "MDFTextAccessibility.h"
+#import "MaterialInk.h"
+#import "MaterialShadowElevations.h"
+#import "MaterialShadowLayer.h"
+#import "MaterialTypography.h"
+#import "private/MDCButton+Subclassing.h"
+
+// TODO(ajsecord): Animate title color when animating between enabled/disabled states.
+// Non-trivial: http://corecocoa.wordpress.com/2011/10/04/animatable-text-color-of-uilabel/
+
+static NSString *const MDCButtonEnabledBackgroundColorKey = @"MDCButtonEnabledBackgroundColorKey";
+static NSString *const MDCButtonDisabledBackgroundColorLightKey =
+    @"MDCButtonDisabledBackgroundColorLightKey";
+static NSString *const MDCButtonDisabledBackgroundColorDarkKey =
+    @"MDCButtonDisabledBackgroundColorDarkKey";
+static NSString *const MDCButtonInkViewInkStyleKey = @"MDCButtonInkViewInkStyleKey";
+static NSString *const MDCButtonInkViewInkColorKey = @"MDCButtonInkViewInkColorKey";
+static NSString *const MDCButtonInkViewInkMaxRippleRadiusKey =
+    @"MDCButtonInkViewInkMaxRippleRadiusKey";
+static NSString *const MDCButtonShouldRaiseOnTouchKey = @"MDCButtonShouldRaiseOnTouchKey";
+// Previous value kept for backwards compatibility.
+static NSString *const MDCButtonUppercaseTitleKey = @"MDCButtonShouldCapitalizeTitleKey";
+// Previous value kept for backwards compatibility.
+static NSString *const MDCButtonUnderlyingColorHintKey = @"MDCButtonUnderlyingColorKey";
+static NSString *const MDCButtonDisableAlphaKey = @"MDCButtonDisableAlphaKey";
+static NSString *const MDCButtonCustomTitleColorKey = @"MDCButtonCustomTitleColorKey";
+static NSString *const MDCButtonAreaInsetKey = @"MDCButtonAreaInsetKey";
+
+static NSString *const MDCButtonUserElevationsKey = @"MDCButtonUserElevationsKey";
+static NSString *const MDCButtonBackgroundColorsKey = @"MDCButtonBackgroundColorsKey";
+static NSString *const MDCButtonAccessibilityLabelsKey = @"MDCButtonAccessibilityLabelsKey";
+
+static const NSTimeInterval MDCButtonAnimationDuration = 0.2;
+
+// http://www.google.com/design/spec/components/buttons.html#buttons-main-buttons
+static const CGFloat MDCButtonDisabledAlpha = 0.1f;
+
+// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t MDCButtonDefaultBackgroundColor = 0x2196F3;
+
+// Checks whether the provided floating point number is exactly zero.
+static inline BOOL MDCButtonFloatIsExactlyZero(CGFloat value) {
+  return (value == 0.f);
+}
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+static NSAttributedString *uppercaseAttributedString(NSAttributedString *string) {
+  // Store the attributes.
+  NSMutableArray<NSDictionary *> *attributes = [NSMutableArray array];
+  [string enumerateAttributesInRange:NSMakeRange(0, [string length])
+                             options:0
+                          usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
+                            [attributes addObject:@{
+                              @"attrs" : attrs,
+                              @"range" : [NSValue valueWithRange:range]
+                            }];
+                          }];
+
+  // Make the string uppercase.
+  NSString *uppercaseString = [[string string] uppercaseStringWithLocale:[NSLocale currentLocale]];
+
+  // Apply the text and attributes to a mutable copy of the title attributed string.
+  NSMutableAttributedString *mutableString = [string mutableCopy];
+  [mutableString replaceCharactersInRange:NSMakeRange(0, [string length])
+                               withString:uppercaseString];
+  for (NSDictionary *attribute in attributes) {
+    [mutableString setAttributes:attribute[@"attrs"] range:[attribute[@"range"] rangeValue]];
+  }
+
+  return [mutableString copy];
+}
+
+@interface MDCButton () {
+  NSMutableDictionary<NSNumber *, NSNumber *> *_userElevations;   // For each UIControlState.
+  NSMutableDictionary<NSNumber *, UIColor *> *_backgroundColors;  // For each UIControlState.
+
+  // Cached accessibility settings.
+  NSMutableDictionary<NSNumber *, NSString *> *_accessibilityLabelForState;
+  NSString *_accessibilityLabelExplicitValue;
+
+  BOOL _mdc_adjustsFontForContentSizeCategory;
+}
+@property(nonatomic, strong) MDCInkView *inkView;
+@end
+
+@implementation MDCButton
+
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCButtonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCButtonInit];
+
+    // TODO(randallli): Add backward compatibility to background colors
+    //    if ([aDecoder containsValueForKey:MDCButtonEnabledBackgroundColorKey]) {
+    //      self.enabledBackgroundColor =
+    //          [aDecoder decodeObjectForKey:MDCButtonEnabledBackgroundColorKey];
+    //    }
+    //    if ([aDecoder containsValueForKey:MDCButtonDisabledBackgroundColorLightKey]) {
+    //      self.disabledBackgroundColorLight =
+    //          [aDecoder decodeObjectForKey:MDCButtonDisabledBackgroundColorLightKey];
+    //    }
+    //    if ([aDecoder containsValueForKey:MDCButtonDisabledBackgroundColorDarkKey]) {
+    //      self.disabledBackgroundColorDark =
+    //          [aDecoder decodeObjectForKey:MDCButtonDisabledBackgroundColorDarkKey];
+    //    }
+    if ([aDecoder containsValueForKey:MDCButtonInkViewInkStyleKey]) {
+      self.inkView.inkStyle = [aDecoder decodeIntegerForKey:MDCButtonInkViewInkStyleKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonInkViewInkColorKey]) {
+      self.inkView.inkColor = [aDecoder decodeObjectForKey:MDCButtonInkViewInkColorKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonInkViewInkMaxRippleRadiusKey]) {
+      self.inkView.maxRippleRadius =
+          (CGFloat)[aDecoder decodeDoubleForKey:MDCButtonInkViewInkMaxRippleRadiusKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonShouldRaiseOnTouchKey]) {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+      self.shouldRaiseOnTouch = [aDecoder decodeBoolForKey:MDCButtonShouldRaiseOnTouchKey];
+#pragma clang diagnostic pop
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonUppercaseTitleKey]) {
+      self.uppercaseTitle = [aDecoder decodeBoolForKey:MDCButtonUppercaseTitleKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonUnderlyingColorHintKey]) {
+      self.underlyingColorHint = [aDecoder decodeObjectForKey:MDCButtonUnderlyingColorHintKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonCustomTitleColorKey]) {
+      self.customTitleColor = [aDecoder decodeObjectForKey:MDCButtonCustomTitleColorKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonDisableAlphaKey]) {
+      self.disabledAlpha = (CGFloat)[aDecoder decodeDoubleForKey:MDCButtonDisableAlphaKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonAreaInsetKey]) {
+      self.hitAreaInsets = [aDecoder decodeUIEdgeInsetsForKey:MDCButtonAreaInsetKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonUserElevationsKey]) {
+      _userElevations = [aDecoder decodeObjectForKey:MDCButtonUserElevationsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonBackgroundColorsKey]) {
+      _backgroundColors = [aDecoder decodeObjectForKey:MDCButtonBackgroundColorsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCButtonAccessibilityLabelsKey]) {
+      _accessibilityLabelForState = [aDecoder decodeObjectForKey:MDCButtonAccessibilityLabelsKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+
+  [aCoder encodeInteger:_inkView.inkStyle forKey:MDCButtonInkViewInkStyleKey];
+  if (_inkView.inkColor) {
+    [aCoder encodeObject:_inkView.inkColor forKey:MDCButtonInkViewInkColorKey];
+  }
+
+  [aCoder encodeDouble:_inkView.maxRippleRadius forKey:MDCButtonInkViewInkMaxRippleRadiusKey];
+  [aCoder encodeBool:_shouldRaiseOnTouch forKey:MDCButtonShouldRaiseOnTouchKey];
+  [aCoder encodeBool:_uppercaseTitle forKey:MDCButtonUppercaseTitleKey];
+  if (_underlyingColorHint) {
+    [aCoder encodeObject:_underlyingColorHint forKey:MDCButtonUnderlyingColorHintKey];
+  }
+  [aCoder encodeDouble:self.disabledAlpha forKey:MDCButtonDisableAlphaKey];
+  if (self.customTitleColor) {
+    [aCoder encodeObject:self.customTitleColor forKey:MDCButtonCustomTitleColorKey];
+  }
+  [aCoder encodeUIEdgeInsets:self.hitAreaInsets forKey:MDCButtonAreaInsetKey];
+  [aCoder encodeObject:_userElevations forKey:MDCButtonUserElevationsKey];
+  [aCoder encodeObject:_backgroundColors forKey:MDCButtonBackgroundColorsKey];
+  [aCoder encodeObject:_accessibilityLabelForState forKey:MDCButtonAccessibilityLabelsKey];
+}
+
+- (void)commonMDCButtonInit {
+  _disabledAlpha = MDCButtonDisabledAlpha;
+  _shouldRaiseOnTouch = YES;
+  _uppercaseTitle = YES;
+  _userElevations = [NSMutableDictionary dictionary];
+  _backgroundColors = [NSMutableDictionary dictionary];
+  _accessibilityLabelForState = [NSMutableDictionary dictionary];
+
+  // Disable default highlight state.
+  self.adjustsImageWhenHighlighted = NO;
+  self.showsTouchWhenHighlighted = NO;
+
+  // Set up title label attributes.
+  self.titleLabel.font = [MDCTypography buttonFont];
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+
+  // Default content insets
+  self.contentEdgeInsets = [self defaultContentEdgeInsets];
+
+  MDCShadowLayer *shadowLayer = [self shadowLayer];
+  shadowLayer.shadowPath = [self boundingPath].CGPath;
+  shadowLayer.shadowColor = [UIColor blackColor].CGColor;
+  shadowLayer.elevation = [self elevationForState:self.state];
+
+  // Set up ink layer.
+  _inkView = [[MDCInkView alloc] initWithFrame:self.bounds];
+  [self insertSubview:_inkView belowSubview:self.imageView];
+
+  // UIButton has a drag enter/exit boundary that is outside of the frame of the button itself.
+  // Because this is not exposed externally, we can't use -touchesMoved: to calculate when to
+  // change ink state. So instead we fall back on adding target/actions for these specific events.
+  [self addTarget:self
+                action:@selector(touchDragEnter:forEvent:)
+      forControlEvents:UIControlEventTouchDragEnter];
+  [self addTarget:self
+                action:@selector(touchDragExit:forEvent:)
+      forControlEvents:UIControlEventTouchDragExit];
+
+  // Block users from activating multiple buttons simultaneously by default.
+  self.exclusiveTouch = YES;
+
+  // Default background colors.
+  [self setBackgroundColor:MDCColorFromRGB(MDCButtonDefaultBackgroundColor)
+                  forState:UIControlStateNormal];
+
+  self.inkColor = [UIColor colorWithWhite:1 alpha:0.2f];
+
+  // Uppercase all titles
+  if (_uppercaseTitle) {
+    [self uppercaseAllTitles];
+  }
+}
+
+- (void)dealloc {
+  [self removeTarget:self action:NULL forControlEvents:UIControlEventAllEvents];
+
+  [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                  name:UIContentSizeCategoryDidChangeNotification
+                                                object:nil];
+}
+
+- (void)setCustomTitleColor:(UIColor *)customTitleColor {
+  _customTitleColor = customTitleColor;
+  [self updateTitleColor];
+}
+
+- (void)setUnderlyingColorHint:(UIColor *)underlyingColorHint {
+  _underlyingColorHint = underlyingColorHint;
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+}
+
+- (void)setDisabledAlpha:(CGFloat)disabledAlpha {
+  _disabledAlpha = disabledAlpha;
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  self.layer.shadowPath = [self boundingPath].CGPath;
+  self.layer.cornerRadius = [self cornerRadius];
+
+  // Center the ink view frame taking into account possible insets using contentRectForBounds.
+
+  CGRect contentRect = [self contentRectForBounds:self.bounds];
+  CGPoint contentCenterPoint = CGPointMake(CGRectGetMidX(contentRect), CGRectGetMidY(contentRect));
+  CGPoint boundsCenterPoint = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
+
+  CGFloat offsetX = contentCenterPoint.x - boundsCenterPoint.x;
+  CGFloat offsetY = contentCenterPoint.y - boundsCenterPoint.y;
+  _inkView.frame = CGRectMake(offsetX, offsetY, self.bounds.size.width, self.bounds.size.height);
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  return CGRectContainsPoint(UIEdgeInsetsInsetRect(self.bounds, _hitAreaInsets), point);
+}
+
+#pragma mark - UIResponder
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesBegan:touches withEvent:event];
+
+  [self handleBeginTouches:touches];
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesMoved:touches withEvent:event];
+
+  // Drag events handled by -touchDragExit:forEvent: and -touchDragEnter:forEvent:
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesEnded:touches withEvent:event];
+
+  CGPoint location = [self locationFromTouches:touches];
+  [_inkView startTouchEndedAnimationAtPoint:location completion:nil];
+
+  BOOL inside = CGRectContainsPoint(self.bounds, location);
+  if (inside && _shouldRaiseOnTouch) {
+    [self animateButtonToHeightForState:UIControlStateNormal];
+  }
+}
+
+// Note - in some cases, event may be nil (e.g. view removed from window).
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesCancelled:touches withEvent:event];
+
+  [self evaporateInkToPoint:[self locationFromTouches:touches]];
+}
+
+#pragma mark - UIButton methods
+
+- (void)setEnabled:(BOOL)enabled {
+  [self setEnabled:enabled animated:NO];
+}
+
+- (void)setEnabled:(BOOL)enabled animated:(BOOL)animated {
+  [super setEnabled:enabled];
+  [self updateAlphaAndBackgroundColorAnimated:animated];
+}
+
+#pragma mark - Title Uppercasing
+
+- (void)setUppercaseTitle:(BOOL)uppercaseTitle {
+  _uppercaseTitle = uppercaseTitle;
+  if (_uppercaseTitle) {
+    [self uppercaseAllTitles];
+  }
+}
+
+- (void)uppercaseAllTitles {
+  // This ensures existing titles will get uppercased.
+  UIControlState allControlStates = UIControlStateNormal | UIControlStateHighlighted |
+                                    UIControlStateDisabled | UIControlStateSelected;
+  for (UIControlState state = 0; state <= allControlStates; ++state) {
+    NSString *title = [self titleForState:state];
+    if (title) {
+      [self setTitle:[title uppercaseStringWithLocale:[NSLocale currentLocale]] forState:state];
+    }
+
+    NSAttributedString *attributedTitle = [self attributedTitleForState:state];
+    if (attributedTitle) {
+      [self setAttributedTitle:uppercaseAttributedString(attributedTitle) forState:state];
+    }
+  }
+}
+
+- (void)setTitle:(NSString *)title forState:(UIControlState)state {
+  // Intercept any setting of the title and store a copy in case the accessibilityLabel
+  // is requested and the original non-uppercased version needs to be returned.
+  if ([title length]) {
+    _accessibilityLabelForState[@(state)] = [title copy];
+  } else {
+    [_accessibilityLabelForState removeObjectForKey:@(state)];
+  }
+
+  if (_uppercaseTitle) {
+    title = [title uppercaseStringWithLocale:[NSLocale currentLocale]];
+  }
+  [super setTitle:title forState:state];
+}
+
+- (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state {
+  // Intercept any setting of the title and store a copy in case the accessibilityLabel
+  // is requested and the original non-uppercased version needs to be returned.
+  if ([title length]) {
+    _accessibilityLabelForState[@(state)] = [[title string] copy];
+  } else {
+    [_accessibilityLabelForState removeObjectForKey:@(state)];
+  }
+
+  if (_uppercaseTitle) {
+    title = uppercaseAttributedString(title);
+  }
+  [super setAttributedTitle:title forState:state];
+}
+
+#pragma mark - Accessibility
+
+- (void)setAccessibilityLabel:(NSString *)accessibilityLabel {
+  // Intercept any explicit setting of the accessibilityLabel so it can be returned
+  // later before the accessibiilityLabel is inferred from the setTitle:forState:
+  // argument values.
+  _accessibilityLabelExplicitValue = [accessibilityLabel copy];
+  [super setAccessibilityLabel:accessibilityLabel];
+}
+
+- (NSString *)accessibilityLabel {
+  if (!_uppercaseTitle) {
+    return [super accessibilityLabel];
+  }
+
+  NSString *label = _accessibilityLabelExplicitValue;
+  if ([label length]) {
+    return label;
+  }
+
+  label = _accessibilityLabelForState[@(self.state)];
+  if ([label length]) {
+    return label;
+  }
+
+  label = _accessibilityLabelForState[@(UIControlStateNormal)];
+  if ([label length]) {
+    return label;
+  }
+
+  label = [super accessibilityLabel];
+  if ([label length]) {
+    return label;
+  }
+
+  return nil;
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  return [super accessibilityTraits] | UIAccessibilityTraitButton;
+}
+
+#pragma mark - Ink
+
+- (MDCInkStyle)inkStyle {
+  return _inkView.inkStyle;
+}
+
+- (void)setInkStyle:(MDCInkStyle)inkStyle {
+  _inkView.inkStyle = inkStyle;
+}
+
+- (UIColor *)inkColor {
+  return _inkView.inkColor;
+}
+
+- (void)setInkColor:(UIColor *)inkColor {
+  _inkView.inkColor = inkColor;
+}
+
+- (CGFloat)inkMaxRippleRadius {
+  return _inkView.maxRippleRadius;
+}
+
+- (void)setInkMaxRippleRadius:(CGFloat)inkMaxRippleRadius {
+  _inkView.maxRippleRadius = inkMaxRippleRadius;
+}
+
+#pragma mark - Shadows
+
+- (MDCShadowLayer *)shadowLayer {
+  return (MDCShadowLayer *)self.layer;
+}
+
+- (void)animateButtonToHeightForState:(UIControlState)state {
+  [CATransaction begin];
+  [CATransaction setAnimationDuration:MDCButtonAnimationDuration];
+  [self shadowLayer].elevation = [self elevationForState:state];
+  [CATransaction commit];
+}
+
+#pragma mark - BackgroundColor
+
+- (UIColor *)backgroundColorForState:(UIControlState)state {
+  return _backgroundColors[@(state)];
+}
+
+- (void)setBackgroundColor:(UIColor *)backgroundColor forState:(UIControlState)state {
+  _backgroundColors[@(state)] = backgroundColor;
+  [self updateAlphaAndBackgroundColorAnimated:NO];
+}
+
+#pragma mark - Elevations
+
+- (CGFloat)elevationForState:(UIControlState)state {
+  NSNumber *elevation = _userElevations[@(state)];
+  return elevation ? (CGFloat)[elevation doubleValue] : [self defaultElevationForState:state];
+}
+
+- (void)setElevation:(CGFloat)elevation forState:(UIControlState)state {
+  _userElevations[@(state)] = @(elevation);
+  [self shadowLayer].elevation = [self elevationForState:self.state];
+
+  // The elevation of the normal state controls whether this button is flat or not, and flat buttons
+  // have different background color requirements than raised buttons.
+  // TODO(ajsecord): Move to MDCFlatButton and update this comment.
+  if (state == UIControlStateNormal) {
+    [self updateAlphaAndBackgroundColorAnimated:NO];
+  }
+}
+
+- (void)resetElevationForState:(UIControlState)state {
+  [_userElevations removeObjectForKey:@(state)];
+  [self shadowLayer].elevation = [self elevationForState:self.state];
+}
+
+#pragma mark - Private methods
+
+- (UIColor *)currentBackgroundColor {
+  UIColor *color = _backgroundColors[@(self.state)];
+  if (color) {
+    return color;
+  }
+  return [self backgroundColorForState:UIControlStateNormal];
+}
+
+/**
+ The background color that a user would see for this button. If self.backgroundColor is not
+ transparent, then returns that. Otherwise, returns self.underlyingColorHint.
+ @note If self.underlyingColorHint is not set, then this method will return nil.
+ */
+- (UIColor *)effectiveBackgroundColor {
+  if (![self isTransparentColor:self.currentBackgroundColor]) {
+    return self.currentBackgroundColor;
+  } else {
+    return self.underlyingColorHint;
+  }
+}
+
+/** Returns YES if the color is not transparent and is a "dark" color. */
+- (BOOL)isDarkColor:(UIColor *)color {
+  // TODO: have a components/private/ColorCalculations/MDCColorCalculations.h|m
+  //  return ![self isTransparentColor:color] && [QTMColorGroup luminanceOfColor:color] < 0.5f;
+  return ![self isTransparentColor:color];
+}
+
+/** Returns YES if the color is transparent (including a nil color). */
+- (BOOL)isTransparentColor:(UIColor *)color {
+  return !color || [color isEqual:[UIColor clearColor]] || CGColorGetAlpha(color.CGColor) == 0.0f;
+}
+
+- (void)touchDragEnter:(MDCButton *)button forEvent:(UIEvent *)event {
+  [self handleBeginTouches:event.allTouches];
+}
+
+- (void)touchDragExit:(MDCButton *)button forEvent:(UIEvent *)event {
+  CGPoint location = [self locationFromTouches:event.allTouches];
+  [self evaporateInkToPoint:location];
+}
+
+- (void)handleBeginTouches:(NSSet *)touches {
+  [_inkView startTouchBeganAnimationAtPoint:[self locationFromTouches:touches] completion:nil];
+  if (_shouldRaiseOnTouch) {
+    [self animateButtonToHeightForState:UIControlStateSelected];
+  }
+}
+
+- (CGPoint)locationFromTouches:(NSSet *)touches {
+  UITouch *touch = [touches anyObject];
+  return [touch locationInView:self];
+}
+
+- (void)evaporateInkToPoint:(CGPoint)toPoint {
+  [_inkView startTouchEndedAnimationAtPoint:toPoint completion:nil];
+  if (_shouldRaiseOnTouch) {
+    [self animateButtonToHeightForState:UIControlStateNormal];
+  }
+}
+
+- (UIBezierPath *)boundingPath {
+  return [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:[self cornerRadius]];
+}
+
+- (CGFloat)cornerRadius {
+  return 2.0f;
+}
+
+- (UIEdgeInsets)defaultContentEdgeInsets {
+  return UIEdgeInsetsMake(8, 16, 8, 16);
+}
+
+- (CGFloat)defaultElevationForState:(UIControlState)state {
+  if (state == UIControlStateNormal) {
+    return 0;
+  }
+
+  if ((state & UIControlStateSelected) == UIControlStateSelected) {
+    CGFloat normalElevation = [self elevationForState:UIControlStateNormal];
+    return normalElevation > 0 ? 2 * normalElevation : 1;
+  }
+
+  return [self elevationForState:UIControlStateNormal];
+}
+
+- (BOOL)shouldHaveOpaqueBackground {
+  BOOL isFlatButton = MDCButtonFloatIsExactlyZero([self elevationForState:UIControlStateNormal]);
+  return !isFlatButton;
+}
+
+- (void)updateAlphaAndBackgroundColorAnimated:(BOOL)animated {
+  void (^animations)() = ^{
+    self.alpha = self.enabled ? 1.0f : _disabledAlpha;
+    [self updateBackgroundColor];
+  };
+
+  if (animated) {
+    [UIView animateWithDuration:MDCButtonAnimationDuration animations:animations];
+  } else {
+    animations();
+  }
+}
+
+- (void)updateBackgroundColor {
+  //  UIColor *color = nil;
+  //  if ([self shouldHaveOpaqueBackground]) {
+  //    if (self.enabled) {
+  ////      color = self.enabledBackgroundColor;
+  //    } else {
+  //      color = [self isDarkColor:_underlyingColorHint] ? _disabledBackgroundColorLight
+  //                                                  : _disabledBackgroundColorDark;
+  //    }
+  //  }
+  [self updateTitleColor];
+  [self updateDisabledTitleColor];
+  super.backgroundColor = self.currentBackgroundColor;
+}
+
+- (void)updateDisabledTitleColor {
+  // Disabled buttons have very low opacity, so we full-opacity text color here to make the text
+  // readable. Also, even for non-flat buttons with opaque backgrounds, the correct background color
+  // to examine is the underlying color, since disabled buttons are so transparent.
+  BOOL darkBackground = [self isDarkColor:[self underlyingColorHint]];
+  [self setTitleColor:darkBackground ? [UIColor whiteColor] : [UIColor blackColor]
+             forState:UIControlStateDisabled];
+}
+
+- (void)updateTitleColor {
+  if (_customTitleColor) {
+    [self setTitleColor:_customTitleColor forState:UIControlStateNormal];
+    return;
+  }
+
+  if (![self isTransparentColor:[self effectiveBackgroundColor]]) {
+    MDFTextAccessibilityOptions options = 0;
+    if ([MDFTextAccessibility isLargeForContrastRatios:self.titleLabel.font]) {
+      options = MDFTextAccessibilityOptionsLargeFont;
+    }
+    UIColor *color =
+        [MDFTextAccessibility textColorOnBackgroundColor:[self effectiveBackgroundColor]
+                                         targetTextAlpha:[MDCTypography buttonFontOpacity]
+                                                 options:options];
+    [self setTitleColor:color forState:UIControlStateNormal];
+  }
+}
+
+- (BOOL)mdc_adjustsFontForContentSizeCategory {
+  return _mdc_adjustsFontForContentSizeCategory;
+}
+
+- (void)mdc_setAdjustsFontForContentSizeCategory:(BOOL)adjusts {
+  _mdc_adjustsFontForContentSizeCategory = adjusts;
+  if (_mdc_adjustsFontForContentSizeCategory) {
+    UIFont *font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleButton];
+    self.titleLabel.font = font;
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(contentSizeCategoryDidChange:)
+                                                 name:UIContentSizeCategoryDidChangeNotification
+                                               object:nil];
+  } else {
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                    name:UIContentSizeCategoryDidChangeNotification
+                                                  object:nil];
+  }
+}
+
+- (void)contentSizeCategoryDidChange:(NSNotification *)notification {
+  UIFont *font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleButton];
+  self.titleLabel.font = font;
+  [self sizeToFit];
+}
+
+#pragma mark - Deprecations
+
+- (BOOL)shouldCapitalizeTitle {
+  return [self isUppercaseTitle];
+}
+
+- (void)setShouldCapitalizeTitle:(BOOL)shouldCapitalizeTitle {
+  [self setUppercaseTitle:shouldCapitalizeTitle];
+}
+
+- (UIColor *)underlyingColor {
+  return [self underlyingColorHint];
+}
+
+- (void)setUnderlyingColor:(UIColor *)underlyingColor {
+  [self setUnderlyingColorHint:underlyingColor];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.h
new file mode 100644
index 0000000..886efe4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.h
@@ -0,0 +1,42 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "MDCButton.h"
+
+/**
+ A "flat" MDCButton.
+
+ Flat buttons should be considered the default button. They do not have their own background color,
+ do not raise when touched, and have uppercased text to indicate to the user that they are buttons.
+ Flat buttons should be used in most situations requiring a button. For layouts with many UI
+ elements in which a flat button might get visually lost, consider using a MDCRaisedButton instead.
+
+ @see http://www.google.com/design/spec/components/buttons.html#buttons-flat-buttons
+ */
+@interface MDCFlatButton : MDCButton
+
+/**
+ Use an opaque background color (default is NO).
+
+ Flat buttons normally have a transparent background and blend seamlessly with their underlying
+ color, but occasionally a flat button with an opaque background will be required. Consider using
+ a raised button instead if possible.
+ */
+@property(nonatomic) BOOL hasOpaqueBackground;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.m
new file mode 100644
index 0000000..4bf35d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFlatButton.m
@@ -0,0 +1,69 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlatButton.h"
+
+#import "private/MDCButton+Subclassing.h"
+
+static NSString *const MDCFlatButtonHasOpaqueBackground = @"MDCFlatButtonHasOpaqueBackground";
+
+@implementation MDCFlatButton
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCFlatButtonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCFlatButtonHasOpaqueBackground]) {
+      self.hasOpaqueBackground = [aDecoder decodeBoolForKey:MDCFlatButtonHasOpaqueBackground];
+    }
+    [self commonMDCFlatButtonInit];
+  }
+  return self;
+}
+
+- (void)commonMDCFlatButtonInit {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  self.shouldRaiseOnTouch = NO;
+#pragma clang diagnostic pop
+  [self setBackgroundColor:nil forState:UIControlStateNormal];
+  self.inkColor = [UIColor colorWithWhite:0 alpha:0.06f];
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeBool:_hasOpaqueBackground forKey:MDCFlatButtonHasOpaqueBackground];
+}
+
+#pragma mark - MDCButton Subclassing
+
+- (void)setHasOpaqueBackground:(BOOL)hasOpaqueBackground {
+  _hasOpaqueBackground = hasOpaqueBackground;
+  [self updateBackgroundColor];
+}
+
+- (BOOL)shouldHaveOpaqueBackground {
+  return [super shouldHaveOpaqueBackground] || self.hasOpaqueBackground;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.h
new file mode 100644
index 0000000..6552b35
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.h
@@ -0,0 +1,87 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <CoreGraphics/CoreGraphics.h>
+#import <Foundation/Foundation.h>
+
+#import "MDCButton.h"
+
+/**
+ Shapes for Material Floating buttons.
+
+ The mini size should only be used when required for visual continuity with other elements on the
+ screen.
+ */
+typedef NS_ENUM(NSInteger, MDCFloatingButtonShape) {
+  MDCFloatingButtonShapeDefault,
+  MDCFloatingButtonShapeMini
+};
+
+/**
+ A "floating" MDCButton.
+
+ Floating action buttons are circular, float a considerable amount above their parent, have
+ their own background color, and also raise briefly when touched. Floating action buttons should
+ only be used rarely, for the main action of a screen.
+
+ @see http://www.google.com/design/spec/components/buttons.html#buttons-main-buttons
+ */
+@interface MDCFloatingButton : MDCButton
+
+/**
+ Returns a MDCFloatingButton with default colors and the given @c shape.
+
+ @param shape Button shape.
+ @return Button with shape.
+ */
++ (nonnull instancetype)floatingButtonWithShape:(MDCFloatingButtonShape)shape;
+
+/**
+ @return The default floating button size dimension.
+ */
++ (CGFloat)defaultDimension;
+
+/**
+ @return The mini floating button size dimension.
+ */
++ (CGFloat)miniDimension;
+
+/**
+ Initializes self to a button with the given @c shape.
+
+ @param frame Button frame.
+ @param shape Button shape.
+ @return Button with shape.
+ */
+- (nonnull instancetype)initWithFrame:(CGRect)frame
+                                shape:(MDCFloatingButtonShape)shape NS_DESIGNATED_INITIALIZER;
+
+/**
+ Initializes self to a button with the MDCFloatingButtonShapeDefault shape.
+
+ @param frame Button frame.
+ @return Button with MDCFloatingButtonShapeDefault shape.
+ */
+- (nonnull instancetype)initWithFrame:(CGRect)frame;
+
+- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
+
+#pragma mark - Deprecations
+
++ (nonnull instancetype)buttonWithShape:(MDCFloatingButtonShape)shape
+    __deprecated_msg("Use floatingButtonWithShape: instead.");
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.m
new file mode 100644
index 0000000..a9b7028
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCFloatingButton.m
@@ -0,0 +1,123 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFloatingButton.h"
+
+#import "MaterialShadowElevations.h"
+#import "private/MDCButton+Subclassing.h"
+
+static const CGFloat MDCFloatingButtonDefaultDimension = 56.0f;
+static const CGFloat MDCFloatingButtonMiniDimension = 40.0f;
+static NSString *const MDCFloatingButtonShapeKey = @"MDCFloatingButtonShapeKey";
+
+@implementation MDCFloatingButton {
+  MDCFloatingButtonShape _shape;
+}
+
++ (CGFloat)defaultDimension {
+  return MDCFloatingButtonDefaultDimension;
+}
+
++ (CGFloat)miniDimension {
+  return MDCFloatingButtonMiniDimension;
+}
+
++ (instancetype)floatingButtonWithShape:(MDCFloatingButtonShape)shape {
+  return [[[self class] alloc] initWithFrame:CGRectZero shape:shape];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  return [self initWithFrame:frame shape:MDCFloatingButtonShapeDefault];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame shape:(MDCFloatingButtonShape)shape {
+  self = [super initWithFrame:frame];
+  if (self) {
+    _shape = shape;
+    // The superclass sets contentEdgeInsets from defaultContentEdgeInsets before the _shape is set.
+    // Set contentEdgeInsets again to ensure the defaults are for the correct shape.
+    self.contentEdgeInsets = [self defaultContentEdgeInsets];
+  }
+  return self;
+}
+
+#pragma mark - NSCoding
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    _shape = [aDecoder decodeIntegerForKey:MDCFloatingButtonShapeKey];
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeInteger:_shape forKey:MDCFloatingButtonShapeKey];
+}
+
+#pragma mark - UIView
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  switch (_shape) {
+    case MDCFloatingButtonShapeDefault:
+      return CGSizeMake([[self class] defaultDimension], [[self class] defaultDimension]);
+    case MDCFloatingButtonShapeMini:
+      return CGSizeMake([[self class] miniDimension], [[self class] miniDimension]);
+  }
+}
+
+- (CGSize)intrinsicContentSize {
+  switch (_shape) {
+    case MDCFloatingButtonShapeDefault:
+      return CGSizeMake([[self class] defaultDimension], [[self class] defaultDimension]);
+    case MDCFloatingButtonShapeMini:
+      return CGSizeMake([[self class] miniDimension], [[self class] miniDimension]);
+  }
+}
+
+#pragma mark - Subclassing
+
+- (UIBezierPath *)boundingPath {
+  return [UIBezierPath bezierPathWithOvalInRect:self.bounds];
+}
+
+- (CGFloat)cornerRadius {
+  return CGRectGetWidth(self.bounds) / 2;
+}
+
+- (UIEdgeInsets)defaultContentEdgeInsets {
+  switch (_shape) {
+    case MDCFloatingButtonShapeDefault:
+      return UIEdgeInsetsMake(16, 16, 16, 16);
+    case MDCFloatingButtonShapeMini:
+      return UIEdgeInsetsMake(8, 8, 8, 8);
+  }
+}
+
+- (CGFloat)defaultElevationForState:(UIControlState)state {
+  return (((state & UIControlStateSelected) == UIControlStateSelected)
+              ? MDCShadowElevationFABPressed
+              : MDCShadowElevationFABResting);
+}
+
+#pragma mark - Deprecations
+
++ (instancetype)buttonWithShape:(MDCFloatingButtonShape)shape {
+  return [[self class] floatingButtonWithShape:shape];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.h
new file mode 100644
index 0000000..f71e770
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+
+/**
+ A "raised" MDCButton.
+
+ Raised buttons have their own background color, float above their parent slightly, and raise
+ briefly when touched. Raised buttons should be used when flat buttons would get lost among other
+ UI elements on the screen.
+
+ @see http://www.google.com/design/spec/components/buttons.html#buttons-raised-buttons
+ */
+@interface MDCRaisedButton : MDCButton
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.m
new file mode 100644
index 0000000..e3b7c29
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MDCRaisedButton.m
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCRaisedButton.h"
+
+#import "MaterialShadowElevations.h"
+#import "private/MDCButton+Subclassing.h"
+
+@implementation MDCRaisedButton
+
+#pragma mark - Subclassing
+
+- (CGFloat)defaultElevationForState:(UIControlState)state {
+  return (((state & UIControlStateSelected) == UIControlStateSelected)
+              ? MDCShadowElevationRaisedButtonPressed
+              : MDCShadowElevationRaisedButtonResting);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MaterialButtons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MaterialButtons.h
new file mode 100644
index 0000000..f2908cc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/MaterialButtons.h
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+#import "MDCFlatButton.h"
+#import "MDCFloatingButton.h"
+#import "MDCRaisedButton.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h
new file mode 100644
index 0000000..06a887e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Buttons/src/private/MDCButton+Subclassing.h
@@ -0,0 +1,51 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCButton.h"
+
+@class MDCInkView;
+
+@interface MDCButton (Subclassing)
+
+/** Access to the ink view layer. Mainly used for subclasses to override ink properties. */
+@property(nonatomic, readonly, strong, nonnull) MDCInkView *inkView;
+
+/** Whether the background color should be opaque. */
+- (BOOL)shouldHaveOpaqueBackground;
+
+/** Updates the background color based on the button's current configuration. */
+- (void)updateBackgroundColor;
+
+/**
+ Should the button raise when touched?
+
+ Default is YES.
+ */
+@property(nonatomic) BOOL shouldRaiseOnTouch;
+
+/** The bounding path of the button. The shadow will follow that path. */
+- (nonnull UIBezierPath *)boundingPath;
+
+/** The corner radius of the button. The shadow will follow that path. */
+- (CGFloat)cornerRadius;
+
+/** The default content edge insets of the button. They are set at initialization time. */
+- (UIEdgeInsets)defaultContentEdgeInsets;
+
+/** The default elevation for a particular button state (if not set by the calling code). */
+- (CGFloat)defaultElevationForState:(UIControlState)state;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
new file mode 100644
index 0000000..c91e729
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.h
@@ -0,0 +1,108 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MaterialInk.h"
+
+#import <UIKit/UIKit.h>
+
+/** The available cell accessory view types. Based on UITableViewCellAccessoryType. */
+typedef NS_ENUM(NSUInteger, MDCCollectionViewCellAccessoryType) {
+  /** Default value. No accessory view shown. */
+  MDCCollectionViewCellAccessoryNone,
+
+  /** A chevron accessory view. */
+  MDCCollectionViewCellAccessoryDisclosureIndicator,
+
+  /** A checkmark accessory view. */
+  MDCCollectionViewCellAccessoryCheckmark,
+
+  /** An info button accessory view. */
+  MDCCollectionViewCellAccessoryDetailButton
+};
+
+// String key for accessibility hint of selected cells.
+FOUNDATION_EXPORT NSString *_Nonnull const kSelectedCellAccessibilityHintKey;
+
+// String key for accessibility hint of deselected cells.
+FOUNDATION_EXPORT NSString *_Nonnull const kDeselectedCellAccessibilityHintKey;
+
+/**
+ The MDCCollectionViewCell class provides an implementation of UICollectionViewCell that
+ supports Material Design layout and styling.
+ */
+@interface MDCCollectionViewCell : UICollectionViewCell
+
+/** The accessory type for this cell. Default is MDCCollectionViewCellAccessoryNone. */
+@property(nonatomic) MDCCollectionViewCellAccessoryType accessoryType;
+
+/** If set, use custom view and ignore accessoryType. Defaults to nil. */
+@property(nonatomic, strong, nullable) UIView *accessoryView;
+
+/**
+ The accessory inset for this cell. Only left/right insets are valid as top/bottom insets will
+ be ignored. These insets are used for both accessories and editing mask controls.
+ Defaults to {0, 16.0f, 0, 16.0f}.
+ */
+@property(nonatomic) UIEdgeInsets accessoryInset;
+
+/**
+ Whether to hide the separator for this cell. If not set, the @c shouldHideSeparators property of
+ the collection view styler will be used. Defaults to NO.
+ */
+@property(nonatomic) BOOL shouldHideSeparator;
+
+/**
+ The separator inset for this cell. Only left/right insets are valid as top/bottom insets will be
+ ignored. If this property is not changed, the @c separatorInset property of the collection view
+ styler will be used instead. Defaults to UIEdgeInsetsZero.
+ */
+@property(nonatomic) UIEdgeInsets separatorInset;
+
+/**
+ A boolean value indicating whether a cell permits interactions with subviews of its content while
+ the cell is in editing mode. If NO, then tapping anywhere in the cell will select it instead of
+ permitting the tapped subview to receive the touch. Defaults to NO.
+ */
+@property(nonatomic) BOOL allowsCellInteractionsWhileEditing;
+
+/**
+ A boolean value indicating whether the a cell is being edited. Setting is not animated.
+
+ When set, the cell will shows/hide editing controls with/without animation.
+ */
+@property(nonatomic, getter=isEditing) BOOL editing;
+
+/**
+ The color for the editing selector when the cell is selected.
+
+ The default is a red color.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *editingSelectorColor UI_APPEARANCE_SELECTOR;
+
+/**
+ Set the editing state with optional animations.
+
+ When set, the cell will shows/hide editing controls with/without animation.
+
+ @param editing YES if editing; otherwise, NO.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
+
+/** View containing the ink effect. */
+@property(nonatomic, strong, nullable) MDCInkView *inkView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.m
new file mode 100644
index 0000000..3a8948f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewCell.m
@@ -0,0 +1,532 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewCell.h"
+
+#import "MaterialCollectionLayoutAttributes.h"
+#import "MaterialIcons+ic_check.h"
+#import "MaterialIcons+ic_check_circle.h"
+#import "MaterialIcons+ic_chevron_right.h"
+#import "MaterialIcons+ic_info.h"
+#import "MaterialIcons+ic_radio_button_unchecked.h"
+#import "MaterialIcons+ic_reorder.h"
+#import "MaterialRTL.h"
+
+#define RGBCOLOR(r, g, b) \
+  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
+#define HEXCOLOR(hex) RGBCOLOR((((hex) >> 16) & 0xFF), (((hex) >> 8) & 0xFF), ((hex)&0xFF))
+
+static CGFloat kEditingControlAppearanceOffset = 16.0f;
+
+// Default accessory insets.
+static const UIEdgeInsets kAccessoryInsetDefault = {0, 16.0f, 0, 16.0f};
+
+// Default editing icon colors.
+static const uint32_t kCellGrayColor = 0x626262;
+static const uint32_t kCellRedColor = 0xF44336;
+
+// File name of the bundle (without the '.bundle' extension) containing resources.
+static NSString *const kResourceBundleName = @"MaterialCollectionCells";
+
+// String table name containing localized strings.
+static NSString *const kStringTableName = @"MaterialCollectionCells";
+
+NSString *const kSelectedCellAccessibilityHintKey =
+    @"MaterialCollectionCellsAccessibilitySelectedHint";
+
+NSString *const kDeselectedCellAccessibilityHintKey =
+    @"MaterialCollectionCellsAccessibilityDeselectedHint";
+
+// To be used as accessory view when an accessory type is set. It has no particular functionalities
+// other than being a private class defined here, to check if an accessory view was set via an
+// accessory type, or if the user of MDCCollectionViewCell set a custom accessory view.
+@interface MDCAccessoryTypeImageView : UIImageView
+@end
+@implementation MDCAccessoryTypeImageView
+@end
+
+@implementation MDCCollectionViewCell {
+  MDCCollectionViewLayoutAttributes *_attr;
+  BOOL _usesCellSeparatorHiddenOverride;
+  BOOL _usesCellSeparatorInsetOverride;
+  BOOL _shouldAnimateEditingViews;
+  UIView *_separatorView;
+  UIImageView *_backgroundImageView;
+  UIImageView *_editingReorderImageView;
+  UIImageView *_editingSelectorImageView;
+}
+
+@synthesize inkView = _inkView;
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionViewCellInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionViewCellInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionViewCellInit {
+  // Separator defaults.
+  _separatorView = [[UIImageView alloc] initWithFrame:CGRectZero];
+  [self addSubview:_separatorView];
+
+  // Accessory defaults.
+  _accessoryType = MDCCollectionViewCellAccessoryNone;
+  _accessoryInset = kAccessoryInsetDefault;
+  _editingSelectorColor = HEXCOLOR(kCellRedColor);
+}
+
+#pragma mark - Layout
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+
+  // Accessory defaults.
+  _accessoryType = MDCCollectionViewCellAccessoryNone;
+  _accessoryInset = kAccessoryInsetDefault;
+  [_accessoryView removeFromSuperview];
+  _accessoryView = nil;
+
+  // Reset properties.
+  _shouldAnimateEditingViews = NO;
+  _usesCellSeparatorHiddenOverride = NO;
+  _usesCellSeparatorInsetOverride = NO;
+  _separatorView.hidden = YES;
+
+  [self drawSeparatorIfNeeded];
+  [self updateInterfaceForEditing];
+
+  // Reset cells hidden during swipe deletion.
+  self.hidden = NO;
+
+  [self.inkView cancelAllAnimationsAnimated:NO];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Layout the accessory view and the content view.
+  [self updateInterfaceForEditing];
+  [self layoutForegroundSubviews];
+
+  void (^editingViewLayout)() = ^() {
+    CGFloat txReorderTransform;
+    CGFloat txSelectorTransform;
+    switch (self.mdc_effectiveUserInterfaceLayoutDirection) {
+      case UIUserInterfaceLayoutDirectionLeftToRight:
+        txReorderTransform = kEditingControlAppearanceOffset;
+        txSelectorTransform = -kEditingControlAppearanceOffset;
+        break;
+      case UIUserInterfaceLayoutDirectionRightToLeft:
+        txReorderTransform = -kEditingControlAppearanceOffset;
+        txSelectorTransform = kEditingControlAppearanceOffset;
+        break;
+    }
+    _editingReorderImageView.alpha = _attr.shouldShowReorderStateMask ? 1.0f : 0.0f;
+    _editingReorderImageView.transform =
+        _attr.shouldShowReorderStateMask ? CGAffineTransformMakeTranslation(txReorderTransform, 0)
+                                         : CGAffineTransformIdentity;
+
+    _editingSelectorImageView.alpha = _attr.shouldShowSelectorStateMask ? 1.0f : 0.0f;
+    _editingSelectorImageView.transform =
+        _attr.shouldShowSelectorStateMask ? CGAffineTransformMakeTranslation(txSelectorTransform, 0)
+                                          : CGAffineTransformIdentity;
+
+    _accessoryView.alpha = _attr.shouldShowSelectorStateMask ? 0.0f : 1.0f;
+    _accessoryInset.right = _attr.shouldShowSelectorStateMask
+                                ? kAccessoryInsetDefault.right + kEditingControlAppearanceOffset
+                                : kAccessoryInsetDefault.right;
+  };
+
+  // Animate editing controls.
+  if (_shouldAnimateEditingViews) {
+    [UIView animateWithDuration:0.3 animations:editingViewLayout];
+    _shouldAnimateEditingViews = NO;
+  } else {
+    [UIView performWithoutAnimation:editingViewLayout];
+  }
+}
+
+- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
+  [super applyLayoutAttributes:layoutAttributes];
+  if ([layoutAttributes isKindOfClass:[MDCCollectionViewLayoutAttributes class]]) {
+    _attr = (MDCCollectionViewLayoutAttributes *)layoutAttributes;
+
+    if (_attr.representedElementCategory == UICollectionElementCategoryCell) {
+      // Cells are often set to editing via layout attributes so we default to animating.
+      // This can be overridden by ensuring layoutSubviews is called inside a non-animation block.
+      [self setEditing:_attr.editing animated:YES];
+    }
+
+    // Create image view to hold cell background image with shadowing.
+    if (!_backgroundImageView) {
+      _backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
+      self.backgroundView = _backgroundImageView;
+    }
+    _backgroundImageView.image = _attr.backgroundImage;
+
+    // Draw separator if needed.
+    [self drawSeparatorIfNeeded];
+
+    // Layout the accessory view and the content view.
+    [self layoutForegroundSubviews];
+
+    // Animate cell on appearance settings.
+    [self updateAppearanceAnimation];
+  }
+}
+
+- (void)layoutForegroundSubviews {
+  // First lay out the accessory view.
+  _accessoryView.frame = [self accessoryFrame];
+  // Then lay out the content view, inset by the accessory view's width.
+  self.contentView.frame = [self contentViewFrame];
+
+  // If necessary flip subviews for RTL.
+  _accessoryView.frame = MDCRectFlippedForRTL(_accessoryView.frame, CGRectGetWidth(self.bounds),
+                                              self.mdc_effectiveUserInterfaceLayoutDirection);
+  self.contentView.frame = MDCRectFlippedForRTL(self.contentView.frame, CGRectGetWidth(self.bounds),
+                                                self.mdc_effectiveUserInterfaceLayoutDirection);
+}
+
+#pragma mark - Accessory Views
+
+- (void)setAccessoryType:(MDCCollectionViewCellAccessoryType)accessoryType {
+  _accessoryType = accessoryType;
+
+  UIImageView *accessoryImageView = nil;
+  if (!_accessoryView && accessoryType != MDCCollectionViewCellAccessoryNone) {
+    // Add accessory view.
+    accessoryImageView = [[MDCAccessoryTypeImageView alloc] initWithFrame:CGRectZero];
+    _accessoryView = accessoryImageView;
+    _accessoryView.userInteractionEnabled = NO;
+    [self addSubview:_accessoryView];
+  }
+
+  switch (_accessoryType) {
+    case MDCCollectionViewCellAccessoryDisclosureIndicator: {
+      UIImage *image = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_chevron_right]];
+      if (self.mdc_effectiveUserInterfaceLayoutDirection ==
+          UIUserInterfaceLayoutDirectionRightToLeft) {
+        image = [image mdc_imageFlippedForRightToLeftLayoutDirection];
+      }
+      accessoryImageView.image = image;
+      break;
+    }
+    case MDCCollectionViewCellAccessoryCheckmark: {
+      UIImage *image = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_check]];
+      accessoryImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+      break;
+    }
+    case MDCCollectionViewCellAccessoryDetailButton: {
+      UIImage *image = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_info]];
+      accessoryImageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+      break;
+    }
+    case MDCCollectionViewCellAccessoryNone: {
+      [_accessoryView removeFromSuperview];
+      _accessoryView = nil;
+      break;
+    }
+  }
+  [_accessoryView sizeToFit];
+}
+
+- (void)setAccessoryView:(UIView *)accessoryView {
+  if (_accessoryView) {
+    [_accessoryView removeFromSuperview];
+  }
+  _accessoryView = accessoryView;
+  if (_accessoryView) {
+    [self addSubview:_accessoryView];
+  }
+}
+
+- (CGRect)accessoryFrame {
+  CGSize size = _accessoryView.frame.size;
+  CGFloat originX = CGRectGetWidth(self.bounds) - size.width - _accessoryInset.right;
+  CGFloat originY = (CGRectGetHeight(self.bounds) - size.height) / 2;
+  return CGRectMake(originX, originY, size.width, size.height);
+}
+
+- (MDCInkView *)inkView {
+  if (!_inkView) {
+    _inkView = [[MDCInkView alloc] initWithFrame:self.bounds];
+    [self addSubview:_inkView];
+  }
+  return _inkView;
+}
+
+- (void)setInkView:(MDCInkView *)inkView {
+  if (inkView == _inkView) {
+    return;
+  }
+  if (_inkView) {
+    [_inkView removeFromSuperview];
+  }
+  if (inkView) {
+    [self addSubview:inkView];
+  }
+  _inkView = inkView;
+}
+
+#pragma mark - Separator
+
+- (void)setShouldHideSeparator:(BOOL)shouldHideSeparator {
+  _usesCellSeparatorHiddenOverride = YES;
+  _shouldHideSeparator = shouldHideSeparator;
+  [self drawSeparatorIfNeeded];
+}
+
+- (void)setSeparatorInset:(UIEdgeInsets)separatorInset {
+  _usesCellSeparatorInsetOverride = YES;
+  _separatorInset = separatorInset;
+  [self drawSeparatorIfNeeded];
+}
+
+- (void)drawSeparatorIfNeeded {
+  // Determine separator spec from attributes and cell overrides. Don't draw separator for bottom
+  // cell or in grid layout cells. Separators are added here as cell subviews instead of decoration
+  // views registered with the layout to overcome inability to animate decoration views in
+  // coordination with cell animations.
+  BOOL isHidden =
+      _usesCellSeparatorHiddenOverride ? _shouldHideSeparator : _attr.shouldHideSeparators;
+  UIEdgeInsets separatorInset =
+      _usesCellSeparatorInsetOverride ? _separatorInset : _attr.separatorInset;
+  BOOL isBottom = _attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalBottom;
+  BOOL isGrid = _attr.isGridLayout;
+
+  BOOL hideSeparator = isBottom || isHidden || isGrid;
+  if (hideSeparator != _separatorView.hidden) {
+    _separatorView.hidden = hideSeparator;
+  }
+
+  if (!hideSeparator) {
+    UIEdgeInsets insets = _attr.backgroundImageViewInsets;
+    // Compute the frame in LTR.
+    CGRect separatorFrame = CGRectMake(
+        insets.left, CGRectGetHeight(self.bounds) - _attr.separatorLineHeight,
+        CGRectGetWidth(self.bounds) - insets.left - insets.right, _attr.separatorLineHeight);
+    separatorFrame = UIEdgeInsetsInsetRect(separatorFrame, separatorInset);
+    _separatorView.frame = MDCRectFlippedForRTL(separatorFrame, CGRectGetWidth(self.bounds),
+                                                self.mdc_effectiveUserInterfaceLayoutDirection);
+    _separatorView.backgroundColor = _attr.separatorColor;
+  }
+}
+
+#pragma mark - Editing
+
+- (void)setEditing:(BOOL)editing {
+  [self setEditing:editing animated:NO];
+}
+
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
+  if (_editing == editing) {
+    return;
+  }
+  _shouldAnimateEditingViews = animated;
+  _editing = editing;
+  [self setNeedsLayout];
+  [self layoutIfNeeded];
+}
+
+- (void)updateInterfaceForEditing {
+  self.contentView.userInteractionEnabled = [self shouldEnableCellInteractions];
+
+  if (_editing) {
+    // Disable implicit animations when setting initial positioning of these subviews.
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+
+    // Create reorder editing controls.
+    if (_attr.shouldShowReorderStateMask) {
+      if (!_editingReorderImageView) {
+        UIImage *reorderImage = [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_reorder]];
+        reorderImage = [reorderImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+        _editingReorderImageView = [[UIImageView alloc] initWithImage:reorderImage];
+        _editingReorderImageView.tintColor = HEXCOLOR(kCellGrayColor);
+        _editingReorderImageView.autoresizingMask =
+            MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+        [self addSubview:_editingReorderImageView];
+      }
+      CGAffineTransform transform = _editingReorderImageView.transform;
+      _editingReorderImageView.transform = CGAffineTransformIdentity;
+      CGSize size = _editingReorderImageView.image.size;
+      CGRect frame =
+          CGRectMake(0, (CGRectGetHeight(self.bounds) - size.height) / 2, size.width, size.height);
+      _editingReorderImageView.frame = MDCRectFlippedForRTL(
+          frame, CGRectGetWidth(self.bounds), self.mdc_effectiveUserInterfaceLayoutDirection);
+      _editingReorderImageView.transform = transform;
+      _editingReorderImageView.alpha = 1.0f;
+    } else {
+      _editingReorderImageView.alpha = 0.0f;
+    }
+
+    // Create selector editing controls.
+    if (_attr.shouldShowSelectorStateMask) {
+      if (!_editingSelectorImageView) {
+        UIImage *selectorImage =
+            [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_radio_button_unchecked]];
+        selectorImage = [selectorImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+        _editingSelectorImageView = [[UIImageView alloc] initWithImage:selectorImage];
+        _editingSelectorImageView.tintColor = HEXCOLOR(kCellGrayColor);
+        _editingSelectorImageView.autoresizingMask =
+            MDCAutoresizingFlexibleLeadingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+        [self addSubview:_editingSelectorImageView];
+      }
+      CGAffineTransform transform = _editingSelectorImageView.transform;
+      _editingSelectorImageView.transform = CGAffineTransformIdentity;
+      CGSize size = _editingSelectorImageView.image.size;
+      CGFloat originX = CGRectGetWidth(self.bounds) - size.width;
+      CGFloat originY = (CGRectGetHeight(self.bounds) - size.height) / 2;
+      CGRect frame = (CGRect){{originX, originY}, size};
+      _editingSelectorImageView.frame = MDCRectFlippedForRTL(
+          frame, CGRectGetWidth(self.bounds), self.mdc_effectiveUserInterfaceLayoutDirection);
+      _editingSelectorImageView.transform = transform;
+      _editingSelectorImageView.alpha = 1.0f;
+    } else {
+      _editingSelectorImageView.alpha = 0.0f;
+    }
+    [CATransaction commit];
+  } else {
+    _editingReorderImageView.alpha = 0.0f;
+    _editingSelectorImageView.alpha = 0.0f;
+  }
+
+  // Update accessory view.
+  _accessoryView.alpha = _attr.shouldShowSelectorStateMask ? 0.0f : 1.0f;
+  _accessoryInset.right = _attr.shouldShowSelectorStateMask
+                              ? kAccessoryInsetDefault.right + kEditingControlAppearanceOffset
+                              : kAccessoryInsetDefault.right;
+}
+
+#pragma mark - Selecting
+
+- (void)setSelected:(BOOL)selected {
+  [super setSelected:selected];
+  if (selected) {
+    _editingSelectorImageView.image =
+        [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_check_circle]];
+    _editingSelectorImageView.tintColor = self.editingSelectorColor;
+    self.accessibilityTraits |= UIAccessibilityTraitSelected;
+  } else {
+    _editingSelectorImageView.image =
+        [UIImage imageWithContentsOfFile:[MDCIcons pathFor_ic_radio_button_unchecked]];
+    _editingSelectorImageView.tintColor = HEXCOLOR(kCellGrayColor);
+    self.accessibilityTraits &= ~UIAccessibilityTraitSelected;
+  }
+  _editingSelectorImageView.image =
+      [_editingSelectorImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+}
+
+- (void)setEditingSelectorColor:(UIColor *)editingSelectorColor {
+  if (editingSelectorColor == nil) {
+    editingSelectorColor = HEXCOLOR(kCellRedColor);
+  }
+  _editingSelectorColor = editingSelectorColor;
+}
+
+#pragma mark - Cell Appearance Animation
+
+- (void)updateAppearanceAnimation {
+  if (_attr.animateCellsOnAppearanceDelay > 0) {
+    // Intially hide content view and separator.
+    self.contentView.alpha = 0;
+    _separatorView.alpha = 0;
+
+    // Animate fade-in after delay.
+    if (!_attr.willAnimateCellsOnAppearance) {
+      [UIView animateWithDuration:_attr.animateCellsOnAppearanceDuration
+                            delay:_attr.animateCellsOnAppearanceDelay
+                          options:UIViewAnimationOptionCurveEaseOut
+                       animations:^{
+                         self.contentView.alpha = 1;
+                         _separatorView.alpha = 1;
+                       }
+                       completion:nil];
+    }
+  }
+}
+
+#pragma mark - RTL
+
+- (void)mdc_setSemanticContentAttribute:(UISemanticContentAttribute)mdc_semanticContentAttribute {
+  [super mdc_setSemanticContentAttribute:mdc_semanticContentAttribute];
+  // Reload the accessory type image if there is one.
+  if ([_accessoryView isKindOfClass:[MDCAccessoryTypeImageView class]]) {
+    self.accessoryType = self.accessoryType;
+  }
+}
+
+#pragma mark - Accessibility
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  UIAccessibilityTraits accessibilityTraits = [super accessibilityTraits];
+  if (self.accessoryType == MDCCollectionViewCellAccessoryCheckmark) {
+    accessibilityTraits |= UIAccessibilityTraitSelected;
+  }
+  return accessibilityTraits;
+}
+
+- (NSString *)accessibilityHint {
+  if (_attr.shouldShowSelectorStateMask) {
+    NSString *localizedHintKey =
+        self.selected ? kSelectedCellAccessibilityHintKey : kDeselectedCellAccessibilityHintKey;
+    return [[self class] localizedStringWithKey:localizedHintKey];
+  }
+  return nil;
+}
+
+#pragma mark - Private
+
++ (NSString *)localizedStringWithKey:(NSString *)key {
+  NSBundle *containingBundle = [NSBundle bundleForClass:self];
+  NSURL *resourceBundleURL =
+      [containingBundle URLForResource:kResourceBundleName withExtension:@"bundle"];
+  NSBundle *resourceBundle = [NSBundle bundleWithURL:resourceBundleURL];
+  return [resourceBundle localizedStringForKey:key value:nil table:kStringTableName];
+}
+
+- (CGRect)contentViewFrame {
+  CGFloat leadingPadding =
+      _attr.shouldShowReorderStateMask
+          ? CGRectGetWidth(_editingReorderImageView.bounds) + kEditingControlAppearanceOffset
+          : 0.f;
+
+  CGFloat accessoryViewPadding =
+      _accessoryView ? CGRectGetWidth(self.bounds) - CGRectGetMinX(_accessoryView.frame) : 0;
+  CGFloat trailingPadding =
+      _attr.shouldShowSelectorStateMask
+          ? CGRectGetWidth(_editingSelectorImageView.bounds) + kEditingControlAppearanceOffset
+          : accessoryViewPadding;
+  UIEdgeInsets insets = UIEdgeInsetsMake(0, leadingPadding, 0, trailingPadding);
+  return UIEdgeInsetsInsetRect(self.bounds, insets);
+}
+
+- (BOOL)shouldEnableCellInteractions {
+  return !_editing || _allowsCellInteractionsWhileEditing;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
new file mode 100644
index 0000000..039747a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.h
@@ -0,0 +1,75 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewCell.h"
+
+/** Default cell height for single line of text. Defaults to 48.0f. */
+extern const CGFloat MDCCellDefaultOneLineHeight;
+
+/** Default cell height for single line of text with avatar. Defaults to 56.0f. */
+extern const CGFloat MDCCellDefaultOneLineWithAvatarHeight;
+
+/** Default cell height for two lines of text. Defaults to 72.0f. */
+extern const CGFloat MDCCellDefaultTwoLineHeight;
+
+/** Default cell height for three lines of text. Defaults to 88.0f. */
+extern const CGFloat MDCCellDefaultThreeLineHeight;
+
+/**
+ The MDCCollectionViewTextCell class provides an implementation of UICollectionViewCell that
+ supports Material Design layout and styling. It provides two labels for text as well as an
+ image view. The default layout specifications can be found at the following link.
+
+ @see http://www.google.com/design/spec/components/lists.html#lists-specs
+ */
+@interface MDCCollectionViewTextCell : MDCCollectionViewCell
+
+/**
+ A text label. Typically this will be the first line of text in the cell.
+
+ Default text label properties:
+  - text            defaults to nil.
+  - font            defaults to [MDCTypography subheadFont].
+  - textColor       defaults to [UIColor colorWithWhite:0 alpha:MDCTypography subheadFontOpacity]].
+  - shadowColor     defaults to nil.
+  - shadowOffset    defaults to CGSizeZero.
+  - textAlignment   defaults to NSTextAlignmentNatural.
+  - lineBreakMode   defaults to NSLineBreakByTruncatingTail.
+  - numberOfLines   defaults to 1.
+ */
+@property(nonatomic, readonly, strong, nullable) UILabel *textLabel;
+
+/**
+ A detail text label. Typically this will be the second line of text in the cell.
+
+ Default detail text label properties:
+ - text            defaults to nil.
+ - font            defaults to [MDCTypography body1Font].
+ - textColor       defaults to [UIColor colorWithWhite:0 alpha:MDCTypography captionFontOpacity]].
+ - shadowColor     defaults to nil.
+ - shadowOffset    defaults to CGSizeZero.
+ - textAlignment   defaults to NSTextAlignmentNatural.
+ - lineBreakMode   defaults to NSLineBreakByTruncatingTail.
+ - numberOfLines   defaults to 1.
+ */
+@property(nonatomic, readonly, strong, nullable) UILabel *detailTextLabel;
+
+/**
+ An image view on the leading side of cell. Default leading padding is 16.0f.
+ */
+@property(nonatomic, readonly, strong, nullable) UIImageView *imageView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.m
new file mode 100644
index 0000000..fea883b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MDCCollectionViewTextCell.m
@@ -0,0 +1,254 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewTextCell.h"
+
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+#import <tgmath.h>
+
+// Default cell heights.
+const CGFloat MDCCellDefaultOneLineHeight = 48.0f;
+const CGFloat MDCCellDefaultOneLineWithAvatarHeight = 56.0f;
+const CGFloat MDCCellDefaultTwoLineHeight = 72.0f;
+const CGFloat MDCCellDefaultThreeLineHeight = 88.0f;
+
+// Default cell fonts.
+#define kCellDefaultTextFont [MDCTypography subheadFont]
+#define kCellDefaultDetailTextFont [MDCTypography body1Font]
+
+// Default cell font opacity.
+#define kCellDefaultTextOpacity [MDCTypography subheadFontOpacity]
+#define kCellDefaultDetailTextFontOpacity [MDCTypography captionFontOpacity]
+
+// Cell padding top/bottom.
+static const CGFloat kCellTwoLinePaddingTop = 20;
+static const CGFloat kCellTwoLinePaddingBottom = 20;
+static const CGFloat kCellThreeLinePaddingTop = 16;
+static const CGFloat kCellThreeLinePaddingBottom = 20;
+// Cell padding leading/trailing.
+static const CGFloat kCellTextNoImagePaddingLeading = 16;
+static const CGFloat kCellTextNoImagePaddingTrailing = 16;
+static const CGFloat kCellTextWithImagePaddingLeading = 72;
+// Cell image view padding.
+static const CGFloat kCellImagePaddingLeading = 16;
+
+static inline CGFloat Ceil(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return ceil(value);
+#else
+  return ceilf(value);
+#endif
+}
+
+static inline CGFloat Floor(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return floor(value);
+#else
+  return floorf(value);
+#endif
+}
+
+// Returns the closest pixel-aligned value higher than |value|, taking the scale factor into
+// account. At a scale of 1, equivalent to Ceil().
+static inline CGFloat AlignValueToUpperPixel(CGFloat value) {
+  CGFloat scale = [[UIScreen mainScreen] scale];
+  return (CGFloat)Ceil(value * scale) / scale;
+}
+
+// Returns the closest pixel-aligned value lower than |value|, taking the scale factor into
+// account. At a scale of 1, equivalent to Floor().
+static inline CGFloat AlignValueToLowerPixel(CGFloat value) {
+  CGFloat scale = [[UIScreen mainScreen] scale];
+  return (CGFloat)Floor(value * scale) / scale;
+}
+
+// Returns the rect resulting from applying AlignSizeToUpperPixel to the rect size.
+static inline CGRect AlignRectToUpperPixel(CGRect rect) {
+  rect = CGRectStandardize(rect);
+  return CGRectMake(AlignValueToLowerPixel(rect.origin.x), AlignValueToLowerPixel(rect.origin.y),
+                    AlignValueToUpperPixel(rect.size.width),
+                    AlignValueToUpperPixel(rect.size.height));
+}
+
+@implementation MDCCollectionViewTextCell {
+  UIView *_contentWrapper;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionViewTextCellInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionViewTextCellInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionViewTextCellInit {
+  _contentWrapper = [[UIView alloc] initWithFrame:self.contentView.bounds];
+  _contentWrapper.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth |
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  _contentWrapper.clipsToBounds = YES;
+  [self.contentView addSubview:_contentWrapper];
+
+  // Text label.
+  _textLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  _textLabel.font = kCellDefaultTextFont;
+  _textLabel.textColor = [UIColor colorWithWhite:0 alpha:kCellDefaultTextOpacity];
+  _textLabel.shadowColor = nil;
+  _textLabel.shadowOffset = CGSizeZero;
+  _textLabel.textAlignment = NSTextAlignmentNatural;
+  _textLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+  _textLabel.autoresizingMask =
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  [_contentWrapper addSubview:_textLabel];
+
+  // Detail text label.
+  _detailTextLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  _detailTextLabel.font = kCellDefaultDetailTextFont;
+  _detailTextLabel.textColor = [UIColor colorWithWhite:0 alpha:kCellDefaultDetailTextFontOpacity];
+  _detailTextLabel.shadowColor = nil;
+  _detailTextLabel.shadowOffset = CGSizeZero;
+  _detailTextLabel.textAlignment = NSTextAlignmentNatural;
+  _detailTextLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+  _detailTextLabel.autoresizingMask =
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  [_contentWrapper addSubview:_detailTextLabel];
+
+  // Image view.
+  _imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
+  _imageView.autoresizingMask =
+      MDCAutoresizingFlexibleTrailingMargin(self.mdc_effectiveUserInterfaceLayoutDirection);
+  [self.contentView addSubview:_imageView];
+}
+
+#pragma mark - Layout
+
+- (void)prepareForReuse {
+  _imageView.image = nil;
+
+  [super prepareForReuse];
+  [self setNeedsLayout];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  [self applyMetrics];
+}
+
+- (CGRect)contentWrapperFrame {
+  CGFloat leadingPadding =
+      _imageView.image ? kCellTextWithImagePaddingLeading : kCellTextNoImagePaddingLeading;
+  CGFloat trailingPadding = kCellTextNoImagePaddingTrailing;
+  UIEdgeInsets insets = MDCInsetsMakeWithLayoutDirection(
+      0, leadingPadding, 0, trailingPadding, self.mdc_effectiveUserInterfaceLayoutDirection);
+  return UIEdgeInsetsInsetRect(self.contentView.bounds, insets);
+}
+
+- (void)applyMetrics {
+  // Set content wrapper frame.
+  _contentWrapper.frame = [self contentWrapperFrame];
+  CGFloat boundsHeight = CGRectGetHeight(_contentWrapper.bounds);
+
+  // Image layout.
+  [_imageView sizeToFit];
+  CGRect imageFrame = _imageView.frame;
+  imageFrame.origin.x = kCellImagePaddingLeading;
+  imageFrame.origin.y =
+      (CGRectGetHeight(self.contentView.frame) / 2) - (imageFrame.size.height / 2);
+
+  // Text layout.
+  CGRect textFrame = CGRectZero;
+  textFrame.size = [self frameSizeForLabel:_textLabel];
+  CGRect detailFrame = CGRectZero;
+  detailFrame.size = [self frameSizeForLabel:_detailTextLabel];
+
+  // Adjust the labels X origin.
+  textFrame.origin.x = 0;
+  detailFrame.origin.x = 0;
+
+  // Adjust the labels Y origin.
+  if ([self numberOfAllVisibleTextLines] == 1) {
+    // Alignment for single line.
+    textFrame.origin.y = (boundsHeight / 2) - (textFrame.size.height / 2);
+    detailFrame.origin.y = (boundsHeight / 2) - (detailFrame.size.height / 2);
+
+  } else if ([self numberOfAllVisibleTextLines] == 2) {
+    if (!CGRectIsEmpty(textFrame) && !CGRectIsEmpty(detailFrame)) {
+      // Alignment for two lines.
+      textFrame.origin.y =
+          kCellTwoLinePaddingTop + _textLabel.font.ascender - textFrame.size.height;
+      detailFrame.origin.y = boundsHeight - kCellTwoLinePaddingBottom - detailFrame.size.height -
+                             _detailTextLabel.font.descender;
+    } else {
+      // Since single wrapped label, just center.
+      textFrame.origin.y = (boundsHeight / 2) - (textFrame.size.height / 2);
+      detailFrame.origin.y = (boundsHeight / 2) - (detailFrame.size.height / 2);
+    }
+
+  } else if ([self numberOfAllVisibleTextLines] == 3) {
+    if (!CGRectIsEmpty(textFrame) && !CGRectIsEmpty(detailFrame)) {
+      // Alignment for three lines.
+      textFrame.origin.y =
+          kCellThreeLinePaddingTop + _textLabel.font.ascender - _textLabel.font.lineHeight;
+      detailFrame.origin.y = boundsHeight - kCellThreeLinePaddingBottom - detailFrame.size.height -
+                             _detailTextLabel.font.descender;
+      imageFrame.origin.y = kCellThreeLinePaddingTop;
+    } else {
+      // Since single wrapped label, just center.
+      textFrame.origin.y = (boundsHeight / 2) - (textFrame.size.height / 2);
+      detailFrame.origin.y = (boundsHeight / 2) - (detailFrame.size.height / 2);
+    }
+  }
+  _textLabel.frame =
+      MDCRectFlippedForRTL(AlignRectToUpperPixel(textFrame), CGRectGetWidth(_contentWrapper.bounds),
+                           self.mdc_effectiveUserInterfaceLayoutDirection);
+  _detailTextLabel.frame = MDCRectFlippedForRTL(AlignRectToUpperPixel(detailFrame),
+                                                CGRectGetWidth(_contentWrapper.bounds),
+                                                self.mdc_effectiveUserInterfaceLayoutDirection);
+  _imageView.frame = MDCRectFlippedForRTL(AlignRectToUpperPixel(imageFrame),
+                                          CGRectGetWidth(self.contentView.bounds),
+                                          self.mdc_effectiveUserInterfaceLayoutDirection);
+}
+
+- (NSInteger)numberOfAllVisibleTextLines {
+  return [self numberOfLinesForLabel:_textLabel] + [self numberOfLinesForLabel:_detailTextLabel];
+}
+
+- (NSInteger)numberOfLinesForLabel:(UILabel *)label {
+  CGSize size = [self frameSizeForLabel:label];
+  return (NSInteger)floor(size.height / label.font.lineHeight);
+}
+
+- (CGSize)frameSizeForLabel:(UILabel *)label {
+  CGFloat width = MIN(CGRectGetWidth(_contentWrapper.bounds),
+                      [label.text sizeWithAttributes:@{NSFontAttributeName : label.font}].width);
+  CGFloat height =
+      [label textRectForBounds:_contentWrapper.bounds limitedToNumberOfLines:label.numberOfLines]
+          .size.height;
+  return CGSizeMake(width, height);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle/Resources/en.lproj/MaterialCollectionCells.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle/Resources/en.lproj/MaterialCollectionCells.strings
new file mode 100644
index 0000000..ce3a9f5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle/Resources/en.lproj/MaterialCollectionCells.strings
@@ -0,0 +1,5 @@
+/* Accessibility hint for selected cells in edit mode. */
+"MaterialCollectionCellsAccessibilitySelectedHint" = "Double tap to deselect.";
+
+/* Accessibility hint for deselected cells in edit mode. */
+"MaterialCollectionCellsAccessibilityDeselectedHint" = "Double tap to select.";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
new file mode 100644
index 0000000..9a0e565
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewCell.h"
+#import "MDCCollectionViewTextCell.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
new file mode 100644
index 0000000..311c16d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h
@@ -0,0 +1,118 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Types of cell ordinal positions available within a collectionView. */
+typedef NS_OPTIONS(NSUInteger, MDCCollectionViewOrdinalPosition) {
+  /** Cell visually has top edge within section. */
+  MDCCollectionViewOrdinalPositionVerticalTop = 1 << 0,
+
+  /** Cell visually has no top/bottom edges within section. */
+  MDCCollectionViewOrdinalPositionVerticalCenter = 1 << 1,
+
+  /** Cell visually has bottom edge within section. */
+  MDCCollectionViewOrdinalPositionVerticalBottom = 1 << 2,
+
+  /**
+   Cell visually has both bottom/top edges within section. Typically for a single or inlaid cell.
+   */
+  MDCCollectionViewOrdinalPositionVerticalTopBottom =
+      (MDCCollectionViewOrdinalPositionVerticalTop |
+       MDCCollectionViewOrdinalPositionVerticalBottom),
+
+  /** Cell visually has left edge within section. */
+  MDCCollectionViewOrdinalPositionHorizontalLeft = 1 << 10,
+
+  /** Cell visually has no left/right edges within section. */
+  MDCCollectionViewOrdinalPositionHorizontalCenter = 1 << 11,
+
+  /** Cell visually has right edge within section. */
+  MDCCollectionViewOrdinalPositionHorizontalRight = 1 << 12
+};
+
+/**
+ The MDCCollectionViewLayoutAttributes class allows passing layout attributes to the cells and
+ supplementary views.
+ */
+@interface MDCCollectionViewLayoutAttributes : UICollectionViewLayoutAttributes <NSCopying>
+
+#pragma mark - Cell Styling
+
+/** A boolean value indicating whether the collectionView is being edited. Defaults to NO. */
+@property(nonatomic, getter=isEditing) BOOL editing;
+
+/**
+ A boolean value indicating whether the collectionView cell should be displayed with reorder
+ state mask. Defaults to NO.
+ */
+@property(nonatomic, assign) BOOL shouldShowReorderStateMask;
+
+/**
+ A boolean value indicating whether the collectionView cell should be displayed with selector
+ state mask. Defaults to NO.
+ */
+@property(nonatomic, assign) BOOL shouldShowSelectorStateMask;
+
+/**
+ A Boolean value indicating whether the collection view cell should allow the grid background
+ decoration view to be drawn at the specified index.
+ */
+@property(nonatomic, assign) BOOL shouldShowGridBackground;
+
+/** The image for use as the cells background image. */
+@property(nonatomic, strong, nullable) UIImage *backgroundImage;
+
+/** The background image view edge insets. */
+@property(nonatomic) UIEdgeInsets backgroundImageViewInsets;
+
+/**
+ A boolean value indicating whether the collectionView cell style is set to
+ MDCCollectionViewCellLayoutTypeGrid.
+ */
+@property(nonatomic, assign) BOOL isGridLayout;
+
+/** The ordinal position within the collectionView section. */
+@property(nonatomic, assign) MDCCollectionViewOrdinalPosition sectionOrdinalPosition;
+
+#pragma mark - Cell Separator
+
+/** Separator color. Defaults to #E0E0E0. */
+@property(nonatomic, strong, nullable) UIColor *separatorColor;
+
+/** Separator inset. Defaults to UIEdgeInsetsZero. */
+@property(nonatomic) UIEdgeInsets separatorInset;
+
+/** Separator line height. Defaults to 1.0f */
+@property(nonatomic) CGFloat separatorLineHeight;
+
+/** Whether to hide the cell separators. Defaults to NO. */
+@property(nonatomic) BOOL shouldHideSeparators;
+
+#pragma mark - Cell Appearance Animation
+
+/** Whether cells will animation on appearance. */
+@property(nonatomic, assign) BOOL willAnimateCellsOnAppearance;
+
+/**
+ The cell appearance animation duration. Defaults to MDCCollectionViewAnimatedAppearanceDuration.
+ */
+@property(nonatomic, assign) NSTimeInterval animateCellsOnAppearanceDuration;
+
+/** The cell delay used to stagger fade-in during appearance animation. Defaults to 0. */
+@property(nonatomic, assign) NSTimeInterval animateCellsOnAppearanceDelay;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m
new file mode 100644
index 0000000..bdb1d94
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m
@@ -0,0 +1,93 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewLayoutAttributes.h"
+
+@implementation MDCCollectionViewLayoutAttributes
+
+- (id)copyWithZone:(NSZone *)zone {
+  MDCCollectionViewLayoutAttributes *attributes =
+      (MDCCollectionViewLayoutAttributes *)[super copyWithZone:zone];
+  attributes->_editing = _editing;
+  attributes->_shouldShowReorderStateMask = _shouldShowReorderStateMask;
+  attributes->_shouldShowSelectorStateMask = _shouldShowSelectorStateMask;
+  attributes->_shouldShowGridBackground = _shouldShowGridBackground;
+  attributes->_sectionOrdinalPosition = _sectionOrdinalPosition;
+  attributes->_backgroundImage = _backgroundImage;
+  attributes->_backgroundImageViewInsets = _backgroundImageViewInsets;
+  attributes->_isGridLayout = _isGridLayout;
+  attributes->_separatorColor = _separatorColor;
+  attributes->_separatorInset = _separatorInset;
+  attributes->_separatorLineHeight = _separatorLineHeight;
+  attributes->_shouldHideSeparators = _shouldHideSeparators;
+  attributes->_willAnimateCellsOnAppearance = _willAnimateCellsOnAppearance;
+  attributes->_animateCellsOnAppearanceDuration = _animateCellsOnAppearanceDuration;
+  attributes->_animateCellsOnAppearanceDelay = _animateCellsOnAppearanceDelay;
+  return attributes;
+}
+
+- (BOOL)isEqual:(id)object {
+  if (object == self) {
+    return YES;
+  }
+  if (!object || ![[object class] isEqual:[self class]]) {
+    return NO;
+  }
+
+  // Compare custom properties that affect layout.
+  MDCCollectionViewLayoutAttributes *otherAttrs = (MDCCollectionViewLayoutAttributes *)object;
+  BOOL backgroundImageIdentity = NO;
+  if (self.backgroundImage && otherAttrs.backgroundImage) {
+    backgroundImageIdentity = [self.backgroundImage isEqual:otherAttrs.backgroundImage];
+  } else if (!self.backgroundImage && !otherAttrs.backgroundImage) {
+    backgroundImageIdentity = YES;
+  }
+
+  BOOL separatorColorIdentity = NO;
+  if (self.separatorColor && otherAttrs.separatorColor) {
+    separatorColorIdentity = [self.separatorColor isEqual:otherAttrs.separatorColor];
+  } else if (!self.separatorColor && !otherAttrs.separatorColor) {
+    separatorColorIdentity = YES;
+  }
+
+  if ((otherAttrs.editing != self.editing) ||
+      (otherAttrs.shouldShowReorderStateMask != self.shouldShowReorderStateMask) ||
+      (otherAttrs.shouldShowSelectorStateMask != self.shouldShowSelectorStateMask) ||
+      (otherAttrs.shouldShowGridBackground != self.shouldShowGridBackground) ||
+      (otherAttrs.sectionOrdinalPosition != self.sectionOrdinalPosition) ||
+      !backgroundImageIdentity ||
+      (!UIEdgeInsetsEqualToEdgeInsets(otherAttrs.backgroundImageViewInsets,
+                                      self.backgroundImageViewInsets)) ||
+      (otherAttrs.isGridLayout != self.isGridLayout) || !separatorColorIdentity ||
+      (!UIEdgeInsetsEqualToEdgeInsets(otherAttrs.separatorInset, self.separatorInset)) ||
+      (otherAttrs.separatorLineHeight != self.separatorLineHeight) ||
+      (otherAttrs.shouldHideSeparators != self.shouldHideSeparators) ||
+      (!CGRectEqualToRect(otherAttrs.frame, self.frame))) {
+    return NO;
+  }
+
+  return [super isEqual:object];
+}
+
+- (NSUInteger)hash {
+  return (NSUInteger)self.editing ^ (NSUInteger)self.shouldShowReorderStateMask ^
+         (NSUInteger)self.shouldShowSelectorStateMask ^ (NSUInteger)self.shouldShowGridBackground ^
+         (NSUInteger)self.sectionOrdinalPosition ^ (NSUInteger)self.backgroundImage ^
+         (NSUInteger)self.isGridLayout ^ (NSUInteger)self.separatorColor ^
+         (NSUInteger)self.separatorLineHeight ^ (NSUInteger)self.shouldHideSeparators;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
new file mode 100644
index 0000000..a423edb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewLayoutAttributes.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.h
new file mode 100644
index 0000000..d61c50b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.h
@@ -0,0 +1,77 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCCollectionViewEditing.h"
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MDCCollectionViewStyling.h"
+#import "MDCCollectionViewStylingDelegate.h"
+
+/**
+ Controller that implements a collection view that adheres to Material Design layout
+ and animation styling.
+ */
+@interface MDCCollectionViewController : UICollectionViewController <
+                                             /** Allows for editing notifications/permissions. */
+                                             MDCCollectionViewEditingDelegate,
+
+                                             /** Allows for styling updates. */
+                                             MDCCollectionViewStylingDelegate,
+
+                                             /** Adheres to flow layout. */
+                                             UICollectionViewDelegateFlowLayout>
+
+/** The collection view styler. */
+@property(nonatomic, strong, readonly, nonnull) id<MDCCollectionViewStyling> styler;
+
+/** The collection view editor. */
+@property(nonatomic, strong, readonly, nonnull) id<MDCCollectionViewEditing> editor;
+
+#pragma mark - Subclassing
+
+/**
+ The following methods require a call to super in their overriding implementations to allow
+ this collection view controller to properly configure the collection view when in editing mode
+ as well as ink during the highlight/unhighlight states.
+ */
+
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didHighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didUnhighlightItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldDeselectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didSelectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didDeselectItemAtIndexPath:(nonnull NSIndexPath *)indexPath NS_REQUIRES_SUPER;
+
+- (void)collectionViewWillBeginEditing:(nonnull UICollectionView *)collectionView NS_REQUIRES_SUPER;
+
+- (void)collectionViewWillEndEditing:(nonnull UICollectionView *)collectionView NS_REQUIRES_SUPER;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.m
new file mode 100644
index 0000000..76e5585
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewController.m
@@ -0,0 +1,601 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewController.h"
+
+#import "MDCCollectionViewFlowLayout.h"
+#import "MaterialCollectionCells.h"
+#import "MaterialInk.h"
+#import "private/MDCCollectionInfoBarView.h"
+#import "private/MDCCollectionStringResources.h"
+#import "private/MDCCollectionViewEditor.h"
+#import "private/MDCCollectionViewStyler.h"
+
+#import <tgmath.h>
+
+@interface MDCCollectionViewController () <MDCCollectionInfoBarViewDelegate,
+                                           MDCInkTouchControllerDelegate>
+@property(nonatomic, assign) BOOL currentlyActiveInk;
+@end
+
+@implementation MDCCollectionViewController {
+  MDCInkTouchController *_inkTouchController;
+  MDCCollectionInfoBarView *_headerInfoBar;
+  MDCCollectionInfoBarView *_footerInfoBar;
+  BOOL _headerInfoBarDismissed;
+  CGPoint _inkTouchLocation;
+}
+
+@synthesize collectionViewLayout = _collectionViewLayout;
+
+- (instancetype)init {
+  return [self initWithCollectionViewLayout:self.collectionViewLayout];
+}
+
+- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout {
+  self = [super initWithCollectionViewLayout:layout];
+  if (self) {
+    _collectionViewLayout = layout;
+  }
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  [self.collectionView setCollectionViewLayout:self.collectionViewLayout];
+  self.collectionView.backgroundColor = [UIColor whiteColor];
+  self.collectionView.alwaysBounceVertical = YES;
+
+  _styler = [[MDCCollectionViewStyler alloc] initWithCollectionView:self.collectionView];
+  _styler.delegate = self;
+
+  _editor = [[MDCCollectionViewEditor alloc] initWithCollectionView:self.collectionView];
+  _editor.delegate = self;
+
+  // Set up ink touch controller.
+  _inkTouchController = [[MDCInkTouchController alloc] initWithView:self.collectionView];
+  _inkTouchController.delegate = self;
+}
+
+- (UICollectionViewLayout *)collectionViewLayout {
+  if (!_collectionViewLayout) {
+    _collectionViewLayout = [[MDCCollectionViewFlowLayout alloc] init];
+  }
+  return _collectionViewLayout;
+}
+
+- (void)setCollectionView:(__kindof UICollectionView *)collectionView {
+  [super setCollectionView:collectionView];
+
+  // Reset editor and ink to provided collection view.
+  _editor = [[MDCCollectionViewEditor alloc] initWithCollectionView:collectionView];
+  _editor.delegate = self;
+  _inkTouchController = [[MDCInkTouchController alloc] initWithView:collectionView];
+  _inkTouchController.delegate = self;
+}
+
+#pragma mark - <MDCCollectionInfoBarViewDelegate>
+
+- (void)updateControllerWithInfoBar:(MDCCollectionInfoBarView *)infoBar {
+  // Updates info bar styling for header/footer.
+  if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+    _headerInfoBar = infoBar;
+    _headerInfoBar.message = MDCCollectionStringResources(infoBarGestureHintString);
+    _headerInfoBar.style = MDCCollectionInfoBarViewStyleHUD;
+    [self updateHeaderInfoBarIfNecessary];
+  } else if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+    _footerInfoBar = infoBar;
+    _footerInfoBar.message = MDCCollectionStringResources(deleteButtonString);
+    _footerInfoBar.style = MDCCollectionInfoBarViewStyleActionable;
+    [self updateFooterInfoBarIfNecessary];
+  }
+}
+
+- (void)didTapInfoBar:(MDCCollectionInfoBarView *)infoBar {
+  if ([infoBar isEqual:_footerInfoBar]) {
+    [self deleteIndexPaths:self.collectionView.indexPathsForSelectedItems];
+  }
+}
+
+- (void)infoBar:(MDCCollectionInfoBarView *)infoBar
+    willShowAnimated:(BOOL)animated
+     willAutoDismiss:(BOOL)willAutoDismiss {
+  if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+    [self updateContentWithBottomInset:MDCCollectionInfoBarFooterHeight];
+  }
+}
+
+- (void)infoBar:(MDCCollectionInfoBarView *)infoBar
+    willDismissAnimated:(BOOL)animated
+        willAutoDismiss:(BOOL)willAutoDismiss {
+  if ([infoBar.kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+    _headerInfoBarDismissed = willAutoDismiss;
+  } else {
+    [self updateContentWithBottomInset:-MDCCollectionInfoBarFooterHeight];
+  }
+}
+
+#pragma mark - <MDCCollectionViewStylingDelegate>
+
+- (MDCCollectionViewCellStyle)collectionView:(UICollectionView *)collectionView
+                         cellStyleForSection:(NSInteger)section {
+  return _styler.cellStyle;
+}
+
+#pragma mark - <UICollectionViewDelegateFlowLayout>
+
+- (CGSize)collectionView:(UICollectionView *)collectionView
+                    layout:(UICollectionViewLayout *)collectionViewLayout
+    sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
+  CGSize size = [self sizeWithAttribute:attr];
+  size = [self inlaidSizeAtIndexPath:indexPath withSize:size];
+  return size;
+}
+
+- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
+                        layout:(UICollectionViewLayout *)collectionViewLayout
+        insetForSectionAtIndex:(NSInteger)section {
+  return [self insetsAtSectionIndex:section];
+}
+
+- (CGFloat)collectionView:(UICollectionView *)collectionView
+                                 layout:(UICollectionViewLayout *)collectionViewLayout
+    minimumLineSpacingForSectionAtIndex:(NSInteger)section {
+  if ([collectionViewLayout isKindOfClass:[UICollectionViewFlowLayout class]]) {
+    if (_styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+      return _styler.gridPadding;
+    }
+    return [(UICollectionViewFlowLayout *)collectionViewLayout minimumLineSpacing];
+  }
+  return 0;
+}
+
+- (CGSize)sizeWithAttribute:(UICollectionViewLayoutAttributes *)attr {
+  CGFloat height = MDCCellDefaultOneLineHeight;
+  if ([_styler.delegate respondsToSelector:@selector(collectionView:cellHeightAtIndexPath:)]) {
+    height =
+        [_styler.delegate collectionView:self.collectionView cellHeightAtIndexPath:attr.indexPath];
+  }
+
+  CGFloat width = [self cellWidthAtSectionIndex:attr.indexPath.section];
+  return CGSizeMake(width, height);
+}
+
+- (CGFloat)cellWidthAtSectionIndex:(NSInteger)section {
+  CGFloat bounds = CGRectGetWidth(
+      UIEdgeInsetsInsetRect(self.collectionView.bounds, self.collectionView.contentInset));
+  UIEdgeInsets sectionInsets = [self insetsAtSectionIndex:section];
+  CGFloat insets = sectionInsets.left + sectionInsets.right;
+  if (_styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    CGFloat cellWidth = bounds - insets - (_styler.gridPadding * (_styler.gridColumnCount - 1));
+    return cellWidth / _styler.gridColumnCount;
+  }
+  return bounds - insets;
+}
+
+- (UIEdgeInsets)insetsAtSectionIndex:(NSInteger)section {
+  // Determine insets based on cell style.
+  CGFloat inset = (CGFloat)floor(MDCCollectionViewCellStyleCardSectionInset);
+  UIEdgeInsets insets = UIEdgeInsetsZero;
+  NSInteger numberOfSections = self.collectionView.numberOfSections;
+  BOOL isTop = (section == 0);
+  BOOL isBottom = (section == numberOfSections - 1);
+  MDCCollectionViewCellStyle cellStyle = [_styler cellStyleAtSectionIndex:section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  // Set left/right insets.
+  if (isCardStyle) {
+    insets.left = inset;
+    insets.right = inset;
+  }
+  // Set top/bottom insets.
+  if (isCardStyle || isGroupedStyle) {
+    insets.top = (CGFloat)floor((isTop) ? inset : inset / 2.0f);
+    insets.bottom = (CGFloat)floor((isBottom) ? inset : inset / 2.0f);
+  }
+  return insets;
+}
+
+- (CGSize)inlaidSizeAtIndexPath:(NSIndexPath *)indexPath withSize:(CGSize)size {
+  // If object is inlaid, return its adjusted size.
+  UICollectionView *collectionView = self.collectionView;
+  if ([_styler isItemInlaidAtIndexPath:indexPath]) {
+    CGFloat inset = MDCCollectionViewCellStyleCardSectionInset;
+    UIEdgeInsets inlayInsets = UIEdgeInsetsZero;
+    BOOL prevCellIsInlaid = NO;
+    BOOL nextCellIsInlaid = NO;
+
+    BOOL hasSectionHeader = NO;
+    if ([self
+            respondsToSelector:@selector(collectionView:layout:referenceSizeForHeaderInSection:)]) {
+      CGSize headerSize = [self collectionView:collectionView
+                                        layout:_collectionViewLayout
+               referenceSizeForHeaderInSection:indexPath.section];
+      hasSectionHeader = !CGSizeEqualToSize(headerSize, CGSizeZero);
+    }
+
+    BOOL hasSectionFooter = NO;
+    if ([self
+            respondsToSelector:@selector(collectionView:layout:referenceSizeForFooterInSection:)]) {
+      CGSize footerSize = [self collectionView:collectionView
+                                        layout:_collectionViewLayout
+               referenceSizeForFooterInSection:indexPath.section];
+      hasSectionFooter = !CGSizeEqualToSize(footerSize, CGSizeZero);
+    }
+
+    // Check if previous cell is inlaid.
+    if (indexPath.item > 0 || hasSectionHeader) {
+      NSIndexPath *prevIndexPath =
+          [NSIndexPath indexPathForItem:(indexPath.item - 1) inSection:indexPath.section];
+      prevCellIsInlaid = [_styler isItemInlaidAtIndexPath:prevIndexPath];
+      inlayInsets.top = prevCellIsInlaid ? inset / 2 : inset;
+    }
+
+    // Check if next cell is inlaid.
+    if (indexPath.item < [collectionView numberOfItemsInSection:indexPath.section] - 1 ||
+        hasSectionFooter) {
+      NSIndexPath *nextIndexPath =
+          [NSIndexPath indexPathForItem:(indexPath.item + 1) inSection:indexPath.section];
+      nextCellIsInlaid = [_styler isItemInlaidAtIndexPath:nextIndexPath];
+      inlayInsets.bottom = nextCellIsInlaid ? inset / 2 : inset;
+    }
+
+    // Apply top/bottom height adjustments to inlaid object.
+    size.height += inlayInsets.top + inlayInsets.bottom;
+  }
+  return size;
+}
+
+#pragma mark - <MDCInkTouchControllerDelegate>
+
+- (BOOL)inkTouchController:(MDCInkTouchController *)inkTouchController
+    shouldProcessInkTouchesAtTouchLocation:(CGPoint)location {
+  // Only store touch location and do not allow ink processing. This ink location will be used when
+  // manually starting/stopping the ink animation during cell highlight/unhighlight states.
+  if (!self.currentlyActiveInk) {
+    _inkTouchLocation = location;
+  }
+  return NO;
+}
+
+- (MDCInkView *)inkTouchController:(MDCInkTouchController *)inkTouchController
+            inkViewAtTouchLocation:(CGPoint)location {
+  NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:location];
+  UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
+  MDCInkView *ink = nil;
+
+  if ([_styler.delegate
+          respondsToSelector:@selector(collectionView:inkTouchController:inkViewAtIndexPath:)]) {
+    return [_styler.delegate collectionView:self.collectionView
+                         inkTouchController:inkTouchController
+                         inkViewAtIndexPath:indexPath];
+  }
+  if ([cell isKindOfClass:[MDCCollectionViewCell class]]) {
+    MDCCollectionViewCell *inkCell = (MDCCollectionViewCell *)cell;
+    if ([inkCell respondsToSelector:@selector(inkView)]) {
+      // Set cell ink.
+      ink = [cell performSelector:@selector(inkView)];
+    }
+  }
+
+  return ink;
+}
+
+#pragma mark - <UICollectionViewDataSource>
+
+- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
+           viewForSupplementaryElementOfKind:(NSString *)kind
+                                 atIndexPath:(NSIndexPath *)indexPath {
+  // TODO (shepj): This implementation of registering cell classes in data source methods should be
+  // rethought. This causes a crash without a workaround when collections with headers or
+  // footers entering editing mode. Also, we should find a way around implementing a data source
+  // method in a super class.
+  // Issue: https://github.com/material-components/material-components-ios/issues/1208
+  // Editing info bar.
+  if ([kind isEqualToString:MDCCollectionInfoBarKindHeader] ||
+      [kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+    NSString *identifier = NSStringFromClass([MDCCollectionInfoBarView class]);
+    identifier = [identifier stringByAppendingFormat:@".%@", kind];
+    [collectionView registerClass:[MDCCollectionInfoBarView class]
+        forSupplementaryViewOfKind:kind
+               withReuseIdentifier:identifier];
+
+    UICollectionReusableView *supplementaryView =
+        [collectionView dequeueReusableSupplementaryViewOfKind:kind
+                                           withReuseIdentifier:identifier
+                                                  forIndexPath:indexPath];
+
+    // Update info bar.
+    if ([supplementaryView isKindOfClass:[MDCCollectionInfoBarView class]]) {
+      MDCCollectionInfoBarView *infoBar = (MDCCollectionInfoBarView *)supplementaryView;
+      infoBar.delegate = self;
+      infoBar.kind = kind;
+      [self updateControllerWithInfoBar:infoBar];
+    }
+    return supplementaryView;
+  }
+  return nil;
+}
+
+#pragma mark - <UICollectionViewDelegate>
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
+  if ([_styler.delegate respondsToSelector:@selector(collectionView:hidesInkViewAtIndexPath:)]) {
+    return ![_styler.delegate collectionView:collectionView hidesInkViewAtIndexPath:indexPath];
+  }
+  return YES;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didHighlightItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
+  CGPoint location = [collectionView convertPoint:_inkTouchLocation toView:cell];
+
+  // Start cell ink show animation.
+  MDCInkView *inkView;
+  if ([cell respondsToSelector:@selector(inkView)]) {
+    inkView = [cell performSelector:@selector(inkView)];
+  } else {
+    return;
+  }
+
+  // Update ink color if necessary.
+  if ([_styler.delegate respondsToSelector:@selector(collectionView:inkColorAtIndexPath:)]) {
+    inkView.inkColor =
+        [_styler.delegate collectionView:collectionView inkColorAtIndexPath:indexPath];
+    if (!inkView.inkColor) {
+      inkView.inkColor = inkView.defaultInkColor;
+    }
+  }
+  self.currentlyActiveInk = YES;
+  [inkView startTouchBeganAnimationAtPoint:location completion:nil];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
+  CGPoint location = [collectionView convertPoint:_inkTouchLocation toView:cell];
+
+  // Start cell ink evaporate animation.
+  MDCInkView *inkView;
+  if ([cell respondsToSelector:@selector(inkView)]) {
+    inkView = [cell performSelector:@selector(inkView)];
+  } else {
+    return;
+  }
+
+  self.currentlyActiveInk = NO;
+  [inkView startTouchEndedAnimationAtPoint:location completion:nil];
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  if (_editor.isEditing) {
+    if ([self collectionView:collectionView canEditItemAtIndexPath:indexPath]) {
+      return [self collectionView:collectionView canSelectItemDuringEditingAtIndexPath:indexPath];
+    }
+    return NO;
+  }
+  return YES;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
+  return collectionView.allowsMultipleSelection;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [self updateFooterInfoBarIfNecessary];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didDeselectItemAtIndexPath:(NSIndexPath *)indexPath {
+  [self updateFooterInfoBarIfNecessary];
+}
+
+#pragma mark - <MDCCollectionViewEditingDelegate>
+
+- (BOOL)collectionViewAllowsEditing:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (void)collectionViewWillBeginEditing:(UICollectionView *)collectionView {
+  if (self.currentlyActiveInk) {
+    MDCInkView *activeInkView =
+        [self inkTouchController:_inkTouchController inkViewAtTouchLocation:_inkTouchLocation];
+    [activeInkView startTouchEndedAnimationAtPoint:_inkTouchLocation completion:nil];
+  }
+  // Inlay all items.
+  _styler.allowsItemInlay = YES;
+  _styler.allowsMultipleItemInlays = YES;
+  [_styler applyInlayToAllItemsAnimated:YES];
+  [self updateHeaderInfoBarIfNecessary];
+}
+
+- (void)collectionViewWillEndEditing:(UICollectionView *)collectionView {
+  // Remove inlay of all items.
+  [_styler removeInlayFromAllItemsAnimated:YES];
+  [self updateFooterInfoBarIfNecessary];
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canEditItemAtIndexPath:(NSIndexPath *)indexPath {
+  return [self collectionViewAllowsEditing:collectionView];
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canSelectItemDuringEditingAtIndexPath:(NSIndexPath *)indexPath {
+  if ([self collectionViewAllowsEditing:collectionView]) {
+    return [self collectionView:collectionView canEditItemAtIndexPath:indexPath];
+  }
+  return NO;
+}
+
+#pragma mark - Item Moving
+
+- (BOOL)collectionViewAllowsReordering:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(NSIndexPath *)indexPath {
+  return ([self collectionViewAllowsEditing:collectionView] &&
+          [self collectionViewAllowsReordering:collectionView]);
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(NSIndexPath *)indexPath
+               toIndexPath:(NSIndexPath *)newIndexPath {
+  // First ensure both source and target items can be moved.
+  return ([self collectionView:collectionView canMoveItemAtIndexPath:indexPath] &&
+          [self collectionView:collectionView canMoveItemAtIndexPath:newIndexPath]);
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didMoveItemAtIndexPath:(NSIndexPath *)indexPath
+               toIndexPath:(NSIndexPath *)newIndexPath {
+  [collectionView moveItemAtIndexPath:indexPath toIndexPath:newIndexPath];
+}
+
+#pragma mark - Swipe-To-Dismiss-Items
+
+- (BOOL)collectionViewAllowsSwipeToDismissItem:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canSwipeToDismissItemAtIndexPath:(NSIndexPath *)indexPath {
+  return [self collectionViewAllowsSwipeToDismissItem:collectionView];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didEndSwipeToDismissItemAtIndexPath:(NSIndexPath *)indexPath {
+  [self deleteIndexPaths:@[ indexPath ]];
+}
+
+#pragma mark - Swipe-To-Dismiss-Sections
+
+- (BOOL)collectionViewAllowsSwipeToDismissSection:(UICollectionView *)collectionView {
+  return NO;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    canSwipeToDismissSection:(NSInteger)section {
+  return [self collectionViewAllowsSwipeToDismissSection:collectionView];
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didEndSwipeToDismissSection:(NSInteger)section {
+  [self deleteSections:[NSIndexSet indexSetWithIndex:section]];
+}
+
+#pragma mark - Private
+
+- (void)deleteIndexPaths:(NSArray<NSIndexPath *> *)indexPaths {
+  if ([self respondsToSelector:@selector(collectionView:willDeleteItemsAtIndexPaths:)]) {
+    void (^batchUpdates)() = ^{
+      // Notify delegate to delete data.
+      [self collectionView:self.collectionView willDeleteItemsAtIndexPaths:indexPaths];
+
+      // Delete index paths.
+      [self.collectionView deleteItemsAtIndexPaths:indexPaths];
+    };
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      [self updateFooterInfoBarIfNecessary];
+      // Notify delegate of deletion.
+      if ([self respondsToSelector:@selector(collectionView:didDeleteItemsAtIndexPaths:)]) {
+        [self collectionView:self.collectionView didDeleteItemsAtIndexPaths:indexPaths];
+      }
+    };
+
+    // Animate deletion.
+    [self.collectionView performBatchUpdates:batchUpdates completion:completionBlock];
+  }
+}
+
+- (void)deleteSections:(NSIndexSet *)sections {
+  if ([self respondsToSelector:@selector(collectionView:willDeleteSections:)]) {
+    void (^batchUpdates)() = ^{
+      // Notify delegate to delete data.
+      [self collectionView:self.collectionView willDeleteSections:sections];
+
+      // Delete sections.
+      [self.collectionView deleteSections:sections];
+    };
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      [self updateFooterInfoBarIfNecessary];
+      // Notify delegate of deletion.
+      if ([self respondsToSelector:@selector(collectionView:didDeleteSections:)]) {
+        [self collectionView:self.collectionView didDeleteSections:sections];
+      }
+    };
+
+    // Animate deletion.
+    [self.collectionView performBatchUpdates:batchUpdates completion:completionBlock];
+  }
+}
+
+- (void)updateHeaderInfoBarIfNecessary {
+  if (_editor.isEditing) {
+    // Show HUD only once before autodissmissing.
+    BOOL allowsSwipeToDismissItem = NO;
+    if ([self respondsToSelector:@selector(collectionViewAllowsSwipeToDismissItem:)]) {
+      allowsSwipeToDismissItem = [self collectionViewAllowsSwipeToDismissItem:self.collectionView];
+    }
+
+    if (!_headerInfoBar.isVisible && !_headerInfoBarDismissed && allowsSwipeToDismissItem) {
+      [_headerInfoBar showAnimated:YES];
+    } else {
+      [_headerInfoBar dismissAnimated:YES];
+    }
+  }
+}
+
+- (void)updateFooterInfoBarIfNecessary {
+  NSInteger selectedItemCount = [self.collectionView.indexPathsForSelectedItems count];
+  if (_editor.isEditing) {
+    // Invalidate layout to add info bar if necessary.
+    [self.collectionView.collectionViewLayout invalidateLayout];
+    if (_footerInfoBar) {
+      if (selectedItemCount > 0 && !_footerInfoBar.isVisible) {
+        [_footerInfoBar showAnimated:YES];
+      } else if (selectedItemCount == 0 && _footerInfoBar.isVisible) {
+        [_footerInfoBar dismissAnimated:YES];
+      }
+    }
+  } else if (selectedItemCount == 0 && _footerInfoBar.isVisible) {
+    [_footerInfoBar dismissAnimated:YES];
+  }
+}
+
+- (void)updateContentWithBottomInset:(CGFloat)inset {
+  // Update bottom inset to account for footer info bar.
+  UIEdgeInsets contentInset = self.collectionView.contentInset;
+  contentInset.bottom += inset;
+  [UIView animateWithDuration:MDCCollectionInfoBarAnimationDuration
+                   animations:^{
+                     self.collectionView.contentInset = contentInset;
+                   }];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
new file mode 100644
index 0000000..de25f58
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditing.h
@@ -0,0 +1,60 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCCollectionViewEditingDelegate;
+
+/** The MDCCollectionViewEditing protocol defines the editing state for a UICollectionView. */
+@protocol MDCCollectionViewEditing <NSObject>
+
+/** The associated collection view. */
+@property(nonatomic, readonly, weak, nullable) UICollectionView *collectionView;
+
+/** The delegate will be informed of editing state changes. */
+@property(nonatomic, weak, nullable) id<MDCCollectionViewEditingDelegate> delegate;
+
+/** The index path of the cell being moved or reordered, if any. */
+@property(nonatomic, readonly, strong, nullable) NSIndexPath *reorderingCellIndexPath;
+
+/** The index path of the cell being dragged for dismissal, if any. */
+@property(nonatomic, readonly, strong, nullable) NSIndexPath *dismissingCellIndexPath;
+
+/** The index of the section being dragged for dismissal, or NSNotFound if none. */
+@property(nonatomic, readonly, assign) NSInteger dismissingSection;
+
+/**
+ A Boolean value indicating whether the a visible cell within the collectionView is being
+ edited.
+
+ When set, all rows show or hide editing controls without animation. To animate the state change see
+ @c setEditing:animated:. Setting the editing state of this class does not propagate to the parent
+ view controller's editing state.
+ */
+@property(nonatomic, getter=isEditing) BOOL editing;
+
+/**
+ Set the editing state with optional animations.
+
+ When set, row shows or hides editing controls with/without animation. Setting the editing
+ state of this class does not propagate to the parent view controller's editing state.
+
+ @param editing YES if editing; otherwise, NO.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
new file mode 100644
index 0000000..b28683d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewEditingDelegate.h
@@ -0,0 +1,329 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ A delegate protocol that provides editing notifications for three types of collection view
+ gestural interations:
+
+  - Cells that are dragging/moved vertically for reordering.
+  - Individual cells being swiped horizontally for dismissal.
+  - Entire cell sections being swiped horizontally for dismissal.
+ */
+@protocol MDCCollectionViewEditingDelegate <NSObject>
+
+@optional
+
+#pragma mark - CollectionView Item Editing
+
+/**
+ If YES, the collectionView will allow editing of its items. Permissions for individual
+ index paths are set by implementing the delegate -collectionView:canEditItemAtIndexPath method.
+ If not implemented, will default to NO.
+ */
+- (BOOL)collectionViewAllowsEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view will begin editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to YES.
+ This will be called before any animations to editing state will begin.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewWillBeginEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view did begin editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to YES.
+ This is called after animations to editing state have completed.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewDidBeginEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view will end editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to NO.
+ This will be called before any animations from editing state begin.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewWillEndEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when the collection view did end editing. Typically this method will be
+ called from a collection view editor that has had its editing property set to NO.
+ This is called after animations from editing state have completed.
+
+ @param collectionView The collection view.
+ */
+- (void)collectionViewDidEndEditing:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver for permission to edit an item at this collection view index path.
+ Returning NO here will prevent editing the designated index path. If not implemented, will
+ default to NO.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ @return if the collection view index path can be edited.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canEditItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver for permission to select an item at this collection view index path
+ during collection view editing. Returning NO here will prevent selecting the designated
+ index path. If not implemented, will default to NO.
+
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ @return if the collection view index path can be selected.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canSelectItemDuringEditingAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+#pragma mark - CollectionView Item Moving
+
+/**
+ If YES, the collectionView will allow reordering of its items. Permissions for individual
+ index paths are be set by the -collectionView:canMoveItemAtIndexPath and/or the
+ -collectionView:canMoveItemAtIndexPath:toIndexPath methods. If not implemented, will default
+ to NO.
+
+ */
+- (BOOL)collectionViewAllowsReordering:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver for permission to move an item at this collection view index path.
+ Returning NO here will prevent moving the designated index path. If not implemented, will
+ default to NO.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ @return if the collection view index path can be moved.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver for permission to move an item at this collection view index path to
+ a new index path. Returning NO here will prevent moving the designated index path. If not
+ implemented, will default to NO.
+
+ @param collectionView The collection view.
+ @param indexPath The current index path of the collection view.
+ @param newIndexPath The propsed new index path of the collection view.
+ @return if the collection view index path can be moved.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath
+               toIndexPath:(nonnull NSIndexPath *)newIndexPath;
+
+/**
+ Sent to the receiver when the collection view will move an item from its previous index path
+ to the new index path.
+
+ @param collectionView The collection view.
+ @param indexPath The previous index path of the collection view.
+ @param newIndexPath The new index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath
+                toIndexPath:(nonnull NSIndexPath *)newIndexPath;
+
+/**
+ Sent to the receiver when the collection view did move an item from its previous index path
+ to the new index path.
+
+ @param collectionView The collection view.
+ @param indexPath The previous index path of the collection view.
+ @param newIndexPath The new index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didMoveItemAtIndexPath:(nonnull NSIndexPath *)indexPath
+               toIndexPath:(nonnull NSIndexPath *)newIndexPath;
+
+/**
+ Sent to the receiver when a collection view item at specified index path will begin dragging.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willBeginDraggingItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver when a collection view item at specified index path has finished dragging.
+
+ @param collectionView The collection view.
+ @param indexPath The index path of the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didEndDraggingItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+#pragma mark - CollectionView Item Deletions
+
+/**
+ Sent to the receiver when an array of index paths will be deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths to be deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willDeleteItemsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+/**
+ Sent to the receiver after an array of index paths did get deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didDeleteItemsAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+#pragma mark - CollectionView Section Deletions
+
+/**
+ Sent to the receiver when an array of index paths will be deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param sections An index set of sections to deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willDeleteSections:(nonnull NSIndexSet *)sections;
+
+/**
+ Sent to the receiver after an array of index paths did get deleted from the collection view.
+
+ @param collectionView The collection view.
+ @param sections An index set of sections deleted from the collection view.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+     didDeleteSections:(nonnull NSIndexSet *)sections;
+
+#pragma mark - CollectionView Swipe To Dismiss Items
+
+/**
+ If YES, the collectionView will allow swiping to dismiss an item. If allowed, swiping is enabled
+ for all items (excluding headers, and footers). Permissions for individual items can be set by
+ implementing the protocol -collectionView:canSwipeToDismissItemAtIndexPath method. If not
+ implemented, will default to NO.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @return if the collection view can swipe to dismiss an item.
+ */
+- (BOOL)collectionViewAllowsSwipeToDismissItem:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when a collection view index path begins to swipe for dismissal. The
+ delegate method -collectionViewAllowsSwipeToDismissItem must return true in order for this
+ subsequent delegate method to be called. The collection view is NOT required to be in
+ edit mode to allow swipe-to-dismiss items. Returning NO here will prevent swiping the
+ designated item at index path. If not implemented, will default to NO.
+
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ @return if the collection view index path can be swiped for dismissal.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver when the collection view index path begins to swipe for dismissal.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willBeginSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver after the collection view item has been dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didEndSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Sent to the receiver when the collection view index path has reset without being dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param indexPath The index path of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didCancelSwipeToDismissItemAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+#pragma mark - CollectionView Swipe To Dismiss Sections
+
+/**
+ If YES, the collectionView will allow swiping to dismiss a section. If allowed, swiping is enabled
+ for all section items, headers, and footers. Permissions for individual sections can be
+ set by implementing the protocol -collectionView:canSwipeToDismissSection method. If not
+ implemented, will default to NO.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @return if the collection view can swipe to dismiss a section.
+ */
+- (BOOL)collectionViewAllowsSwipeToDismissSection:(nonnull UICollectionView *)collectionView;
+
+/**
+ Sent to the receiver when a collection view section begins to swipe for dismissal. The
+ collection view property @c allowsSwipeToDismissSection must be true in order for this
+ subsequent delegate method to be called. The collection view is NOT required to be in
+ edit mode to allow swipe-to-dismiss sections. Returning NO here will prevent swiping the
+ designated section. If not implemented, will default to NO.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ @return if the collection view section can be swiped for dismissal.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    canSwipeToDismissSection:(NSInteger)section;
+
+/**
+ Sent to the receiver when the collection view section begins to swipe for dismissal.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    willBeginSwipeToDismissSection:(NSInteger)section;
+
+/**
+ Sent to the receiver after the collection view section has been dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didEndSwipeToDismissSection:(NSInteger)section;
+
+/**
+ Sent to the receiver when the collection view section has reset without being dismissed.
+
+ @param collectionView The collection view being swiped for dismissal.
+ @param section The section of the collection view being swiped for dismissal.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didCancelSwipeToDismissSection:(NSInteger)section;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
new file mode 100644
index 0000000..fdce1ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.h
@@ -0,0 +1,28 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The MDCCollectionViewFlowLayout class provides a Material Design layout implementation of a
+ UICollectionViewFlowLayout layout.
+
+ Learn more at the
+ [Material spec](https://www.google.com/design/spec/components/lists.html#lists-specs)
+ */
+@interface MDCCollectionViewFlowLayout : UICollectionViewFlowLayout
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.m
new file mode 100644
index 0000000..9ef9bd5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewFlowLayout.m
@@ -0,0 +1,775 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewFlowLayout.h"
+
+#import "MDCCollectionViewController.h"
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MDCCollectionViewStyling.h"
+#import "MaterialCollectionLayoutAttributes.h"
+#import "private/MDCCollectionGridBackgroundView.h"
+#import "private/MDCCollectionInfoBarView.h"
+#import "private/MDCCollectionViewEditor.h"
+
+#import <tgmath.h>
+
+/** The grid background decoration view kind. */
+NSString *const kCollectionDecorationView = @"MDCCollectionDecorationView";
+
+static const NSInteger kSupplementaryViewZIndex = 99;
+
+@implementation MDCCollectionViewFlowLayout {
+  NSMutableArray<NSIndexPath *> *_deletedIndexPaths;
+  NSMutableArray<NSIndexPath *> *_insertedIndexPaths;
+  NSMutableIndexSet *_deletedSections;
+  NSMutableIndexSet *_insertedSections;
+  NSMutableIndexSet *_headerSections;
+  NSMutableIndexSet *_footerSections;
+  NSMutableDictionary *_decorationViewAttributeCache;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    // Defaults.
+    self.minimumLineSpacing = 0;
+    self.minimumInteritemSpacing = 0;
+    self.scrollDirection = UICollectionViewScrollDirectionVertical;
+    self.sectionInset = UIEdgeInsetsZero;
+
+    // Register decoration view for grid background.
+    _decorationViewAttributeCache = [NSMutableDictionary dictionary];
+    [self registerClass:[MDCCollectionGridBackgroundView class]
+        forDecorationViewOfKind:kCollectionDecorationView];
+  }
+  return self;
+}
+
+- (id<MDCCollectionViewEditing>)editor {
+  if ([self.collectionView.delegate isKindOfClass:[MDCCollectionViewController class]]) {
+    MDCCollectionViewController *controller =
+        (MDCCollectionViewController *)self.collectionView.delegate;
+    return controller.editor;
+  }
+  return nil;
+}
+
+- (id<MDCCollectionViewStyling>)styler {
+  if ([self.collectionView.delegate isKindOfClass:[MDCCollectionViewController class]]) {
+    MDCCollectionViewController *controller =
+        (MDCCollectionViewController *)self.collectionView.delegate;
+    return controller.styler;
+  }
+  return nil;
+}
+
+#pragma mark - UICollectionViewLayout (SubclassingHooks)
+
+- (NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:
+        (CGRect)rect {
+  // If performing appearance animation, increase bounds height in order to retrieve additional
+  // offscreen attributes needed during animation.
+  rect = [self boundsForAppearanceAnimationWithInitialBounds:rect];
+  NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *attributes =
+      [[NSMutableArray alloc] initWithArray:[super layoutAttributesForElementsInRect:rect]
+                                  copyItems:YES];
+
+  // Store index path sections of any headers/footers within these attributes.
+  [self storeSupplementaryViewsWithAttributes:attributes];
+
+  // Set layout attributes.
+  for (MDCCollectionViewLayoutAttributes *attr in attributes) {
+    [self updateAttribute:attr];
+  }
+
+  // Add info bar header/footer supplementary view if necessary.
+  [self addInfoBarAttributesIfNecessary:attributes];
+
+  // Begin cell appearance animation if necessary.
+  [self beginCellAppearanceAnimationIfNecessary:attributes];
+
+  // Add a grid background decoration view for each section if necessary.
+  [self addDecorationViewIfNecessary:attributes];
+
+  return attributes;
+}
+
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
+  if (!CGSizeEqualToSize(self.collectionView.bounds.size, newBounds.size) ||
+      self.editor.isEditing) {
+    // Invalidate the layout to force cells to respect the new collection view bounds. Doing here
+    // removes necessity to implement methods -willRotateToInterfaceOrientation:duration: and/or
+    // -viewWillTransitionToSize:withTransitionCoordinator: on the collection view controller.
+    [self invalidateLayout];
+    return YES;
+  }
+  return NO;
+}
+
+- (void)invalidateLayout {
+  [super invalidateLayout];
+
+  // Clear decoration attribute cache.
+  [_decorationViewAttributeCache removeAllObjects];
+}
+
+#pragma mark - UICollectionViewLayout (UISubclassingHooks)
+
++ (Class)layoutAttributesClass {
+  return [MDCCollectionViewLayoutAttributes class];
+}
+
+- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super layoutAttributesForItemAtIndexPath:indexPath] copy];
+  return [self updateAttribute:(MDCCollectionViewLayoutAttributes *)attr];
+}
+
+- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind
+                                                                     atIndexPath:
+                                                                         (NSIndexPath *)indexPath {
+  UICollectionViewLayoutAttributes *attr;
+
+  if ([kind isEqualToString:UICollectionElementKindSectionHeader] ||
+      [kind isEqualToString:UICollectionElementKindSectionFooter]) {
+    // Update section headers/Footers attributes.
+    attr = [[super layoutAttributesForSupplementaryViewOfKind:kind atIndexPath:indexPath] copy];
+    if (!attr) {
+      attr =
+          [MDCCollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:kind
+                                                                          withIndexPath:indexPath];
+    }
+    [self updateAttribute:(MDCCollectionViewLayoutAttributes *)attr];
+
+  } else {
+    // Update editing info bar attributes.
+    attr = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:kind
+                                                                          withIndexPath:indexPath];
+
+    // Force the info bar supplementary views to stay fixed to their respective positions
+    // at top/bottom of the collectionView bounds.
+    CGFloat offsetY = 0;
+    CGRect currentBounds = self.collectionView.bounds;
+    attr.zIndex = kSupplementaryViewZIndex;
+
+    if ([kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+      attr.size = CGSizeMake(CGRectGetWidth(currentBounds), MDCCollectionInfoBarHeaderHeight);
+      // Allow header to move upwards with scroll, but prevent from moving downwards with scroll.
+      CGFloat insetTop = self.collectionView.contentInset.top;
+      CGFloat boundsY = currentBounds.origin.y;
+      CGFloat maxOffsetY = MAX(boundsY + insetTop, 0);
+      offsetY = boundsY + (attr.size.height / 2) + insetTop - maxOffsetY;
+    } else if ([kind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+      attr.size = CGSizeMake(CGRectGetWidth(currentBounds), MDCCollectionInfoBarFooterHeight);
+      offsetY = currentBounds.origin.y + currentBounds.size.height - (attr.size.height / 2);
+    }
+    attr.center = CGPointMake(CGRectGetMidX(currentBounds), offsetY);
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)
+    layoutAttributesForDecorationViewOfKind:(NSString *)elementKind
+                                atIndexPath:(NSIndexPath *)indexPath {
+  // Check cache for decoration view attributes, and add to cache if they don't exist.
+  MDCCollectionViewLayoutAttributes *decorationAttr =
+      [_decorationViewAttributeCache objectForKey:indexPath];
+  if (!decorationAttr) {
+    decorationAttr =
+        [MDCCollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:elementKind
+                                                                     withIndexPath:indexPath];
+    [_decorationViewAttributeCache setObject:decorationAttr forKey:indexPath];
+  }
+
+  // Determine section frame by summing all of its item frames.
+  CGRect sectionFrame = CGRectNull;
+  for (NSInteger i = 0; i < [self numberOfItemsInSection:indexPath.section]; ++i) {
+    indexPath = [NSIndexPath indexPathForItem:i inSection:indexPath.section];
+    UICollectionViewLayoutAttributes *attribute =
+        [self layoutAttributesForItemAtIndexPath:indexPath];
+    if (!CGRectIsNull(attribute.frame)) {
+      sectionFrame = CGRectUnion(sectionFrame, attribute.frame);
+    }
+  }
+  decorationAttr.frame = sectionFrame;
+  decorationAttr.zIndex = -1;
+  return decorationAttr;
+}
+
+- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset {
+  // Return current contentOffset to prevent any layout animations from jumping to new offset.
+  return [super targetContentOffsetForProposedContentOffset:self.collectionView.contentOffset];
+}
+
+#pragma mark - UICollectionViewLayout (UIUpdateSupportHooks)
+
+- (void)prepareForCollectionViewUpdates:(NSArray<UICollectionViewUpdateItem *> *)updateItems {
+  [super prepareForCollectionViewUpdates:updateItems];
+  _deletedIndexPaths = [NSMutableArray array];
+  _insertedIndexPaths = [NSMutableArray array];
+  _deletedSections = [NSMutableIndexSet indexSet];
+  _insertedSections = [NSMutableIndexSet indexSet];
+
+  for (UICollectionViewUpdateItem *item in updateItems) {
+    if (item.updateAction == UICollectionUpdateActionDelete) {
+      // Store deleted sections or indexPaths.
+      if (item.indexPathBeforeUpdate.item == NSNotFound) {
+        [_deletedSections addIndex:item.indexPathBeforeUpdate.section];
+      } else {
+        [_deletedIndexPaths addObject:item.indexPathBeforeUpdate];
+      }
+
+    } else if (item.updateAction == UICollectionUpdateActionInsert) {
+      // Store inserted sections or indexPaths.
+      if (item.indexPathAfterUpdate.item == NSNotFound) {
+        [_insertedSections addIndex:item.indexPathAfterUpdate.section];
+      } else {
+        [_insertedIndexPaths addObject:item.indexPathAfterUpdate];
+      }
+    }
+  }
+}
+
+- (void)finalizeCollectionViewUpdates {
+  [super finalizeCollectionViewUpdates];
+  _deletedIndexPaths = nil;
+  _insertedIndexPaths = nil;
+  _deletedSections = nil;
+  _insertedSections = nil;
+}
+
+- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:
+        (NSIndexPath *)itemIndexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super initialLayoutAttributesForAppearingItemAtIndexPath:itemIndexPath] copy];
+  // Adding new section or item.
+  if ([_insertedSections containsIndex:itemIndexPath.section] ||
+      [_insertedIndexPaths containsObject:itemIndexPath]) {
+    attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+  } else {
+    attr.alpha = 1;
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)
+    initialLayoutAttributesForAppearingSupplementaryElementOfKind:(NSString *)elementKind
+                                                      atIndexPath:(NSIndexPath *)elementIndexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super initialLayoutAttributesForAppearingSupplementaryElementOfKind:elementKind
+                                                                atIndexPath:elementIndexPath] copy];
+  if ([elementKind isEqualToString:UICollectionElementKindSectionHeader] ||
+      [elementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+    // Adding new section header or footer.
+    if ([_insertedSections containsIndex:elementIndexPath.section]) {
+      attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+    } else {
+      attr.alpha = 1;
+    }
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)finalLayoutAttributesForDisappearingItemAtIndexPath:
+        (NSIndexPath *)itemIndexPath {
+  UICollectionViewLayoutAttributes *attr =
+      [[super finalLayoutAttributesForDisappearingItemAtIndexPath:itemIndexPath] copy];
+  // Deleting section or item.
+  if ([_deletedSections containsIndex:itemIndexPath.section] ||
+      [_deletedIndexPaths containsObject:itemIndexPath]) {
+    attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+  } else {
+    attr.alpha = 1;
+  }
+  return attr;
+}
+
+- (UICollectionViewLayoutAttributes *)
+    finalLayoutAttributesForDisappearingSupplementaryElementOfKind:(NSString *)elementKind
+                                                       atIndexPath:(NSIndexPath *)elementIndexPath {
+  UICollectionViewLayoutAttributes *attr = [[super
+      finalLayoutAttributesForDisappearingSupplementaryElementOfKind:elementKind
+                                                         atIndexPath:elementIndexPath] copy];
+  if ([elementKind isEqualToString:UICollectionElementKindSectionHeader] ||
+      [elementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+    // Deleting section header or footer.
+    if ([_deletedSections containsIndex:elementIndexPath.section]) {
+      attr.transform = CGAffineTransformMakeTranslation(0, -CGRectGetHeight(attr.bounds) / 2);
+    } else {
+      attr.alpha = 1;
+    }
+  }
+  return attr;
+}
+
+#pragma mark - Header/Footer Caching
+
+- (void)storeSupplementaryViewsWithAttributes:
+        (NSArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  _headerSections = [NSMutableIndexSet indexSet];
+  _footerSections = [NSMutableIndexSet indexSet];
+
+  // Store index path sections for headers/footers.
+  for (MDCCollectionViewLayoutAttributes *attr in attributes) {
+    if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
+      [_headerSections addIndex:attr.indexPath.section];
+    } else if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+      [_footerSections addIndex:attr.indexPath.section];
+    }
+  }
+}
+
+#pragma mark - Private
+
+- (MDCCollectionViewLayoutAttributes *)updateAttribute:(MDCCollectionViewLayoutAttributes *)attr {
+  if (attr.representedElementCategory == UICollectionElementCategoryCell) {
+    attr.editing = self.editor.isEditing;
+  }
+  attr.isGridLayout = NO;
+  if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeList) {
+    attr.sectionOrdinalPosition = [self ordinalPositionForListElementWithAttribute:attr];
+  } else if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    attr.sectionOrdinalPosition = [self ordinalPositionForGridElementWithAttribute:attr];
+    attr.isGridLayout = YES;
+  }
+
+  [self updateCellStateMaskWithAttribute:attr];
+
+  if (attr.representedElementCategory == UICollectionElementCategorySupplementaryView) {
+    attr = [self updateSupplementaryViewAttribute:attr];
+  }
+
+  // Set cell background.
+  attr.backgroundImage = [self.styler backgroundImageForCellLayoutAttributes:attr];
+  attr.backgroundImageViewInsets =
+      [self.styler backgroundImageViewOutsetsForCellWithAttribute:attr];
+
+  // Set separator styling.
+  attr.separatorColor = self.styler.separatorColor;
+  attr.separatorInset = self.styler.separatorInset;
+  attr.separatorLineHeight = self.styler.separatorLineHeight;
+  attr.shouldHideSeparators = self.styler.shouldHideSeparators;
+
+  // Set inlay and hidden state if necessary.
+  [self inlayAttributeIfNecessary:attr];
+  [self hideAttributeIfNecessary:attr];
+
+  return attr;
+}
+
+- (MDCCollectionViewLayoutAttributes *)updateSupplementaryViewAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // In vertical scrolling, supplementary views only respect their height and ignore their width
+  // value. The opposite is true for horizontal scrolling. Therefore we must manually set insets
+  // on both the backgroundView and contentView in order to match the insets of the collection
+  // view rows.
+  CGRect insetFrame = attr.frame;
+  UIEdgeInsets insets = [self insetsAtSectionIndex:attr.indexPath.section];
+  if (self.scrollDirection == UICollectionViewScrollDirectionVertical) {
+    insetFrame = CGRectInset(insetFrame, insets.left / 2 + insets.right / 2, 0);
+    if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader]) {
+      insetFrame.origin.y += insets.top;
+    } else if ([attr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter]) {
+      insetFrame.origin.y -= insets.bottom;
+    }
+    attr.frame = insetFrame;
+  }
+  return attr;
+}
+
+- (UIEdgeInsets)insetsAtSectionIndex:(NSInteger)section {
+  // Determine insets based on cell style.
+  CGFloat inset = (CGFloat)floor(MDCCollectionViewCellStyleCardSectionInset);
+  UIEdgeInsets insets = UIEdgeInsetsZero;
+  NSInteger numberOfSections = self.collectionView.numberOfSections;
+  BOOL isTop = (section == 0);
+  BOOL isBottom = (section == numberOfSections - 1);
+  MDCCollectionViewCellStyle cellStyle = [self.styler cellStyleAtSectionIndex:section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  // Set left/right insets.
+  if (isCardStyle) {
+    insets.left = inset;
+    insets.right = inset;
+  }
+  // Set top/bottom insets.
+  if (isCardStyle || isGroupedStyle) {
+    insets.top = (CGFloat)floor((isTop) ? inset : inset / 2.0f);
+    insets.bottom = (CGFloat)floor((isBottom) ? inset : inset / 2.0f);
+  }
+  return insets;
+}
+
+- (MDCCollectionViewOrdinalPosition)ordinalPositionForListElementWithAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // Returns the ordinal position of cells and supplementary views within a list layout. This is
+  // used to determine the layout attributes applied to their styling.
+  MDCCollectionViewOrdinalPosition position = 0;
+  NSIndexPath *indexPath = attr.indexPath;
+  NSInteger numberOfItemsInSection = [self numberOfItemsInSection:indexPath.section];
+  BOOL isTop = NO;
+  BOOL isBottom = NO;
+  BOOL hasSectionHeader = [_headerSections containsIndex:indexPath.section];
+  BOOL hasSectionFooter = [_footerSections containsIndex:indexPath.section];
+  BOOL hasSectionItems = YES;
+
+  BOOL hidesHeaderBackground = NO;
+  if ([self.styler.delegate
+          respondsToSelector:@selector(collectionView:shouldHideHeaderBackgroundForSection:)]) {
+    hidesHeaderBackground = [self.styler.delegate collectionView:self.styler.collectionView
+                            shouldHideHeaderBackgroundForSection:indexPath.section];
+  }
+
+  BOOL hidesFooterBackground = NO;
+  if ([self.styler.delegate
+          respondsToSelector:@selector(collectionView:shouldHideFooterBackgroundForSection:)]) {
+    hidesFooterBackground = [self.styler.delegate collectionView:self.styler.collectionView
+                            shouldHideFooterBackgroundForSection:indexPath.section];
+  }
+
+  if (attr.representedElementCategory == UICollectionElementCategoryCell) {
+    isTop = (indexPath.item == 0) && (!hasSectionHeader || hidesHeaderBackground);
+    isBottom = (indexPath.item == numberOfItemsInSection - 1) &&
+               (!hasSectionFooter || hidesFooterBackground);
+  } else if (attr.representedElementCategory == UICollectionElementCategorySupplementaryView) {
+    NSString *kind = attr.representedElementKind;
+    BOOL isElementHeader = ([kind isEqualToString:UICollectionElementKindSectionHeader]);
+    BOOL isElementFooter = ([kind isEqualToString:UICollectionElementKindSectionFooter]);
+    isTop = (isElementFooter && !hasSectionItems && !hasSectionHeader) || isElementHeader;
+    isBottom = (isElementHeader && !hasSectionItems && !hasSectionFooter) || isElementFooter;
+  }
+
+  if (attr.editing || [self.styler isItemInlaidAtIndexPath:attr.indexPath]) {
+    isTop = YES;
+    isBottom = YES;
+  }
+
+  if (!isTop && !isBottom) {
+    position |= MDCCollectionViewOrdinalPositionVerticalCenter;
+  } else {
+    position |= isTop ? MDCCollectionViewOrdinalPositionVerticalTop : position;
+    position |= isBottom ? MDCCollectionViewOrdinalPositionVerticalBottom : position;
+  }
+  return position;
+}
+
+- (MDCCollectionViewOrdinalPosition)ordinalPositionForGridElementWithAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // Returns the ordinal position of cells and supplementary views within a grid layout. This is
+  // used to determine the layout attributes applied to their styling.
+  MDCCollectionViewOrdinalPosition position = 0;
+  NSIndexPath *indexPath = attr.indexPath;
+  NSInteger numberOfItemsInSection = [self numberOfItemsInSection:indexPath.section];
+  NSInteger gridColumnCount = self.styler.gridColumnCount;
+  NSInteger maxRowIndex = (NSInteger)(floor(numberOfItemsInSection / gridColumnCount) - 1);
+  NSInteger maxColumnIndex = gridColumnCount - 1;
+  NSInteger ordinalRow = (NSInteger)(floor(indexPath.item / gridColumnCount));
+  NSInteger ordinalColumn = (NSInteger)(floor(indexPath.item % gridColumnCount));
+
+  // Set vertical ordinal position.
+  if (ordinalRow > 0 && ordinalRow < maxRowIndex) {
+    position = position | MDCCollectionViewOrdinalPositionVerticalCenter;
+  } else {
+    position =
+        (ordinalRow == 0) ? position | MDCCollectionViewOrdinalPositionVerticalTop : position;
+    position = (ordinalRow == maxRowIndex)
+                   ? position | MDCCollectionViewOrdinalPositionVerticalBottom
+                   : position;
+  }
+
+  // Set horizontal ordinal position.
+  if (ordinalColumn > 0 && ordinalColumn < maxColumnIndex) {
+    position = position | MDCCollectionViewOrdinalPositionHorizontalCenter;
+  } else {
+    position =
+        (ordinalColumn == 0) ? position | MDCCollectionViewOrdinalPositionHorizontalLeft : position;
+    position = (ordinalColumn == maxColumnIndex)
+                   ? position | MDCCollectionViewOrdinalPositionHorizontalRight
+                   : position;
+  }
+  return position;
+}
+
+- (void)updateCellStateMaskWithAttribute:(MDCCollectionViewLayoutAttributes *)attr {
+  attr.shouldShowSelectorStateMask = NO;
+  attr.shouldShowReorderStateMask = NO;
+
+  // Determine proper state to show cell if editing.
+  if (attr.editing) {
+    if ([self.collectionView.dataSource
+            conformsToProtocol:@protocol(MDCCollectionViewEditingDelegate)]) {
+      id<MDCCollectionViewEditingDelegate> editingDelegate =
+          (id<MDCCollectionViewEditingDelegate>)self.collectionView.dataSource;
+
+      // Check if delegate can select during editing.
+      if ([editingDelegate respondsToSelector:@selector(collectionView:
+                                                  canSelectItemDuringEditingAtIndexPath:)]) {
+        attr.shouldShowSelectorStateMask = [editingDelegate collectionView:self.collectionView
+                                     canSelectItemDuringEditingAtIndexPath:attr.indexPath];
+      }
+
+      // Check if delegate can reorder.
+      if ([editingDelegate respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)]) {
+        attr.shouldShowReorderStateMask = [editingDelegate collectionView:self.collectionView
+                                                   canMoveItemAtIndexPath:attr.indexPath];
+      }
+    }
+  }
+}
+
+- (void)inlayAttributeIfNecessary:(MDCCollectionViewLayoutAttributes *)attr {
+  // Inlay this attribute if necessary.
+  CGFloat inset = MDCCollectionViewCellStyleCardSectionInset;
+  UIEdgeInsets inlayInsets = UIEdgeInsetsZero;
+  NSInteger item = attr.indexPath.item;
+  NSArray<NSIndexPath *> *inlaidIndexPaths = [self.styler indexPathsForInlaidItems];
+
+  // Update ordinal position for index paths adjacent to inlaid index path.
+  for (NSIndexPath *inlaidIndexPath in inlaidIndexPaths) {
+    if (inlaidIndexPath.section == attr.indexPath.section) {
+      NSInteger numberOfItemsInSection = [self numberOfItemsInSection:inlaidIndexPath.section];
+      if (attr.representedElementCategory == UICollectionElementCategoryCell) {
+        if (item == inlaidIndexPath.item) {
+          // Get previous and next index paths to the inlaid index path.
+          BOOL prevAttrIsInlaid = NO;
+          BOOL nextAttrIsInlaid = NO;
+          BOOL hasSectionHeader = [_headerSections containsIndex:inlaidIndexPath.section];
+          BOOL hasSectionFooter = [_footerSections containsIndex:inlaidIndexPath.section];
+
+          if (inlaidIndexPath.item > 0 || hasSectionHeader) {
+            NSIndexPath *prevIndexPath = [NSIndexPath indexPathForItem:(inlaidIndexPath.item - 1)
+                                                             inSection:inlaidIndexPath.section];
+            prevAttrIsInlaid = [self.styler isItemInlaidAtIndexPath:prevIndexPath];
+            inlayInsets.top = prevAttrIsInlaid ? inset / 2 : inset;
+          }
+
+          if (inlaidIndexPath.item < numberOfItemsInSection - 1 || hasSectionFooter) {
+            NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:(inlaidIndexPath.item + 1)
+                                                             inSection:inlaidIndexPath.section];
+            nextAttrIsInlaid = [self.styler isItemInlaidAtIndexPath:nextIndexPath];
+            inlayInsets.bottom = nextAttrIsInlaid ? inset / 2 : inset;
+          }
+
+          // Is attribute to be inlaid.
+          attr.frame = UIEdgeInsetsInsetRect(attr.frame, inlayInsets);
+          attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+        } else if (item == inlaidIndexPath.item - 1) {
+          // Is previous to inlaid attribute.
+          if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalTop) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+          } else if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalCenter) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalBottom;
+          }
+        } else if (item == inlaidIndexPath.item + 1) {
+          // Is next to inlaid attribute.
+          if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalCenter) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTop;
+          } else if (attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalBottom) {
+            attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalBottom;
+          }
+        }
+
+      } else if (attr.representedElementCategory == UICollectionElementCategorySupplementaryView) {
+        // If header/footer attribute, update if adjacent to inlaid index path.
+        NSString *kind = attr.representedElementKind;
+        BOOL isElementHeader = ([kind isEqualToString:UICollectionElementKindSectionHeader]);
+        BOOL isElementFooter = ([kind isEqualToString:UICollectionElementKindSectionFooter]);
+        if (isElementHeader && inlaidIndexPath.item == 0) {
+          attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+        } else if (isElementFooter && inlaidIndexPath.item == numberOfItemsInSection - 1) {
+          attr.sectionOrdinalPosition = MDCCollectionViewOrdinalPositionVerticalTopBottom;
+        }
+      }
+    }
+  }
+}
+
+- (void)hideAttributeIfNecessary:(MDCCollectionViewLayoutAttributes *)attr {
+  if (self.editor) {
+    // Hide the attribute if the editor is either currently handling a cell item or section swipe
+    // for dismissal, or is reordering a cell item.
+    BOOL isCell = attr.representedElementCategory == UICollectionElementCategoryCell;
+    if (attr.indexPath.section == self.editor.dismissingSection ||
+        ([attr.indexPath isEqual:self.editor.dismissingCellIndexPath] && isCell) ||
+        ([attr.indexPath isEqual:self.editor.reorderingCellIndexPath] && isCell)) {
+      attr.hidden = YES;
+    }
+  }
+}
+
+- (void)addInfoBarAttributesIfNecessary:
+        (NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  if (self.editor.isEditing && [attributes count] > 0) {
+    NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
+
+    // Add header info bar if editing.
+    [attributes
+        addObject:[self layoutAttributesForSupplementaryViewOfKind:MDCCollectionInfoBarKindHeader
+                                                       atIndexPath:indexPath]];
+
+    // Add footer info bar if editing and item(s) are selected.
+    NSInteger selectedItemCount = [self.collectionView.indexPathsForSelectedItems count];
+    if (selectedItemCount > 0) {
+      [attributes
+          addObject:[self layoutAttributesForSupplementaryViewOfKind:MDCCollectionInfoBarKindFooter
+                                                         atIndexPath:indexPath]];
+    }
+  }
+}
+
+- (void)addDecorationViewIfNecessary:
+        (NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  // If necessary, adds a decoration view to a section drawn below its items. This will only happen
+  // for a grid layout when it is either A) grouped-style or B) card-style with zero padding. When
+  // this happens, the background for those items will not be drawn, and instead this decoration
+  // view will extend to the bounds of the sum of its respective section item frames. Shadowing and
+  // border will be applied to this decoration view as per the styler settings.
+  if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    NSMutableSet *sectionSet = [NSMutableSet set];
+    BOOL shouldShowGridBackground = NO;
+    NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *decorationAttributes =
+        [NSMutableArray array];
+    for (MDCCollectionViewLayoutAttributes *attr in attributes) {
+      NSInteger section = attr.indexPath.section;
+
+      // Only add one decoration view per section.
+      if (![sectionSet containsObject:@(section)]) {
+        NSIndexPath *decorationIndexPath = [NSIndexPath indexPathForItem:0 inSection:section];
+        MDCCollectionViewLayoutAttributes *decorationAttr =
+            (MDCCollectionViewLayoutAttributes *)[self
+                layoutAttributesForDecorationViewOfKind:kCollectionDecorationView
+                                            atIndexPath:decorationIndexPath];
+        shouldShowGridBackground = [self shouldShowGridBackgroundWithAttribute:decorationAttr];
+        decorationAttr.shouldShowGridBackground = shouldShowGridBackground;
+        decorationAttr.backgroundImage =
+            shouldShowGridBackground
+                ? [self.styler backgroundImageForCellLayoutAttributes:decorationAttr]
+                : nil;
+        [decorationAttributes addObject:decorationAttr];
+        [sectionSet addObject:@(section)];
+      }
+      if (shouldShowGridBackground) {
+        attr.backgroundImage = nil;
+      }
+    }
+    [attributes addObjectsFromArray:decorationAttributes];
+  }
+}
+
+- (BOOL)shouldShowGridBackgroundWithAttribute:(MDCCollectionViewLayoutAttributes *)attr {
+  // Determine whether to show grid background.
+  if (self.styler.cellLayoutType == MDCCollectionViewCellLayoutTypeGrid) {
+    if (self.styler.cellStyle == MDCCollectionViewCellStyleGrouped ||
+        (self.styler.cellStyle == MDCCollectionViewCellStyleCard && self.styler.gridPadding == 0)) {
+      return YES;
+    }
+  }
+  return NO;
+}
+
+- (NSInteger)numberOfItemsInSection:(NSInteger)section {
+  return [self.collectionView numberOfItemsInSection:section];
+}
+
+#pragma mark - Cell Appearance Animation
+
+- (CGRect)boundsForAppearanceAnimationWithInitialBounds:(CGRect)initialBounds {
+  // Increase initial bounds by 25% allowing offscreen attributes to be included in the
+  // appearance animation.
+  if (self.styler.shouldAnimateCellsOnAppearance && self.styler.willAnimateCellsOnAppearance) {
+    CGRect newBounds = initialBounds;
+    newBounds.size.height += (newBounds.size.height / 4);
+    return newBounds;
+  }
+  return initialBounds;
+}
+
+- (void)beginCellAppearanceAnimationIfNecessary:
+        (NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *)attributes {
+  // Here we want to assign a delay to each attribute such that the animation will fade-in from the
+  // top downwards in a staggered manner. However, the array of attributes we receive here are not
+  // in the correct order and must be sorted and re-ordered to properly assign these delays.
+  //
+  // First we will sort the array of attributes by index path to ensure proper ordering. Secondly
+  // we will manipulate the array to bring any headers before their first respective cell items.
+  //
+  // When completed, we will end up with an array of attributes in the form of
+  // header -> item -> footer ... repeated for each section. Now we can use this ordered array
+  // to assign delays based on their proper ordinal position from top down.
+  __block NSInteger attributeCount = attributes.count;
+  NSTimeInterval duration = self.styler.animateCellsOnAppearanceDuration;
+  if (self.styler.shouldAnimateCellsOnAppearance && attributeCount > 0) {
+    // First sort by index path.
+    NSArray<__kindof UICollectionViewLayoutAttributes *> *sortedByIndexPath = [attributes
+        sortedArrayUsingComparator:^NSComparisonResult(MDCCollectionViewLayoutAttributes *attr1,
+                                                       MDCCollectionViewLayoutAttributes *attr2) {
+          return [attr1.indexPath compare:attr2.indexPath];
+        }];
+
+    // Next create new array containing attributes in the form of header -> item -> footer.
+    NSMutableArray<__kindof UICollectionViewLayoutAttributes *> *sortedAttributes =
+        [NSMutableArray array];
+    [sortedByIndexPath enumerateObjectsUsingBlock:^(MDCCollectionViewLayoutAttributes *attr,
+                                                    NSUInteger idx, BOOL *stop) {
+      if (sortedAttributes.count > 0) {
+        // Check if current attribute is a header and previous attribute is an item. If so,
+        // insert the current header attribute before the cell.
+        MDCCollectionViewLayoutAttributes *prevAttr =
+            [sortedAttributes objectAtIndex:sortedAttributes.count - 1];
+        BOOL prevAttrIsItem =
+            prevAttr.representedElementCategory == UICollectionElementCategoryCell;
+        BOOL attrIsHeader =
+            [attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader];
+        if (attrIsHeader && prevAttrIsItem) {
+          [sortedAttributes insertObject:attr atIndex:sortedAttributes.count - 1];
+          return;
+        }
+        if ([attr.representedElementKind isEqualToString:MDCCollectionInfoBarKindHeader] ||
+            [attr.representedElementKind isEqualToString:MDCCollectionInfoBarKindFooter]) {
+          // Reduce the attributeCount here to reflect only attributes that can be animated.
+          attributeCount--;
+          return;
+        }
+      }
+      [sortedAttributes addObject:attr];
+    }];
+
+    // Now assign delays and add padding to frame Y coordinate which gets removed during animation.
+    [sortedAttributes enumerateObjectsUsingBlock:^(MDCCollectionViewLayoutAttributes *attr,
+                                                   NSUInteger idx, BOOL *stop) {
+      // If the element is an info bar header, then don't do anything.
+      attr.willAnimateCellsOnAppearance = self.styler.willAnimateCellsOnAppearance;
+      attr.animateCellsOnAppearanceDuration = self.styler.animateCellsOnAppearanceDuration;
+      attr.animateCellsOnAppearanceDelay =
+          (attributeCount > 0) ? ((CGFloat)idx / attributeCount) * duration : 0;
+
+      if (self.styler.willAnimateCellsOnAppearance) {
+        CGRect frame = attr.frame;
+        frame.origin.y += self.styler.animateCellsOnAppearancePadding;
+        attr.frame = frame;
+      }
+    }];
+
+    // Call asynchronously to allow the current layout cycle to complete before issuing animations.
+    if (self.styler.willAnimateCellsOnAppearance) {
+      dispatch_async(dispatch_get_main_queue(), ^{
+        [self.styler beginCellAppearanceAnimation];
+      });
+    }
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
new file mode 100644
index 0000000..b0f577a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStyling.h
@@ -0,0 +1,265 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCCollectionViewStylingDelegate;
+@class MDCCollectionViewLayoutAttributes;
+
+/** The default section insets. Should be an even number to allow even division. */
+extern const CGFloat MDCCollectionViewCellStyleCardSectionInset;
+
+/** The styles in which the collectionView cells can be shown. */
+typedef NS_ENUM(NSUInteger, MDCCollectionViewCellStyle) {
+  /** Cells displayed full width without section padding. */
+  MDCCollectionViewCellStyleDefault,
+
+  /** Cells displayed full width with section padding. */
+  MDCCollectionViewCellStyleGrouped,
+
+  /** Cells displayed card style with sections padding. */
+  MDCCollectionViewCellStyleCard,
+};
+
+/** The layout types in which the collectionView cells can be shown. */
+typedef NS_ENUM(NSUInteger, MDCCollectionViewCellLayoutType) {
+  /** Cells displayed in list layout. */
+  MDCCollectionViewCellLayoutTypeList,
+
+  /** Cells displayed in grid layout. */
+  MDCCollectionViewCellLayoutTypeGrid,
+
+  /**
+   Cells displayed in custom defined layout. A new UICollectionViewLayout must be
+   provided and set on the collection view.
+   */
+  MDCCollectionViewCellLayoutTypeCustom
+};
+
+/**
+ The MDCCollectionViewStyling protocol defines the stylable properties for a Material collection
+ view.
+ */
+@protocol MDCCollectionViewStyling <NSObject>
+
+/** The associated collection view. */
+@property(nonatomic, readonly, weak, nullable) UICollectionView *collectionView;
+
+/** The delegate is sent messages when styles change. */
+@property(nonatomic, weak, nullable) id<MDCCollectionViewStylingDelegate> delegate;
+
+/** Indicates whether the collection view layout should be invalidated. */
+@property(nonatomic, assign) BOOL shouldInvalidateLayout;
+
+#pragma mark - Cell Styling
+
+/** The cell background color. Defaults to white color. */
+@property(nonatomic, strong, nonnull) UIColor *cellBackgroundColor;
+
+/**
+ The cell layout type. Defaults to MDCCollectionViewCellLayoutTypeList if not set. Not animated.
+ Defaults to MDCCollectionViewCellLayoutTypeList.
+ */
+@property(nonatomic, assign) MDCCollectionViewCellLayoutType cellLayoutType;
+
+/**
+ The grid column count. Requires cellLayoutType to be set to MDCCollectionViewCellLayoutTypeGrid.
+ Not animated.
+ */
+@property(nonatomic, assign) NSInteger gridColumnCount;
+
+/**
+ The grid padding property is used when the cellLayoutType is MDCCollectionViewCellLayoutTypeGrid
+ and the gridColumnCount is greater than or equal to 2. This value ensure that the left, center,
+ and right padding are equivalent. This prevents double padding at center. Not animated.
+ */
+@property(nonatomic, assign) CGFloat gridPadding;
+
+/** The cell style. Not animated. @c setCellStyle:animated: for animated layout type changes. */
+@property(nonatomic, assign) MDCCollectionViewCellStyle cellStyle;
+
+/**
+ Updates the cell style with/without animation.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)setCellStyle:(MDCCollectionViewCellStyle)cellStyle animated:(BOOL)animated;
+
+/**
+ The collection view cell style at the specified section index.
+
+ @param section The collection view section.
+ @return The cell style at specified section.
+ */
+- (MDCCollectionViewCellStyle)cellStyleAtSectionIndex:(NSInteger)section;
+
+/**
+ The collection view cell background image view (utilized to render the background color and
+ shadows) edge outsets as determined for a cell and its layout attributes.
+
+ @param attr The cell's layout attributes.
+ @return Edge outsets as detemined by cell style at this index.
+ */
+- (UIEdgeInsets)backgroundImageViewOutsetsForCellWithAttribute:
+        (nonnull MDCCollectionViewLayoutAttributes *)attr;
+
+/**
+ Returns an image for use with the given cell style and ordinal position within section.
+
+ The returned image is cached internally after the first request. Changing any of the display
+ properties will invalidate the cached images.
+
+ @param attr The cell's layout attributes.
+ @return Image as determined by cell style and section ordinal position.
+ */
+- (nullable UIImage *)backgroundImageForCellLayoutAttributes:
+        (nonnull MDCCollectionViewLayoutAttributes *)attr;
+
+#pragma mark - Cell Separator
+
+/** Separator color. Defaults to #E0E0E0. */
+@property(nonatomic, strong, nullable) UIColor *separatorColor;
+
+/** Separator inset. Defaults to UIEdgeInsetsZero. */
+@property(nonatomic) UIEdgeInsets separatorInset;
+
+/** Separator line height. Defaults to 1.0f */
+@property(nonatomic) CGFloat separatorLineHeight;
+
+/* Whether to hide the cell separators. Defaults to NO. */
+@property(nonatomic) BOOL shouldHideSeparators;
+
+#pragma mark - Item Inlaying
+
+/**
+ Whether inlaying a collection view item is allowed. When an item is inlaid, it will be given
+ padding at its edges to make it inset from other sibling items. A typical use case for inlaying
+ is when setting a collection view into editing mode, in which each cell gets inlaid so that they
+ can individually be selected/unselected/swiped for deletion.
+
+ If YES, call the -inlayItemAtIndexPath:animated method to inlay the item at the specified
+ index path. Remove the inlay by calling the -removeInlayAtIndexPath:animated: method.
+ Not animated. Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL allowsItemInlay;
+
+/** Whether inlaying multiple items is allowed. Not animated. Defaults to NO. */
+@property(nonatomic, assign) BOOL allowsMultipleItemInlays;
+
+/**
+ Returns an array of collection view index paths for items that have their respective frames
+ inlaid.
+
+ @return An array of index paths.
+ */
+- (nullable NSArray<NSIndexPath *> *)indexPathsForInlaidItems;
+
+/**
+ A Boolean value indicating if the collection view item at the specified index path has its
+ frame inlaid.
+
+ @param indexPath The collection view index path.
+ @return YES if the cells are Material styled cards. Otherwise No.
+ */
+- (BOOL)isItemInlaidAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Inlays the item at the specified index path.
+
+ Property allowsItemInlay must be set to YES, otherwise no-op.
+
+ @param indexPath The specified index path.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)applyInlayToItemAtIndexPath:(nonnull NSIndexPath *)indexPath animated:(BOOL)animated;
+
+/**
+ Removes the inlaid state of the item at the specified index path.
+
+ @param indexPath The specified index path.
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)removeInlayFromItemAtIndexPath:(nonnull NSIndexPath *)indexPath animated:(BOOL)animated;
+
+/**
+ Inlays items at all available index paths.
+
+ Property allowsItemInlay must be set to YES, otherwise no-op.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)applyInlayToAllItemsAnimated:(BOOL)animated;
+
+/**
+ Removes the inlaid state of items at all available index paths.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)removeInlayFromAllItemsAnimated:(BOOL)animated;
+
+/**
+ Resets the internal storage array of all item index paths for inlaid items. When modifying
+ items in the collection view model, a call to this method will ensure that all inserted
+ and/or deleted index paths are reflected properly in the return array from the
+ method -indexPathsForInlaidItems. Calling this is not animated.
+ */
+- (void)resetIndexPathsForInlaidItems;
+
+#pragma mark - Cell Appearance Animation
+
+/**
+ Whether cells should animate on appearance. This property typically should be set in the
+ -viewDidLoad method of the controller. If YES, cells will animate the following properties:
+
+ A) Cell heights will begin expanded by the padding specified by animateCellsOnAppearancePadding.
+    It will then animate to original height.
+
+ B) Cell frame will begin with positive y-offset as specified by animateCellsOnAppearancePadding.
+    It will animate upwards to original y coordinate.
+
+ C) Cell contentView and separatorView will begin hidden by setting alpha to 0. It will then
+    animate with a fade-in transition in a staggered fashion from the top cell down to last
+    visible cell.
+ */
+@property(nonatomic, assign) BOOL shouldAnimateCellsOnAppearance;
+
+/** Whether cells should calculate their initial properties before animation on appearance. */
+@property(nonatomic, readonly, assign) BOOL willAnimateCellsOnAppearance;
+
+/*
+ The cell appearance animation padding. This value is ignored unless
+ shouldAnimateCellsOnAppearance is set to YES. Its value is set at initialization time by the
+ constant MDCCollectionViewAnimatedAppearancePadding.
+ */
+@property(nonatomic, readonly, assign) CGFloat animateCellsOnAppearancePadding;
+
+/*
+ The cell appearance animation duration. This value is ignored unless
+ shouldAnimateCellsOnAppearance is set to YES. Its value is set at initialization time by the
+ constant MDCCollectionViewAnimatedAppearanceDuration.
+ */
+@property(nonatomic, readonly, assign) NSTimeInterval animateCellsOnAppearanceDuration;
+
+/**
+ This method should only be called from MDCCollectionViewFlowLayout class once all visible
+ collection view attributes are available. By calling -updateLayoutAnimated within this method's
+ animation block, it will trigger the collection view to query both the item and supplementary
+ view sizing methods of the UICollectionViewDelegateFlowLayout protocol, resulting in an
+ animated resizing of the cells by the height specified in animateCellsOnAppearancePadding.
+ */
+- (void)beginCellAppearanceAnimation;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
new file mode 100644
index 0000000..620cde6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MDCCollectionViewStylingDelegate.h
@@ -0,0 +1,151 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCCollectionViewStyling.h"
+
+@class MDCInkTouchController;
+@class MDCInkView;
+
+/** A delegate protocol which allows setting collection view cell styles. */
+@protocol MDCCollectionViewStylingDelegate <NSObject>
+@optional
+
+#pragma mark - Styling
+
+/**
+ Asks the delegate for the cell height at the specified collection view index path. The style
+ controller will make padding/insets adjustments to this value as needed depending on the cell
+ style and editing mode.
+
+ @param collectionView The collection view.
+ @param indexPath The item's index path.
+ @return The cell height at the specified index path.
+ */
+- (CGFloat)collectionView:(nonnull UICollectionView *)collectionView
+    cellHeightAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate for the cell style at the specified collection view section index. All
+ remaining sections to have their cells styled per the styler @c cellStyle property.
+
+ @param collectionView The collection view.
+ @param section The collection view section.
+ @return The cell style to be used at the specified index.
+ */
+- (MDCCollectionViewCellStyle)collectionView:(nonnull UICollectionView *)collectionView
+                         cellStyleForSection:(NSInteger)section;
+
+/**
+ Asks the delegate for the cell background color at the specified collection view index path.
+
+ @param collectionView The collection view.
+ @param indexPath The item's index path.
+ @return The cell background color at the specified index path.
+ */
+- (nullable UIColor *)collectionView:(nonnull UICollectionView *)collectionView
+      cellBackgroundColorAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate whether the specified item should hide its background image/shadowing.
+
+ @param collectionView The collection view.
+ @param indexPath The item's index path.
+ @return If the item background should be hidden at the specified index path.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHideItemBackgroundAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate whether the specified header should hide its background image/shadowing.
+
+ @param collectionView The collection view.
+ @param section The collection view section.
+ @return If the header background should be hidden at the specified section.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHideHeaderBackgroundForSection:(NSInteger)section;
+
+/**
+ Asks the delegate whether the specified footer should hide its background image/shadowing.
+
+ @param collectionView The collection view.
+ @param section The collection view section.
+ @return If the footer background should be hidden at the specified section.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    shouldHideFooterBackgroundForSection:(NSInteger)section;
+
+#pragma mark - Item inlaying
+
+/**
+ Allows the receiver to receive notification that items at the specified index paths did
+ inlay their frame.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didApplyInlayToItemAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+/**
+ Allows the receiver to receive notification that items at the specified index paths did
+ remove the inlay of their frames.
+
+ @param collectionView The collection view.
+ @param indexPaths An array of index paths.
+ */
+- (void)collectionView:(nonnull UICollectionView *)collectionView
+    didRemoveInlayFromItemAtIndexPaths:(nonnull NSArray<NSIndexPath *> *)indexPaths;
+
+#pragma mark - Ink Touches
+
+/**
+ Asks the delegate whether the inkView for a specified index path should be hidden.
+
+ @param collectionView The collection view.
+ @param indexPath The collection view index path.
+ @return If the ink view should be hidden at the specified index path.
+ */
+- (BOOL)collectionView:(nonnull UICollectionView *)collectionView
+    hidesInkViewAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Asks the delegate for the ink color at the specified index path.
+
+ If nil, defaults to MDCInkView defaultInkColor.
+
+ @param collectionView The collection view.
+ @param indexPath The collection view index path.
+ @return The ink color at the specified index path.
+ */
+- (nullable UIColor *)collectionView:(nonnull UICollectionView *)collectionView
+                 inkColorAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+/**
+ Allows the receiver to set the ink view at the specified collection view index path.
+
+ @param collectionView The collection view.
+ @param inkTouchController The ink controller of the ink view.
+ @param indexPath The collection view index path.
+ @return The inkView to be used at the specified index path.
+ */
+- (nonnull MDCInkView *)collectionView:(nonnull UICollectionView *)collectionView
+                    inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+                    inkViewAtIndexPath:(nonnull NSIndexPath *)indexPath;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MaterialCollections.bundle/Resources/en.lproj/MaterialCollections.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MaterialCollections.bundle/Resources/en.lproj/MaterialCollections.strings
new file mode 100644
index 0000000..4e9cd34
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MaterialCollections.bundle/Resources/en.lproj/MaterialCollections.strings
@@ -0,0 +1,4 @@
+/* Label for a button indicating a collectionView row can be deleted. (40 chars.) */
+"DeleteButton" = "Delete";
+/* Label for info bar indicating available editing gestures for collectionView. (40 chars.) */
+"InfoBarGestureHint" = "Swipe an item to delete";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MaterialCollections.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MaterialCollections.h
new file mode 100644
index 0000000..2190414
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/MaterialCollections.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewController.h"
+#import "MDCCollectionViewEditing.h"
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MDCCollectionViewFlowLayout.h"
+#import "MDCCollectionViewStyling.h"
+#import "MDCCollectionViewStylingDelegate.h"
+#import "MaterialCollectionCells.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h
new file mode 100644
index 0000000..04b2e4d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The MDCCollectionGridBackgroundView class provides an implementation of UICollectionReusableView
+ that displays a background view under cells at each section of a collection view in grid layout.
+
+ This will only happen for a grid layout when it is either A) grouped-style or B) card-style with
+ zero padding. When this happens, the background for the section cells will not be drawn, and
+ instead this view will extend to the bounds of the sum of its respective section item frames.
+ */
+@interface MDCCollectionGridBackgroundView : UICollectionReusableView
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.m
new file mode 100644
index 0000000..9101e33
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionGridBackgroundView.m
@@ -0,0 +1,56 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionGridBackgroundView.h"
+
+#import "MaterialCollectionLayoutAttributes.h"
+
+@implementation MDCCollectionGridBackgroundView {
+  UIImageView *_backgroundImageView;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionGridBackgroundViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionGridBackgroundViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionGridBackgroundViewInit {
+  _backgroundImageView = [[UIImageView alloc] initWithFrame:self.bounds];
+  _backgroundImageView.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+  [self addSubview:_backgroundImageView];
+}
+
+- (void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
+  [super applyLayoutAttributes:layoutAttributes];
+  NSAssert([layoutAttributes isKindOfClass:[MDCCollectionViewLayoutAttributes class]],
+           @"LayoutAttributes must be a subclass of MDCCollectionViewLayoutAttributes.");
+  MDCCollectionViewLayoutAttributes *attr = (MDCCollectionViewLayoutAttributes *)layoutAttributes;
+  _backgroundImageView.image = attr.backgroundImage;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h
new file mode 100644
index 0000000..3b079db
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.h
@@ -0,0 +1,184 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCCollectionInfoBarView;
+
+/** The info bar supplementary view kind when shown in header. */
+extern NSString *_Nonnull const MDCCollectionInfoBarKindHeader;
+
+/** The info bar supplementary view kind when shown in footer. */
+extern NSString *_Nonnull const MDCCollectionInfoBarKindFooter;
+
+/** The animation duration for the info bar. */
+extern const CGFloat MDCCollectionInfoBarAnimationDuration;
+
+/** Height for the info bar when shown in header. */
+extern const CGFloat MDCCollectionInfoBarHeaderHeight;
+
+/** Height for the info bar when shown in footer. */
+extern const CGFloat MDCCollectionInfoBarFooterHeight;
+
+/** The available styles that the info bar can be shown within a collectionView. */
+typedef NS_ENUM(NSUInteger, MDCCollectionInfoBarViewStyle) {
+  MDCCollectionInfoBarViewStyleActionable,
+  MDCCollectionInfoBarViewStyleHUD
+};
+
+/** Delegate protocol for the MDCCollectionInfoBarView. */
+@protocol MDCCollectionInfoBarViewDelegate <NSObject>
+@required
+/**
+ Allows the receiver to update the info bar after it has been created.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ */
+- (void)updateControllerWithInfoBar:(nonnull MDCCollectionInfoBarView *)infoBar;
+
+@optional
+/**
+ Allows the receiver to get notifed when a tap gesture has been performed on the info bar.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ */
+- (void)didTapInfoBar:(nonnull MDCCollectionInfoBarView *)infoBar;
+
+/**
+ Allows the receiver to get notifed when an info bar will show.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition will be animated; otherwise, NO.
+ @param willAutoDismiss YES the info bar will be auto-dismissed after the time interval
+        set in @c autoDismissAfterDuration.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    willShowAnimated:(BOOL)animated
+     willAutoDismiss:(BOOL)willAutoDismiss;
+
+/**
+ Allows the receiver to get notifed after an info bar did show.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition was animated; otherwise, NO.
+ @param willAutoDismiss YES the info bar will be auto-dismissed after the time interval
+        set in @c autoDismissAfterDuration.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    didShowAnimated:(BOOL)animated
+    willAutoDismiss:(BOOL)willAutoDismiss;
+
+/**
+ Allows the receiver to get notifed when an info bar will dismiss.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition will be animated; otherwise, NO.
+ @param willAutoDismiss YES the info bar will be auto-dismissed after the time interval
+        set in @c autoDismissAfterDuration.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    willDismissAnimated:(BOOL)animated
+        willAutoDismiss:(BOOL)willAutoDismiss;
+
+/**
+ Allows the receiver to get notifed after an info bar has been dismissed.
+
+ @param infoBar The MDCCollectionInfoBarView info bar.
+ @param animated YES the transition was animated; otherwise, NO.
+ @param didAutoDismiss YES the info bar was auto-dismissed.
+ */
+- (void)infoBar:(nonnull MDCCollectionInfoBarView *)infoBar
+    didDismissAnimated:(BOOL)animated
+        didAutoDismiss:(BOOL)didAutoDismiss;
+
+@end
+
+/**
+ The MDCCollectionInfoBarView class provides an implementation of
+ UICollectionReusableView that displays an animated view in either the header
+ or footer.
+ */
+@interface MDCCollectionInfoBarView : UICollectionReusableView
+
+/** A delegate through which the MDCCollectionInfoBarView may inform of updates. */
+@property(nonatomic, weak, nullable) id<MDCCollectionInfoBarViewDelegate> delegate;
+
+/** The background view containing the message label. This view is animatable on show/dismiss. */
+@property(nonatomic, readonly, strong, nullable) UIView *backgroundView;
+
+/** Whether the background view should be shown with a shadow. */
+@property(nonatomic, assign) BOOL shouldApplyBackgroundViewShadow;
+
+/**
+ The color assigned to the background view.
+
+ Defaults to #448AFF for header, and white for footer.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *tintColor;
+
+/**
+ The color assigned to the info bar message label.
+
+ Defaults to white for header, and #F44336 for footer.
+ */
+@property(nonatomic, strong, nullable) UIColor *titleColor;
+
+/** The info bar message label. */
+@property(nonatomic, readonly, strong, nullable) UILabel *titleLabel;
+
+/** The info bar message text. */
+@property(nonatomic, strong, nullable) NSString *message;
+
+/** The horizontal position of bar message. */
+@property(nonatomic, assign) NSTextAlignment textAlignment;
+
+/** Whether the background view can receive a tap gesture. */
+@property(nonatomic, assign) BOOL allowsTap;
+
+/** The optional style that the info bar can be shown. */
+@property(nonatomic, assign) MDCCollectionInfoBarViewStyle style;
+
+/**
+ The info bar supplementary view kind as set by the collectionView model
+ |collectionView:viewForSupplementaryElementOfKind:atIndexPath| method. Possible values
+ are MDCCollectionInfoBarKindHeader or MDCCollectionInfoBarKindFooter.
+ */
+@property(nonatomic, strong, nonnull) NSString *kind;
+
+/**
+ The desired duration after which the info bar will be automatically dismissed. If set to
+ 0, autoDismiss will be ignored.
+ */
+@property(nonatomic, assign) NSTimeInterval autoDismissAfterDuration;
+
+/** Whether the info bar is currently being shown. */
+@property(nonatomic, readonly, assign) BOOL isVisible;
+
+/**
+ Shows the info bar with/without animation.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)showAnimated:(BOOL)animated;
+
+/**
+ Dismisses the info bar with/without animation.
+
+ @param animated YES the transition will be animated; otherwise, NO.
+ */
+- (void)dismissAnimated:(BOOL)animated;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.m
new file mode 100644
index 0000000..7d7c4ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionInfoBarView.m
@@ -0,0 +1,254 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionInfoBarView.h"
+
+#import "MaterialShadowLayer.h"
+#import "MaterialTypography.h"
+
+NSString *const MDCCollectionInfoBarKindHeader = @"MDCCollectionInfoBarKindHeader";
+NSString *const MDCCollectionInfoBarKindFooter = @"MDCCollectionInfoBarKindFooter";
+
+const CGFloat MDCCollectionInfoBarAnimationDuration = 0.3f;
+const CGFloat MDCCollectionInfoBarHeaderHeight = 48.0f;
+const CGFloat MDCCollectionInfoBarFooterHeight = 48.0f;
+
+static const CGFloat MDCCollectionInfoBarLabelHorizontalPadding = 16.0f;
+
+// Colors derived from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t kCollectionInfoBarBlueColor = 0x448AFF;  // Blue A200
+static const uint32_t kCollectionInfoBarRedColor = 0xF44336;   // Red 500
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+@interface ShadowedView : UIView
+@end
+
+@implementation ShadowedView
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+@end
+
+@implementation MDCCollectionInfoBarView {
+  CGFloat _backgroundTransformY;
+  CALayer *_backgroundBorderLayer;
+  UITapGestureRecognizer *_tapGesture;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCCollectionInfoBarViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCCollectionInfoBarViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCCollectionInfoBarViewInit {
+  self.backgroundColor = [UIColor clearColor];
+  self.userInteractionEnabled = NO;
+  _backgroundView = [[ShadowedView alloc] initWithFrame:self.bounds];
+  _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  _backgroundView.hidden = YES;
+
+  _titleLabel = [[UILabel alloc]
+      initWithFrame:CGRectInset(self.bounds, MDCCollectionInfoBarLabelHorizontalPadding, 0)];
+  _titleLabel.backgroundColor = [UIColor clearColor];
+  _titleLabel.textAlignment = NSTextAlignmentCenter;
+  _titleLabel.font = [MDCTypography body1Font];
+  _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  [_backgroundView addSubview:_titleLabel];
+
+  [self addSubview:_backgroundView];
+
+  _tapGesture =
+      [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
+  [_backgroundView addGestureRecognizer:_tapGesture];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  if (_shouldApplyBackgroundViewShadow) {
+    [self setShouldApplyBackgroundViewShadow:_shouldApplyBackgroundViewShadow];
+  }
+}
+
+- (void)layoutSublayersOfLayer:(CALayer *)layer {
+  [super layoutSublayersOfLayer:layer];
+  // Set border layer frame.
+  _backgroundBorderLayer.frame = CGRectMake(-1, 0, CGRectGetWidth(self.backgroundView.bounds) + 2,
+                                            CGRectGetHeight(self.backgroundView.bounds) + 1);
+}
+
+- (void)setTintColor:(UIColor *)tintColor {
+  _tintColor = tintColor;
+  _backgroundView.backgroundColor = _tintColor;
+}
+
+- (void)setMessage:(NSString *)message {
+  _message = message;
+  _titleLabel.text = message;
+}
+
+- (void)setKind:(NSString *)kind {
+  _kind = kind;
+  if ([kind isEqualToString:MDCCollectionInfoBarKindHeader]) {
+    _backgroundTransformY = -MDCCollectionInfoBarHeaderHeight;
+  } else {
+    _backgroundTransformY = MDCCollectionInfoBarFooterHeight;
+  }
+  _backgroundView.transform = CGAffineTransformMakeTranslation(0, _backgroundTransformY);
+}
+
+- (void)setShouldApplyBackgroundViewShadow:(BOOL)shouldApplyBackgroundViewShadow {
+  _shouldApplyBackgroundViewShadow = shouldApplyBackgroundViewShadow;
+  MDCShadowLayer *shadowLayer = (MDCShadowLayer *)_backgroundView.layer;
+  shadowLayer.elevation = shouldApplyBackgroundViewShadow ? 1 : 0;
+}
+
+- (void)setTextAlignment:(NSTextAlignment)textAlignment {
+  _textAlignment = textAlignment;
+  _titleLabel.textAlignment = textAlignment;
+}
+
+- (void)setStyle:(MDCCollectionInfoBarViewStyle)style {
+  _style = style;
+  if (style == MDCCollectionInfoBarViewStyleHUD) {
+    self.allowsTap = NO;
+    self.shouldApplyBackgroundViewShadow = NO;
+    self.textAlignment = NSTextAlignmentLeft;
+    self.tintColor = ColorFromRGB(kCollectionInfoBarBlueColor);
+    self.titleLabel.textColor = [UIColor whiteColor];
+    self.autoDismissAfterDuration = 1.0f;
+    self.backgroundView.alpha = 0.9f;
+  } else if (style == MDCCollectionInfoBarViewStyleActionable) {
+    self.allowsTap = YES;
+    self.shouldApplyBackgroundViewShadow = YES;
+    self.textAlignment = NSTextAlignmentCenter;
+    self.tintColor = [UIColor whiteColor];
+    self.titleLabel.textColor = ColorFromRGB(kCollectionInfoBarRedColor);
+    self.autoDismissAfterDuration = 0.0f;
+    self.backgroundView.alpha = 1.0f;
+    self.isAccessibilityElement = YES;
+    self.accessibilityTraits = UIAccessibilityTraitButton;
+    self.accessibilityLabel = self.message;
+
+    // Adds border to be positioned during sublayer layout.
+    self.backgroundView.clipsToBounds = YES;
+    if (!_backgroundBorderLayer) {
+      _backgroundBorderLayer = [CALayer layer];
+      _backgroundBorderLayer.borderColor = [UIColor colorWithWhite:0 alpha:0.1f].CGColor;
+      _backgroundBorderLayer.borderWidth = 1.0f / [[UIScreen mainScreen] scale];
+      [self.backgroundView.layer addSublayer:_backgroundBorderLayer];
+    }
+  }
+}
+
+- (BOOL)isVisible {
+  return !_backgroundView.hidden;
+}
+
+- (void)showAnimated:(BOOL)animated {
+  _backgroundView.hidden = NO;
+  // Notify delegate.
+  if ([_delegate respondsToSelector:@selector(infoBar:willShowAnimated:willAutoDismiss:)]) {
+    [_delegate infoBar:self willShowAnimated:animated willAutoDismiss:[self shouldAutoDismiss]];
+  }
+
+  NSTimeInterval duration = (animated) ? MDCCollectionInfoBarAnimationDuration : 0.0f;
+  [UIView animateWithDuration:duration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseOut
+      animations:^{
+        _backgroundView.transform = CGAffineTransformIdentity;
+      }
+      completion:^(BOOL finished) {
+        self.userInteractionEnabled = _allowsTap;
+
+        // Notify delegate.
+        if ([_delegate respondsToSelector:@selector(infoBar:didShowAnimated:willAutoDismiss:)]) {
+          [_delegate infoBar:self
+              didShowAnimated:animated
+              willAutoDismiss:[self shouldAutoDismiss]];
+        }
+
+        [self autoDismissIfNecessaryWithAnimation:animated];
+      }];
+}
+
+- (void)dismissAnimated:(BOOL)animated {
+  // Notify delegate.
+  if ([_delegate respondsToSelector:@selector(infoBar:willDismissAnimated:willAutoDismiss:)]) {
+    [_delegate infoBar:self willDismissAnimated:animated willAutoDismiss:[self shouldAutoDismiss]];
+  }
+
+  NSTimeInterval duration = (animated) ? MDCCollectionInfoBarAnimationDuration : 0.0f;
+  [UIView animateWithDuration:duration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseIn
+      animations:^{
+        _backgroundView.transform = CGAffineTransformMakeTranslation(0, _backgroundTransformY);
+      }
+      completion:^(BOOL finished) {
+        self.userInteractionEnabled = NO;
+        _backgroundView.hidden = YES;
+
+        // Notify delegate.
+        if ([_delegate respondsToSelector:@selector(infoBar:didDismissAnimated:didAutoDismiss:)]) {
+          [_delegate infoBar:self
+              didDismissAnimated:animated
+                  didAutoDismiss:[self shouldAutoDismiss]];
+        }
+      }];
+}
+
+#pragma mark - Private
+
+- (void)handleTapGesture:(UITapGestureRecognizer *)recognizer {
+  if ([_delegate respondsToSelector:@selector(didTapInfoBar:)]) {
+    [_delegate didTapInfoBar:self];
+  }
+}
+
+- (BOOL)shouldAutoDismiss {
+  return (_autoDismissAfterDuration > 0);
+}
+
+- (void)autoDismissIfNecessaryWithAnimation:(BOOL)animation {
+  if ([self shouldAutoDismiss]) {
+    dispatch_time_t popTime =
+        dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoDismissAfterDuration * NSEC_PER_SEC));
+    dispatch_after(popTime, dispatch_get_main_queue(), ^{
+      [self dismissAnimated:animation];
+    });
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h
new file mode 100644
index 0000000..9390b5b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.h
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ Shorthand for returning a resource from MDCCollectionStringResources's singleton.
+ */
+#define MDCCollectionStringResources(sel) [[MDCCollectionStringResources sharedInstance] sel]
+
+/** String resources that are used for collection views. */
+@interface MDCCollectionStringResources : NSObject
+
+/** Returns the shared resources singleton instance. */
++ (nonnull instancetype)sharedInstance;
+
+/** Returns cell delete string. */
+- (nonnull NSString *)deleteButtonString;
+
+/** Returns cell gesture hint string. */
+- (nonnull NSString *)infoBarGestureHintString;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.m
new file mode 100644
index 0000000..9e269c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionStringResources.m
@@ -0,0 +1,72 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionStringResources.h"
+
+#import "MaterialCollectionsStrings.h"
+#import "MaterialCollectionsStrings_table.h"
+
+// The Bundle for string resources.
+static NSString *const kBundleName = @"MaterialCollections.bundle";
+
+@implementation MDCCollectionStringResources
+
++ (instancetype)sharedInstance {
+  static MDCCollectionStringResources *sharedInstance;
+  @synchronized(self) {
+    if (sharedInstance == nil) {
+      sharedInstance = [[MDCCollectionStringResources alloc] init];
+    }
+  }
+  return sharedInstance;
+}
+
+- (NSString *)stringForId:(MaterialCollectionsStringId)stringID {
+  NSString *stringKey = kMaterialCollectionsStringTable[stringID];
+  NSBundle *bundle = [[self class] bundle];
+  NSString *tableName = [kBundleName stringByDeletingPathExtension];
+  return [bundle localizedStringForKey:stringKey value:nil table:tableName];
+}
+
+- (NSString *)deleteButtonString {
+  return [self stringForId:kStr_MaterialCollectionsDeleteButton];
+}
+
+- (NSString *)infoBarGestureHintString {
+  return [self stringForId:kStr_MaterialCollectionsInfoBarGestureHint];
+}
+
+#pragma mark - Resource bundle
+
++ (NSBundle *)bundle {
+  static NSBundle *bundle = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    bundle = [NSBundle bundleWithPath:[self bundlePathWithName:kBundleName]];
+  });
+
+  return bundle;
+}
+
++ (NSString *)bundlePathWithName:(NSString *)bundleName {
+  // In iOS 8+, we could be included by way of a dynamic framework, and our resource bundles may
+  // not be in the main .app bundle, but rather in a nested framework, so figure out where we live
+  // and use that as the search location.
+  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+  NSString *resourcePath = [(nil == bundle ? [NSBundle mainBundle] : bundle)resourcePath];
+  return [resourcePath stringByAppendingPathComponent:bundleName];
+}
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h
new file mode 100644
index 0000000..e020ef8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewEditing.h"
+
+/**
+ The MDCCollectionViewEditingManager class provides an implementation for a UICollectionView to
+ set its editing properties.
+ */
+@interface MDCCollectionViewEditor : NSObject <MDCCollectionViewEditing>
+
+/**
+ Initialize the controller with a collection view.
+
+ Designated initializer.
+
+ @param collectionView The controller's collection view.
+ */
+- (nonnull instancetype)initWithCollectionView:(nullable UICollectionView *)collectionView
+    NS_DESIGNATED_INITIALIZER;
+
+/** Use initWithCollectionView: instead. */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/** Use initWithCollectionView: instead. */
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.m
new file mode 100644
index 0000000..9a4a25e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewEditor.m
@@ -0,0 +1,819 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewEditor.h"
+
+#import "MDCCollectionViewEditingDelegate.h"
+#import "MaterialShadowLayer.h"
+
+#import <tgmath.h>
+
+// Distance from center before we start fading the item.
+static const CGFloat kDismissalDistanceBeforeFading = 50.0f;
+
+// Minimum alpha for an item being dismissed.
+static const CGFloat kDismissalMinimumAlpha = 0.5f;
+
+// Final angle of the arc the item travels through during dismissal.
+static const CGFloat kDismissalArcAngle = (CGFloat)(M_PI / 6.0f);
+
+// The centroid for the item dismissal arc.
+static const CGFloat kDismissalArcYOffset = 400.0f;
+
+// Simple linear friction applied to swipe velocity.
+static const CGFloat kDismissalSwipeFriction = 0.05f;
+
+// Animation duration for dismissal / restore.
+static const NSTimeInterval kDismissalAnimationDuration = 0.3;
+static const NSTimeInterval kRestoreAnimationDuration = 0.2;
+
+// Distance from collection view bounds that reorder panning should trigger autoscroll.
+static const CGFloat kMDCAutoscrollPanningBuffer = 60.0f;
+
+// Distance collection view should offset during autoscroll.
+static const CGFloat kMDCAutoscrollPanningOffset = 10.0f;
+
+/** Autoscroll panning direction. */
+typedef NS_ENUM(NSInteger, MDCAutoscrollPanningDirection) {
+  kMDCAutoscrollPanningDirectionNone,
+  kMDCAutoscrollPanningDirectionUp,
+  kMDCAutoscrollPanningDirectionDown
+};
+
+/** A view that uses an MDCShadowLayer as its sublayer. */
+@interface ShadowedSnapshotView : UIView
+@end
+
+@implementation ShadowedSnapshotView
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+@end
+
+@interface MDCCollectionViewEditor () <UIGestureRecognizerDelegate>
+@end
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCCollectionViewEditor () <CAAnimationDelegate>
+@end
+#endif
+
+@implementation MDCCollectionViewEditor {
+  UILongPressGestureRecognizer *_longPressGestureRecognizer;
+  UIPanGestureRecognizer *_panGestureRecognizer;
+  CGPoint _selectedCellLocation;
+  CGPoint _initialCellLocation;
+  ShadowedSnapshotView *_cellSnapshot;
+  CADisplayLink *_autoscrollTimer;
+  MDCAutoscrollPanningDirection _autoscrollPanningDirection;
+}
+
+@synthesize collectionView = _collectionView;
+@synthesize delegate = _delegate;
+@synthesize reorderingCellIndexPath = _reorderingCellIndexPath;
+@synthesize dismissingCellIndexPath = _dismissingCellIndexPath;
+@synthesize dismissingSection = _dismissingSection;
+@synthesize editing = _editing;
+
+#pragma mark - Public
+
+- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
+  self = [super init];
+  if (self) {
+    _collectionView = collectionView;
+    _dismissingSection = NSNotFound;
+
+    // Setup gestures to handle collectionView editing.
+
+    SEL longPressSelector = @selector(handleLongPressGesture:);
+    _longPressGestureRecognizer =
+        [[UILongPressGestureRecognizer alloc] initWithTarget:self action:longPressSelector];
+    _longPressGestureRecognizer.delegate = self;
+    [_collectionView addGestureRecognizer:_longPressGestureRecognizer];
+
+    SEL panSelector = @selector(handlePanGesture:);
+    _panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:panSelector];
+    _panGestureRecognizer.delegate = self;
+    [_collectionView addGestureRecognizer:_panGestureRecognizer];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  _longPressGestureRecognizer.delegate = nil;
+  _panGestureRecognizer.delegate = nil;
+
+  // Remove gesture recognizers to prevent duplicates when re-initializing this controller.
+  [_collectionView removeGestureRecognizer:_longPressGestureRecognizer];
+  [_collectionView removeGestureRecognizer:_panGestureRecognizer];
+}
+
+- (void)setEditing:(BOOL)editing {
+  [self setEditing:editing animated:NO];
+}
+
+- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
+  _editing = editing;
+  _collectionView.allowsMultipleSelection = editing;
+
+  // Clear any selected indexPaths.
+  for (NSIndexPath *indexPath in [_collectionView indexPathsForSelectedItems]) {
+    [_collectionView deselectItemAtIndexPath:indexPath animated:NO];
+  }
+
+  [CATransaction begin];
+  if (editing) {
+    // Notify delegate will begin editing.
+    if ([_delegate respondsToSelector:@selector(collectionViewWillBeginEditing:)]) {
+      [_delegate collectionViewWillBeginEditing:_collectionView];
+    }
+
+    [CATransaction setCompletionBlock:^{
+      // Notify delegate did begin editing.
+      if ([_delegate respondsToSelector:@selector(collectionViewDidBeginEditing:)]) {
+        [_delegate collectionViewDidBeginEditing:_collectionView];
+      }
+    }];
+
+  } else {
+    // Notify delegate will end editing.
+    if ([_delegate respondsToSelector:@selector(collectionViewWillEndEditing:)]) {
+      [_delegate collectionViewWillEndEditing:_collectionView];
+    }
+
+    [CATransaction setCompletionBlock:^{
+      // Notify delegate did end editing.
+      if ([_delegate respondsToSelector:@selector(collectionViewDidEndEditing:)]) {
+        [_delegate collectionViewDidEndEditing:_collectionView];
+      }
+    }];
+  }
+  [CATransaction commit];
+}
+
+#pragma mark - Private
+
+- (NSArray *)attributesAtSection:(NSInteger)section {
+  UICollectionViewLayout *layout = _collectionView.collectionViewLayout;
+  NSIndexPath *indexPath;
+  NSMutableArray *sectionAttributes = [NSMutableArray array];
+
+  // Get all item attributes at section.
+  NSInteger numberOfItemsInSection = [_collectionView numberOfItemsInSection:section];
+
+  for (NSInteger i = 0; i < numberOfItemsInSection; ++i) {
+    indexPath = [NSIndexPath indexPathForItem:i inSection:section];
+    UICollectionViewLayoutAttributes *attribute =
+        [layout layoutAttributesForItemAtIndexPath:indexPath];
+    [sectionAttributes addObject:attribute];
+  }
+
+  // Headers/footers require section but ignore item of index path, so set to zero.
+  indexPath = [NSIndexPath indexPathForItem:0 inSection:section];
+
+  // Get header attributes at section.
+  UICollectionViewLayoutAttributes *headerAttribute =
+      [layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
+                                             atIndexPath:indexPath];
+  [sectionAttributes addObject:headerAttribute];
+
+  // Get footer attributes at section.
+  UICollectionViewLayoutAttributes *footerAttribute =
+      [layout layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter
+                                             atIndexPath:indexPath];
+  [sectionAttributes addObject:footerAttribute];
+
+  return sectionAttributes;
+}
+
+- (NSInteger)swipedSectionAtLocation:(CGPoint)location {
+  // Returns section index being swiped for dismissal, or NSNotFound for an invalid swipes
+  // where location does not return an item or section header/footer.
+  CGRect contentFrame = _collectionView.frame;
+  contentFrame.size = _collectionView.contentSize;
+  NSArray *visibleAttributes =
+      [_collectionView.collectionViewLayout layoutAttributesForElementsInRect:contentFrame];
+  for (UICollectionViewLayoutAttributes *attribute in visibleAttributes) {
+    if (!CGRectIsNull(attribute.frame) && CGRectContainsPoint(attribute.frame, location)) {
+      return attribute.indexPath.section;
+    }
+  }
+  return NSNotFound;
+}
+
+#pragma mark - Snapshotting
+
+- (UIView *)snapshotWithIndexPath:(NSIndexPath *)indexPath {
+  // Here we will take a snapshot of the collectionView item.
+  if (_cellSnapshot) {
+    [_cellSnapshot removeFromSuperview];
+    _cellSnapshot = nil;
+  }
+
+  // Create snapshot.
+  UICollectionViewLayoutAttributes *attributes =
+      [_collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
+  _cellSnapshot = [[ShadowedSnapshotView alloc] initWithFrame:attributes.frame];
+  UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath];
+  [_cellSnapshot addSubview:[cell snapshotViewAfterScreenUpdates:NO]];
+
+  // Invalidate layout here to force attributes to now be hidden.
+  [_collectionView.collectionViewLayout invalidateLayout];
+  return _cellSnapshot;
+}
+
+- (UIView *)snapshotWithSection:(NSInteger)section {
+  // Here we will take a snapshot of the collectionView section items, header, and footer.
+  if (_cellSnapshot) {
+    [_cellSnapshot removeFromSuperview];
+    _cellSnapshot = nil;
+  }
+
+  // The snapshot frame encompasses all of the section items, header, and footer attribute frames.
+  NSArray *sectionAttributes = [self attributesAtSection:section];
+  CGRect snapshotFrame = CGRectNull;
+  for (UICollectionViewLayoutAttributes *attribute in sectionAttributes) {
+    if (!CGRectIsNull(attribute.frame) && !CGRectIsInfinite(attribute.frame)) {
+      snapshotFrame = CGRectUnion(snapshotFrame, attribute.frame);
+    }
+  }
+
+  // Create snapshot.
+  _cellSnapshot = [[ShadowedSnapshotView alloc] initWithFrame:snapshotFrame];
+  UIImageView *snapshotView =
+      [[UIImageView alloc] initWithImage:[self snapshotWithRect:snapshotFrame]];
+  [_cellSnapshot addSubview:snapshotView];
+
+  // Invalidate layout here to force attributes to now be hidden.
+  [_collectionView.collectionViewLayout invalidateLayout];
+  return _cellSnapshot;
+}
+
+- (UIImage *)snapshotWithRect:(CGRect)rect {
+  // Here we will take a snapshot of a rect within the collectionView.
+  UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
+  CGContextRef cx = UIGraphicsGetCurrentContext();
+  CGContextTranslateCTM(cx, -rect.origin.x, -rect.origin.y);
+
+  // Save original collection view properties.
+  id<UICollectionViewDelegate> savedDelegate = _collectionView.delegate;
+  _collectionView.delegate = nil;
+  CGPoint savedContentOffset = _collectionView.contentOffset;
+  BOOL savedClipsToBounds = _collectionView.clipsToBounds;
+  _collectionView.clipsToBounds = NO;
+
+  // Hide any scroll indicators.
+  BOOL showsHorizontalScrollIndicator = _collectionView.showsHorizontalScrollIndicator;
+  BOOL showsVerticalScrollIndicator = _collectionView.showsVerticalScrollIndicator;
+  _collectionView.showsHorizontalScrollIndicator = NO;
+  _collectionView.showsVerticalScrollIndicator = NO;
+
+  // Render snapshot.
+  [_collectionView.layer renderInContext:cx];
+  _collectionView.layer.rasterizationScale = [UIScreen mainScreen].scale;
+  _collectionView.layer.shouldRasterize = YES;
+  UIImage *screenshotImage = UIGraphicsGetImageFromCurrentImageContext();
+
+  // Reset collection view.
+  _collectionView.contentOffset = savedContentOffset;
+  _collectionView.showsHorizontalScrollIndicator = showsHorizontalScrollIndicator;
+  _collectionView.showsVerticalScrollIndicator = showsVerticalScrollIndicator;
+  _collectionView.delegate = savedDelegate;
+  _collectionView.clipsToBounds = savedClipsToBounds;
+  _collectionView.layer.shouldRasterize = NO;
+
+  UIGraphicsEndImageContext();
+  return screenshotImage;
+}
+
+- (void)applyLayerShadowing:(CALayer *)layer {
+  MDCShadowLayer *shadowLayer = (MDCShadowLayer *)_cellSnapshot.layer;
+  shadowLayer.shadowMaskEnabled = NO;
+  shadowLayer.elevation = 3;
+}
+
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
+  if ([gestureRecognizer isEqual:_longPressGestureRecognizer]) {
+    // Only allow longpress if collectionView is editing.
+    return self.isEditing;
+
+  } else if ([gestureRecognizer isEqual:_panGestureRecognizer]) {
+    // Only allow panning if collectionView is editing or dismissing item/section.
+    BOOL allowsSwipeToDismissItem = NO;
+    if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissItem:)]) {
+      allowsSwipeToDismissItem = [_delegate collectionViewAllowsSwipeToDismissItem:_collectionView];
+    }
+
+    BOOL allowsSwipeToDismissSection = NO;
+    if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissSection:)]) {
+      allowsSwipeToDismissSection =
+          [_delegate collectionViewAllowsSwipeToDismissSection:_collectionView];
+    }
+    return (self.isEditing || allowsSwipeToDismissItem || allowsSwipeToDismissSection);
+  }
+  return YES;
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+    shouldRecognizeSimultaneouslyWithGestureRecognizer:
+        (UIGestureRecognizer *)otherGestureRecognizer {
+  return YES;
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+    shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
+  // Prevent panning to dismiss when scrolling.
+  return ([gestureRecognizer isEqual:_panGestureRecognizer] &&
+          [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]);
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+       shouldReceiveTouch:(UITouch *)touch {
+  if (self.isEditing) {
+    return YES;
+  } else {
+    return NO;
+  }
+}
+
+#pragma mark - LongPress Gesture Handling
+
+- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)recognizer {
+  switch (recognizer.state) {
+    case UIGestureRecognizerStateBegan: {
+      _initialCellLocation = [recognizer locationInView:_collectionView];
+      _selectedCellLocation = [recognizer locationInView:_collectionView];
+      _reorderingCellIndexPath = [_collectionView indexPathForItemAtPoint:_selectedCellLocation];
+
+      if ([_delegate respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] &&
+          ![_delegate collectionView:_collectionView
+              canMoveItemAtIndexPath:_reorderingCellIndexPath]) {
+        _reorderingCellIndexPath = nil;
+        return;
+      }
+
+      // Notify delegate dragging has began.
+      if ([_delegate
+              respondsToSelector:@selector(collectionView:willBeginDraggingItemAtIndexPath:)]) {
+        [_delegate collectionView:_collectionView
+            willBeginDraggingItemAtIndexPath:_reorderingCellIndexPath];
+      }
+
+      // Create cell snapshot with shadowing.
+      [_collectionView addSubview:[self snapshotWithIndexPath:_reorderingCellIndexPath]];
+      [self applyLayerShadowing:_cellSnapshot.layer];
+
+      // Disable scrolling.
+      [_collectionView setScrollEnabled:NO];
+      break;
+    }
+    case UIGestureRecognizerStateCancelled:
+    case UIGestureRecognizerStateEnded: {
+      // Stop autoscroll.
+      [self stopAutoscroll];
+      NSIndexPath *currentIndexPath = _reorderingCellIndexPath;
+      if (currentIndexPath) {
+        UICollectionViewLayoutAttributes *attributes = [_collectionView.collectionViewLayout
+            layoutAttributesForItemAtIndexPath:currentIndexPath];
+
+        void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+          // Notify delegate dragging has finished.
+          if ([_delegate
+                  respondsToSelector:@selector(collectionView:didEndDraggingItemAtIndexPath:)]) {
+            [_delegate collectionView:_collectionView
+                didEndDraggingItemAtIndexPath:_reorderingCellIndexPath];
+          }
+          [self restoreEditingItem];
+
+          // Re-enable scrolling.
+          [_collectionView setScrollEnabled:YES];
+        };
+
+        [UIView animateWithDuration:kDismissalAnimationDuration
+                              delay:0
+                            options:UIViewAnimationOptionBeginFromCurrentState
+                         animations:^{
+                           _cellSnapshot.frame = attributes.frame;
+                         }
+                         completion:completionBlock];
+      }
+      break;
+    }
+    default:
+      break;
+  }
+}
+
+#pragma mark - Pan Gesture Handling
+
+- (void)handlePanGesture:(UIPanGestureRecognizer *)recognizer {
+  if (_reorderingCellIndexPath) {
+    [self panToReorderWithRecognizer:recognizer];
+  } else {
+    [self panToDismissWithRecognizer:recognizer];
+  }
+}
+
+- (void)panToReorderWithRecognizer:(UIPanGestureRecognizer *)recognizer {
+  if (recognizer.state == UIGestureRecognizerStateChanged) {
+    // Transform snapshot position when panning.
+    _selectedCellLocation = [recognizer locationInView:_collectionView];
+    CGFloat change = _selectedCellLocation.y - _initialCellLocation.y;
+    CGAffineTransform transform = CGAffineTransformMakeTranslation(0, change);
+    _cellSnapshot.layer.transform = CATransform3DMakeAffineTransform(transform);
+
+    // Determine moved index paths.
+    NSIndexPath *newIndexPath = [_collectionView indexPathForItemAtPoint:_selectedCellLocation];
+    NSIndexPath *previousIndexPath = _reorderingCellIndexPath;
+    if ((newIndexPath == nil) || [newIndexPath isEqual:previousIndexPath]) {
+      return;
+    }
+
+    // Autoscroll if the cell is dragged out of the collectionView's bounds.
+    CGFloat buffer = kMDCAutoscrollPanningBuffer;
+    if (_selectedCellLocation.y < CGRectGetMinY(self.collectionView.bounds) + buffer) {
+      [self startAutoscroll];
+      _autoscrollPanningDirection = kMDCAutoscrollPanningDirectionUp;
+    } else if (_selectedCellLocation.y > (CGRectGetMaxY(self.collectionView.bounds) - buffer)) {
+      [self startAutoscroll];
+      _autoscrollPanningDirection = kMDCAutoscrollPanningDirectionDown;
+    } else {
+      [self stopAutoscroll];
+    }
+
+    // Check delegate for permission to move item.
+    if ([_delegate
+            respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:toIndexPath:)]) {
+      if ([_delegate collectionView:_collectionView
+              canMoveItemAtIndexPath:previousIndexPath
+                         toIndexPath:newIndexPath]) {
+        _reorderingCellIndexPath = newIndexPath;
+
+        // Notify delegate that item will move.
+        if ([_delegate respondsToSelector:@selector(collectionView:
+                                              willMoveItemAtIndexPath:
+                                                          toIndexPath:)]) {
+          [_delegate collectionView:_collectionView
+              willMoveItemAtIndexPath:previousIndexPath
+                          toIndexPath:newIndexPath];
+        }
+
+        // Notify delegate item did move.
+        if ([_delegate
+                respondsToSelector:@selector(collectionView:didMoveItemAtIndexPath:toIndexPath:)]) {
+          [_delegate collectionView:_collectionView
+              didMoveItemAtIndexPath:previousIndexPath
+                         toIndexPath:newIndexPath];
+        }
+      } else {
+        // Exit if delegate will not allow this indexPath to move.
+        return;
+      }
+    }
+  }
+}
+
+- (void)panToDismissWithRecognizer:(UIPanGestureRecognizer *)recognizer {
+  CGPoint translation = [recognizer translationInView:_collectionView];
+  CGPoint velocity = [recognizer velocityInView:_collectionView];
+  CGPoint location = [recognizer locationInView:_collectionView];
+
+  switch (recognizer.state) {
+    case UIGestureRecognizerStateBegan: {
+      if (fabs(velocity.y) > fabs(velocity.x)) {
+        // Exit if panning vertically.
+        return [self exitPanToDismissWithRecognizer:recognizer];
+      }
+
+      BOOL allowsSwipeToDismissSection = NO;
+      if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissSection:)]) {
+        allowsSwipeToDismissSection =
+            [_delegate collectionViewAllowsSwipeToDismissSection:_collectionView];
+      }
+
+      BOOL allowsSwipeToDismissItem = NO;
+      if ([_delegate respondsToSelector:@selector(collectionViewAllowsSwipeToDismissItem:)]) {
+        allowsSwipeToDismissItem =
+            [_delegate collectionViewAllowsSwipeToDismissItem:_collectionView];
+      }
+
+      if (allowsSwipeToDismissSection && !self.isEditing) {
+        // Determine panned section to dismiss.
+        _dismissingSection = [self swipedSectionAtLocation:location];
+        if (_dismissingSection == NSNotFound) {
+          return [self exitPanToDismissWithRecognizer:recognizer];
+        }
+
+        // Check delegate for permission to swipe section.
+        if ([_delegate respondsToSelector:@selector(collectionView:canSwipeToDismissSection:)]) {
+          if ([_delegate collectionView:_collectionView
+                  canSwipeToDismissSection:_dismissingSection]) {
+            // Notify delegate.
+            if ([_delegate
+                    respondsToSelector:@selector(collectionView:willBeginSwipeToDismissSection:)]) {
+              [_delegate collectionView:_collectionView
+                  willBeginSwipeToDismissSection:_dismissingSection];
+            }
+          } else {
+            // Cannot swipe so exit.
+            return [self exitPanToDismissWithRecognizer:recognizer];
+          }
+        }
+
+        // Create section snapshot.
+        [_collectionView insertSubview:[self snapshotWithSection:_dismissingSection] atIndex:0];
+        break;
+
+      } else if (allowsSwipeToDismissItem) {
+        // Determine panned index path to dismiss.
+        _dismissingCellIndexPath = [_collectionView indexPathForItemAtPoint:location];
+        if (!_dismissingCellIndexPath) {
+          return [self exitPanToDismissWithRecognizer:recognizer];
+        }
+
+        // Check delegate for permission to swipe item.
+        if ([_delegate
+                respondsToSelector:@selector(collectionView:canSwipeToDismissItemAtIndexPath:)]) {
+          if ([_delegate collectionView:_collectionView
+                  canSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath]) {
+            // Notify delegate.
+            if ([_delegate respondsToSelector:@selector(collectionView:
+                                                  willBeginSwipeToDismissItemAtIndexPath:)]) {
+              [_delegate collectionView:_collectionView
+                  willBeginSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath];
+            }
+          } else {
+            // Cannot swipe so exit.
+            return [self exitPanToDismissWithRecognizer:recognizer];
+          }
+        }
+
+        // Create item snapshot.
+        [_collectionView insertSubview:[self snapshotWithIndexPath:_dismissingCellIndexPath]
+                               atIndex:0];
+        break;
+      }
+    }
+
+    case UIGestureRecognizerStateChanged: {
+      // Update the tracked item's position and alpha.
+      CGAffineTransform transform;
+      CGFloat alpha;
+      // The item is fully opaque until it pans at least @c kDismissalDistanceBeforeFading points.
+      CGFloat panDistance = (CGFloat)fabs(translation.x) - kDismissalDistanceBeforeFading;
+      if (panDistance > 0) {
+        transform = [self transformItemDismissalToTranslationX:translation.x];
+        alpha = [self dismissalAlphaForTranslationX:translation.x];
+      } else {
+        // Pan the item.
+        transform = CGAffineTransformMakeTranslation(translation.x, 0);
+        alpha = 1;
+      }
+      _cellSnapshot.layer.transform = CATransform3DMakeAffineTransform(transform);
+      _cellSnapshot.alpha = alpha;
+      break;
+    }
+
+    case UIGestureRecognizerStateEnded: {
+      // Check the final translation, including the final velocity, to determine
+      // if the item should be dismissed.
+      CGFloat momentumX = velocity.x * kDismissalSwipeFriction;
+      CGFloat translationX = translation.x + momentumX;
+
+      if (fabs(translationX) > [self distanceThresholdForDismissal]) {
+        // @c translationX is only guaranteed to be over the dismissal threshold;
+        // make sure the view animates all the way off the screen.
+        translationX = (CGFloat)copysign(
+            MAX(fabs(translationX), CGRectGetWidth(_collectionView.bounds)), translationX);
+        [self animateFinalItemDismissalToTranslationX:translationX];
+      } else {
+        [self restorePanningItemIfNecessaryWithMomentumX:momentumX];
+      }
+      break;
+    }
+    default: {
+      [self restorePanningItemIfNecessaryWithMomentumX:0];
+      break;
+    }
+  }
+}
+
+- (void)exitPanToDismissWithRecognizer:(UIPanGestureRecognizer *)recognizer {
+  // To exit, disable the recognizer immediately which forces it to drop out of the current
+  // loop and prevent any state updates. Then re-enable to allow future panning.
+  recognizer.enabled = NO;
+  recognizer.enabled = YES;
+}
+
+#pragma mark - Dismissal animation.
+
+- (CGAffineTransform)transformItemDismissalToTranslationX:(CGFloat)translationX {
+  // Returns a transform that can be applied to the snapshot during dismissal. The
+  // translation will pan along an arc facing downwards.
+  CGFloat panDistance = (CGFloat)fabs(translationX) - kDismissalDistanceBeforeFading;
+  CGFloat panRatio = panDistance / CGRectGetWidth(_collectionView.bounds);
+  CGFloat arcAngle = (translationX > 0 ? kDismissalArcAngle : -kDismissalArcAngle);
+
+  CGAffineTransform initialTranslation = CGAffineTransformMakeTranslation(0, -kDismissalArcYOffset);
+  CGAffineTransform rotation = CGAffineTransformMakeRotation(panRatio * arcAngle);
+
+  // Modify the X translation to take account of the rotation angle.
+  // This makes the item continue to track the finger as it follows the arc.
+  CGFloat correctedXTranslation = (CGFloat)(translationX * (1 - cos(kDismissalArcAngle) / 2));
+  if (translationX > 0) {
+    correctedXTranslation = MAX(kDismissalDistanceBeforeFading, correctedXTranslation);
+  } else {
+    correctedXTranslation = MIN(-kDismissalDistanceBeforeFading, correctedXTranslation);
+  }
+
+  // Reverse @c initialTranslation and add @c translation.x to ensure that
+  // we pan along with the arc.
+  CGAffineTransform reverseTranslation =
+      CGAffineTransformMakeTranslation(correctedXTranslation, kDismissalArcYOffset);
+
+  CGAffineTransform arcTransform = CGAffineTransformConcat(initialTranslation, rotation);
+  return CGAffineTransformConcat(arcTransform, reverseTranslation);
+}
+
+- (void)animateFinalItemDismissalToTranslationX:(CGFloat)translationX {
+  // Called at the end of a pan gesture that results in the item being dismissed.
+  // Animation that moves the dismissed item to the final location and fades it out.
+  CGAffineTransform transform = [self transformItemDismissalToTranslationX:translationX];
+
+  // Notify delegate of dismissed section.
+  if (_dismissingSection != NSNotFound) {
+    if ([_delegate respondsToSelector:@selector(collectionView:didEndSwipeToDismissSection:)]) {
+      [_delegate collectionView:_collectionView didEndSwipeToDismissSection:_dismissingSection];
+    }
+  }
+
+  // Notify delegate of dismissed item.
+  if (_dismissingCellIndexPath) {
+    if ([_delegate
+            respondsToSelector:@selector(collectionView:didEndSwipeToDismissItemAtIndexPath:)]) {
+      [_delegate collectionView:_collectionView
+          didEndSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath];
+    }
+  }
+
+  [UIView animateWithDuration:kDismissalAnimationDuration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseOut
+      animations:^{
+        _cellSnapshot.layer.transform = CATransform3DMakeAffineTransform(transform);
+        _cellSnapshot.alpha = 0;
+      }
+      completion:^(BOOL finished) {
+        [self restoreEditingItem];
+      }];
+}
+
+- (void)restorePanningItemIfNecessaryWithMomentumX:(CGFloat)momentumX {
+  // If we never had a snapshot, or the snapshot never moved, then skip straight to cleanup.
+  if (_cellSnapshot == nil || CGAffineTransformIsIdentity(_cellSnapshot.transform)) {
+    [self restoreEditingItem];
+    return;
+  }
+
+  CAAnimationGroup *allAnimations = [CAAnimationGroup animation];
+  allAnimations.duration = kRestoreAnimationDuration;
+
+  CATransform3D startTransform = CATransform3DMakeAffineTransform(_cellSnapshot.transform);
+  CATransform3D midTransform = CATransform3DTranslate(startTransform, momentumX, 0, 0);
+  CATransform3D endTransform = CATransform3DIdentity;
+
+  CAKeyframeAnimation *transformAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
+  transformAnimation.values = @[
+    [NSValue valueWithCATransform3D:startTransform], [NSValue valueWithCATransform3D:midTransform],
+    [NSValue valueWithCATransform3D:endTransform]
+  ];
+  transformAnimation.calculationMode = kCAAnimationCubicPaced;
+
+  CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+  opacityAnimation.fromValue = @(_cellSnapshot.alpha);
+  opacityAnimation.toValue = @1;
+
+  allAnimations.animations = @[ transformAnimation, opacityAnimation ];
+  allAnimations.delegate = self;
+  allAnimations.fillMode = kCAFillModeBackwards;
+  _cellSnapshot.layer.transform = CATransform3DIdentity;
+  _cellSnapshot.alpha = 1;
+  [_cellSnapshot.layer addAnimation:allAnimations forKey:nil];
+}
+
+- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)didFinish {
+  [self cancelPanningItem];
+}
+
+- (void)cancelPanningItem {
+  // Notify delegate of panned section cancellation.
+  if (_dismissingSection != NSNotFound) {
+    if ([_delegate respondsToSelector:@selector(collectionView:didCancelSwipeToDismissSection:)]) {
+      [_delegate collectionView:_collectionView didCancelSwipeToDismissSection:_dismissingSection];
+    }
+  }
+
+  // Notify delegate of panned index path cancellation.
+  if (_dismissingCellIndexPath) {
+    if ([_delegate
+            respondsToSelector:@selector(collectionView:didCancelSwipeToDismissItemAtIndexPath:)]) {
+      [_delegate collectionView:_collectionView
+          didCancelSwipeToDismissItemAtIndexPath:_dismissingCellIndexPath];
+    }
+  }
+
+  [self restoreEditingItem];
+}
+
+- (void)restoreEditingItem {
+  // Remove snapshot and reset item.
+  [_cellSnapshot removeFromSuperview];
+  _cellSnapshot = nil;
+  _dismissingSection = NSNotFound;
+  _dismissingCellIndexPath = nil;
+  _reorderingCellIndexPath = nil;
+  [_collectionView.collectionViewLayout invalidateLayout];
+}
+
+// The distance an item must be panned before it is dismissed. Currently half of the bounds width.
+- (CGFloat)distanceThresholdForDismissal {
+  return _collectionView.bounds.size.width / 2;
+}
+
+- (CGFloat)dismissalAlphaForTranslationX:(CGFloat)translationX {
+  translationX = (CGFloat)fabs(translationX) - kDismissalDistanceBeforeFading;
+  CGFloat adjustedThreshold = [self distanceThresholdForDismissal] - kDismissalDistanceBeforeFading;
+  CGFloat dismissalPercentage = (CGFloat)MIN(1, fabs(translationX) / adjustedThreshold);
+  return kDismissalMinimumAlpha + (1 - kDismissalMinimumAlpha) * (1 - dismissalPercentage);
+}
+
+#pragma mark - Reordering Autoscroll
+
+- (void)startAutoscroll {
+  if (_autoscrollTimer) {
+    [self stopAutoscroll];
+  }
+  _autoscrollTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(autoscroll:)];
+  [_autoscrollTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
+}
+
+- (void)stopAutoscroll {
+  if (_autoscrollTimer) {
+    [_autoscrollTimer invalidate];
+    _autoscrollTimer = nil;
+    _autoscrollPanningDirection = kMDCAutoscrollPanningDirectionNone;
+  }
+}
+
+- (void)autoscroll:(CADisplayLink *)sender {
+  // Scrolls at each tick of CADisplayLink by setting scroll contentOffset. Animation is performed
+  // within UIView animation block rather than directly calling -setContentOffset:animated: method
+  // in order to prevent jerkiness in scrolling.
+  BOOL isPanningDown = _autoscrollPanningDirection == kMDCAutoscrollPanningDirectionDown;
+  CGFloat yOffset = kMDCAutoscrollPanningOffset * (isPanningDown ? 1 : -1);
+  CGFloat contentYOffset = self.collectionView.contentOffset.y;
+
+  // Quit early if scrolling past collection view bounds.
+  if ((!isPanningDown && contentYOffset <= 0) ||
+      (isPanningDown &&
+       contentYOffset >=
+           self.collectionView.contentSize.height - CGRectGetHeight(self.collectionView.bounds))) {
+    [self stopAutoscroll];
+    return;
+  }
+
+  // When autoscrolling, keep cell snapshot transform to longpress position.
+  CGAffineTransform snapshotTransform =
+      CATransform3DGetAffineTransform(_cellSnapshot.layer.transform);
+  snapshotTransform.ty += yOffset;
+
+  [UIView animateWithDuration:0.3
+                        delay:0
+                      options:UIViewAnimationOptionBeginFromCurrentState
+                   animations:^{
+                     self.collectionView.contentOffset =
+                         CGPointMake(0, MAX(0, contentYOffset + yOffset));
+
+                     // Transform snapshot position when panning.
+                     _cellSnapshot.layer.transform =
+                         CATransform3DMakeAffineTransform(snapshotTransform);
+                   }
+                   completion:nil];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h
new file mode 100644
index 0000000..6e899da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewStyling.h"
+
+/**
+ The MDCCollectionViewStyler class provides a default implementation for a UICollectionView to set
+ its style properties.
+ */
+@interface MDCCollectionViewStyler : NSObject <MDCCollectionViewStyling>
+
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Initializes and returns a newly allocated styler object with the specified collection view.
+
+ Designated initializer.
+
+ @param collectionView The controller's collection view.
+ */
+- (nonnull instancetype)initWithCollectionView:(nonnull UICollectionView *)collectionView
+    NS_DESIGNATED_INITIALIZER;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.m
new file mode 100644
index 0000000..fc8c9ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MDCCollectionViewStyler.m
@@ -0,0 +1,733 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCCollectionViewStyler.h"
+
+#import "MDCCollectionViewStylingDelegate.h"
+#import "MaterialCollectionLayoutAttributes.h"
+
+#import <tgmath.h>
+
+#define RGBCOLOR(r, g, b) \
+  [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:1]
+
+typedef NS_OPTIONS(NSUInteger, BackgroundCacheKey) {
+  BackgroundCacheKeyFlat = 0,
+  BackgroundCacheKeyTop = 1 << 0,
+  BackgroundCacheKeyBottom = 1 << 1,
+  BackgroundCacheKeyCard = 1 << 2,
+  BackgroundCacheKeyGrouped = 1 << 3,
+  BackgroundCacheKeyHighlighted = 1 << 4,
+  BackgroundCacheKeyMax = 1 << 5,
+};
+
+const CGFloat MDCCollectionViewCellStyleCardSectionInset = 8.0f;
+
+/** Cell content view insets for card-style cells */
+static const CGFloat kFourThirds = 4.0f / 3.0f;
+static const UIEdgeInsets kCollectionViewCellContentInsetsRetina3x = {kFourThirds, kFourThirds,
+                                                                      kFourThirds, kFourThirds};
+static const UIEdgeInsets kCollectionViewCellContentInsetsRetina = {1.5, 1.5, 1.5, 1.5};
+static const UIEdgeInsets kCollectionViewCellContentInsets = {1, 2, 1, 2};
+
+/** Default cell separator style settings */
+static const CGFloat kCollectionViewCellSeparatorDefaultHeightInPixels = 1.0f;
+
+/** Grid layout defaults */
+static const NSInteger kCollectionViewGridDefaultColumnCount = 2;
+static const CGFloat kCollectionViewGridDefaultPadding = 4.0f;
+
+/** The drawn cell background */
+static const CGSize kCellImageSize = {44, 44};
+static const CGFloat kCollectionViewCellDefaultBorderWidth = 1.0f;
+static const CGFloat kCollectionViewCellDefaultBorderRadius = 1.5f;
+static inline UIColor *kCollectionViewCellDefaultBorderColor() {
+  return [UIColor colorWithWhite:0 alpha:0.05f];
+}
+
+/** Cell shadowing */
+static const CGFloat kCollectionViewCellDefaultShadowWidth = 1.0f;
+static inline CGSize kCollectionViewCellDefaultShadowOffset() {
+  return CGSizeMake(0, 1);
+}
+static inline UIColor *kCollectionViewCellDefaultShadowColor() {
+  return [UIColor colorWithWhite:0 alpha:0.1f];
+}
+
+/** Animate cell on appearance settings */
+static const CGFloat kCollectionViewAnimatedAppearancePadding = 20.0f;
+static const NSTimeInterval kCollectionViewAnimatedAppearanceDelay = 0.1;
+static const NSTimeInterval kCollectionViewAnimatedAppearanceDuration = 0.3;
+
+/** Modifies only the right and bottom edges of a CGRect. */
+NS_INLINE CGRect RectContract(CGRect rect, CGFloat dx, CGFloat dy) {
+  return CGRectMake(rect.origin.x, rect.origin.y, rect.size.width - dx, rect.size.height - dy);
+}
+
+/** Modifies only the top and left edges of a CGRect. */
+NS_INLINE CGRect RectShift(CGRect rect, CGFloat dx, CGFloat dy) {
+  return CGRectOffset(RectContract(rect, dx, dy), dx, dy);
+}
+
+@interface MDCCollectionViewStyler ()
+
+/**
+ A dictionary of NSPointerArray caches, keyed by UIColor, for cached cell background images
+ using that background color. Index into the NSPointerArray using the results of
+ backgroundCacheKeyForCardStyle:isGroupedStyle:isTop:isBottom:isHighlighted:
+ */
+@property(nonatomic, readonly) NSMutableDictionary *cellBackgroundCaches;
+
+/** An set of index paths for items that are inlaid. */
+@property(nonatomic, strong) NSMutableSet *inlaidIndexPathSet;
+
+@end
+
+@implementation MDCCollectionViewStyler
+
+@synthesize collectionView = _collectionView;
+@synthesize delegate = _delegate;
+@synthesize shouldInvalidateLayout = _shouldInvalidateLayout;
+@synthesize cellBackgroundColor = _cellBackgroundColor;
+@synthesize cellLayoutType = _cellLayoutType;
+@synthesize gridColumnCount = _gridColumnCount;
+@synthesize gridPadding = _gridPadding;
+@synthesize cellStyle = _cellStyle;
+@synthesize separatorColor = _separatorColor;
+@synthesize separatorInset = _separatorInset;
+@synthesize separatorLineHeight = _separatorLineHeight;
+@synthesize shouldHideSeparators = _shouldHideSeparators;
+@synthesize allowsItemInlay = _allowsItemInlay;
+@synthesize allowsMultipleItemInlays = _allowsMultipleItemInlays;
+@synthesize shouldAnimateCellsOnAppearance = _shouldAnimateCellsOnAppearance;
+@synthesize willAnimateCellsOnAppearance = _willAnimateCellsOnAppearance;
+@synthesize animateCellsOnAppearancePadding = _animateCellsOnAppearancePadding;
+@synthesize animateCellsOnAppearanceDuration = _animateCellsOnAppearanceDuration;
+
+- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
+  self = [super init];
+  if (self) {
+    _collectionView = collectionView;
+
+    // Cell default style properties.
+    _cellBackgroundColor = [UIColor whiteColor];
+    _cellStyle = MDCCollectionViewCellStyleDefault;
+    _collectionView.backgroundColor = RGBCOLOR(0xEE, 0xEE, 0xEE);
+    _inlaidIndexPathSet = [NSMutableSet set];
+
+    // Cell separator defaults.
+    _separatorColor = RGBCOLOR(224, 224, 224);
+    _separatorInset = UIEdgeInsetsZero;
+    _separatorLineHeight =
+        kCollectionViewCellSeparatorDefaultHeightInPixels / [[UIScreen mainScreen] scale];
+    _shouldHideSeparators = NO;
+
+    // Grid defaults.
+    _cellLayoutType = MDCCollectionViewCellLayoutTypeList;
+    _gridColumnCount = kCollectionViewGridDefaultColumnCount;
+    _gridPadding = kCollectionViewGridDefaultPadding;
+
+    // Animate cell on appearance settings.
+    _animateCellsOnAppearancePadding = kCollectionViewAnimatedAppearancePadding;
+    _animateCellsOnAppearanceDuration = kCollectionViewAnimatedAppearanceDuration;
+
+    // Caching.
+    _cellBackgroundCaches = [NSMutableDictionary dictionary];
+  }
+  return self;
+}
+
+- (BOOL)isEqual:(id)object {
+  // If shouldInvalidateLayout property is NO, prevent a collection view layout caused when
+  // layout attributes check here if they are equal.
+  return (self == object) && ![self shouldInvalidateLayoutForStyleChange];
+}
+
+#pragma mark - Cell Appearance Animation
+
+- (void)setShouldAnimateCellsOnAppearance:(BOOL)shouldAnimateCellsOnAppearance {
+  _shouldAnimateCellsOnAppearance = shouldAnimateCellsOnAppearance;
+  _willAnimateCellsOnAppearance = shouldAnimateCellsOnAppearance;
+}
+
+- (void)beginCellAppearanceAnimation {
+  if (_shouldAnimateCellsOnAppearance) {
+    _willAnimateCellsOnAppearance = NO;
+    [UIView animateWithDuration:_animateCellsOnAppearanceDuration
+        delay:kCollectionViewAnimatedAppearanceDelay
+        options:UIViewAnimationOptionCurveEaseInOut
+        animations:^{
+          [self updateLayoutAnimated:YES];
+        }
+        completion:^(BOOL finished) {
+          [self setShouldAnimateCellsOnAppearance:NO];
+        }];
+  }
+}
+
+#pragma mark - Caching
+
+- (BackgroundCacheKey)backgroundCacheKeyForCardStyle:(BOOL)isCardStyle
+                                      isGroupedStyle:(BOOL)isGroupedStyle
+                                               isTop:(BOOL)isTop
+                                            isBottom:(BOOL)isBottom
+                                       isHighlighted:(BOOL)isHighlighted {
+  if (!isCardStyle && !isGroupedStyle) {
+    return BackgroundCacheKeyFlat;
+  }
+  BackgroundCacheKey options = isTop ? BackgroundCacheKeyTop : 0;
+  options |= isBottom ? BackgroundCacheKeyBottom : 0;
+  options |= isCardStyle ? BackgroundCacheKeyCard : 0;
+  options |= isGroupedStyle ? BackgroundCacheKeyGrouped : 0;
+  options |= isHighlighted ? BackgroundCacheKeyHighlighted : 0;
+  NSAssert(isCardStyle != isGroupedStyle, @"Cannot be both card and grouped style");
+  return options;
+}
+
+- (NSPointerArray *)cellBackgroundCache {
+  NSPointerArray *cache = [NSPointerArray strongObjectsPointerArray];
+  cache.count = BackgroundCacheKeyMax;
+  return cache;
+}
+
+#pragma mark - Separators
+
+- (void)setSeparatorColor:(UIColor *)separatorColor {
+  if (_separatorColor == separatorColor) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _separatorColor = separatorColor;
+}
+
+- (void)setSeparatorInset:(UIEdgeInsets)separatorInset {
+  if (UIEdgeInsetsEqualToEdgeInsets(_separatorInset, separatorInset)) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _separatorInset = separatorInset;
+}
+
+- (void)setSeparatorLineHeight:(CGFloat)separatorLineHeight {
+  if (_separatorLineHeight == separatorLineHeight) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _separatorLineHeight = separatorLineHeight;
+}
+
+- (void)setShouldHideSeparators:(BOOL)shouldHideSeparators {
+  if (_shouldHideSeparators == shouldHideSeparators) {
+    return;
+  }
+  [self invalidateLayoutForStyleChange];
+  _shouldHideSeparators = shouldHideSeparators;
+}
+
+- (void)setCellStyle:(MDCCollectionViewCellStyle)cellStyle {
+  if (_cellStyle == cellStyle) {
+    return;
+  }
+  [_cellBackgroundCaches removeAllObjects];
+  [self invalidateLayoutForStyleChange];
+  _cellStyle = cellStyle;
+}
+
+#pragma mark - Public
+
+- (UIEdgeInsets)backgroundImageViewOutsetsForCellWithAttribute:
+        (MDCCollectionViewLayoutAttributes *)attr {
+  // Inset contentView to allow for shadowed borders in cards.
+  UIEdgeInsets insets = UIEdgeInsetsZero;
+
+  MDCCollectionViewCellStyle cellStyle = [self cellStyleAtSectionIndex:attr.indexPath.section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  BOOL isHighlighted = NO;
+
+  MDCCollectionViewOrdinalPosition position = attr.sectionOrdinalPosition;
+
+  if ([self drawShadowForCellWithIsCardStye:isCardStyle
+                               isGroupStyle:isGroupedStyle
+                              isHighlighted:isHighlighted]) {
+    CGFloat mainScreenScale = [[UIScreen mainScreen] scale];
+    if (mainScreenScale > (CGFloat)2.1) {
+      insets = kCollectionViewCellContentInsetsRetina3x;
+    } else if (mainScreenScale > (CGFloat)1.1) {
+      insets = kCollectionViewCellContentInsetsRetina;
+    } else {
+      insets = kCollectionViewCellContentInsets;
+    }
+
+    if (!isCardStyle) {
+      insets = UIEdgeInsetsMake(insets.top, 0, insets.bottom, 0);
+    }
+
+    switch (position) {
+      case MDCCollectionViewOrdinalPositionVerticalTop:
+        insets = UIEdgeInsetsMake(insets.top, insets.left, 0, insets.right);
+        break;
+      case MDCCollectionViewOrdinalPositionVerticalBottom:
+        insets = UIEdgeInsetsMake(0, insets.left, insets.bottom, insets.right);
+        break;
+      case MDCCollectionViewOrdinalPositionVerticalCenter:
+        insets = UIEdgeInsetsMake(0, insets.left, 0, insets.right);
+        break;
+      default:
+        break;
+    }
+  }
+
+  return insets;
+}
+
+- (void)setCellStyle:(MDCCollectionViewCellStyle)cellStyle animated:(BOOL)animated {
+  _cellStyle = cellStyle;
+  [self updateLayoutAnimated:animated];
+}
+
+- (MDCCollectionViewCellStyle)cellStyleAtSectionIndex:(NSInteger)section {
+  MDCCollectionViewCellStyle cellStyle = self.cellStyle;
+  if (self.delegate &&
+      [self.delegate respondsToSelector:@selector(collectionView:cellStyleForSection:)]) {
+    cellStyle = [self.delegate collectionView:_collectionView cellStyleForSection:section];
+  }
+  return cellStyle;
+}
+
+- (NSArray *)indexPathsForInlaidItems {
+  return [_inlaidIndexPathSet allObjects];
+}
+
+- (BOOL)isItemInlaidAtIndexPath:(NSIndexPath *)indexPath {
+  return [_inlaidIndexPathSet containsObject:indexPath];
+}
+
+- (void)applyInlayToItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated {
+  if (_allowsItemInlay) {
+    // If necessary, remove any previously inlaid items.
+    if (!_allowsMultipleItemInlays) {
+      for (NSIndexPath *inlaidIndexPath in [self indexPathsForInlaidItems]) {
+        [self removeInlayFromItemAtIndexPath:inlaidIndexPath animated:animated];
+      }
+    }
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      if ([self.delegate
+              respondsToSelector:@selector(collectionView:didApplyInlayToItemAtIndexPaths:)]) {
+        [self.delegate collectionView:_collectionView
+            didApplyInlayToItemAtIndexPaths:@[ indexPath ]];
+      }
+    };
+
+    // Inlay this item.
+    [_inlaidIndexPathSet addObject:indexPath];
+    [self updateLayoutAnimated:animated completion:completionBlock];
+  }
+}
+
+- (void)removeInlayFromItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated {
+  [_inlaidIndexPathSet removeObject:indexPath];
+
+  void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+    if ([self.delegate
+            respondsToSelector:@selector(collectionView:didRemoveInlayFromItemAtIndexPaths:)]) {
+      [self.delegate collectionView:_collectionView
+          didRemoveInlayFromItemAtIndexPaths:@[ indexPath ]];
+    }
+  };
+
+  [self updateLayoutAnimated:animated completion:completionBlock];
+}
+
+- (void)applyInlayToAllItemsAnimated:(BOOL)animated {
+  if (_allowsItemInlay && _allowsMultipleItemInlays) {
+    // Store all index paths.
+    [_inlaidIndexPathSet removeAllObjects];
+    NSInteger sections = [_collectionView numberOfSections];
+    for (NSInteger section = 0; section < sections; section++) {
+      for (NSInteger item = 0; item < [_collectionView numberOfItemsInSection:section]; item++) {
+        [_inlaidIndexPathSet addObject:[NSIndexPath indexPathForItem:item inSection:section]];
+      }
+    }
+
+    void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+      if ([self.delegate
+              respondsToSelector:@selector(collectionView:didApplyInlayToItemAtIndexPaths:)]) {
+        [self.delegate collectionView:_collectionView
+            didApplyInlayToItemAtIndexPaths:[_inlaidIndexPathSet allObjects]];
+      }
+    };
+
+    // Inlay all items.
+    [self updateLayoutAnimated:animated completion:completionBlock];
+  }
+}
+
+- (void)removeInlayFromAllItemsAnimated:(BOOL)animated {
+  NSArray *indexPaths = [_inlaidIndexPathSet allObjects];
+  [_inlaidIndexPathSet removeAllObjects];
+
+  void (^completionBlock)(BOOL finished) = ^(BOOL finished) {
+    if ([self.delegate
+            respondsToSelector:@selector(collectionView:didRemoveInlayFromItemAtIndexPaths:)]) {
+      [self.delegate collectionView:_collectionView didRemoveInlayFromItemAtIndexPaths:indexPaths];
+    }
+  };
+
+  [self updateLayoutAnimated:animated completion:completionBlock];
+}
+
+- (void)resetIndexPathsForInlaidItems {
+  [_inlaidIndexPathSet removeAllObjects];
+  [self applyInlayToAllItemsAnimated:NO];
+}
+
+- (void)updateLayoutAnimated:(BOOL)animated {
+  [self updateLayoutAnimated:animated completion:nil];
+}
+
+#pragma mark - Private
+
+- (void)updateLayoutAnimated:(BOOL)animated completion:(void (^)(BOOL finished))completion {
+  if (animated) {
+    // Invalidate current layout while allowing animation to new layout.
+    [UIView animateWithDuration:0
+        animations:^{
+          [_collectionView.collectionViewLayout invalidateLayout];
+        }
+        completion:^(BOOL finished) {
+          if (completion) {
+            completion(finished);
+          }
+        }];
+  } else {
+    _shouldInvalidateLayout = YES;
+
+    // Create new layout with existing layout properties.
+    NSData *data =
+        [NSKeyedArchiver archivedDataWithRootObject:_collectionView.collectionViewLayout];
+    UICollectionViewFlowLayout *newLayout = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+    [_collectionView setCollectionViewLayout:newLayout
+                                    animated:animated
+                                  completion:^(BOOL finished) {
+                                    if (completion) {
+                                      completion(finished);
+                                    }
+                                  }];
+  }
+}
+
+- (void)invalidateLayoutForStyleChange {
+  _shouldInvalidateLayout = YES;
+}
+
+- (BOOL)shouldInvalidateLayoutForStyleChange {
+  // Whether the collection view layout should be invalidated due to a style property that has
+  // changed value.
+  return _shouldInvalidateLayout;
+}
+
+#pragma mark - Cell Image Background
+
+- (BOOL)drawShadowForCellWithIsCardStye:(BOOL)isCardStyle
+                           isGroupStyle:(BOOL)isGroupStyle
+                          isHighlighted:(BOOL)isHighlighted {
+  return (isCardStyle || isGroupStyle) && kCollectionViewCellDefaultShadowWidth > 0 &&
+         !isHighlighted;
+}
+
+- (UIImage *)backgroundImageForCellLayoutAttributes:(MDCCollectionViewLayoutAttributes *)attr {
+  BOOL isSectionHeader =
+      [attr.representedElementKind isEqualToString:UICollectionElementKindSectionHeader];
+  BOOL isSectionFooter =
+      [attr.representedElementKind isEqualToString:UICollectionElementKindSectionFooter];
+  BOOL isDecorationView =
+      attr.representedElementCategory == UICollectionElementCategoryDecorationView;
+  BOOL isTop = attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalTop;
+  BOOL isBottom = attr.sectionOrdinalPosition & MDCCollectionViewOrdinalPositionVerticalBottom;
+
+  MDCCollectionViewCellStyle cellStyle = [self cellStyleAtSectionIndex:attr.indexPath.section];
+  BOOL isCardStyle = cellStyle == MDCCollectionViewCellStyleCard;
+  BOOL isGroupedStyle = cellStyle == MDCCollectionViewCellStyleGrouped;
+  BOOL isGridLayout = (_cellLayoutType == MDCCollectionViewCellLayoutTypeGrid);
+  if (!isCardStyle && !isGroupedStyle) {
+    // If not card or grouped style, revert @c isBottom to allow drawing separator at bottom.
+    isBottom = NO;
+  }
+  CGFloat borderRadius = (isCardStyle) ? kCollectionViewCellDefaultBorderRadius : 0.0f;
+
+  // Allowance for grid decoration view.
+  if (isGridLayout) {
+    if (!isDecorationView && attr.shouldShowGridBackground) {
+      return nil;
+    } else {
+      isTop = isBottom = YES;
+    }
+  }
+
+  // If no-background section header, return nil image.
+  BOOL hidesHeaderBackground = NO;
+  if ([_delegate
+          respondsToSelector:@selector(collectionView:shouldHideHeaderBackgroundForSection:)]) {
+    hidesHeaderBackground = [_delegate collectionView:_collectionView
+                 shouldHideHeaderBackgroundForSection:attr.indexPath.section];
+  }
+  if (hidesHeaderBackground && isSectionHeader) {
+    return nil;
+  }
+
+  // If no-background section footer, return nil image.
+  BOOL hidesFooterBackground = NO;
+  if ([_delegate
+          respondsToSelector:@selector(collectionView:shouldHideFooterBackgroundForSection:)]) {
+    hidesFooterBackground = [_delegate collectionView:_collectionView
+                 shouldHideFooterBackgroundForSection:attr.indexPath.section];
+  }
+  if (hidesFooterBackground && isSectionFooter) {
+    return nil;
+  }
+
+  // If no-background section item, return nil image.
+  BOOL hidesBackground = NO;
+  if ([_delegate
+          respondsToSelector:@selector(collectionView:shouldHideItemBackgroundAtIndexPath:)]) {
+    hidesBackground = [_delegate collectionView:_collectionView
+            shouldHideItemBackgroundAtIndexPath:attr.indexPath];
+  }
+  if (hidesBackground && !(isDecorationView || isSectionFooter || isSectionHeader)) {
+    return nil;
+  }
+
+  BOOL isHighlighted = NO;
+
+  BackgroundCacheKey backgroundCacheKey = [self backgroundCacheKeyForCardStyle:isCardStyle
+                                                                isGroupedStyle:isGroupedStyle
+                                                                         isTop:isTop
+                                                                      isBottom:isBottom
+                                                                 isHighlighted:isHighlighted];
+
+  if (backgroundCacheKey > BackgroundCacheKeyMax) {
+    NSAssert(NO, @"Invalid styler cell background cache key");
+    return nil;
+  }
+
+  // Get cell color.
+  UIColor *backgroundColor = _cellBackgroundColor;
+  if ([_delegate respondsToSelector:@selector(collectionView:cellBackgroundColorAtIndexPath:)]) {
+    backgroundColor =
+        [_delegate collectionView:_collectionView cellBackgroundColorAtIndexPath:attr.indexPath];
+  }
+
+  NSPointerArray *cellBackgroundCache = _cellBackgroundCaches[backgroundColor];
+  if (!cellBackgroundCache) {
+    cellBackgroundCache = [self cellBackgroundCache];
+    _cellBackgroundCaches[backgroundColor] = cellBackgroundCache;
+  } else if ([cellBackgroundCache pointerAtIndex:backgroundCacheKey]) {
+    return (__bridge UIImage *)[cellBackgroundCache pointerAtIndex:backgroundCacheKey];
+  }
+
+  CGRect imageRect = CGRectMake(0, 0, kCellImageSize.width, kCellImageSize.height);
+  UIGraphicsBeginImageContextWithOptions(imageRect.size, NO, 0);
+
+  CGContextRef cx = UIGraphicsGetCurrentContext();
+
+  // Create a transparent background.
+  CGContextClearRect(cx, imageRect);
+
+  // Inner background color
+  CGContextSetFillColorWithColor(cx, backgroundColor.CGColor);
+
+  CGRect contentFrame = imageRect;
+
+  // Draw the shadow.
+  if ([self drawShadowForCellWithIsCardStye:isCardStyle
+                               isGroupStyle:isGroupedStyle
+                              isHighlighted:isHighlighted]) {
+    if (isCardStyle) {
+      contentFrame = CGRectInset(imageRect, kCollectionViewCellDefaultShadowWidth, 0);
+    }
+    if (isTop) {
+      contentFrame = RectShift(contentFrame, 0, kCollectionViewCellDefaultShadowWidth);
+    }
+    if (isBottom) {
+      contentFrame = RectContract(contentFrame, 0, kCollectionViewCellDefaultShadowWidth);
+    }
+
+    CGContextSaveGState(cx);
+    CGRect shadowFrame = contentFrame;
+
+    // We want the shadow to clip to the top and bottom edges of the image so that when two cells
+    // are next to each other their shadows line up perfectly.
+    if (!isTop) {
+      shadowFrame = RectShift(shadowFrame, 0, -kCollectionViewCellDefaultShadowWidth);
+    }
+    if (!isBottom) {
+      shadowFrame = RectContract(shadowFrame, 0, -kCollectionViewCellDefaultShadowWidth);
+    }
+
+    [self applyBackgroundPathToContext:cx
+                                  rect:shadowFrame
+                                 isTop:isTop
+                              isBottom:isBottom
+                                isCard:(isCardStyle || isGroupedStyle)
+                          borderRadius:borderRadius];
+    CGContextSetShadowWithColor(cx, kCollectionViewCellDefaultShadowOffset(),
+                                kCollectionViewCellDefaultShadowWidth,
+                                kCollectionViewCellDefaultShadowColor().CGColor);
+    CGContextDrawPath(cx, kCGPathFill);
+    CGContextRestoreGState(cx);
+  } else {
+    // Draw a flat cell background.
+    CGContextSaveGState(cx);
+    [self applyBackgroundPathToContext:cx
+                                  rect:contentFrame
+                                 isTop:isTop
+                              isBottom:isBottom
+                                isCard:(isCardStyle || isGroupedStyle)
+                          borderRadius:borderRadius];
+    CGContextFillPath(cx);
+    CGContextRestoreGState(cx);
+  }
+  // Draw border paths for cells. We want the cell border to overlap the shadow and the content.
+  if ((isCardStyle || isGroupedStyle) && !isHighlighted) {
+    CGFloat minPixelOffset = [self minPixelOffset];
+    CGRect borderFrame = CGRectInset(contentFrame, -minPixelOffset, -minPixelOffset);
+    CGContextSaveGState(cx);
+    CGContextSetLineWidth(cx, kCollectionViewCellDefaultBorderWidth);
+    CGContextSetStrokeColorWithColor(cx, kCollectionViewCellDefaultBorderColor().CGColor);
+    [self applyBorderPathToContext:cx
+                              rect:borderFrame
+                             isTop:isTop
+                          isBottom:isBottom
+                            isCard:isCardStyle
+                      borderRadius:borderRadius];
+    CGContextStrokePath(cx);
+    CGContextRestoreGState(cx);
+  }
+
+  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+  UIGraphicsEndImageContext();
+  UIImage *resizableImage = [self resizableImage:image];
+  [cellBackgroundCache replacePointerAtIndex:backgroundCacheKey
+                                 withPointer:(__bridge void *)(resizableImage)];
+  return resizableImage;
+}
+
+#pragma mark - Private Context Paths
+
+// We want to draw the borders and shadows on single retina-pixel boundaries if possible, but
+// we need to avoid doing this on non-retina devices because it'll look blurry.
+- (CGFloat)minPixelOffset {
+  return 1.0f / [[UIScreen mainScreen] scale];
+}
+
+- (UIImage *)resizableImage:(UIImage *)image {
+  // Returns a resizable version of this image with cap insets equal to center point.
+  CGFloat capWidth = (CGFloat)floor(image.size.width / 2);
+  CGFloat capHeight = (CGFloat)floor(image.size.height / 2);
+  UIEdgeInsets capInsets = UIEdgeInsetsMake(capHeight, capWidth, capHeight, capWidth);
+  return [image resizableImageWithCapInsets:capInsets];
+}
+
+- (void)applyBackgroundPathToContext:(CGContextRef)c
+                                rect:(CGRect)rect
+                               isTop:(BOOL)isTop
+                            isBottom:(BOOL)isBottom
+                              isCard:(BOOL)isCard
+                        borderRadius:(CGFloat)borderRadius {
+  // Draw background paths for cell.
+  CGFloat minPixelOffset = (isCard) ? [self minPixelOffset] : 0.0f;
+  CGFloat minX = CGRectGetMinX(rect) + minPixelOffset;
+  CGFloat midX = CGRectGetMidX(rect) + minPixelOffset;
+  CGFloat maxX = CGRectGetMaxX(rect) - minPixelOffset;
+  CGFloat minY = CGRectGetMinY(rect) - minPixelOffset;
+  CGFloat midY = CGRectGetMidY(rect) - minPixelOffset;
+  CGFloat maxY = CGRectGetMaxY(rect) + minPixelOffset;
+
+  CGContextBeginPath(c);
+
+  CGContextMoveToPoint(c, minX, midY);
+  if (isTop && isCard) {
+    CGContextAddArcToPoint(c, minX, minY + 1, midX, minY + 1, borderRadius);
+    CGContextAddArcToPoint(c, maxX, minY + 1, maxX, midY, borderRadius);
+  } else {
+    CGContextAddLineToPoint(c, minX, minY);
+    CGContextAddLineToPoint(c, maxX, minY);
+  }
+
+  CGContextAddLineToPoint(c, maxX, midY);
+
+  if (isBottom & isCard) {
+    CGContextAddArcToPoint(c, maxX, maxY - 1, midX, maxY - 1, borderRadius);
+    CGContextAddArcToPoint(c, minX, maxY - 1, minX, midY, borderRadius);
+  } else {
+    CGContextAddLineToPoint(c, maxX, maxY);
+    CGContextAddLineToPoint(c, minX, maxY);
+  }
+  CGContextAddLineToPoint(c, minX, midY);
+
+  CGContextClosePath(c);
+}
+
+- (void)applyBorderPathToContext:(CGContextRef)c
+                            rect:(CGRect)rect
+                           isTop:(BOOL)isTop
+                        isBottom:(BOOL)isBottom
+                          isCard:(BOOL)isCard
+                    borderRadius:(CGFloat)borderRadius {
+  // Draw border paths for cell.
+  CGFloat minPixelOffset = (isCard) ? [self minPixelOffset] : 0.0f;
+  CGFloat minX = CGRectGetMinX(rect) + minPixelOffset;
+  CGFloat midX = CGRectGetMidX(rect) + minPixelOffset;
+  CGFloat maxX = CGRectGetMaxX(rect) - minPixelOffset;
+  CGFloat minY = CGRectGetMinY(rect) - minPixelOffset;
+  CGFloat midY = CGRectGetMidY(rect) - minPixelOffset;
+  CGFloat maxY = CGRectGetMaxY(rect) + minPixelOffset;
+
+  CGContextBeginPath(c);
+
+  if (isTop && isBottom) {
+    CGContextMoveToPoint(c, minX, midY);
+    CGContextAddArcToPoint(c, minX, minY + 1, midX, minY + 1, borderRadius);
+    CGContextAddArcToPoint(c, maxX, minY + 1, maxX, midY, borderRadius);
+    CGContextAddLineToPoint(c, maxX, midY);
+    CGContextAddArcToPoint(c, maxX, maxY - 1, midX, maxY - 1, borderRadius);
+    CGContextAddArcToPoint(c, minX, maxY - 1, minX, midY, borderRadius);
+    CGContextAddLineToPoint(c, minX, midY);
+  } else if (isTop) {
+    CGContextMoveToPoint(c, minX, maxY);
+    CGContextAddLineToPoint(c, minX, midY);
+    CGContextAddArcToPoint(c, minX, minY + 1, midX, minY + 1, borderRadius);
+    CGContextAddArcToPoint(c, maxX, minY + 1, maxX, midY, borderRadius);
+    CGContextAddLineToPoint(c, maxX, maxY);
+  } else if (isBottom) {
+    CGContextMoveToPoint(c, maxX, minY);
+    CGContextAddLineToPoint(c, maxX, midY);
+    CGContextAddArcToPoint(c, maxX, maxY - 1, midX, maxY - 1, borderRadius);
+    CGContextAddArcToPoint(c, minX, maxY - 1, minX, midY, borderRadius);
+    CGContextAddLineToPoint(c, minX, minY);
+  } else {
+    CGContextMoveToPoint(c, minX, minY);
+    CGContextAddLineToPoint(c, minX, maxY);
+    CGContextMoveToPoint(c, maxX, minY);
+    CGContextAddLineToPoint(c, maxX, maxY);
+  }
+
+  CGContextClosePath(c);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h
new file mode 100644
index 0000000..58553ff
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings.h
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+typedef enum {
+  kStr_MaterialCollectionsInfoBarGestureHint = 0,
+  kStr_MaterialCollectionsDeleteButton = 1,
+} MaterialCollectionsStringId;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h
new file mode 100644
index 0000000..41e4aa8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Collections/src/private/MaterialCollectionsStrings_table.h
@@ -0,0 +1,27 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// A table of string keys to look-up localized strings in the bundle.
+// This table is to be indexed using the generated enum.
+
+static NSString *const kMaterialCollectionsStringTable[] = {
+    @"InfoBarGestureHint",  // Swipe an item to delete
+    @"DeleteButton",        // Delete
+};
+#define kNumMaterialCollectionsStrings 2
+#define kMaterialCollectionsStringsOffset 0
+#define kMaterialCollectionsStringsEnd 10000
+static NSString *const kMaterialCollectionsStringsTableName = @"MaterialCollections";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.h
new file mode 100644
index 0000000..ea8330a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.h
@@ -0,0 +1,145 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+@class MDCAlertAction;
+
+/**
+ MDCAlertController displays an alert message to the user, similar to UIAlertController.
+
+ https://material.google.com/components/dialogs.html
+
+ MDCAlertController requires iOS 8 or later.
+
+ MDCAlertController class is intended to be used as-is and does not support subclassing. The view
+ hierarchy for this class is private and must not be modified.
+ */
+@interface MDCAlertController : UIViewController
+
+/**
+ Convenience constructor to create and return a view controller for displaying an alert to the user.
+
+ After creating the alert controller, add actions to the controller by calling -addAction.
+
+ @note Most alerts don't need titles. Use only for high-risk situations.
+
+ @param title The title of the alert.
+ @param message Descriptive text that summarizes a decision in a sentence of two.
+ @return An initialized MDCAlertController object.
+ */
++ (nonnull instancetype)alertControllerWithTitle:(nullable NSString *)title
+                                         message:(nullable NSString *)message;
+
+/** Alert controllers must be created with alertControllerWithTitle:message: */
+- (nonnull instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
+                                 bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
+
+/** Alert controllers must be created with alertControllerWithTitle:message: */
+- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+
+/**
+ Adds an action to the alert dialog.
+
+ Actions are the possible reactions of the user to the presented alert. Actions are added as a
+ button at the bottom of the alert. Affirmative actions should be added before dismissive actions.
+ Action buttons will be laid out from right to left if possible or top to bottom depending on space.
+
+ Material spec recommends alerts should not have more than two actions.
+
+ @param action Will be added to the end of MDCAlertController.actions.
+ */
+- (void)addAction:(nonnull MDCAlertAction *)action;
+
+/**
+ The actions that the user can take in response to the alert.
+
+ The order of the actions in the array matches the order in which they were added to the alert.
+ */
+@property(nonatomic, nonnull, readonly) NSArray<MDCAlertAction *> *actions;
+
+// TODO(iangordon): Add support for preferredAction to match UIAlertController.
+// TODO(iangordon): Consider adding support for UITextFields to match UIAlertController.
+
+/**
+ High level description of the alert or decision being made.
+
+ Use title only for high-risk situations, such as the potential loss of connectivity. If used,
+ users should be able to understand the choices based on the title and button text alone.
+ */
+@property(nonatomic, nullable, copy) NSString *title;
+
+/** Descriptive text that summarizes a decision in a sentence of two. */
+@property(nonatomic, nullable, copy) NSString *message;
+
+/*
+ Indicates whether the alert contents should automatically update their font when the device’s
+ UIContentSizeCategory changes.
+
+ This property is modeled after the adjustsFontForContentSizeCategory property in the
+ UIConnectSizeCategoryAdjusting protocol added by Apple in iOS 10.0.
+
+ Default value is NO.
+ */
+@property(nonatomic, readwrite, setter=mdc_setAdjustsFontForContentSizeCategory:)
+    BOOL mdc_adjustsFontForContentSizeCategory UI_APPEARANCE_SELECTOR;
+
+/** MDCAlertController handles its own transitioning delegate. */
+- (void)setTransitioningDelegate:
+        (_Nullable id<UIViewControllerTransitioningDelegate>)transitioningDelegate NS_UNAVAILABLE;
+
+/** MDCAlertController.modalPresentationStyle is always UIModalPresentationCustom. */
+- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle NS_UNAVAILABLE;
+
+@end
+
+/**
+ MDCActionHandler is a block that will be invoked when the action is selected.
+ */
+typedef void (^MDCActionHandler)(MDCAlertAction *_Nonnull action);
+
+/**
+ MDCAlertAction is passed to an MDCAlertController to add a button to the alert dialog.
+ */
+@interface MDCAlertAction : NSObject <NSCopying>
+
+/**
+ Action alerts control the buttons that will be displayed on the bottom of an alert controller.
+
+ @param title The title of the button shown on the alert dialog.
+ @param handler A block to execute when the user selects the action.
+ @return An initialized MDCActionAlert object.
+ */
++ (nonnull instancetype)actionWithTitle:(nonnull NSString *)title
+                                handler:(__nullable MDCActionHandler)handler;
+
+/** Alert actions must be created with actionWithTitle:handler: */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Title of the button shown on the alert dialog.
+
+ Alert actions titles must be set in the actionWithTitle:handler: method.
+ */
+@property(nonatomic, nullable, readonly) NSString *title;
+
+// TODO(iangordon): Add support for enabled property to match UIAlertAction
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.m
new file mode 100644
index 0000000..d0dccf9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCAlertController.m
@@ -0,0 +1,554 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAlertController.h"
+
+#import "MDCDialogTransitionController.h"
+#import "MaterialButtons.h"
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+@interface MDCAlertAction ()
+
+@property(nonatomic, nullable, copy) MDCActionHandler completionHandler;
+
+@end
+
+@implementation MDCAlertAction
+
++ (instancetype)actionWithTitle:(nonnull NSString *)title
+                        handler:(void (^__nullable)(MDCAlertAction *action))handler {
+  return [[MDCAlertAction alloc] initWithTitle:title handler:handler];
+}
+
+- (instancetype)initWithTitle:(nonnull NSString *)title
+                      handler:(void (^__nullable)(MDCAlertAction *action))handler {
+  self = [super init];
+  if (self) {
+    _title = [title copy];
+    _completionHandler = [handler copy];
+  }
+  return self;
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+  MDCAlertAction *action = [[self class] actionWithTitle:self.title handler:self.completionHandler];
+
+  return action;
+}
+
+@end
+
+// https://material.google.com/components/dialogs.html#dialogs-specs
+static const UIEdgeInsets MDCDialogContentInsets = {24.0, 24.0, 24.0, 24.0};
+static const CGFloat MDCDialogContentVerticalPadding = 20.0;
+
+static const UIEdgeInsets MDCDialogActionsInsets = {8.0, 8.0, 8.0, 8.0};
+static const CGFloat MDCDialogActionsHorizontalPadding = 8.0;
+static const CGFloat MDCDialogActionsVerticalPadding = 8.0;
+static const CGFloat MDCDialogActionButtonHeight = 36.0;
+static const CGFloat MDCDialogActionButtonMinimumWidth = 48.0;
+
+static const CGFloat MDCDialogMessageOpacity = 0.38f;
+
+@interface MDCAlertController ()
+
+@property(nonatomic, nonnull, strong) NSMutableArray<UIButton *> *actionButtons;
+
+@property(nonatomic, strong) UIScrollView *contentScrollView;
+@property(nonatomic, strong) UIScrollView *actionsScrollView;
+
+@property(nonatomic, strong) UILabel *titleLabel;
+@property(nonatomic, strong) UILabel *messageLabel;
+
+@property(nonatomic, getter=isVerticalActionsLayout) BOOL verticalActionsLayout;
+
+@property(nonatomic, strong) MDCDialogTransitionController *transitionController;
+
+- (nonnull instancetype)initWithTitle:(nullable NSString *)title
+                              message:(nullable NSString *)message;
+
+@end
+
+@implementation MDCAlertController {
+  NSString *_alertTitle;
+  NSString *_message;
+
+  NSMutableArray<MDCAlertAction *> *_actions;
+
+  CGSize _previousLayoutSize;
+
+  BOOL _mdc_adjustsFontForContentSizeCategory;
+}
+
++ (instancetype)alertControllerWithTitle:(nullable NSString *)alertTitle
+                                 message:(nullable NSString *)message {
+  MDCAlertController *alertController =
+      [[MDCAlertController alloc] initWithTitle:alertTitle message:message];
+
+  return alertController;
+}
+
+- (nonnull instancetype)initWithTitle:(nullable NSString *)title
+                              message:(nullable NSString *)message {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _alertTitle = [title copy];
+    _message = [message copy];
+
+    _contentScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
+    _actionsScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
+
+    _actions = [[NSMutableArray alloc] init];
+    _actionButtons = [[NSMutableArray alloc] init];
+
+    _transitionController = [[MDCDialogTransitionController alloc] init];
+    super.transitioningDelegate = _transitionController;
+    super.modalPresentationStyle = UIModalPresentationCustom;
+  }
+  return self;
+}
+
+/* Disable setter. Always use internal transition controller */
+- (void)setTransitioningDelegate:(id<UIViewControllerTransitioningDelegate>)transitioningDelegate {
+  NSAssert(NO, @"MDCAlertController.transitioningDelegate cannot be changed.");
+  return;
+}
+
+/* Disable setter. Always use custom presentation style */
+- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
+  NSAssert(NO, @"MDCAlertController.modalPresentationStyle cannot be changed.");
+  return;
+}
+
+- (NSString *)title {
+  return _alertTitle;
+}
+
+- (void)setTitle:(NSString *)title {
+  _alertTitle = [title copy];
+  self.titleLabel.text = _alertTitle;
+
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  [self.view setNeedsLayout];
+}
+
+- (NSString *)message {
+  return _message;
+}
+
+- (void)setMessage:(NSString *)message {
+  _message = [message copy];
+  self.messageLabel.text = _message;
+
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  [self.view setNeedsLayout];
+}
+
+- (NSArray<MDCAlertAction *> *)actions {
+  return [_actions copy];
+}
+
+- (void)addAction:(MDCAlertAction *)action {
+  [_actions addObject:[action copy]];
+
+  MDCFlatButton *actionButton = [[MDCFlatButton alloc] initWithFrame:CGRectZero];
+  actionButton.mdc_adjustsFontForContentSizeCategory = self.mdc_adjustsFontForContentSizeCategory;
+  [actionButton setTitle:action.title forState:UIControlStateNormal];
+  // TODO(iangordon): Determine default text color values for Normal and Disabled
+  [actionButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
+  [actionButton sizeToFit];
+  CGRect buttonRect = actionButton.bounds;
+  buttonRect.size.height = MAX(buttonRect.size.height, MDCDialogActionButtonHeight);
+  buttonRect.size.width = MAX(buttonRect.size.width, MDCDialogActionButtonMinimumWidth);
+  actionButton.frame = buttonRect;
+  [actionButton addTarget:self
+                   action:@selector(actionButtonPressed:)
+         forControlEvents:UIControlEventTouchUpInside];
+  [self.actionsScrollView addSubview:actionButton];
+
+  [self.actionButtons addObject:actionButton];
+
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  [self.view setNeedsLayout];
+}
+
+- (BOOL)mdc_adjustsFontForContentSizeCategory {
+  return _mdc_adjustsFontForContentSizeCategory;
+}
+
+- (void)mdc_setAdjustsFontForContentSizeCategory:(BOOL)adjusts {
+  _mdc_adjustsFontForContentSizeCategory = adjusts;
+
+  // Update any action buttons to match the alert controller.
+  for (MDCButton *actionButton in self.actionButtons) {
+    actionButton.mdc_adjustsFontForContentSizeCategory = adjusts;
+  }
+
+  if (_mdc_adjustsFontForContentSizeCategory) {
+    [self updateFontsForDynamicType];
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(contentSizeCategoryDidChange:)
+                                                 name:UIContentSizeCategoryDidChangeNotification
+                                               object:nil];
+  } else {
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                    name:UIContentSizeCategoryDidChangeNotification
+                                                  object:nil];
+  }
+}
+
+// Handles UIContentSizeCategoryDidChangeNotifications
+- (void)contentSizeCategoryDidChange:(NSNotification *)notification {
+  [self updateFontsForDynamicType];
+}
+
+// Update the fonts used based on mdc_preferredFontForMaterialTextStyle and recalculate the
+// preferred content size.
+- (void)updateFontsForDynamicType {
+  self.titleLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleTitle];
+  self.messageLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleBody1];
+
+  // The action MDCButtons handle their own resizing
+
+  // Our presentation controller reacts to changes to preferredContentSize to determine our
+  // frame at the presented controller.
+  self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+}
+
+- (void)actionButtonPressed:(id)sender {
+  NSInteger actionIndex = [self.actionButtons indexOfObject:sender];
+  MDCAlertAction *action = self.actions[actionIndex];
+
+  if (action.completionHandler) {
+    action.completionHandler(action);
+  }
+
+  [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  self.view.backgroundColor = [UIColor whiteColor];
+
+  self.contentScrollView.backgroundColor = [UIColor whiteColor];
+  [self.view addSubview:self.contentScrollView];
+
+  self.actionsScrollView.backgroundColor = [UIColor whiteColor];
+  [self.view addSubview:self.actionsScrollView];
+
+  self.titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  self.titleLabel.numberOfLines = 0;
+  self.titleLabel.textAlignment = NSTextAlignmentNatural;
+  if (self.mdc_adjustsFontForContentSizeCategory) {
+    self.titleLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleTitle];
+  } else {
+    self.titleLabel.font = [MDCTypography titleFont];
+  }
+  [self.contentScrollView addSubview:self.titleLabel];
+
+  self.messageLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+  self.messageLabel.numberOfLines = 0;
+  self.messageLabel.textAlignment = NSTextAlignmentNatural;
+  if (self.mdc_adjustsFontForContentSizeCategory) {
+    self.messageLabel.font = [UIFont mdc_preferredFontForMaterialTextStyle:MDCFontTextStyleBody1];
+  } else {
+    self.messageLabel.font = [MDCTypography body1Font];
+  }
+  self.messageLabel.textColor = [UIColor colorWithWhite:0.0 alpha:MDCDialogMessageOpacity];
+  [self.contentScrollView addSubview:self.messageLabel];
+
+  self.titleLabel.text = self.title;
+  self.messageLabel.text = self.message;
+
+  CGSize idealSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+
+  self.preferredContentSize = idealSize;
+  _previousLayoutSize = CGSizeZero;
+
+  [self.view setNeedsLayout];
+}
+
+- (void)viewWillLayoutSubviews {
+  [super viewWillLayoutSubviews];
+
+  const CGSize viewSize = self.view.bounds.size;
+
+  // Recalculate preferredSize, which is based on width available, if the viewSize has changed.
+  if (viewSize.width != _previousLayoutSize.width ||
+      viewSize.height != _previousLayoutSize.height) {
+    CGSize currentPreferredContentSize = self.preferredContentSize;
+    CGSize calculatedPreferredContentSize = [self calculatePreferredContentSizeForBounds:viewSize];
+
+    if (!CGSizeEqualToSize(currentPreferredContentSize, calculatedPreferredContentSize)) {
+      self.preferredContentSize = calculatedPreferredContentSize;
+    }
+
+    _previousLayoutSize = viewSize;
+  }
+
+  CGSize boundsSize = CGRectInfinite.size;
+  boundsSize.width = viewSize.width;
+
+  // Content
+  CGSize contentSize = [self calculateContentSizeThatFitsWidth:boundsSize.width];
+
+  CGRect contentRect = CGRectZero;
+  contentRect.size.width = viewSize.width;
+  contentRect.size.height = contentSize.height;
+
+  self.contentScrollView.contentSize = contentRect.size;
+
+  // Place Content in contentScrollView
+  boundsSize.width = boundsSize.width - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
+  CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
+  titleSize.width = boundsSize.width;
+  CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
+  messageSize.width = boundsSize.width;
+  boundsSize.width = boundsSize.width + MDCDialogContentInsets.left + MDCDialogContentInsets.right;
+
+  CGFloat contentInternalVerticalPadding = 0.0;
+  if (0.0 < titleSize.height && 0.0 < messageSize.height) {
+    contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
+  }
+
+  CGRect titleFrame = CGRectMake(MDCDialogContentInsets.left, MDCDialogContentInsets.top,
+                                 titleSize.width, titleSize.height);
+  CGRect messageFrame = CGRectMake(MDCDialogContentInsets.left,
+                                   CGRectGetMaxY(titleFrame) + contentInternalVerticalPadding,
+                                   messageSize.width, messageSize.height);
+
+  self.titleLabel.frame = titleFrame;
+  self.messageLabel.frame = messageFrame;
+
+  // Actions
+  CGSize actionSize = [self calculateActionsSizeThatFitsWidth:boundsSize.width];
+  const CGFloat horizontalActionHeight =
+      MDCDialogActionsInsets.top + MDCDialogActionButtonHeight + MDCDialogActionsInsets.bottom;
+  if (horizontalActionHeight < actionSize.height) {
+    self.verticalActionsLayout = YES;
+  } else {
+    self.verticalActionsLayout = NO;
+  }
+
+  CGRect actionsFrame = CGRectZero;
+  actionsFrame.size.width = self.view.bounds.size.width;
+  if (0 < [self.actions count]) {
+    actionsFrame.size.height = actionSize.height;
+  }
+  self.actionsScrollView.contentSize = actionsFrame.size;
+
+  // Place buttons in actionsScrollView
+  if (self.isVerticalActionsLayout) {
+    CGPoint buttonCenter;
+    buttonCenter.x = self.actionsScrollView.contentSize.width * 0.5f;
+    buttonCenter.y = self.actionsScrollView.contentSize.height - MDCDialogActionsInsets.bottom;
+    for (UIButton *button in self.actionButtons) {
+      CGRect buttonRect = button.frame;
+
+      buttonCenter.y -= buttonRect.size.height * 0.5;
+
+      button.center = buttonCenter;
+
+      if (button != [self.actionButtons lastObject]) {
+        buttonCenter.y -= buttonRect.size.height * 0.5;
+        buttonCenter.y -= MDCDialogActionsVerticalPadding;
+      }
+    }
+  } else {
+    CGPoint buttonOrigin = CGPointZero;
+    buttonOrigin.x = self.actionsScrollView.contentSize.width - MDCDialogActionsInsets.right;
+    buttonOrigin.y = MDCDialogActionsInsets.top;
+    for (UIButton *button in self.actionButtons) {
+      CGRect buttonRect = button.frame;
+
+      buttonOrigin.x -= buttonRect.size.width;
+      buttonRect.origin = buttonOrigin;
+
+      button.frame = buttonRect;
+
+      if (button != [self.actionButtons lastObject]) {
+        buttonOrigin.x -= MDCDialogActionsHorizontalPadding;
+      }
+    }
+    // Handle RTL
+    if (self.view.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      for (UIButton *button in self.actionButtons) {
+        CGRect buttonRect = button.frame;
+        CGRect flippedRect = MDCRectFlippedForRTL(buttonRect, CGRectGetWidth(self.view.bounds),
+                                                  UIUserInterfaceLayoutDirectionRightToLeft);
+        button.frame = flippedRect;
+      }
+    }
+  }
+
+  // Place scrollviews
+  CGRect contentScrollViewRect = CGRectZero;
+  contentScrollViewRect.size = self.contentScrollView.contentSize;
+
+  CGRect actionsScrollViewRect = CGRectZero;
+  actionsScrollViewRect.size = self.actionsScrollView.contentSize;
+
+  const CGFloat requestedHeight =
+      self.contentScrollView.contentSize.height + self.actionsScrollView.contentSize.height;
+  if (requestedHeight <= self.view.bounds.size.height) {
+    // Simple layout case : both content and actions fit on the screen at once
+    self.contentScrollView.frame = contentScrollViewRect;
+
+    actionsScrollViewRect.origin.y =
+        self.view.bounds.size.height - actionsScrollViewRect.size.height;
+    self.actionsScrollView.frame = actionsScrollViewRect;
+  } else {
+    // Complex layout case : Split the space between the two scrollviews
+    CGFloat maxActionsHeight = self.view.bounds.size.height * 0.5f;
+    actionsScrollViewRect.size.height = MIN(maxActionsHeight, actionsScrollViewRect.size.height);
+    actionsScrollViewRect.origin.y =
+        self.view.bounds.size.height - actionsScrollViewRect.size.height;
+    self.actionsScrollView.frame = actionsScrollViewRect;
+
+    contentScrollViewRect.size.height =
+        self.view.bounds.size.height - actionsScrollViewRect.size.height;
+    self.contentScrollView.frame = contentScrollViewRect;
+  }
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+
+  [coordinator animateAlongsideTransition:^(
+                   id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
+    // Reset preferredContentSize on viewWIllTransition to take advantage of additional width
+    self.preferredContentSize = [self calculatePreferredContentSizeForBounds:CGRectInfinite.size];
+  }
+                               completion:nil];
+}
+
+#pragma mark - Internal
+
+// @param boundingWidth should not include any internal margins or padding
+- (CGSize)calculateContentSizeThatFitsWidth:(CGFloat)boundingWidth {
+  CGSize boundsSize = CGRectInfinite.size;
+  boundsSize.width = boundingWidth - MDCDialogContentInsets.left - MDCDialogContentInsets.right;
+
+  CGSize titleSize = [self.titleLabel sizeThatFits:boundsSize];
+  CGSize messageSize = [self.messageLabel sizeThatFits:boundsSize];
+
+  CGFloat contentWidth = MAX(titleSize.width, messageSize.width);
+  contentWidth += MDCDialogContentInsets.left + MDCDialogContentInsets.right;
+
+  CGFloat contentInternalVerticalPadding = 0.0;
+  if (0.0 < titleSize.height && 0.0 < messageSize.height) {
+    contentInternalVerticalPadding = MDCDialogContentVerticalPadding;
+  }
+  CGFloat contentHeight = titleSize.height + contentInternalVerticalPadding + messageSize.height;
+  contentHeight += MDCDialogContentInsets.top + MDCDialogContentInsets.bottom;
+
+  CGSize contentSize;
+  contentSize.width = (CGFloat)ceil(contentWidth);
+  contentSize.height = (CGFloat)ceil(contentHeight);
+
+  return contentSize;
+}
+
+// @param boundingWidth should not include any internal margins or padding
+- (CGSize)calculateActionsSizeThatFitsWidth:(CGFloat)boundingWidth {
+  CGSize boundsSize = CGRectInfinite.size;
+  boundsSize.width = boundingWidth;
+
+  CGSize horizontalSize = [self actionButtonsSizeInHorizontalLayout];
+  CGSize verticalSize = [self actionButtonsSizeInVericalLayout];
+
+  CGSize actionsSize;
+  if (boundsSize.width < horizontalSize.width) {
+    // Use VerticalLayout
+    actionsSize.width = MIN(verticalSize.width, boundsSize.width);
+    actionsSize.height = MIN(verticalSize.height, boundsSize.height);
+  } else {
+    // Use HorizontalLayout
+    actionsSize.width = MIN(horizontalSize.width, boundsSize.width);
+    actionsSize.height = MIN(horizontalSize.height, boundsSize.height);
+  }
+
+  actionsSize.width = (CGFloat)ceil(actionsSize.width);
+  actionsSize.height = (CGFloat)ceil(actionsSize.height);
+
+  return actionsSize;
+}
+
+// @param boundsSize should not include any internal margins or padding
+- (CGSize)calculatePreferredContentSizeForBounds:(CGSize)boundsSize {
+  // Content & Actions
+  CGSize contentSize = [self calculateContentSizeThatFitsWidth:boundsSize.width];
+  CGSize actionSize = [self calculateActionsSizeThatFitsWidth:boundsSize.width];
+
+  // Final Sizing
+  CGSize totalSize;
+  totalSize.width = MAX(contentSize.width, actionSize.width);
+  totalSize.height = contentSize.height + actionSize.height;
+
+  return totalSize;
+}
+
+- (CGSize)actionButtonsSizeInHorizontalLayout {
+  CGSize size = CGSizeZero;
+  if (0 < [self.actions count]) {
+    size.height =
+        MDCDialogActionsInsets.top + MDCDialogActionButtonHeight + MDCDialogActionsInsets.bottom;
+    size.width = MDCDialogActionsInsets.left + MDCDialogActionsInsets.right;
+    for (UIButton *button in self.actionButtons) {
+      size.width += CGRectGetWidth(button.bounds);
+      if (button != [self.actionButtons lastObject]) {
+        size.width += MDCDialogActionsHorizontalPadding;
+      }
+    }
+  }
+
+  return size;
+}
+
+- (CGSize)actionButtonsSizeInVericalLayout {
+  CGSize size = CGSizeZero;
+  if (0 < [self.actions count]) {
+    size.height = MDCDialogActionsInsets.top + MDCDialogActionsInsets.bottom;
+    size.width = MDCDialogActionsInsets.left + MDCDialogActionsInsets.right;
+    for (UIButton *button in self.actionButtons) {
+      size.height += CGRectGetHeight(button.bounds);
+      size.width = MAX(size.width, CGRectGetWidth(button.bounds));
+      if (button != [self.actionButtons lastObject]) {
+        size.height += MDCDialogActionsVerticalPadding;
+      }
+    }
+  }
+
+  return size;
+}
+
+#pragma mark - UIAccessibilityAction
+
+- (BOOL)accessibilityPerformEscape {
+  [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
+  return YES;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
new file mode 100644
index 0000000..628d0a2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.h
@@ -0,0 +1,71 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+/**
+ MDCDialogPresentationController will present a modal ViewController as a dialog according to the
+ Material spec.
+
+ https://material.google.com/components/dialogs.html
+
+ MDCDialogPresentationController should not be used to present full-screen dialogs.
+
+ The presented UIViewController will be asked for it's preferredContentSize to help determine
+ the best size for the dialog to be displayed.
+
+ This controller will manage the background dimming view and add a material-styled shadow underneath
+ the presented view.
+
+ This controller will respond to the display / dismissal of the keyboard and update the
+ presentedView's frame.
+ */
+@interface MDCDialogPresentationController : UIPresentationController
+
+/**
+ Should a tap on the dimmed background view dismiss the presented controller.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL dismissOnBackgroundTap;
+
+/**
+ Returns the size of the specified child view controller's content.
+
+ The size is initially based on container.preferredSize. Width is will have a minimum of 280 and a
+ maximum of the parentSize - 40 for the padding on the left and right size.
+
+ Height has no minimum.  Height has a maximum of the parentSize - height of any displayed
+ keyboards - 48 for the padding on the top and bottom.  If preferredSize.height is 0, height will
+ be set to the maximum.
+ */
+- (CGSize)sizeForChildContentContainer:(nonnull id<UIContentContainer>)container
+               withParentContainerSize:(CGSize)parentSize;
+
+/**
+ Returns the frame rectangle to assign to the presented view at the end of the animations.
+
+ The size of the frame is determined by sizeForChildContentContainer:withParentContainerSize:. The
+ presentedView is centered horizontally and verically in the available space.  The available space
+ is the size of the containerView subtracting any space taken up by the keyboard.
+ */
+- (CGRect)frameOfPresentedViewInContainerView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.m
new file mode 100644
index 0000000..5ad9103
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogPresentationController.m
@@ -0,0 +1,320 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCDialogPresentationController.h"
+
+#import "MaterialKeyboardWatcher.h"
+#import "private/MDCDialogShadowedView.h"
+
+static CGFloat MDCDialogMinimumWidth = 280.0f;
+// TODO: Spec indicates 40 side margins and 280 minimum width.
+// That is incompatible with a 320 wide device.
+// Side margins set to 20 until we have a resolution
+static UIEdgeInsets MDCDialogEdgeInsets = {24, 20, 24, 20};
+
+@interface MDCDialogPresentationController ()
+
+// View matching the container's bounds that dims the entire screen and catchs taps to dismiss.
+@property(nonatomic) UIView *dimmingView;
+
+// Tracking view that adds a shadow under the presented view. This view's frame should always match
+// the presented view's.
+@property(nonatomic) UIView *trackingView;
+
+@end
+
+@implementation MDCDialogPresentationController {
+  UITapGestureRecognizer *_dismissGestureRecognizer;
+}
+
+#pragma mark - UIPresentationController
+
+// dismissOnBackgroundTap wraps the enable property of our gesture recognizer to
+// avoid duplication.
+- (void)setDismissOnBackgroundTap:(BOOL)dismissOnBackgroundTap {
+  _dismissGestureRecognizer.enabled = dismissOnBackgroundTap;
+}
+
+- (BOOL)dismissOnBackgroundTap {
+  return _dismissGestureRecognizer.enabled;
+}
+
+- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController
+                       presentingViewController:(UIViewController *)presentingViewController {
+  self = [super initWithPresentedViewController:presentedViewController
+                       presentingViewController:presentingViewController];
+  if (self) {
+    _dimmingView = [[UIView alloc] initWithFrame:CGRectZero];
+    _dimmingView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.4f];
+    _dimmingView.alpha = 0.0f;
+    _dismissGestureRecognizer =
+        [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss:)];
+    [_dimmingView addGestureRecognizer:_dismissGestureRecognizer];
+
+    _trackingView = [[MDCDialogShadowedView alloc] init];
+
+    [self registerKeyboardNotifications];
+  }
+
+  return self;
+}
+
+- (void)dealloc {
+  [self unregisterKeyboardNotifications];
+}
+
+- (CGRect)frameOfPresentedViewInContainerView {
+  CGRect presentedViewFrame = CGRectZero;
+
+  CGRect containerBounds = self.containerView.bounds;
+  containerBounds.size.height -= [MDCKeyboardWatcher sharedKeyboardWatcher].keyboardOffset;
+
+  presentedViewFrame.size = [self sizeForChildContentContainer:self.presentedViewController
+                                       withParentContainerSize:containerBounds.size];
+
+  presentedViewFrame.origin.x = (containerBounds.size.width - presentedViewFrame.size.width) * 0.5f;
+  presentedViewFrame.origin.y =
+      (containerBounds.size.height - presentedViewFrame.size.height) * 0.5f;
+
+  presentedViewFrame.origin.x = (CGFloat)floor(presentedViewFrame.origin.x);
+  presentedViewFrame.origin.y = (CGFloat)floor(presentedViewFrame.origin.y);
+
+  return presentedViewFrame;
+}
+
+- (void)presentationTransitionWillBegin {
+  // TODO: Follow the Material spec description of Autonomous surface creation for both
+  // presentation and dismissal of the dialog.
+  // https://spec.googleplex.com/quantum/motion/choreography.html#choreography-creation
+
+  // Set the dimming view to the container's bounds and fully transparent.
+  self.dimmingView.frame = self.containerView.bounds;
+  self.dimmingView.alpha = 0.0f;
+  [self.containerView addSubview:self.dimmingView];
+
+  // Set the shadowing view to the same frame as the presented view.
+  CGRect presentedFrame = [self frameOfPresentedViewInContainerView];
+  self.trackingView.frame = presentedFrame;
+  self.trackingView.alpha = 0.0f;
+  [self.containerView addSubview:self.trackingView];
+
+  // Fade-in chrome views to be fully visible.
+  id<UIViewControllerTransitionCoordinator> transitionCoordinator =
+      [self.presentedViewController transitionCoordinator];
+  if (transitionCoordinator) {
+    [transitionCoordinator
+        animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+          self.dimmingView.alpha = 1.0f;
+          self.trackingView.alpha = 1.0f;
+        }
+                        completion:NULL];
+  } else {
+    self.dimmingView.alpha = 1.0f;
+    self.trackingView.alpha = 1.0f;
+  }
+}
+
+- (void)presentationTransitionDidEnd:(BOOL)completed {
+  if (completed) {
+    // Stop the presenting view from being tapped for voiceover while this view is up.
+    // Setting @c accessibilityViewIsModal on the presented view (or its parent) should be enough,
+    // but it's not.
+    // b/19519321
+    self.presentingViewController.view.accessibilityElementsHidden = YES;
+    self.presentedView.accessibilityViewIsModal = YES;
+    UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, [self presentedView]);
+  } else {
+    // Transition was cancelled.
+    [self.dimmingView removeFromSuperview];
+    [self.trackingView removeFromSuperview];
+  }
+}
+
+- (void)dismissalTransitionWillBegin {
+  // Fade-out dimmingView and trackingView to be fully transparent.
+  id<UIViewControllerTransitionCoordinator> transitionCoordinator =
+      [self.presentedViewController transitionCoordinator];
+  if (transitionCoordinator != nil) {
+    [transitionCoordinator
+        animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+          self.dimmingView.alpha = 0.0f;
+          self.trackingView.alpha = 0.0f;
+        }
+                        completion:NULL];
+  } else {
+    self.dimmingView.alpha = 0.0f;
+    self.trackingView.alpha = 0.0f;
+  }
+}
+
+- (void)dismissalTransitionDidEnd:(BOOL)completed {
+  if (completed) {
+    [self.dimmingView removeFromSuperview];
+    [self.trackingView removeFromSuperview];
+
+    // Re-enable accessibilityElements on the presenting view controller.
+    self.presentingViewController.view.accessibilityElementsHidden = NO;
+  }
+
+  [super dismissalTransitionDidEnd:completed];
+}
+
+/**
+ Indicate that the presenting view controller's view should not be removed when the presentation
+ animations finish.
+
+ MDCDialogPresentationController does not cover the presenting view controller's content entirely
+ so we must return NO.
+ */
+- (BOOL)shouldRemovePresentersView {
+  return NO;
+}
+
+#pragma mark - UIContentContainer
+
+/**
+ Determines the size of the presented container's view based on available space and the preferred
+ content size of the container.
+ */
+- (CGSize)sizeForChildContentContainer:(id<UIContentContainer>)container
+               withParentContainerSize:(CGSize)parentSize {
+  if (CGSizeEqualToSize(parentSize, CGSizeZero)) {
+    return CGSizeZero;
+  }
+
+  CGSize maxChildSize;
+  maxChildSize.width = parentSize.width - MDCDialogEdgeInsets.left - MDCDialogEdgeInsets.right;
+  maxChildSize.height = parentSize.height - MDCDialogEdgeInsets.top - MDCDialogEdgeInsets.bottom;
+
+  CGSize targetSize = maxChildSize;
+
+  const CGSize preferredContentSize = container.preferredContentSize;
+  if (!CGSizeEqualToSize(preferredContentSize, CGSizeZero)) {
+    targetSize = preferredContentSize;
+
+    // If the targetSize.width is greater than 0.0 it must be at least MDCDialogMinimumWidth.
+    if (0.0f < targetSize.width && targetSize.width < MDCDialogMinimumWidth) {
+      targetSize.width = MDCDialogMinimumWidth;
+    }
+    // targetSize cannot exceed maxChildSize.
+    targetSize.width = MIN(targetSize.width, maxChildSize.width);
+    targetSize.height = MIN(targetSize.height, maxChildSize.height);
+  }
+
+  targetSize.width = (CGFloat)ceil(targetSize.width);
+  targetSize.height = (CGFloat)ceil(targetSize.height);
+
+  return targetSize;
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
+
+  [coordinator
+      animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        self.dimmingView.frame = self.containerView.bounds;
+        CGRect presentedViewFrame = [self frameOfPresentedViewInContainerView];
+        self.presentedView.frame = presentedViewFrame;
+        self.trackingView.frame = presentedViewFrame;
+      }
+                      completion:NULL];
+}
+
+/**
+ If the container's preferred content size has changed and we are able to accommidate the new size,
+ update the frame of the presented view and the shadowing view.
+ */
+- (void)preferredContentSizeDidChangeForChildContentContainer:(id<UIContentContainer>)container {
+  [super preferredContentSizeDidChangeForChildContentContainer:container];
+
+  CGSize existingSize = self.presentedView.bounds.size;
+  CGSize newSize = [self sizeForChildContentContainer:container
+                              withParentContainerSize:self.containerView.bounds.size];
+
+  if (!CGSizeEqualToSize(existingSize, newSize)) {
+    CGRect presentedViewFrame = [self frameOfPresentedViewInContainerView];
+    self.presentedView.frame = presentedViewFrame;
+    self.trackingView.frame = presentedViewFrame;
+  }
+}
+
+#pragma mark - Internal
+
+- (void)dismiss:(UIGestureRecognizer *)gesture {
+  if (gesture.state == UIGestureRecognizerStateRecognized) {
+    [self.presentingViewController dismissViewControllerAnimated:YES completion:NULL];
+  }
+}
+
+#pragma mark - Keyboard handling
+
+- (void)registerKeyboardNotifications {
+  [[NSNotificationCenter defaultCenter] addObserver:self
+                                           selector:@selector(keyboardWatcherHandler:)
+                                               name:MDCKeyboardWatcherKeyboardWillShowNotification
+                                             object:nil];
+
+  [[NSNotificationCenter defaultCenter] addObserver:self
+                                           selector:@selector(keyboardWatcherHandler:)
+                                               name:MDCKeyboardWatcherKeyboardWillHideNotification
+                                             object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector(keyboardWatcherHandler:)
+             name:MDCKeyboardWatcherKeyboardWillChangeFrameNotification
+           object:nil];
+}
+
+- (void)unregisterKeyboardNotifications {
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:MDCKeyboardWatcherKeyboardWillShowNotification
+              object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:MDCKeyboardWatcherKeyboardWillHideNotification
+              object:nil];
+
+  [[NSNotificationCenter defaultCenter]
+      removeObserver:self
+                name:MDCKeyboardWatcherKeyboardWillChangeFrameNotification
+              object:nil];
+}
+
+#pragma mark - KeyboardWatcher Notifications
+
+- (void)keyboardWatcherHandler:(NSNotification *)aNotification {
+  NSTimeInterval animationDuration =
+      [MDCKeyboardWatcher animationDurationFromKeyboardNotification:aNotification];
+
+  UIViewAnimationOptions animationCurveOption =
+      [MDCKeyboardWatcher animationCurveOptionFromKeyboardNotification:aNotification];
+
+  [UIView animateWithDuration:animationDuration
+                        delay:0.0f
+                      options:animationCurveOption | UIViewAnimationOptionTransitionNone
+                   animations:^{
+                     CGRect presentedViewFrame = [self frameOfPresentedViewInContainerView];
+                     self.presentedView.frame = presentedViewFrame;
+                     self.trackingView.frame = presentedViewFrame;
+                   }
+                   completion:NULL];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
new file mode 100644
index 0000000..6353b5f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.h
@@ -0,0 +1,43 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+/**
+ MDCDialogTransitionController is be used to setup a custom transition and animationed presentation
+ and dismissal for material-styled alerts, simple dialogs and confirmation dialogs.
+
+ https://material.google.com/components/dialogs.html
+
+ This class provides a basic implementation of UIViewControllerAnimatedTransitioning and
+ UIViewControllerTransitioningDelegate.
+
+ In order to use a custom modal transition, the UIViewController to be presented must set two
+ properties. The UIViewControllers transitioningDelegate should be set to an instance of this class.
+ myDialogViewController.modalPresentationStyle = UIModalPresentationCustom;
+ myDialogViewController.transitioningDelegate = dialogTransitionController;
+
+ The presenting UIViewController then calls presentViewController:animated:completion:
+ [rootViewController presentViewController:myDialogViewController animated:YES completion:...];
+ */
+@interface MDCDialogTransitionController
+    : NSObject <UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate>
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.m
new file mode 100644
index 0000000..4735814
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MDCDialogTransitionController.m
@@ -0,0 +1,112 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCDialogTransitionController.h"
+
+#import "MDCDialogPresentationController.h"
+
+@implementation MDCDialogTransitionController
+
+static const NSTimeInterval MDCDialogTransitionDuration = 0.5;
+
+#pragma mark - UIViewControllerAnimatedTransitioning
+
+- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext {
+  return MDCDialogTransitionDuration;
+}
+
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
+  // If a view in the transitionContext is nil, it likely hasn't been loaded by its ViewController
+  // yet.  Ask for it directly to initiate a loadView on the ViewController.
+  UIViewController *fromViewController =
+      [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
+  UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
+  if (fromView == nil) {
+    fromView = fromViewController.view;
+  }
+
+  UIViewController *toViewController =
+      [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
+  UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
+  if (toView == nil) {
+    toView = toViewController.view;
+  }
+
+  UIViewController *toPresentingViewController = toViewController.presentingViewController;
+  BOOL presenting = (toPresentingViewController == fromViewController) ? YES : NO;
+
+  UIViewController *animatingViewController = presenting ? toViewController : fromViewController;
+  UIView *animatingView = presenting ? toView : fromView;
+
+  UIView *containerView = transitionContext.containerView;
+
+  if (presenting) {
+    [containerView addSubview:toView];
+  }
+
+  CGFloat startingAlpha = presenting ? 0.0f : 1.0f;
+  CGFloat endingAlpha = presenting ? 1.0f : 0.0f;
+
+  animatingView.frame = [transitionContext finalFrameForViewController:animatingViewController];
+  animatingView.alpha = startingAlpha;
+
+  NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
+  UIViewAnimationOptions options =
+      UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState;
+
+  [UIView animateWithDuration:transitionDuration
+      delay:0.0
+      options:options
+      animations:^{
+        animatingView.alpha = endingAlpha;
+      }
+      completion:^(BOOL finished) {
+        // If we're dismissing, remove the presented view from the hierarchy
+        if (!presenting) {
+          [fromView removeFromSuperview];
+        }
+
+        // From ADC : UIViewControllerContextTransitioning
+        // When you do create transition animations, always call the
+        // completeTransition: from an appropriate completion block to let UIKit know
+        // when all of your animations have finished.
+        [transitionContext completeTransition:YES];
+      }];
+}
+
+#pragma mark - UIViewControllerTransitioningDelegate
+
+- (UIPresentationController *)
+    presentationControllerForPresentedViewController:(UIViewController *)presented
+                            presentingViewController:(UIViewController *)presenting
+                                sourceViewController:(UIViewController *)source {
+  return [[MDCDialogPresentationController alloc] initWithPresentedViewController:presented
+                                                         presentingViewController:presenting];
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)
+    animationControllerForPresentedController:(UIViewController *)presented
+                         presentingController:(UIViewController *)presenting
+                             sourceController:(UIViewController *)source {
+  return self;
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:
+        (UIViewController *)dismissed {
+  return self;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MaterialDialogs.h
new file mode 100644
index 0000000..5beed78
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/MaterialDialogs.h
@@ -0,0 +1,20 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCAlertController.h"
+#import "MDCDialogPresentationController.h"
+#import "MDCDialogTransitionController.h"
+#import "UIViewController+MaterialDialogs.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
new file mode 100644
index 0000000..2733b17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+#error "This component only supports iOS 8.0 and above."
+#endif
+
+@class MDCDialogPresentationController;
+
+/**
+ Material Dialog UIViewController Category
+ */
+@interface UIViewController (MaterialDialogs)
+
+/**
+ The Material dialog presentation controller that is managing the current view controller.
+
+ @return nil if the view controller is not managed by a Material dialog presentaiton controller.
+ */
+@property(nonatomic, readonly) MDCDialogPresentationController *mdc_dialogPresentationController;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.m
new file mode 100644
index 0000000..a12b3e9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/UIViewController+MaterialDialogs.m
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIViewController+MaterialDialogs.h"
+
+#import "MDCDialogPresentationController.h"
+
+@implementation UIViewController (MaterialDialogs)
+
+- (MDCDialogPresentationController *)mdc_dialogPresentationController {
+  id presentationController = self.presentationController;
+  if ([presentationController isKindOfClass:[MDCDialogPresentationController class]]) {
+    return (MDCDialogPresentationController *)presentationController;
+  }
+
+  return nil;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h
new file mode 100644
index 0000000..2c0eff1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.h
@@ -0,0 +1,21 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCDialogShadowedView : UIView
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.m
new file mode 100644
index 0000000..adf62f6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Dialogs/src/private/MDCDialogShadowedView.m
@@ -0,0 +1,40 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCDialogShadowedView.h"
+
+#import "MDCShadowElevations.h"
+#import "MDCShadowLayer.h"
+
+@implementation MDCDialogShadowedView
+
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+
+- (MDCShadowLayer *)shadowLayer {
+  return (MDCShadowLayer *)self.layer;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    [[self shadowLayer] setElevation:MDCShadowElevationDialog];
+  }
+  return self;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
new file mode 100644
index 0000000..fcbfc82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h
@@ -0,0 +1,125 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** The default alpha for the outer highlight circle. */
+extern const CGFloat kMDCFeatureHighlightOuterHighlightAlpha;
+
+/**
+ Completion block called when the feature highlight is dismissed either by calling |acceptFeature|
+ or |rejectFeature| on the feature highlight or the user accepts or rejects the highlight by tapping
+ somewhere on the highlight view.
+
+ @param accepted Whether the highlight was accepted or rejected
+ */
+typedef void (^MDCFeatureHighlightCompletion)(BOOL accepted);
+
+/**
+ MDCFeatureHighlightViewController highlights an element of a UI to introduce features or
+ functionality that a user hasn’t tried.
+
+ https://material.googleplex.com/growth-communications/feature-discovery.html
+
+ MDCFeatureHighlightViewController should be presented modally and dismissed using either
+ |acceptFeature| or |rejectFeature|.
+
+ While MDCFeatureHighlightViewController supports changing state while presented, it is not
+ recommended as the design spec does not specify any patterns for that behavior.
+
+ @note Due to a bug in the iOS simulator it is possible that the feature highlight will not render
+ correctly in the simulator. If you're encountering issues make sure to test on device.
+ */
+@interface MDCFeatureHighlightViewController : UIViewController
+
+/**
+ Initializes the controller.
+
+ @param highlightedView The highlight will be presented above the |center| of |highlightedView|
+ @param displayedView Added to the highlight view and centered at the |center| of |highlightedView|
+ @param completion The completion block called when the highlight is dismissed
+ */
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                    andShowView:(nonnull UIView *)displayedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion
+    NS_DESIGNATED_INITIALIZER;
+
+/**
+ Initializes the controller.
+
+ This is a convience method for |initWithHighlightedView:andShowView:| with a snapshot of
+ |highlightedView| sent as |displayedView|.
+
+ @param highlightedView The highlight will be presented above the |center| of |highlightedView|
+ */
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion;
+
+/**
+ Feature Highlight controllers must be created with either initWithHighlightedView: constructor.
+ */
+- (nonnull instancetype)initWithNibName:(nullable NSString *)nibNameOrNil
+                                 bundle:(nullable NSBundle *)nibBundleOrNil NS_UNAVAILABLE;
+- (nonnull instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_UNAVAILABLE;
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Sets the text to be displayed as the header of the help text.
+
+ The header is displayed above the body text.
+ */
+@property(nonatomic, copy, nullable) NSString *titleText;
+
+/**
+ Sets the text to be displayed as the body of the help text.
+
+ The body is displayed below the header text. If you are only showing a single block of text without
+ any header/body distinction, prefer |titleText|.
+ */
+@property(nonatomic, copy, nullable) NSString *bodyText;
+
+/**
+ Sets the color to be used for the outer highlight. Defaults to blue with an alpha of
+ kMDCFeatureHighlightOuterHighlightAlpha.
+
+ Alpha should be set to kMDCFeatureHighlightOuterHighlightAlpha.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *outerHighlightColor;
+
+/**
+ Sets the color to be used for the inner highlight. Defaults to white.
+
+ Should be opaque.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *innerHighlightColor;
+
+/**
+ Dismisses the feature highlight using the 'accept' style dismissal animation and triggers the
+ completion block with accepted set to YES.
+
+ Identical to the user tapping on the inner highlight.
+ */
+- (void)acceptFeature;
+
+/**
+ Dismisses the feature highlight using the 'reject' style dismissal animation and triggers the
+ completion block with accepted set to NO.
+
+ Identical to the user tapping outside of the inner highlight.
+ */
+- (void)rejectFeature;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m
new file mode 100644
index 0000000..a6c822b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m
@@ -0,0 +1,195 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightViewController.h"
+
+#import "private/MDCFeatureHighlightAnimationController.h"
+#import "private/MDCFeatureHighlightView.h"
+
+const CGFloat kMDCFeatureHighlightOuterHighlightAlpha = 0.96f;
+
+static const CGFloat kMDCFeatureHighlightPulseAnimationInterval = 1.5f;
+
+@interface MDCFeatureHighlightViewController () <UIViewControllerTransitioningDelegate>
+@end
+
+@implementation MDCFeatureHighlightViewController {
+  MDCFeatureHighlightAnimationController *_animationController;
+  MDCFeatureHighlightCompletion _completion;
+  MDCFeatureHighlightView *_featureHighlightView;
+  NSTimer *_pulseTimer;
+  UIView *_displayedView;
+  UIView *_highlightedView;
+}
+
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                    andShowView:(nonnull UIView *)displayedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion {
+  if (self = [super initWithNibName:nil bundle:nil]) {
+    _highlightedView = highlightedView;
+    _displayedView = displayedView;
+    _completion = completion;
+    _animationController = [[MDCFeatureHighlightAnimationController alloc] init];
+    _animationController.presenting = YES;
+
+    [_highlightedView addObserver:self
+                       forKeyPath:@"frame"
+                          options:NSKeyValueObservingOptionNew
+                          context:nil];
+
+    super.transitioningDelegate = self;
+    super.modalPresentationStyle = UIModalPresentationCustom;
+  }
+  return self;
+}
+
+/* Disable setter. Always use internal transition controller */
+- (void)setTransitioningDelegate:(id<UIViewControllerTransitioningDelegate>)transitioningDelegate {
+  NSAssert(NO, @"MDCAlertController.transitioningDelegate cannot be changed.");
+  return;
+}
+
+/* Disable setter. Always use custom presentation style */
+- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
+  NSAssert(NO, @"MDCAlertController.modalPresentationStyle cannot be changed.");
+  return;
+}
+
+- (nonnull instancetype)initWithHighlightedView:(nonnull UIView *)highlightedView
+                                     completion:(nullable MDCFeatureHighlightCompletion)completion {
+  return [self initWithHighlightedView:highlightedView
+                           andShowView:[highlightedView snapshotViewAfterScreenUpdates:YES]
+                            completion:completion];
+}
+
+- (void)dealloc {
+  [_pulseTimer invalidate];
+  [_highlightedView removeObserver:self forKeyPath:@"frame"];
+}
+
+- (void)loadView {
+  _featureHighlightView = [[MDCFeatureHighlightView alloc] initWithFrame:CGRectZero];
+  _featureHighlightView.displayedView = _displayedView;
+  _featureHighlightView.titleLabel.text = self.titleText;
+  _featureHighlightView.bodyLabel.text = self.bodyText;
+  _featureHighlightView.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+  _featureHighlightView.outerHighlightColor = self.outerHighlightColor;
+  _featureHighlightView.innerHighlightColor = self.innerHighlightColor;
+
+  __weak __typeof__(self) weakSelf = self;
+  _featureHighlightView.interactionBlock = ^(BOOL accepted) {
+    __typeof__(self) strongSelf = weakSelf;
+    [strongSelf dismiss:accepted];
+  };
+
+  self.view = _featureHighlightView;
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+
+  CGPoint point = [_highlightedView.superview convertPoint:_highlightedView.center
+                                         toCoordinateSpace:_featureHighlightView];
+  _featureHighlightView.highlightPoint = point;
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+  [super viewDidAppear:animated];
+
+  _pulseTimer = [NSTimer scheduledTimerWithTimeInterval:kMDCFeatureHighlightPulseAnimationInterval
+                                                 target:_featureHighlightView
+                                               selector:@selector(animatePulse)
+                                               userInfo:NULL
+                                                repeats:YES];
+}
+
+- (void)viewWillDisappear:(BOOL)animated {
+  [super viewWillDisappear:animated];
+
+  [_pulseTimer invalidate];
+}
+
+- (UIColor *)outerHighlightColor {
+  if (!_outerHighlightColor) {
+    return [[UIColor blueColor] colorWithAlphaComponent:kMDCFeatureHighlightOuterHighlightAlpha];
+  }
+  return _outerHighlightColor;
+}
+
+- (UIColor *)innerHighlightColor {
+  if (!_innerHighlightColor) {
+    return [UIColor whiteColor];
+  }
+  return _innerHighlightColor;
+}
+
+- (void)acceptFeature {
+  [self dismiss:YES];
+}
+
+- (void)rejectFeature {
+  [self dismiss:NO];
+}
+
+- (void)dismiss:(BOOL)accepted {
+  _animationController.presenting = NO;
+  if (accepted) {
+    _animationController.dismissStyle = MDCFeatureHighlightDismissAccepted;
+  } else {
+    _animationController.dismissStyle = MDCFeatureHighlightDismissRejected;
+  }
+  [self dismissViewControllerAnimated:YES
+                           completion:^() {
+                             if (self->_completion) {
+                               self->_completion(accepted);
+                             }
+                           }];
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary<NSString *, id> *)change
+                       context:(void *)context {
+  if (object == _highlightedView && [keyPath isEqualToString:@"frame"]) {
+    CGPoint point = [_highlightedView.superview convertPoint:_highlightedView.center
+                                                      toView:_featureHighlightView];
+    _featureHighlightView.highlightPoint = point;
+    [_featureHighlightView layoutIfNeeded];
+  }
+}
+
+#pragma mark - UIViewControllerTransitioningDelegate
+
+- (id<UIViewControllerAnimatedTransitioning>)
+    animationControllerForPresentedController:(UIViewController *)presented
+                         presentingController:(UIViewController *)presenting
+                             sourceController:(UIViewController *)source {
+  if (presented == self) {
+    return _animationController;
+  }
+  return nil;
+}
+
+- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:
+        (UIViewController *)dismissed {
+  if (dismissed == self) {
+    return _animationController;
+  }
+  return nil;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
new file mode 100644
index 0000000..61cd5d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/MaterialFeatureHighlight.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightViewController.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h
new file mode 100644
index 0000000..7046b85
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+typedef enum : NSUInteger {
+  MDCFeatureHighlightDismissAccepted,
+  MDCFeatureHighlightDismissRejected,
+} MDCFeatureHighlightDismissStyle;
+
+@interface MDCFeatureHighlightAnimationController : NSObject <UIViewControllerAnimatedTransitioning>
+
+@property(nonatomic, assign) MDCFeatureHighlightDismissStyle dismissStyle;
+@property(nonatomic, assign, getter=isPresenting) BOOL presenting;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m
new file mode 100644
index 0000000..39fa989
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m
@@ -0,0 +1,91 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightAnimationController.h"
+
+#import "MDCFeatureHighlightView.h"
+
+const NSTimeInterval kMDCFeatureHighlightPresentationDuration = 0.35f;
+const NSTimeInterval kMDCFeatureHighlightDismissalDuration = 0.2f;
+
+@implementation MDCFeatureHighlightAnimationController
+
+- (NSTimeInterval)transitionDuration:
+        (nullable id<UIViewControllerContextTransitioning>)transitionContext {
+  if (self.presenting) {
+    return kMDCFeatureHighlightPresentationDuration;
+  } else {
+    return kMDCFeatureHighlightDismissalDuration;
+  }
+}
+
+- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
+  UIViewController *toViewController =
+      [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
+  UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
+  UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
+
+  MDCFeatureHighlightView *highlightView = nil;
+  if ([fromView isKindOfClass:[MDCFeatureHighlightView class]]) {
+    highlightView = (MDCFeatureHighlightView *)fromView;
+  } else if ([toView isKindOfClass:[MDCFeatureHighlightView class]]) {
+    highlightView = (MDCFeatureHighlightView *)toView;
+  }
+
+  if (self.presenting) {
+    [transitionContext.containerView addSubview:toView];
+    toView.frame = [transitionContext finalFrameForViewController:toViewController];
+  }
+
+  NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
+
+  [highlightView layoutIfNeeded];
+  if (self.presenting) {
+    [highlightView animateDiscover:transitionDuration];
+  } else {
+    switch (self.dismissStyle) {
+      case MDCFeatureHighlightDismissAccepted:
+        [highlightView animateAccepted:transitionDuration];
+        break;
+
+      case MDCFeatureHighlightDismissRejected:
+        [highlightView animateRejected:transitionDuration];
+        break;
+    }
+  }
+  [UIView animateWithDuration:transitionDuration
+      delay:0.0
+      options:UIViewAnimationOptionBeginFromCurrentState
+      animations:^{
+        // We have to perform an animation on highlightView in this block or else UIKit
+        // will not know we are performing an animation and will cancel our
+        // CAAnimations.
+        if (self.presenting) {
+          [highlightView layoutAppearing];
+        } else {
+          [highlightView layoutDisappearing];
+        }
+      }
+      completion:^(BOOL finished) {
+        // If we're dismissing, remove the highlight view from the hierarchy
+        if (!self.presenting) {
+          [fromView removeFromSuperview];
+        }
+        [transitionContext completeTransition:YES];
+      }];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h
new file mode 100644
index 0000000..ee6a603
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+
+@interface MDCFeatureHighlightLayer : CAShapeLayer
+
+@property(nonatomic, assign) CGPoint center;
+
+- (void)setCenter:(CGPoint)center radius:(CGFloat)radius animated:(BOOL)animated;
+
+- (void)setFillColor:(CGColorRef)fillColor animated:(BOOL)animated;
+
+- (void)animateRadiusOverKeyframes:(NSArray *)radii
+                          keyTimes:(NSArray *)keyTimes
+                            center:(CGPoint)center;
+
+- (void)animateFillColorOverKeyframes:(NSArray *)colors keyTimes:(NSArray *)keyTimes;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m
new file mode 100644
index 0000000..66e9f1c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m
@@ -0,0 +1,94 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightLayer.h"
+
+@implementation MDCFeatureHighlightLayer {
+  CGFloat _radius;
+}
+
+- (void)setCenter:(CGPoint)center {
+  _center = center;
+
+  CGRect circleRect = CGRectMake(center.x - _radius, center.y - _radius, _radius * 2, _radius * 2);
+  self.path = (__bridge CGPathRef _Nullable)
+      (CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL)));
+}
+
+- (void)setCenter:(CGPoint)center radius:(CGFloat)radius animated:(BOOL)animated {
+  _center = center;
+  _radius = radius;
+
+  CGRect circleRect = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
+  if (animated) {
+    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
+    animation.duration = [CATransaction animationDuration];
+    animation.timingFunction = [CATransaction animationTimingFunction];
+    if (self.path) {
+      animation.fromValue = (__bridge id)self.path;
+    } else {
+      animation.fromValue = CFBridgingRelease(
+          CGPathCreateWithEllipseInRect(CGRectMake(center.x, center.y, 0, 0), NULL));
+    }
+    self.path = (__bridge CGPathRef _Nullable)
+        CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL));
+    [self addAnimation:animation forKey:@"path"];
+  } else {
+    self.path = (__bridge CGPathRef _Nullable)
+        CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL));
+  }
+}
+
+- (void)setFillColor:(CGColorRef)fillColor animated:(BOOL)animated {
+  if (animated) {
+    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"fillColor"];
+    animation.duration = [CATransaction animationDuration];
+    animation.timingFunction = [CATransaction animationTimingFunction];
+    animation.fromValue = (__bridge id)self.fillColor;
+    self.fillColor = fillColor;
+    [self addAnimation:animation forKey:@"fillColor"];
+  } else {
+    self.fillColor = fillColor;
+  }
+}
+
+- (void)animateRadiusOverKeyframes:(NSArray *)radii
+                          keyTimes:(NSArray *)keyTimes
+                            center:(CGPoint)center {
+  NSMutableArray *values = [NSMutableArray arrayWithCapacity:radii.count];
+  for (NSNumber *radius in radii) {
+    CGFloat r = radius.floatValue;
+    CGRect circleRect = CGRectMake(center.x - r, center.y - r, r * 2, r * 2);
+    [values addObject:CFBridgingRelease(CGPathCreateWithEllipseInRect(circleRect, NULL))];
+  }
+  CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
+  animation.duration = [CATransaction animationDuration];
+  animation.timingFunction = [CATransaction animationTimingFunction];
+  animation.values = values;
+  animation.keyTimes = keyTimes;
+  [self addAnimation:animation forKey:@"path"];
+}
+
+- (void)animateFillColorOverKeyframes:(NSArray *)colors keyTimes:(NSArray *)keyTimes {
+  CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"fillColor"];
+  animation.duration = [CATransaction animationDuration];
+  animation.timingFunction = [CATransaction animationTimingFunction];
+  animation.values = colors;
+  animation.keyTimes = keyTimes;
+  [self addAnimation:animation forKey:@"fillColor"];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h
new file mode 100644
index 0000000..8d3279a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.h
@@ -0,0 +1,40 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+typedef void (^MDCFeatureHighlightInteractionBlock)(BOOL accepted);
+
+@interface MDCFeatureHighlightView : UIView
+
+@property(nonatomic, strong) UIColor *outerHighlightColor;
+@property(nonatomic, strong) UIColor *innerHighlightColor;
+
+@property(nonatomic, assign) CGPoint highlightPoint;
+@property(nonatomic, strong) UIView *displayedView;
+@property(nonatomic, strong) UILabel *titleLabel;
+@property(nonatomic, strong) UILabel *bodyLabel;
+@property(nonatomic, strong) MDCFeatureHighlightInteractionBlock interactionBlock;
+
+- (void)layoutAppearing;
+- (void)layoutDisappearing;
+
+- (void)animateDiscover:(NSTimeInterval)duration;
+- (void)animateAccepted:(NSTimeInterval)duration;
+- (void)animateRejected:(NSTimeInterval)duration;
+- (void)animatePulse;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.m
new file mode 100644
index 0000000..a6a95e7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FeatureHighlight/src/private/MDCFeatureHighlightView.m
@@ -0,0 +1,344 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFeatureHighlightView.h"
+
+#import "MDCFeatureHighlightLayer.h"
+#import "MDFTextAccessibility.h"
+#import "MaterialTypography.h"
+
+const CGFloat kMDCFeatureHighlightMinimumInnerRadius = 44.0f;
+const CGFloat kMDCFeatureHighlightInnerContentPadding = 10.0f;
+const CGFloat kMDCFeatureHighlightInnerPadding = 20.0f;
+const CGFloat kMDCFeatureHighlightTextPadding = 40.0f;
+const CGFloat kMDCFeatureHighlightTextMaxWidth = 300.0f;
+const CGFloat kMDCFeatureHighlightConcentricBound = 88.0f;
+const CGFloat kMDCFeatureHighlightNonconcentricOffset = 20.0f;
+const CGFloat kMDCFeatureHighlightMaxTextHeight = 1000.0f;
+const CGFloat kMDCFeatureHighlightTitleFontSize = 20.0f;
+
+// Animation consts
+const CGFloat kMDCFeatureHighlightInnerRadiusFactor = 1.1f;
+const CGFloat kMDCFeatureHighlightOuterRadiusFactor = 1.125f;
+const CGFloat kMDCFeatureHighlightPulseRadiusFactor = 2.0f;
+const CGFloat kMDCFeatureHighlightPulseStartAlpha = 0.54f;
+const CGFloat kMDCFeatureHighlightInnerRadiusBloomAmount =
+    (kMDCFeatureHighlightInnerRadiusFactor - 1) * kMDCFeatureHighlightMinimumInnerRadius;
+const CGFloat kMDCFeatureHighlightPulseRadiusBloomAmount =
+    (kMDCFeatureHighlightPulseRadiusFactor - 1) * kMDCFeatureHighlightMinimumInnerRadius;
+
+@implementation MDCFeatureHighlightView {
+  BOOL _forceConcentricLayout;
+  UIView *_highlightView;
+  CGPoint _highlightPoint;
+  CGPoint _highlightCenter;
+  CGFloat _innerRadius;
+  CGPoint _outerCenter;
+  CGFloat _outerRadius;
+  MDCFeatureHighlightLayer *_outerLayer;
+  MDCFeatureHighlightLayer *_pulseLayer;
+  MDCFeatureHighlightLayer *_innerLayer;
+  MDCFeatureHighlightLayer *_displayMaskLayer;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  if (self = [super initWithFrame:frame]) {
+    self.backgroundColor = [UIColor clearColor];
+
+    _outerLayer = [[MDCFeatureHighlightLayer alloc] init];
+    [self.layer addSublayer:_outerLayer];
+
+    _pulseLayer = [[MDCFeatureHighlightLayer alloc] init];
+    [self.layer addSublayer:_pulseLayer];
+
+    _innerLayer = [[MDCFeatureHighlightLayer alloc] init];
+    [self.layer addSublayer:_innerLayer];
+
+    _displayMaskLayer = [[MDCFeatureHighlightLayer alloc] init];
+    _displayMaskLayer.fillColor = [UIColor whiteColor].CGColor;
+
+    _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    _titleLabel.font =
+        [[MDCTypography fontLoader] regularFontOfSize:kMDCFeatureHighlightTitleFontSize];
+    _titleLabel.textAlignment = NSTextAlignmentNatural;
+    _titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+    _titleLabel.numberOfLines = 0;
+    [self addSubview:_titleLabel];
+
+    _bodyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    _bodyLabel.font = [MDCTypography subheadFont];
+    _bodyLabel.shadowColor = nil;
+    _bodyLabel.shadowOffset = CGSizeZero;
+    _bodyLabel.textAlignment = NSTextAlignmentNatural;
+    _bodyLabel.lineBreakMode = NSLineBreakByTruncatingTail;
+    _bodyLabel.numberOfLines = 0;
+    [self addSubview:_bodyLabel];
+
+    UITapGestureRecognizer *tapRecognizer =
+        [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapView:)];
+    [self addGestureRecognizer:tapRecognizer];
+
+    self.outerHighlightColor = [UIColor blueColor];
+    self.innerHighlightColor = [UIColor whiteColor];
+
+    // We want the inner and outer highlights to animate from the same origin so we start them from
+    // a concentric position.
+    _forceConcentricLayout = YES;
+  }
+  return self;
+}
+
+- (void)layoutAppearing {
+  // TODO: Mask the labels during the presentation and dismissal animations.
+  _titleLabel.alpha = 1;
+  _bodyLabel.alpha = 1;
+}
+
+- (void)layoutDisappearing {
+  _titleLabel.alpha = 0;
+  _bodyLabel.alpha = 0;
+}
+
+- (void)setOuterHighlightColor:(UIColor *)outerHighlightColor {
+  _outerHighlightColor = outerHighlightColor;
+  _outerLayer.fillColor = _outerHighlightColor.CGColor;
+
+  MDFTextAccessibilityOptions options = MDFTextAccessibilityOptionsPreferLighter;
+  if ([MDFTextAccessibility isLargeForContrastRatios:_bodyLabel.font]) {
+    options |= MDFTextAccessibilityOptionsLargeFont;
+  }
+
+  UIColor *outerColor = [_outerHighlightColor colorWithAlphaComponent:1.0];
+  _bodyLabel.textColor =
+      [MDFTextAccessibility textColorOnBackgroundColor:outerColor
+                                       targetTextAlpha:[MDCTypography captionFontOpacity]
+                                               options:options];
+
+  options = MDFTextAccessibilityOptionsPreferLighter;
+  if ([MDFTextAccessibility isLargeForContrastRatios:_titleLabel.font]) {
+    options |= MDFTextAccessibilityOptionsLargeFont;
+  }
+  // Since MDFTextAccessibility can return either a dark value or light value color we want to
+  // guarantee that the title and body have the same value.
+  CGFloat titleAlpha = [MDFTextAccessibility minAlphaOfTextColor:_bodyLabel.textColor
+                                               onBackgroundColor:outerColor
+                                                         options:options];
+  titleAlpha = MAX([MDCTypography titleFontOpacity], titleAlpha);
+  _titleLabel.textColor = [_bodyLabel.textColor colorWithAlphaComponent:titleAlpha];
+}
+
+- (void)setInnerHighlightColor:(UIColor *)innerHighlightColor {
+  _innerHighlightColor = innerHighlightColor;
+
+  _pulseLayer.fillColor = _innerHighlightColor.CGColor;
+  _innerLayer.fillColor = _innerHighlightColor.CGColor;
+}
+
+- (void)setDisplayedView:(UIView *)displayedView {
+  CGSize displayedSize = displayedView.frame.size;
+  CGFloat viewRadius =
+      (CGFloat)sqrt(pow(displayedSize.width / 2, 2) + pow(displayedSize.height / 2, 2));
+  viewRadius += kMDCFeatureHighlightInnerContentPadding;
+  _innerRadius = MAX(viewRadius, kMDCFeatureHighlightMinimumInnerRadius);
+
+  _displayedView.layer.mask = nil;
+  [_displayedView removeFromSuperview];
+  _displayedView = displayedView;
+  [self addSubview:_displayedView];
+  _displayedView.layer.mask = _displayMaskLayer;
+}
+
+- (void)setHighlightPoint:(CGPoint)highlightPoint {
+  _highlightPoint = highlightPoint;
+
+  [self setNeedsLayout];
+  [self layoutIfNeeded];
+}
+
+- (void)animateDiscover:(NSTimeInterval)duration {
+  [_innerLayer setFillColor:[_innerHighlightColor colorWithAlphaComponent:0].CGColor];
+  [_outerLayer setFillColor:[_outerHighlightColor colorWithAlphaComponent:0].CGColor];
+
+  CGPoint displayMaskCenter =
+      CGPointMake(_displayedView.frame.size.width / 2, _displayedView.frame.size.height / 2);
+
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  [CATransaction setAnimationDuration:duration];
+  [_displayMaskLayer setCenter:displayMaskCenter radius:_innerRadius animated:YES];
+  [_innerLayer setFillColor:[_innerHighlightColor colorWithAlphaComponent:1].CGColor animated:YES];
+  [_innerLayer setCenter:_highlightPoint radius:_innerRadius animated:YES];
+  [_outerLayer setFillColor:_outerHighlightColor.CGColor animated:YES];
+  [_outerLayer setCenter:_highlightCenter radius:_outerRadius animated:YES];
+  [CATransaction commit];
+
+  _forceConcentricLayout = NO;
+}
+
+- (void)animatePulse {
+  NSArray *keyTimes = @[ @0, @0.5, @1 ];
+  id pulseColorStart =
+      (__bridge id)
+          [_innerHighlightColor colorWithAlphaComponent:kMDCFeatureHighlightPulseStartAlpha]
+              .CGColor;
+  id pulseColorEnd = (__bridge id)[_innerHighlightColor colorWithAlphaComponent:0].CGColor;
+  CGFloat radius = _innerRadius;
+
+  [CATransaction begin];
+  [CATransaction setAnimationDuration:1.0f];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  CGFloat innerBloomRadius = radius + kMDCFeatureHighlightInnerRadiusBloomAmount;
+  CGFloat pulseBloomRadius = radius + kMDCFeatureHighlightPulseRadiusBloomAmount;
+  NSArray *innerKeyframes = @[ @(radius), @(innerBloomRadius), @(radius) ];
+  [_innerLayer animateRadiusOverKeyframes:innerKeyframes keyTimes:keyTimes center:_highlightPoint];
+  NSArray *pulseKeyframes = @[ @(radius), @(radius), @(pulseBloomRadius) ];
+  [_pulseLayer animateRadiusOverKeyframes:pulseKeyframes keyTimes:keyTimes center:_highlightPoint];
+  [_pulseLayer animateFillColorOverKeyframes:@[ pulseColorStart, pulseColorStart, pulseColorEnd ]
+                                    keyTimes:keyTimes];
+  [CATransaction commit];
+}
+
+- (void)animateAccepted:(NSTimeInterval)duration {
+  CGPoint displayMaskCenter =
+      CGPointMake(_displayedView.frame.size.width / 2, _displayedView.frame.size.height / 2);
+
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  [CATransaction setAnimationDuration:duration];
+  [_displayMaskLayer setCenter:displayMaskCenter radius:0.0 animated:YES];
+  [_innerLayer setCenter:_highlightPoint radius:0 animated:YES];
+  [_outerLayer setFillColor:[_outerHighlightColor colorWithAlphaComponent:0].CGColor animated:YES];
+  [_outerLayer setCenter:_highlightCenter
+                  radius:kMDCFeatureHighlightOuterRadiusFactor * _outerRadius
+                animated:YES];
+  [CATransaction commit];
+
+  _forceConcentricLayout = YES;
+}
+
+- (void)animateRejected:(NSTimeInterval)duration {
+  CGPoint displayMaskCenter =
+      CGPointMake(_displayedView.frame.size.width / 2, _displayedView.frame.size.height / 2);
+
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction
+                                                functionWithName:kCAMediaTimingFunctionEaseOut]];
+  [CATransaction setAnimationDuration:duration];
+  [_displayMaskLayer setCenter:displayMaskCenter radius:0 animated:YES];
+  [_innerLayer setCenter:_highlightPoint radius:0 animated:YES];
+  [_outerLayer setFillColor:[_outerHighlightColor colorWithAlphaComponent:0].CGColor animated:YES];
+  [_outerLayer setCenter:_highlightPoint radius:0 animated:YES];
+  [CATransaction commit];
+
+  _forceConcentricLayout = NO;
+}
+
+- (void)layoutSubviews {
+  [_innerLayer removeAllAnimations];
+  [_outerLayer removeAllAnimations];
+  [_pulseLayer removeAllAnimations];
+
+  BOOL leftHalf = _highlightPoint.x < self.frame.size.width / 2;
+  BOOL topHalf = _highlightPoint.y < self.frame.size.height / 2;
+
+  CGFloat textWidth = MIN(self.frame.size.width - 2 * kMDCFeatureHighlightTextPadding,
+                          kMDCFeatureHighlightTextMaxWidth);
+  CGSize titleSize =
+      [_titleLabel sizeThatFits:CGSizeMake(textWidth, kMDCFeatureHighlightMaxTextHeight)];
+  CGSize detailSize =
+      [_bodyLabel sizeThatFits:CGSizeMake(textWidth, kMDCFeatureHighlightMaxTextHeight)];
+  titleSize.width = MAX(titleSize.width, detailSize.width);
+  detailSize.width = titleSize.width;
+
+  CGFloat textHeight = titleSize.height + detailSize.height;
+
+  if ((_highlightPoint.y <= kMDCFeatureHighlightConcentricBound) ||
+      (_highlightPoint.y >= self.frame.size.height - kMDCFeatureHighlightConcentricBound)) {
+    _highlightCenter = _highlightPoint;
+  } else {
+    if (topHalf) {
+      _highlightCenter.y = _highlightPoint.y + _innerRadius + textHeight / 2;
+    } else {
+      _highlightCenter.y = _highlightPoint.y - _innerRadius - textHeight / 2;
+    }
+    if (leftHalf) {
+      _highlightCenter.x = _highlightPoint.x + kMDCFeatureHighlightNonconcentricOffset;
+    } else {
+      _highlightCenter.x = _highlightPoint.x - kMDCFeatureHighlightNonconcentricOffset;
+    }
+  }
+
+  _displayedView.center = _highlightPoint;
+  _innerLayer.center = _highlightPoint;
+  _pulseLayer.center = _highlightPoint;
+
+  if (_forceConcentricLayout) {
+    _outerLayer.center = _highlightPoint;
+  } else {
+    _outerLayer.center = _highlightCenter;
+  }
+
+  CGFloat leftTextBound = kMDCFeatureHighlightTextPadding;
+  CGFloat rightTextBound = self.frame.size.width - MAX(titleSize.width, detailSize.width) -
+                           kMDCFeatureHighlightTextPadding;
+  CGPoint titlePos = CGPointMake(0, 0);
+  titlePos.x = MIN(MAX(_highlightCenter.x - textWidth / 2, leftTextBound), rightTextBound);
+  if (topHalf) {
+    titlePos.y = _highlightPoint.y + kMDCFeatureHighlightInnerPadding + _innerRadius;
+  } else {
+    titlePos.y = _highlightPoint.y - kMDCFeatureHighlightInnerPadding - _innerRadius - textHeight;
+  }
+
+  CGRect titleFrame = (CGRect){titlePos, titleSize};
+  _titleLabel.frame = titleFrame;
+
+  CGRect detailFrame = (CGRect){CGPointMake(titlePos.x, CGRectGetMaxY(titleFrame)), detailSize};
+  _bodyLabel.frame = detailFrame;
+
+  // Calculating the radius required for a circle centered at _highlightCenter that fully encircles
+  // both labels.
+  CGRect textFrames = CGRectUnion(_titleLabel.frame, _bodyLabel.frame);
+  CGFloat distX = ABS(CGRectGetMidX(textFrames) - _highlightCenter.x) + textFrames.size.width / 2;
+  CGFloat distY = ABS(CGRectGetMidY(textFrames) - _highlightCenter.y) + textFrames.size.height / 2;
+  CGFloat minTextRadius =
+      (CGFloat)(sqrt(pow(distX, 2) + pow(distY, 2)) + kMDCFeatureHighlightTextPadding);
+
+  // Calculating the radius required for a circle centered at _highlightCenter that fully encircles
+  // the inner highlight.
+  distX = ABS(_highlightCenter.x - _highlightPoint.x);
+  distY = ABS(_highlightCenter.y - _highlightPoint.y);
+  CGFloat minInnerHighlightRadius = (CGFloat)(sqrt(pow(distX, 2) + pow(distY, 2)) + _innerRadius +
+                                              kMDCFeatureHighlightInnerPadding);
+
+  // Use the larger of the two radii to ensure everything is encircled.
+  _outerRadius = MAX(minTextRadius, minInnerHighlightRadius);
+}
+
+- (void)didTapView:(UITapGestureRecognizer *)tapGestureRecognizer {
+  CGPoint pos = [tapGestureRecognizer locationInView:self];
+  CGFloat dist =
+      (float)(sqrt(pow(pos.x - _highlightPoint.x, 2) + pow(pos.y - _highlightPoint.y, 2)));
+  BOOL accepted = dist <= _innerRadius;
+
+  if (self.interactionBlock) {
+    self.interactionBlock(accepted);
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
new file mode 100644
index 0000000..38fa58c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h
@@ -0,0 +1,44 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCFlexibleHeaderViewController;
+
+/**
+ The MDCFlexibleHeaderContainerViewController controller is a straightforward container of a
+ content view controller and a MDCFlexibleHeaderViewController.
+
+ This view controller may be used in situations where the content view controller can't have a
+ header injected into its view hierarchy. UIPageViewController is one such view controller.
+ */
+@interface MDCFlexibleHeaderContainerViewController : UIViewController
+
+- (nonnull instancetype)initWithContentViewController:
+        (nullable UIViewController *)contentViewController NS_DESIGNATED_INITIALIZER;
+
+/**
+ The header view controller that lives alongside the content view controller.
+
+ This view controller's view will be placed in front of the content view controller's view.
+ */
+@property(nonatomic, strong, nonnull, readonly)
+    MDCFlexibleHeaderViewController *headerViewController;
+
+/** The content view controller to be displayed behind the header. */
+@property(nonatomic, strong, nullable) UIViewController *contentViewController;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m
new file mode 100644
index 0000000..85577db
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m
@@ -0,0 +1,98 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderContainerViewController.h"
+
+#import "MDCFlexibleHeaderView.h"
+#import "MDCFlexibleHeaderViewController.h"
+
+@implementation MDCFlexibleHeaderContainerViewController
+
+- (instancetype)initWithContentViewController:(UIViewController *)contentViewController {
+  self = [super initWithNibName:nil bundle:nil];
+  if (self) {
+    _headerViewController = [[MDCFlexibleHeaderViewController alloc] init];
+    [self addChildViewController:_headerViewController];
+
+    self.contentViewController = contentViewController;
+  }
+  return self;
+}
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+  return [self initWithContentViewController:nil];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  return [self initWithContentViewController:nil];
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+
+  [self.view addSubview:self.contentViewController.view];
+  [self.contentViewController didMoveToParentViewController:self];
+
+  // Enforce the header's desire to fully cover the width of its parent view.
+  CGRect frame = self.view.frame;
+  frame.origin.x = 0;
+  frame.size.width = self.view.bounds.size.width;
+  self.headerViewController.view.frame = self.view.bounds;
+  [self.view addSubview:self.headerViewController.view];
+  [self.headerViewController didMoveToParentViewController:self];
+}
+
+- (void)viewWillLayoutSubviews {
+  [super viewWillLayoutSubviews];
+  [self.headerViewController updateTopLayoutGuide];
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _headerViewController.prefersStatusBarHidden;
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  return _headerViewController.preferredStatusBarStyle;
+}
+
+#pragma mark - Public
+
+- (void)setContentViewController:(UIViewController *)contentViewController {
+  if (_contentViewController == contentViewController) {
+    return;
+  }
+
+  // Teardown of the old controller
+
+  [_contentViewController willMoveToParentViewController:nil];
+  if ([_contentViewController isViewLoaded]) {
+    [_contentViewController.view removeFromSuperview];
+  }
+  [_contentViewController removeFromParentViewController];
+
+  // Setup of the new controller
+
+  _contentViewController = contentViewController;
+
+  [self addChildViewController:contentViewController];
+  if ([self isViewLoaded]) {
+    [self.view insertSubview:contentViewController.view
+                belowSubview:self.headerViewController.headerView];
+    [contentViewController didMoveToParentViewController:self];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
new file mode 100644
index 0000000..a0d180e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.h
@@ -0,0 +1,455 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+typedef void (^MDCFlexibleHeaderChangeContentInsetsBlock)(void);
+typedef void (^MDCFlexibleHeaderShadowIntensityChangeBlock)(CALayer *_Nonnull shadowLayer,
+                                                            CGFloat intensity);
+
+/**
+ The possible translation (shift) behaviors of a flexible header view.
+
+ Enabling shifting allows the header to enter the
+ @c MDCFlexibleHeaderScrollPhaseShifting scroll phase.
+ */
+typedef NS_ENUM(NSInteger, MDCFlexibleHeaderShiftBehavior) {
+
+  /** Header's y position never changes in reaction to scroll events. */
+  MDCFlexibleHeaderShiftBehaviorDisabled,
+
+  /** When fully-collapsed, the header translates vertically in reaction to scroll events. */
+  MDCFlexibleHeaderShiftBehaviorEnabled,
+
+  /**
+   When fully-collapsed, the header translates vertically in reaction to scroll events along with
+   the status bar.
+
+   If used with a vertically-paging scroll view, this behavior acts like
+   MDCFlexibleHeaderShiftBehaviorEnabled.
+   */
+  MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar,
+};
+
+/** The importance of content contained within the flexible header view. */
+typedef NS_ENUM(NSInteger, MDCFlexibleHeaderContentImportance) {
+
+  /**
+   Default behavior requires at most approximately a single swipe before the header re-appears.
+   */
+  MDCFlexibleHeaderContentImportanceDefault,
+
+  /**
+   Highly-important header content will re-appear faster than default importance.
+
+   Examples of important content:
+
+   - Search bar.
+   - Non-navigational actions.
+   */
+  MDCFlexibleHeaderContentImportanceHigh,
+};
+
+/** Mutually exclusive phases that the flexible header view can be in. */
+typedef NS_ENUM(NSInteger, MDCFlexibleHeaderScrollPhase) {
+
+  /**
+   The header is at its min height and shifting off/on screen.
+
+   frame.origin.y is changing.
+   */
+  MDCFlexibleHeaderScrollPhaseShifting,
+
+  /**
+   The header is changing its height within the min-max range.
+
+   frame.size.height is changing.
+   */
+  MDCFlexibleHeaderScrollPhaseCollapsing,
+
+  /**
+   The header is changing its height and is taller than its maximum height.
+
+   frame.size.height is changing.
+   */
+  MDCFlexibleHeaderScrollPhaseOverExtending,
+};
+
+@protocol MDCFlexibleHeaderViewDelegate;
+
+/**
+ MDCFlexibleHeaderView tracks the content offset of a scroll view and adjusts its size and
+ position according to a configurable set of behaviors.
+
+ ### UIScrollViewDelegate forwarding
+
+ This view relies on you informing it of certain UIScrollViewDelegate events as they happen. These
+ events are listed in the UIScrollViewDelegate events section.
+ */
+IB_DESIGNABLE
+@interface MDCFlexibleHeaderView : UIView
+
+#pragma mark Custom shadow
+
+/**
+ Custom shadow shown under flexible header content.
+ */
+@property(nonatomic, strong, nullable) CALayer *shadowLayer;
+
+/**
+ Sets a custom shadow layer and a block that should be executed when shadow intensity changes.
+ */
+- (void)setShadowLayer:(nonnull CALayer *)shadowLayer
+    intensityDidChangeBlock:(nonnull MDCFlexibleHeaderShadowIntensityChangeBlock)block;
+
+#pragma mark UIScrollViewDelegate events
+
+/**
+ Informs the receiver that the tracking scroll view's contentOffset has changed.
+
+ Must be called from the trackingScrollView delegate's UIScrollViewDelegate::scrollViewDidScroll:
+ implementor.
+ */
+- (void)trackingScrollViewDidScroll;
+
+/**
+ Informs the receiver that the tracking scroll view has finished dragging.
+
+ Must be called from the trackingScrollView delegate's
+ UIScrollViewDelegate::scrollViewDidEndDragging:willDecelerate: implementor.
+ */
+- (void)trackingScrollViewDidEndDraggingWillDecelerate:(BOOL)willDecelerate;
+
+/**
+ Informs the receiver that the tracking scroll view has finished decelerating.
+
+ Must be called from the trackingScrollView delegate's
+ UIScrollViewDelegate::scrollViewDidEndDecelerating: implementor.
+ */
+- (void)trackingScrollViewDidEndDecelerating;
+
+/**
+ Potentially modifies the target content offset in order to ensure that the header view is either
+ visible or hidden depending on its current position.
+
+ Must be called from the trackingScrollView delegate's
+ -scrollViewWillEndDragging:withVelocity:targetContentOffset: implementor.
+
+ If your scroll view is vertically paging then this method will do nothing. You should also
+ disable hidesStatusBarWhenCollapsed.
+
+ @return A Boolean value indicating whether the target content offset was modified.
+ */
+- (BOOL)trackingScrollViewWillEndDraggingWithVelocity:(CGPoint)velocity
+                                  targetContentOffset:(inout nonnull CGPoint *)targetContentOffset;
+
+#pragma mark Changing the tracking scroll view
+
+/**
+ Informs the receiver that the tracking scroll view might be about to change to a new tracking
+ scroll view.
+ */
+- (void)trackingScrollWillChangeToScrollView:(nullable UIScrollView *)scrollView;
+
+#pragma mark Shifting the tracking scroll view on-screen
+
+/** Asks the receiver to bring the header on-screen if it's currently off-screen. */
+- (void)shiftHeaderOnScreenAnimated:(BOOL)animated;
+
+/** Asks the receiver to take the header off-screen if it's currently on-screen. */
+- (void)shiftHeaderOffScreenAnimated:(BOOL)animated;
+
+#pragma mark UIKit Hooks
+
+// All of these UIKit hooks must be called from the view controller that owns this header view.
+// Failure to do so will result in undefined behavior of the flexible header view.
+
+/**
+ Returns a Boolean value indicating whether the status bar should be visible.
+
+ Must be called by the owning UIViewController's -prefersStatusBarHidden.
+ */
+@property(nonatomic, readonly) BOOL prefersStatusBarHidden;
+
+// Pre-iOS 8 Interface Orientation APIs
+
+/**
+ Informs the receiver that the interface orientation is about to change.
+
+ Must be called from UIViewController::willRotateToInterfaceOrientation:duration:.
+ */
+- (void)interfaceOrientationWillChange;
+
+/**
+ Informs the receiver that the interface orientation is in the process of changing.
+
+ Must be called from UIViewController::willAnimateRotationToInterfaceOrientation:duration:.
+ */
+- (void)interfaceOrientationIsChanging;
+
+/**
+ Informs the receiver that the interface orientation has changed.
+
+ Must be called from UIViewController::didRotateFromInterfaceOrientation:.
+ */
+- (void)interfaceOrientationDidChange;
+
+// iOS 8 Interface Orientation APIs
+
+/**
+ Informs the receiver that the owning view controller's size will change.
+
+ Must be called from UIViewController::viewWillTransitionToSize:withTransitionCoordinator: on apps
+ targeting iOS 8 and onward.
+ */
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(nonnull id<UIViewControllerTransitionCoordinator>)coordinator;
+
+#pragma mark Changing Content Insets
+
+/**
+ Must be called by a client that wishes to update the content insets of the tracking scroll view.
+
+ Not using this method can lead to undefined behavior due to the flexible header view assuming
+ that a certain amount of additional content insets have been provided to the tracking scroll
+ view.
+
+ The provided block will be executed after the flexible header has removed its modifications to
+ the tracking scroll view. Upon completion of the block, the flexible header will re-inject these
+ modifications into the new content insets and ensure that the content offset doesn't change due
+ to the new content insets.
+ */
+- (void)changeContentInsets:(nonnull MDCFlexibleHeaderChangeContentInsetsBlock)block;
+
+#pragma mark Forwarding Touch Events
+
+/**
+ Forwards any tap events made to the provided view on to the tracking scroll view.
+
+ Views will only forward their taps if they are a subview of this header view and are interactive.
+
+ Touch forwarding does not apply to subviews of the provided view.
+ */
+- (void)forwardTouchEventsForView:(nonnull UIView *)view;
+
+/** Stops forwarding tap events on the given view to the tracking scroll view. */
+- (void)stopForwardingTouchEventsForView:(nonnull UIView *)view;
+
+#pragma mark Scroll Phase
+
+/**
+ Returns the current scroll phase of the flexible header.
+
+ There are three mutually-exclusive scroll phases: shifting, collapsing, and over-extending.
+ Whichever phase the header view is in governs what scrollPhaseValue and scrollPhasePercentage
+ represent.
+
+ This and the related scrollPhase properties are only valid immediately after a call to
+ -trackingScrollViewDidScroll.
+ */
+@property(nonatomic, readonly) MDCFlexibleHeaderScrollPhase scrollPhase;
+
+/**
+ A value in screen points denoting the absolute position within the current scroll phase.
+
+ The range for each phase follows:
+
+ - Shifting:       [0, minimumHeight)
+ - Collapsing:     [minimumHeight, maximumHeight)
+ - Over-extending: [maximumHeight, +inf)
+ */
+@property(nonatomic, readonly) CGFloat scrollPhaseValue;
+
+/**
+ A normalized value denoting the position within the current scroll phase.
+
+ The meaning of the percentage for each phase follows:
+
+ - Shifting:       0 is unshifted, 1.0 is fully shifted off-screen
+ - Collapsing:     0 == minimumHeight, 1.0 == maximumHeight
+ - Over-extending: 1.0 height == maximumHeight, every additional 1.0 is one maximumHeight unit
+
+ Note that a single percentage does not necessarily have equal weight between the three phases, so
+ you should not use this value for any behavior that is active across any two phases; use
+ scrollPhaseValue instead.
+ */
+@property(nonatomic, readonly) CGFloat scrollPhasePercentage;
+
+#pragma mark Bounding Dimensions
+
+/**
+ The minimum height that this header can shrink to.
+
+ If you change the value of this property and the maximumHeight of the receiver is below the new
+ minimumHeight, maximumHeight will be adjusted to match the new minimum value.
+ */
+@property(nonatomic) CGFloat minimumHeight;
+
+/**
+ The maximum height that this header can expand to.
+
+ If you change the value of this property and the minimumHeight of the receiver is above the new
+ maximumHeight, minimumHeight will be adjusted to match the new maximumHeight.
+ */
+@property(nonatomic) CGFloat maximumHeight;
+
+#pragma mark Behaviors
+
+/** The behavior of the header in response to the user interacting with the tracking scroll view. */
+@property(nonatomic) MDCFlexibleHeaderShiftBehavior shiftBehavior;
+
+/**
+ If shiftBehavior is enabled, this property affects the manner in which the Header reappears when
+ pulling content down in the tracking scroll view.
+
+ Ignored if shiftBehavior == MDCFlexibleHeaderShiftBehaviorDisabled.
+
+ Default: MDCFlexibleHeaderContentImportanceDefault
+ */
+@property(nonatomic) MDCFlexibleHeaderContentImportance headerContentImportance;
+
+/**
+ Whether or not the header view is allowed to expand past its maximum height when the tracking
+ scroll view has been dragged past its top edge.
+
+ Default: YES
+ */
+@property(nonatomic) BOOL canOverExtend;
+
+/**
+ A hint stating whether or not the operating system's status bar frame can ever overlap the header's
+ frame.
+
+ This property is enabled by default with the expectation that the flexible header will primarily
+ be used in full-screen settings on the phone.
+
+ Disabling this property informs the flexible header that it should not concern itself with the
+ status bar in any manner. shiftBehavior .EnabledWithStatusBar will be treated simply as .Enabled
+ in this case.
+
+ Default: YES
+ */
+@property(nonatomic) BOOL statusBarHintCanOverlapHeader;
+
+@property(nonatomic) float visibleShadowOpacity;  ///< The visible shadow opacity. Default: 0.4
+
+#pragma mark Scroll View Tracking
+
+/**
+ The scroll view whose content offset affects the height/offset of the flexible header view.
+
+ The receiver will inject the maximum height of the header view into the top component of the
+ tracking scroll view's content insets. This ensures that there is enough space in the top insets
+ to fit the header. This should be taken into account when working with the tracking scroll view's
+ content insets.
+
+ Importantly, if you wish to make changes to the tracking scroll view's content insets after it
+ has been registered to a flexible header view, you must do so from within a -changeContentInsets:
+ invocation on the flexible header view.
+
+ The tracking scroll view is weakly held so that we don't unintentionally keep the scroll view
+ around any longer than it needs to be. Doing so could get into tricky situations where the view
+ controller didn't nil out the scroll view's delegate in dealloc and UIScrollView's non-weak
+ delegate points to a dead object.
+ */
+@property(nonatomic, weak, nullable) UIScrollView *trackingScrollView;
+
+/**
+ When enabled, the header view will prioritize shifting off-screen and collapsing over shifting
+ on-screen and expanding.
+
+ This should only be enabled when the user is scrubbing the tracking scroll view, i.e. they're
+ able to jump large distances using a scrubber control.
+ */
+@property(nonatomic) BOOL trackingScrollViewIsBeingScrubbed;
+
+/**
+ Whether or not the header is floating in front of an infinite stream of content.
+
+ Enabling this behavior will cause the header to always appear to be floating "in front of" the
+ content in Material space. This behavior should _only_ be enabled for content that has no top
+ edge, e.g. an infinite stream of vertical content.
+
+ Default: NO
+ */
+@property(nonatomic, getter=isInFrontOfInfiniteContent) BOOL inFrontOfInfiniteContent;
+
+/**
+ Whether or not the receiver is shared by many scroll views, such as in a tabbed interface with
+ many columns of content.
+
+ Default: NO
+ */
+@property(nonatomic) BOOL sharedWithManyScrollViews;
+
+#pragma mark Configuring Status Bar Behaviors
+
+/**
+ Whether this header view's content is translucent/transparent. Provides a hint to status bar
+ rendering, to correctly display contents scrolling under the status bar as it shifts on/off screen.
+
+ Default: NO
+ */
+@property(nonatomic) BOOL contentIsTranslucent;
+
+#pragma mark Header View Delegate
+
+/** The delegate for this header view. */
+@property(nonatomic, weak, nullable) id<MDCFlexibleHeaderViewDelegate> delegate;
+
+@end
+
+/**
+ The MDCFlexibleHeaderViewDelegate protocol allows a delegate to respond to changes in the header
+ view's state.
+
+ The delegate is typically the UIViewController that owns this flexible header view.
+ */
+@protocol MDCFlexibleHeaderViewDelegate <NSObject>
+@required
+
+/**
+ Informs the receiver that the flexible header view's preferred status bar visibility has changed.
+ */
+- (void)flexibleHeaderViewNeedsStatusBarAppearanceUpdate:
+        (nonnull MDCFlexibleHeaderView *)headerView;
+
+/**
+ Informs the receiver that the flexible header view's frame has changed.
+
+ The frame may change in response to scroll events of the tracking scroll view. The receiver
+ should use the MDCFlexibleHeaderView scrollPhase APIs to determine which phase the header's frame
+ is in.
+ */
+- (void)flexibleHeaderViewFrameDidChange:(nonnull MDCFlexibleHeaderView *)headerView;
+
+@end
+
+// clang-format off
+@interface MDCFlexibleHeaderView ()
+
+/** @see shiftBehavior */
+@property(nonatomic) MDCFlexibleHeaderShiftBehavior behavior
+__deprecated_msg("Use shiftBehavior instead.");
+
+#pragma mark Accessing the header's views
+
+/** Deprecated. Please register views directly to the flexible header. */
+@property(nonatomic, strong, nonnull) UIView *contentView
+__deprecated_msg("Please register views directly to the flexible header.");
+
+@end
+// clang-format on
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
new file mode 100644
index 0000000..7fa143e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderView.m
@@ -0,0 +1,1276 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderView.h"
+
+#import "private/MDCStatusBarShifter.h"
+
+#if TARGET_IPHONE_SIMULATOR
+float UIAnimationDragCoefficient(void);  // Private API for simulator animation speed
+#endif
+
+static const CGFloat kExpectedStatusBarHeight = 20;
+
+// The default maximum height for the header. Includes the status bar height.
+static const CGFloat kFlexibleHeaderDefaultHeight = 76;
+
+// The maximum default opacity of the shadow.
+static const float kDefaultVisibleShadowOpacity = 0.4f;
+
+// This length defines the moment at which the shadow will be fully visible as the header shifts
+// on-screen.
+static const CGFloat kShadowScaleLength = 8;
+
+// Duration of the UIKit animation that occurs when changing the tracking scroll view.
+static const NSTimeInterval kTrackingScrollViewDidChangeAnimationDuration = 0.2;
+
+// The epsilon used to determine when we've arrived at the destination while shifting the header
+// on/off-screen with the display link.
+static const float kShiftEpsilon = 0.1f;
+
+// The minimum delta y before we change the scroll direction.
+static const CGFloat kDeltaYSlop = 5;
+
+// Affects how fast the header shifts on/off-screen while animating. Bigger value = faster.
+static const CGFloat kAttachmentCoefficient = 12;
+
+// The amount the user needs to scroll back before the header starts shifting back on-screen.
+static const CGFloat kMaxAnchorLengthFullSwipe = 175;
+static const CGFloat kMaxAnchorLengthQuickSwipe = 25;
+
+// The minimum proportion of the header that will cause it to slide back on screen when the scroll
+// view finishes decelerating with the header partially shifted.
+static const CGFloat kMinimumVisibleProportion = 0.25;
+
+static inline MDCFlexibleHeaderShiftBehavior ShiftBehaviorForCurrentAppContext(
+    MDCFlexibleHeaderShiftBehavior intendedShiftBehavior) {
+  if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"] &&
+      intendedShiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar) {
+    return MDCFlexibleHeaderShiftBehaviorEnabled;
+  }
+  return intendedShiftBehavior;
+}
+
+static NSString *const MDCFlexibleHeaderMinimumHeightKey = @"MDCFlexibleHeaderMinimumHeightKey";
+static NSString *const MDCFlexibleHeaderMaximumHeightKey = @"MDCFlexibleHeaderMaximumHeightKey";
+static NSString *const MDCFlexibleHeaderShiftBehaviorKey = @"MDCFlexibleHeaderShiftBehaviorKey";
+static NSString *const MDCFlexibleHeaderContentImportanceKey =
+    @"MDCFlexibleHeaderContentImportanceKey";
+static NSString *const MDCFlexibleHeaderCanOverExtendKey = @"MDCFlexibleHeaderCanOverExtendKey";
+static NSString *const MDCFlexibleHeaderStatusBarCanOverlapKey =
+    @"MDCFlexibleHeaderStatusBarCanOverlapKey";
+static NSString *const MDCFlexibleHeaderVisibleShadowOpacityKey =
+    @"MDCFlexibleHeaderVisibleShadowOpacityKey";
+static NSString *const MDCFlexibleHeaderTrackingScrollViewKey =
+    @"MDCFlexibleHeaderTrackingScrollViewKey";
+static NSString *const MDCFlexibleHeaderInFrontOfInfiniteContentKey =
+    @"MDCFlexibleHeaderInFrontOfInfiniteContentKey";
+static NSString *const MDCFlexibleHeaderSharedWithManyScrollViewsKey =
+    @"MDCFlexibleHeaderSharedWithManyScrollViewsKey";
+static NSString *const MDCFlexibleHeaderContentIsTranslucentKey =
+    @"MDCFlexibleHeaderContentIsTranslucentKey";
+static NSString *const MDCFlexibleHeaderDelegateKey = @"MDCFlexibleHeaderDelegateKey";
+
+@interface MDCFlexibleHeaderView () <MDCStatusBarShifterDelegate>
+
+// The intensity strength of the shadow being displayed under the flexible header. Use this property
+// to check what the intensity of a custom shadow should be depending on a scroll position. Valid
+// values range from 0 to 1. Where 0 is no shadow is visible and 1 is the shadow is fully visible.
+@property(nonatomic, readonly) CGFloat shadowIntensity;
+
+@end
+
+// All injections into the content and scroll indicator insets are tracked here. It's super
+// important that we track what we added, rather than trying to cache the original values, because
+// we can't know if the insets have changed out from under us by another party.
+//
+// A separate info object is tracked for each scroll view tracked by the flexible header view.
+@interface MDCFlexibleHeaderScrollViewInfo : NSObject
+
+// The amount injected into contentInsets.top
+@property(nonatomic) CGFloat injectedTopContentInset;
+
+// Whether or not we've injected the top content inset
+@property(nonatomic) BOOL hasInjectedTopContentInset;
+
+// The amount injected into scrollIndicatorInsets.top
+@property(nonatomic) CGFloat injectedTopScrollIndicatorInset;
+
+@end
+
+@implementation MDCFlexibleHeaderView {
+  // We keep a weak reference to all forwarding views in case the client forgets to stop forwarding
+  // events for a view that's been removed from the header view. If we held a strong reference here
+  // then the removed view would never be deallocated.
+  NSHashTable *_forwardingViews;  // [UIView]
+
+  // A weak reference map of scroll views to info that have been tracked by this header view.
+  NSMapTable *_trackedScrollViews;  // {UIScrollView:MDCFlexibleHeaderScrollViewInfo}
+  MDCFlexibleHeaderScrollViewInfo *_trackingInfo;
+
+  // The ideal visibility state of the header. This may not match the present visibility if the user
+  // is interacting with the header or if we're presently animating it.
+  BOOL _wantsToBeHidden;
+
+  // Shift behavior state
+
+  // Prevents delta calculations on first update pass.
+  BOOL _shiftAccumulatorLastContentOffsetIsValid;
+  // When the header can slide off-screen, this tracks how off-screen the header is.
+  // Essentially: view's top edge = -_shiftAccumulator
+  CGFloat _shiftAccumulator;
+  CGPoint _shiftAccumulatorLastContentOffset;  // Stores our last delta'd content offset.
+  CGFloat _shiftAccumulatorDeltaY;
+  CADisplayLink *_shiftAccumulatorDisplayLink;
+
+  BOOL _interfaceOrientationIsChanging;
+  BOOL _contentInsetsAreChanging;
+  BOOL _isChangingStatusBarVisibility;
+
+  MDCStatusBarShifter *_statusBarShifter;
+
+  // Layers for header shadows.
+  CALayer *_defaultShadowLayer;
+  CALayer *_customShadowLayer;
+
+  // The block executed when shadow intensity changes.
+  MDCFlexibleHeaderShadowIntensityChangeBlock _shadowIntensityChangeBlock;
+
+#if DEBUG
+  // Keeps track of whether the client called ...WillEndDraggingWithVelocity:...
+  BOOL _didAdjustTargetContentOffset;
+#endif
+}
+
+// MDCFlexibleHeader properties
+@synthesize trackingScrollViewIsBeingScrubbed = _trackingScrollViewIsBeingScrubbed;
+@synthesize scrollPhase = _scrollPhase;
+@synthesize scrollPhaseValue = _scrollPhaseValue;
+@synthesize scrollPhasePercentage = _scrollPhasePercentage;
+
+// MDCFlexibleHeaderConfiguration properties
+@synthesize trackingScrollView = _trackingScrollView;
+@synthesize minimumHeight = _minimumHeight;
+@synthesize maximumHeight = _maximumHeight;
+@synthesize canOverExtend = _canOverExtend;
+@synthesize inFrontOfInfiniteContent = _inFrontOfInfiniteContent;
+@synthesize sharedWithManyScrollViews = _sharedWithManyScrollViews;
+@synthesize visibleShadowOpacity = _visibleShadowOpacity;
+
+#if DEBUG
+- (void)dealloc {
+  [_trackingScrollView.panGestureRecognizer removeTarget:self
+                                                  action:@selector(fhv_scrollViewDidPan:)];
+}
+#endif
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCFlexibleHeaderViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCFlexibleHeaderViewInit];
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderMinimumHeightKey]) {
+      _minimumHeight = (CGFloat)[aDecoder decodeDoubleForKey:MDCFlexibleHeaderMinimumHeightKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderMaximumHeightKey]) {
+      _maximumHeight = (CGFloat)[aDecoder decodeDoubleForKey:MDCFlexibleHeaderMaximumHeightKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderShiftBehaviorKey]) {
+      _shiftBehavior = [aDecoder decodeIntegerForKey:MDCFlexibleHeaderShiftBehaviorKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderContentImportanceKey]) {
+      _headerContentImportance =
+          [aDecoder decodeIntegerForKey:MDCFlexibleHeaderContentImportanceKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderCanOverExtendKey]) {
+      _canOverExtend = [aDecoder decodeBoolForKey:MDCFlexibleHeaderCanOverExtendKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderStatusBarCanOverlapKey]) {
+      _statusBarHintCanOverlapHeader =
+          [aDecoder decodeBoolForKey:MDCFlexibleHeaderStatusBarCanOverlapKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderVisibleShadowOpacityKey]) {
+      _visibleShadowOpacity = [aDecoder decodeFloatForKey:MDCFlexibleHeaderVisibleShadowOpacityKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderTrackingScrollViewKey]) {
+      _trackingScrollView = [aDecoder decodeObjectForKey:MDCFlexibleHeaderTrackingScrollViewKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderInFrontOfInfiniteContentKey]) {
+      _inFrontOfInfiniteContent =
+          [aDecoder decodeBoolForKey:MDCFlexibleHeaderInFrontOfInfiniteContentKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderSharedWithManyScrollViewsKey]) {
+      _sharedWithManyScrollViews =
+          [aDecoder decodeBoolForKey:MDCFlexibleHeaderSharedWithManyScrollViewsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderContentIsTranslucentKey]) {
+      _contentIsTranslucent = [aDecoder decodeBoolForKey:MDCFlexibleHeaderContentIsTranslucentKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderDelegateKey]) {
+      _delegate = [aDecoder decodeObjectForKey:MDCFlexibleHeaderDelegateKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+
+  [aCoder encodeDouble:self.minimumHeight forKey:MDCFlexibleHeaderMinimumHeightKey];
+  [aCoder encodeDouble:self.maximumHeight forKey:MDCFlexibleHeaderMaximumHeightKey];
+  [aCoder encodeInteger:self.shiftBehavior forKey:MDCFlexibleHeaderShiftBehaviorKey];
+  [aCoder encodeInteger:self.headerContentImportance forKey:MDCFlexibleHeaderContentImportanceKey];
+  [aCoder encodeBool:self.canOverExtend forKey:MDCFlexibleHeaderCanOverExtendKey];
+  [aCoder encodeBool:self.statusBarHintCanOverlapHeader
+              forKey:MDCFlexibleHeaderStatusBarCanOverlapKey];
+  [aCoder encodeFloat:self.visibleShadowOpacity forKey:MDCFlexibleHeaderVisibleShadowOpacityKey];
+  [aCoder encodeBool:self.inFrontOfInfiniteContent
+              forKey:MDCFlexibleHeaderInFrontOfInfiniteContentKey];
+  [aCoder encodeBool:self.sharedWithManyScrollViews
+              forKey:MDCFlexibleHeaderSharedWithManyScrollViewsKey];
+  [aCoder encodeBool:self.contentIsTranslucent forKey:MDCFlexibleHeaderContentIsTranslucentKey];
+  if (self.trackingScrollView) {
+    [aCoder encodeConditionalObject:self.trackingScrollView
+                             forKey:MDCFlexibleHeaderTrackingScrollViewKey];
+  }
+  if (self.delegate) {
+    [aCoder encodeConditionalObject:self.delegate forKey:MDCFlexibleHeaderDelegateKey];
+  }
+}
+
+- (void)commonMDCFlexibleHeaderViewInit {
+  _statusBarShifter = [[MDCStatusBarShifter alloc] init];
+  _statusBarShifter.delegate = self;
+  _statusBarShifter.enabled = [self fhv_shouldAllowShifting];
+
+  NSPointerFunctionsOptions options =
+      (NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality);
+  _forwardingViews = [NSHashTable hashTableWithOptions:options];
+
+  NSPointerFunctionsOptions keyOptions =
+      (NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality);
+  NSPointerFunctionsOptions valueOptions =
+      (NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPointerPersonality);
+  _trackedScrollViews = [NSMapTable mapTableWithKeyOptions:keyOptions valueOptions:valueOptions];
+
+  _headerContentImportance = MDCFlexibleHeaderContentImportanceDefault;
+  _statusBarHintCanOverlapHeader = YES;
+
+  _minimumHeight = kFlexibleHeaderDefaultHeight;
+  _maximumHeight = kFlexibleHeaderDefaultHeight;
+  _visibleShadowOpacity = kDefaultVisibleShadowOpacity;
+  _canOverExtend = YES;
+
+  _defaultShadowLayer = [CALayer layer];
+  _defaultShadowLayer.shadowColor = [[UIColor blackColor] CGColor];
+  _defaultShadowLayer.shadowOffset = CGSizeMake(0, 1.f);
+  _defaultShadowLayer.shadowRadius = 4.f;
+  _defaultShadowLayer.shadowOpacity = 0;
+  _defaultShadowLayer.hidden = YES;
+  [self.layer addSublayer:_defaultShadowLayer];
+
+  // Allow for custom shadows to be used.
+  _customShadowLayer = [CALayer layer];
+  _customShadowLayer.hidden = YES;
+  [self.layer addSublayer:_customShadowLayer];
+
+  _contentView = [[UIView alloc] initWithFrame:self.bounds];
+  _contentView.autoresizingMask =
+      (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+  [super addSubview:_contentView];
+
+  self.backgroundColor = [UIColor lightGrayColor];
+  _defaultShadowLayer.backgroundColor = self.backgroundColor.CGColor;
+
+  self.layer.shadowColor = [[UIColor blackColor] CGColor];
+  self.layer.shadowOffset = CGSizeMake(0, 1);
+  self.layer.shadowRadius = 4.f;
+  self.layer.shadowOpacity = 0;
+}
+
+- (void)setVisibleShadowOpacity:(float)visibleShadowOpacity {
+  _visibleShadowOpacity = visibleShadowOpacity;
+  [self fhv_accumulatorDidChange];
+}
+
+- (void)fhv_setShadowLayer:(CALayer *)shadowLayer
+    intensityDidChangeBlock:(MDCFlexibleHeaderShadowIntensityChangeBlock)block {
+  _shadowIntensityChangeBlock = block;
+
+  // If there is a custom shadow make sure the shadow on self.layer is not visible.
+  self.layer.shadowOpacity = 0;
+  CALayer *oldShadowLayer = _shadowLayer;
+  if (shadowLayer == _shadowLayer) {
+    return;
+  }
+  _shadowLayer = shadowLayer;
+  [oldShadowLayer removeFromSuperlayer];
+  if (shadowLayer) {
+    // When a custom shadow is being used hide the default shadow.
+    _defaultShadowLayer.hidden = YES;
+    _customShadowLayer.hidden = NO;
+    [_customShadowLayer addSublayer:_shadowLayer];
+  } else {
+    _defaultShadowLayer.hidden = NO;
+    _customShadowLayer.hidden = YES;
+    _shadowLayer = nil;
+  }
+}
+
+- (void)setShadowLayer:(CALayer *)shadowLayer {
+  [self fhv_setShadowLayer:shadowLayer intensityDidChangeBlock:nil];
+}
+
+- (void)setShadowLayer:(CALayer *)shadowLayer
+    intensityDidChangeBlock:(MDCFlexibleHeaderShadowIntensityChangeBlock)block {
+  [self fhv_setShadowLayer:shadowLayer intensityDidChangeBlock:block];
+}
+
+#pragma mark - UIView
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return CGSizeMake(size.width, _minimumHeight);
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self fhv_updateShadowPath];
+  BOOL disableActions = [CATransaction disableActions];
+  [CATransaction setDisableActions:YES];
+  _defaultShadowLayer.frame = self.bounds;
+  _customShadowLayer.frame = self.bounds;
+  _shadowLayer.frame = self.bounds;
+  [_defaultShadowLayer layoutIfNeeded];
+  [_customShadowLayer layoutIfNeeded];
+  [_shadowLayer layoutIfNeeded];
+  [CATransaction setDisableActions:disableActions];
+}
+
+- (void)willMoveToSuperview:(UIView *)newSuperview {
+  [super willMoveToSuperview:newSuperview];
+
+  if (newSuperview == self.trackingScrollView) {
+    self.transform = CGAffineTransformMakeTranslation(0, self.trackingScrollView.contentOffset.y);
+  }
+}
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+  UIView *hitView = [super hitTest:point withEvent:event];
+
+  // Forwards taps to the scroll view.
+  if (hitView == self || [_forwardingViews containsObject:hitView]) {
+    hitView = _trackingScrollView;
+  }
+
+  return hitView;
+}
+
+- (void)setFrame:(CGRect)frame {
+  [super setFrame:frame];
+
+  if (!_interfaceOrientationIsChanging) {
+    [self fhv_updateLayout];
+  }
+}
+
+#pragma mark - Private (fhv_ prefix)
+
+- (void)fhv_removeInsetsFromScrollView:(UIScrollView *)scrollView {
+  if (!scrollView) {
+    return;
+  }
+  if (_sharedWithManyScrollViews) {
+    return;  // Never remove our insets from scroll views while the header is being shared.
+  }
+
+  MDCFlexibleHeaderScrollViewInfo *info = [_trackedScrollViews objectForKey:scrollView];
+  if (!info) {
+    return;
+  }
+
+  UIEdgeInsets insets = scrollView.contentInset;
+  insets.top -= info.injectedTopContentInset;
+  info.injectedTopContentInset = 0;
+  info.hasInjectedTopContentInset = NO;
+  scrollView.contentInset = insets;
+
+  UIEdgeInsets scrollIndicatorInsets = _trackingScrollView.scrollIndicatorInsets;
+  scrollIndicatorInsets.top -= info.injectedTopScrollIndicatorInset;
+  info.injectedTopScrollIndicatorInset = 0;
+  _trackingScrollView.scrollIndicatorInsets = scrollIndicatorInsets;
+}
+
+- (MDCFlexibleHeaderScrollViewInfo *)fhv_addInsetsToScrollView:(UIScrollView *)scrollView {
+  if (!scrollView) {
+    return nil;
+  }
+
+  MDCFlexibleHeaderScrollViewInfo *info = [_trackedScrollViews objectForKey:scrollView];
+  if (!info) {
+    info = [[MDCFlexibleHeaderScrollViewInfo alloc] init];
+    [_trackedScrollViews setObject:info forKey:scrollView];
+    if (_trackingScrollView == scrollView) {
+      _trackingInfo = info;
+    }
+  }
+
+  if (!info.hasInjectedTopContentInset) {
+    UIEdgeInsets insets = scrollView.contentInset;
+    insets.top += _maximumHeight;
+    info.injectedTopContentInset = _maximumHeight;
+    info.hasInjectedTopContentInset = YES;
+    scrollView.contentInset = insets;
+  }
+
+  // The scroll indicator insets are updated by fhv_accumulatorDidChange and change dynamically with
+  // the header.
+  return info;
+}
+
+- (void)fhv_updateShadowPath {
+  UIBezierPath *path =
+      [UIBezierPath bezierPathWithRect:CGRectInset(self.bounds, -self.layer.shadowRadius, 0)];
+  self.layer.shadowPath = [path CGPath];
+}
+
+#pragma mark Typically-used values
+
+// Returns the contentOffset of the tracking scroll view bounded to the range of content offsets
+// that will affect the header.
+- (CGPoint)fhv_boundedContentOffset {
+  // We don't care about rubber banding beyond the bottom of the content.
+  return CGPointMake(_trackingScrollView.contentOffset.x,
+                     MIN(_trackingScrollView.contentOffset.y, [self fhv_contentOffsetMaxY]));
+}
+
+- (CGFloat)fhv_rawTopContentInset {
+  return _trackingScrollView.contentInset.top - _trackingInfo.injectedTopContentInset;
+}
+
+- (CGFloat)fhv_contentOffsetWithoutInjectedTopInset {
+  return _trackingScrollView.contentOffset.y + [self fhv_rawTopContentInset];
+}
+
+- (CGFloat)fhv_contentOffsetMaxY {
+  return _trackingScrollView.contentSize.height - _trackingScrollView.bounds.size.height;
+}
+
+// Returns a value indicating how much the header is overlapping the tracking scroll view's content.
+// > 0 overlapping the content
+// = 0 attached to top of content
+// < 0 the content is below the header
+- (CGFloat)fhv_projectedHeaderBottomEdge {
+  CGFloat offsetWithoutInset = [self fhv_contentOffsetWithoutInjectedTopInset];
+  CGRect projectedFrame = [self convertRect:self.bounds toView:self.trackingScrollView.superview];
+  CGFloat frameBottomEdge = CGRectGetMaxY(projectedFrame);
+  return frameBottomEdge + offsetWithoutInset;
+}
+
+- (CGFloat)fhv_accumulatorMax {
+  BOOL shouldCollapseToStatusBar = [self fhv_shouldCollapseToStatusBar];
+  return (shouldCollapseToStatusBar ? _minimumHeight - kExpectedStatusBarHeight : _minimumHeight);
+}
+
+#pragma mark Logical short forms
+
+- (BOOL)fhv_shouldAllowShifting {
+  return self.hidesStatusBarWhenCollapsed && self.statusBarHintCanOverlapHeader;
+}
+
+- (BOOL)fhv_shouldCollapseToStatusBar {
+  return !self.hidesStatusBarWhenCollapsed && self.statusBarHintCanOverlapHeader;
+}
+
+- (BOOL)fhv_canShiftOffscreen {
+  return ((_shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabled ||
+           _shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar) &&
+          !_trackingScrollView.pagingEnabled);
+}
+
+- (BOOL)fhv_isPartiallyShifted {
+  return ([self fhv_isDetachedFromTopOfContent] && _shiftAccumulator > 0 &&
+          _shiftAccumulator < [self fhv_accumulatorMax]);
+}
+
+// The flexible header is "in front of" the content.
+- (BOOL)fhv_isDetachedFromTopOfContent {
+  // Epsilon here is somewhat large in order to be visually-forgiving for sub-point situations.
+  return [self fhv_projectedHeaderBottomEdge] > (CGFloat)0.5;
+}
+
+- (BOOL)fhv_isOverExtendingBottom {
+  CGFloat bottomEdgeOfScrollView =
+      (_trackingScrollView.contentOffset.y + _trackingScrollView.bounds.size.height);
+  CGFloat bottomEdgeOfContent =
+      (_trackingScrollView.contentSize.height + _trackingScrollView.contentInset.bottom);
+  BOOL canOverExtendBottom =
+      (_trackingScrollView.contentSize.height > _trackingScrollView.bounds.size.height);
+  return (canOverExtendBottom && (bottomEdgeOfScrollView >= bottomEdgeOfContent));
+}
+
+#pragma mark Phase Calculation
+
+// Given the current frame, calculates the scroll phase, value, and percentage.
+- (void)fhv_recalculatePhase {
+  CGRect frame = self.frame;
+
+  if (frame.origin.y < 0) {
+    _scrollPhase = MDCFlexibleHeaderScrollPhaseShifting;
+    _scrollPhaseValue = frame.origin.y + _minimumHeight;
+    CGFloat adjustedHeight = _minimumHeight;
+    if ([self fhv_shouldCollapseToStatusBar]) {
+      adjustedHeight -= kExpectedStatusBarHeight;
+    }
+    if (adjustedHeight > 0) {
+      _scrollPhasePercentage = -frame.origin.y / adjustedHeight;
+    } else {
+      _scrollPhasePercentage = 0;
+    }
+
+    return;
+  }
+
+  _scrollPhaseValue = frame.size.height;
+
+  if (frame.size.height < _maximumHeight) {
+    _scrollPhase = MDCFlexibleHeaderScrollPhaseCollapsing;
+
+    CGFloat heightLength = _maximumHeight - _minimumHeight;
+    if (heightLength > 0) {
+      _scrollPhasePercentage = (frame.size.height - _minimumHeight) / heightLength;
+    } else {
+      _scrollPhasePercentage = 0;
+    }
+
+    return;
+  }
+
+  _scrollPhase = MDCFlexibleHeaderScrollPhaseOverExtending;
+  if (_maximumHeight > 0) {
+    _scrollPhasePercentage = 1 + (frame.size.height - _maximumHeight) / _maximumHeight;
+  } else {
+    _scrollPhasePercentage = 0;
+  }
+}
+
+#pragma mark Display Link
+
+// The display link is only active when the user is no longer interacting with the scroll view and
+// we'd like to shift the header either on- or off-screen.
+
+#if TARGET_IPHONE_SIMULATOR
+- (float)fhv_dragCoefficient {
+  if (&UIAnimationDragCoefficient) {
+    float coeff = UIAnimationDragCoefficient();
+    if (coeff > 1) {
+      return coeff;
+    }
+  }
+  return 1;
+}
+#endif
+
+- (void)fhv_startDisplayLink {
+  [self fhv_stopDisplayLink];
+
+  // NOTE: This may cause a retain cycle.
+  // cl/129917749
+  _shiftAccumulatorDisplayLink =
+      [CADisplayLink displayLinkWithTarget:self
+                                  selector:@selector(fhv_shiftAccumulatorDisplayLinkDidFire:)];
+  [_shiftAccumulatorDisplayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
+}
+
+- (void)fhv_stopDisplayLink {
+  [_shiftAccumulatorDisplayLink invalidate];
+  _shiftAccumulatorDisplayLink = nil;
+}
+
+- (void)fhv_shiftAccumulatorDisplayLinkDidFire:(CADisplayLink *)displayLink {
+  // Erase any scrollback that was injected into the accumulator by capping it back down.
+  _shiftAccumulator = MIN([self fhv_accumulatorMax], _shiftAccumulator);
+
+  CGFloat destination = _wantsToBeHidden ? [self fhv_accumulatorMax] : 0;
+  CGFloat distanceToDestination = destination - _shiftAccumulator;
+
+  NSTimeInterval duration = displayLink.duration;
+
+#if TARGET_IPHONE_SIMULATOR
+  duration /= [self fhv_dragCoefficient];
+#endif
+
+  // This is a simple "force" that's stronger the further we are from the destination.
+  _shiftAccumulator += kAttachmentCoefficient * distanceToDestination * duration;
+  _shiftAccumulator = MAX(0, MIN([self fhv_accumulatorMax], _shiftAccumulator));
+
+  [_statusBarShifter setOffset:_shiftAccumulator];
+
+  // Have we reached our destination?
+  if (fabs(destination - _shiftAccumulator) <= kShiftEpsilon) {
+    _shiftAccumulator = destination;
+
+    [self fhv_stopDisplayLink];
+  }
+
+  [self fhv_commitAccumulatorToFrame];
+}
+
+#pragma mark Shift Accumulator
+
+- (void)fhv_accumulatorDidChange {
+  if (!_trackingScrollView) {
+    // Set the shadow opacity directly.
+    self.layer.shadowOpacity = _visibleShadowOpacity;
+
+    return;
+  }
+
+  CGRect frame = self.frame;
+
+  CGFloat frameBottomEdge = [self fhv_projectedHeaderBottomEdge];
+  frameBottomEdge = MAX(0, MIN(kShadowScaleLength, frameBottomEdge));
+
+  CGFloat boundedAccumulator = MIN([self fhv_accumulatorMax], _shiftAccumulator);
+
+  CGFloat shadowIntensity;
+  if (self.hidesStatusBarWhenCollapsed) {
+    // Calculate the desired shadow strength for the offset & accumulator and then take the
+    // weakest strength.
+    CGFloat accumulator = MAX(0, MIN(kShadowScaleLength, _minimumHeight - boundedAccumulator));
+    if (self.isInFrontOfInfiniteContent) {
+      // When in front of infinite content we only care to hide the shadow when our header is
+      // off-screen.
+      shadowIntensity = MAX(0, MIN(1, accumulator / kShadowScaleLength));
+
+    } else {
+      // When over non-infinite content we also want to hide the shadow when we're anchored to the
+      // top of our content.
+      shadowIntensity = MAX(0, MIN(1, MIN(accumulator, frameBottomEdge) / kShadowScaleLength));
+    }
+
+  } else if (self.isInFrontOfInfiniteContent) {
+    shadowIntensity = 1;
+
+  } else {
+    // Adjust the opacity as the bottom edge of the header increasingly overlaps the contents
+    shadowIntensity = frameBottomEdge / kShadowScaleLength;
+  }
+  if (_defaultShadowLayer.hidden && _customShadowLayer.hidden) {
+    self.layer.shadowOpacity = (float)(_visibleShadowOpacity * shadowIntensity);
+  } else {
+    _defaultShadowLayer.shadowOpacity = (float)(_visibleShadowOpacity * shadowIntensity);
+  }
+  _shadowIntensity = shadowIntensity;
+  if (_shadowIntensityChangeBlock) {
+    _shadowIntensityChangeBlock(_shadowLayer, _shadowIntensity);
+  }
+
+  [_statusBarShifter setOffset:boundedAccumulator];
+
+  // Small performance improvement to not set the hidden property on every scroll tick.
+  BOOL isHidden = boundedAccumulator >= _minimumHeight;
+  if (isHidden != self.hidden) {
+    self.hidden = isHidden;
+  }
+
+  UIEdgeInsets scrollIndicatorInsets = _trackingScrollView.scrollIndicatorInsets;
+  scrollIndicatorInsets.top -= _trackingInfo.injectedTopScrollIndicatorInset;
+
+  _trackingInfo.injectedTopScrollIndicatorInset = frame.size.height - boundedAccumulator;
+  scrollIndicatorInsets.top += _trackingInfo.injectedTopScrollIndicatorInset;
+
+  _trackingScrollView.scrollIndicatorInsets = scrollIndicatorInsets;
+}
+
+#pragma mark Layout
+
+- (void)fhv_updateLayout {
+  if (!_trackingScrollView) {
+    return;
+  }
+
+  // We use the content offset to calculate the unclamped height of the frame.
+  CGFloat offsetWithoutInset = [self fhv_contentOffsetWithoutInjectedTopInset];
+  CGFloat headerHeight = -offsetWithoutInset;
+
+  if (_trackingScrollView.isTracking) {
+    [self fhv_stopDisplayLink];
+  }
+
+  if (_shiftAccumulatorLastContentOffsetIsValid) {
+    // We track the last direction for our target offset behavior.
+    CGFloat deltaY = [self fhv_boundedContentOffset].y - _shiftAccumulatorLastContentOffset.y;
+
+    if (_shiftAccumulatorDeltaY * deltaY < 0) {
+      // Direction has changed.
+      _shiftAccumulatorDeltaY = 0;
+    }
+    _shiftAccumulatorDeltaY += deltaY;
+
+    // Keeps track of the last direction the user moved their finger in.
+    if (_trackingScrollView.isTracking) {
+      if (_shiftAccumulatorDeltaY > kDeltaYSlop) {
+        _wantsToBeHidden = YES;
+      } else if (_shiftAccumulatorDeltaY < -kDeltaYSlop) {
+        _wantsToBeHidden = NO;
+      }
+    }
+
+    if (![self fhv_isOverExtendingBottom] && !_shiftAccumulatorDisplayLink) {
+      // When we're not allowed to shift offscreen, only allow the header to shift further
+      // on-screen in case it was previously off-screen due to a behavior change.
+      if (![self fhv_canShiftOffscreen]) {
+        deltaY = MIN(0, deltaY);
+      }
+
+      // When scrubbing we only allow the header to shrink and shift off-screen.
+      if (self.trackingScrollViewIsBeingScrubbed) {
+        deltaY = MAX(0, deltaY);
+      }
+
+      // Check if our delta y will cause us to cross the boundary from shrinking to shifting and,
+      // if so, cap the deltaY to only the overshoot, otherwise the header will overshift.
+
+      // headerHeight and deltaY are in inverted coordinate spaces, so when we do
+      // headerHeight + deltaY we're calculating where the headerHeight was _before_ this update.
+
+      CGFloat previousHeaderHeight = headerHeight + deltaY;
+
+      // Overshoot coming in
+      if (headerHeight < _minimumHeight && previousHeaderHeight > _minimumHeight) {
+        deltaY = _minimumHeight - headerHeight;
+
+        // Overshoot going out
+      } else if (headerHeight > _minimumHeight && previousHeaderHeight < _minimumHeight) {
+        deltaY = (headerHeight + deltaY) - _minimumHeight;
+      }
+
+      // Calculate the upper bound of the accumulator based on what phase we're in.
+
+      CGFloat upperBound;
+
+      if (headerHeight < 0) {  // Header is shifting while detached from content.
+        upperBound = [self fhv_accumulatorMax] + [self fhv_anchorLength];
+
+      } else if (headerHeight < _minimumHeight) {  // Header is shifting while attached to content.
+        upperBound = [self fhv_accumulatorMax];
+
+      } else {  // Header is not shifting.
+        upperBound = 0;
+      }
+
+      // Ensure that we don't lose any deltaY by first capping the accumulator within its valid
+      // range.
+      _shiftAccumulator = MIN(upperBound, _shiftAccumulator);
+
+      // Accumulate the deltaY.
+      _shiftAccumulator = MAX(0, MIN(upperBound, _shiftAccumulator + deltaY));
+    }
+  }
+
+  CGRect bounds = self.bounds;
+
+  if (_canOverExtend) {
+    bounds.size.height = MAX(_minimumHeight, headerHeight);
+
+  } else {
+    bounds.size.height = MAX(_minimumHeight, MIN(_maximumHeight, headerHeight));
+  }
+
+  self.bounds = bounds;
+
+  [self fhv_commitAccumulatorToFrame];
+
+  _shiftAccumulatorLastContentOffset = [self fhv_boundedContentOffset];
+  _shiftAccumulatorLastContentOffsetIsValid = YES;
+}
+
+- (CGFloat)fhv_anchorLength {
+  switch (_headerContentImportance) {
+    case MDCFlexibleHeaderContentImportanceDefault:
+      return kMaxAnchorLengthFullSwipe;
+
+    case MDCFlexibleHeaderContentImportanceHigh:
+      return kMaxAnchorLengthQuickSwipe;
+  }
+}
+
+// Commit the current shiftOffscreenAccumulator value to the view's position.
+- (void)fhv_commitAccumulatorToFrame {
+  CGPoint position = self.center;
+  // Offset the frame.
+  position.y = -MIN([self fhv_accumulatorMax], _shiftAccumulator);
+  position.y += self.bounds.size.height / 2;
+
+  self.center = position;
+
+  [self fhv_accumulatorDidChange];
+  [self fhv_recalculatePhase];
+
+  [_statusBarShifter setOffset:_shiftAccumulator];
+
+  [self.delegate flexibleHeaderViewFrameDidChange:self];
+}
+
+- (void)fhv_contentOffsetDidChange {
+#if DEBUG
+  _didAdjustTargetContentOffset = NO;
+#endif
+
+  // We generally expect the tracking scroll view to be a sibling to the flexible header, but there
+  // are cases where this assumption is always incorrect.
+  //
+  // Notably, UITableViewController's .view _is_ the tableView, so there is no way to add a flexible
+  // header other than as a subview to the scroll view. This is the most common case to which the
+  // following logic has been written.
+  if (self.superview == self.trackingScrollView) {
+    self.transform = CGAffineTransformMakeTranslation(0, self.trackingScrollView.contentOffset.y);
+
+    if (self.superview.subviews.lastObject != self) {
+      [self.superview bringSubviewToFront:self];
+    }
+  }
+
+  // While the interface orientation is rotating we don't respond to any adjustments to the content
+  // offset.
+  if (_interfaceOrientationIsChanging || _contentInsetsAreChanging ||
+      _isChangingStatusBarVisibility) {
+    return;
+  }
+
+  [self fhv_updateLayout];
+}
+
+#pragma mark Gestures
+
+// TODO(#1254): Re-enable sanity check assert on viewDidPan
+// This function is a temporary inclusion to stop an assert from triggering on iOS 10.3b until
+// we determine the cause. Remove once #1254 is closed.
+#if DEBUG
+static BOOL isRunningiOS10_3OrAbove() {
+  static dispatch_once_t onceToken;
+  static BOOL isRunningiOS10_3OrAbove;
+  dispatch_once(&onceToken, ^{
+    NSProcessInfo *info = [NSProcessInfo processInfo];
+    if ([info respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)]) {
+      isRunningiOS10_3OrAbove = [info isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){
+                                                                          .majorVersion = 10,
+                                                                          .minorVersion = 3,
+                                                                          .patchVersion = 0,
+                                                                      }];
+    }
+  });
+  return isRunningiOS10_3OrAbove;
+}
+#endif
+
+#if DEBUG
+- (void)fhv_scrollViewDidPan:(UIPanGestureRecognizer *)pan {
+  if (pan.state == UIGestureRecognizerStateEnded && [self fhv_canShiftOffscreen]) {
+    // You _must_ implement the target content offset method in your UIScrollViewDelegate.
+    // Not implementing the target content offset method can allow the status bar to get into an
+    // indeterminate state and may cause your app to be rejected.
+
+    // TODO(#1254): Re-enable sanity check assert on viewDidPan
+    // To re-enable, remove isRunningiOS10_3OrAbove() function and always assert.
+    if (!isRunningiOS10_3OrAbove()) {
+      NSAssert(_didAdjustTargetContentOffset, @"%@ isn't invoking %@'s %@.",
+               NSStringFromClass([_trackingScrollView class]), NSStringFromClass([self class]),
+               NSStringFromSelector(
+                   @selector(trackingScrollViewWillEndDraggingWithVelocity:targetContentOffset:)));
+    }
+  }
+}
+#endif
+
+#pragma mark - MDCStatusBarShifterDelegate
+
+- (void)statusBarShifterNeedsStatusBarAppearanceUpdate:(MDCStatusBarShifter *)statusBarShifter {
+  // UINavigationController reacts to status bar visibility changes by adjusting the content offset.
+  // To counteract this sort of behavior, we forcefully stash the content offset and restore it
+  // after updating the status bar appearance.
+  _isChangingStatusBarVisibility = YES;
+  CGPoint stashedContentOffset = _trackingScrollView.contentOffset;
+  [self.delegate flexibleHeaderViewNeedsStatusBarAppearanceUpdate:self];
+  [UIView performWithoutAnimation:^{
+    _trackingScrollView.contentOffset = stashedContentOffset;
+  }];
+  _isChangingStatusBarVisibility = NO;
+}
+
+- (void)statusBarShifter:(MDCStatusBarShifter *)statusBarShifter
+    wantsSnapshotViewAdded:(UIView *)view {
+  [self addSubview:view];
+}
+
+#pragma mark - Public
+
+- (void)setTrackingScrollView:(UIScrollView *)trackingScrollView {
+  if (_trackingScrollView == trackingScrollView) {
+    return;
+  }
+
+#if DEBUG
+  [_trackingScrollView.panGestureRecognizer removeTarget:self
+                                                  action:@selector(fhv_scrollViewDidPan:)];
+  [trackingScrollView.panGestureRecognizer addTarget:self action:@selector(fhv_scrollViewDidPan:)];
+
+#if 0   // TODO(featherless):
+        // https://github.com/material-components/material-components-ios/issues/214
+  // Verify existence of a delegate.
+  NSAssert(!trackingScrollView || trackingScrollView.delegate,
+           @"The provided tracking scroll view %@ has no delegate. Without a delegate, %@ will not"
+           @" be able to react to scroll events and may perform incorrectly."
+           @" This assertion will only fire in debug builds.",
+           NSStringFromClass([trackingScrollView class]),
+           NSStringFromClass([self class]));
+#endif  // #if 0
+#endif  // #if DEBUG
+
+  // If this header is shared by many scroll views then we leave the insets when switching the
+  // tracking scroll view.
+  [self fhv_removeInsetsFromScrollView:_trackingScrollView];
+
+  BOOL wasTrackingScrollView = _trackingScrollView != nil;
+
+  _trackingScrollView = trackingScrollView;
+
+  _shiftAccumulatorLastContentOffsetIsValid = NO;
+  _shiftAccumulatorLastContentOffset = _trackingScrollView.contentOffset;
+  _shiftAccumulatorDeltaY = 0;
+
+  _trackingInfo = [_trackedScrollViews objectForKey:_trackingScrollView];
+  if (!_sharedWithManyScrollViews || !_trackingInfo) {
+    [self fhv_addInsetsToScrollView:_trackingScrollView];
+  }
+  void (^animate)() = ^{
+    [self fhv_updateLayout];
+  };
+  void (^completion)(BOOL) = ^(BOOL finished) {
+    if (!finished) {
+      return;
+    }
+
+    // When the tracking scroll view is cleared we need a shadow update.
+    if (!_trackingScrollView) {
+      [self fhv_accumulatorDidChange];
+    }
+  };
+  if (wasTrackingScrollView) {
+    [UIView animateWithDuration:kTrackingScrollViewDidChangeAnimationDuration
+                     animations:animate
+                     completion:completion];
+  } else {
+    animate();
+    completion(YES);
+  }
+}
+
+- (void)trackingScrollViewDidScroll {
+  [self fhv_contentOffsetDidChange];
+}
+
+- (void)trackingScrollViewDidEndDraggingWillDecelerate:(BOOL)willDecelerate {
+  if (![self fhv_canShiftOffscreen]) {
+    _wantsToBeHidden = NO;
+  }
+  if (!willDecelerate && [self fhv_isPartiallyShifted]) {
+    [self fhv_startDisplayLink];
+  }
+}
+
+- (void)trackingScrollViewDidEndDecelerating {
+  if ([self fhv_isPartiallyShifted]) {
+    _wantsToBeHidden =
+        (_shiftAccumulator >= (1 - kMinimumVisibleProportion) * [self fhv_accumulatorMax]);
+    [self fhv_startDisplayLink];
+  }
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _statusBarShifter.prefersStatusBarHidden;
+}
+
+- (BOOL)hidesStatusBarWhenCollapsed {
+  return (_shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar &&
+          !_trackingScrollView.pagingEnabled);
+}
+
+- (void)setstatusBarHintCanOverlapHeader:(BOOL)statusBarHintCanOverlapHeader {
+  if (_statusBarHintCanOverlapHeader == statusBarHintCanOverlapHeader) {
+    return;
+  }
+  _statusBarHintCanOverlapHeader = statusBarHintCanOverlapHeader;
+
+  _statusBarShifter.enabled = [self fhv_shouldAllowShifting];
+
+  [self fhv_startDisplayLink];
+}
+
+- (void)setShiftBehavior:(MDCFlexibleHeaderShiftBehavior)shiftBehavior {
+  shiftBehavior = ShiftBehaviorForCurrentAppContext(shiftBehavior);
+  if (_shiftBehavior == shiftBehavior) {
+    return;
+  }
+  BOOL needsShiftOnScreen = (_shiftBehavior != MDCFlexibleHeaderShiftBehaviorDisabled &&
+                             shiftBehavior == MDCFlexibleHeaderShiftBehaviorDisabled);
+  _shiftBehavior = shiftBehavior;
+
+  _statusBarShifter.enabled = [self fhv_shouldAllowShifting];
+
+  if (needsShiftOnScreen) {
+    _wantsToBeHidden = NO;
+    [self fhv_startDisplayLink];
+  }
+}
+
+- (void)setBehavior:(MDCFlexibleHeaderShiftBehavior)behavior {
+  self.shiftBehavior = behavior;
+}
+
+- (MDCFlexibleHeaderShiftBehavior)behavior {
+  return self.shiftBehavior;
+}
+
+- (void)changeContentInsets:(MDCFlexibleHeaderChangeContentInsetsBlock)block {
+  if (!block) {
+    return;
+  }
+  _contentInsetsAreChanging = YES;
+  UIEdgeInsets previousInsets = _trackingScrollView.contentInset;
+  block();
+  CGFloat delta = _trackingScrollView.contentInset.top - previousInsets.top;
+  CGPoint contentOffset = _trackingScrollView.contentOffset;
+  contentOffset.y -= delta;  // Keeps the scroll view offset from jumping.
+  _trackingScrollView.contentOffset = contentOffset;
+  _contentInsetsAreChanging = NO;
+}
+
+- (void)interfaceOrientationWillChange {
+  NSAssert(!_interfaceOrientationIsChanging, @"Call to %@::%@ not matched by a call to %@.",
+           NSStringFromClass([self class]), NSStringFromSelector(_cmd),
+           NSStringFromSelector(@selector(interfaceOrientationDidChange)));
+
+  _interfaceOrientationIsChanging = YES;
+
+  [_statusBarShifter interfaceOrientationWillChange];
+}
+
+- (void)interfaceOrientationIsChanging {
+  NSAssert(_interfaceOrientationIsChanging, @"Call to %@::%@ not matched by a call to %@.",
+           NSStringFromClass([self class]), NSStringFromSelector(_cmd),
+           NSStringFromSelector(@selector(interfaceOrientationWillChange)));
+}
+
+- (void)interfaceOrientationDidChange {
+  NSAssert(_interfaceOrientationIsChanging, @"Call to %@::%@ not matched by a call to %@.",
+           NSStringFromClass([self class]), NSStringFromSelector(_cmd),
+           NSStringFromSelector(@selector(interfaceOrientationWillChange)));
+
+  _interfaceOrientationIsChanging = NO;
+
+  // Ignore any content offset delta that occured as a result of any orientation change.
+  _shiftAccumulatorLastContentOffset = [self fhv_boundedContentOffset];
+
+  [self fhv_updateLayout];
+
+  [_statusBarShifter interfaceOrientationDidChange];
+}
+
+- (void)viewWillTransitionToSize:(CGSize)size
+       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
+  [self interfaceOrientationWillChange];
+  [coordinator
+      animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        [self interfaceOrientationIsChanging];
+      }
+      completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
+        [self interfaceOrientationDidChange];
+      }];
+}
+
+- (void)forwardTouchEventsForView:(UIView *)view {
+  [_forwardingViews addObject:view];
+}
+
+- (void)stopForwardingTouchEventsForView:(UIView *)view {
+  [_forwardingViews removeObject:view];
+}
+
+- (void)setMinimumHeight:(CGFloat)minimumHeight {
+  if (_minimumHeight == minimumHeight) {
+    return;
+  }
+
+  _minimumHeight = minimumHeight;
+
+  if (_minimumHeight > _maximumHeight) {
+    [self setMaximumHeight:_minimumHeight];
+  } else {
+    [self fhv_updateLayout];
+  }
+}
+
+- (void)setMaximumHeight:(CGFloat)maximumHeight {
+  if (_maximumHeight == maximumHeight) {
+    return;
+  }
+
+  CGPoint originalOffset = _trackingScrollView.contentOffset;
+
+  [self fhv_removeInsetsFromScrollView:_trackingScrollView];
+
+  _maximumHeight = maximumHeight;
+
+  CGPoint stashedOffset = _trackingScrollView.contentOffset;
+  [self fhv_addInsetsToScrollView:_trackingScrollView];
+
+  // Only restore the content offset if UIScrollView didn't decide to update the content offset for
+  // us. Notably, it seems to automatically adjust the content offset in the first runloop in which
+  // the scroll view's been created, but not in any further runloops.
+  if (CGPointEqualToPoint(stashedOffset, _trackingScrollView.contentOffset)) {
+    originalOffset.y = MAX(originalOffset.y, -_trackingScrollView.contentInset.top);
+    _trackingScrollView.contentOffset = originalOffset;
+  }
+
+  if (_maximumHeight < _minimumHeight) {
+    [self setMinimumHeight:_maximumHeight];
+  } else {
+    [self fhv_updateLayout];
+  }
+}
+
+- (void)setInFrontOfInfiniteContent:(BOOL)inFrontOfInfiniteContent {
+  if (_inFrontOfInfiniteContent == inFrontOfInfiniteContent) {
+    return;
+  }
+  _inFrontOfInfiniteContent = inFrontOfInfiniteContent;
+
+  [self fhv_updateLayout];
+}
+
+- (BOOL)trackingScrollViewWillEndDraggingWithVelocity:(CGPoint)velocity
+                                  targetContentOffset:(inout CGPoint *)targetContentOffset {
+#if DEBUG
+  _didAdjustTargetContentOffset = YES;
+#endif
+
+  if ([self fhv_canShiftOffscreen]) {
+    CGPoint target = *targetContentOffset;
+
+    CGFloat offsetTargetY = target.y + [self fhv_rawTopContentInset];
+    CGFloat flexHeight = -offsetTargetY;
+
+    if ([self fhv_canShiftOffscreen] && (0 < flexHeight && flexHeight < _minimumHeight)) {
+      // Don't allow the header to be partially visible.
+      if (_wantsToBeHidden) {
+        target.y = -[self fhv_rawTopContentInset];
+      } else {
+        target.y = -_minimumHeight - [self fhv_rawTopContentInset];
+      }
+      *targetContentOffset = target;
+      return YES;
+    }
+  }
+
+  return NO;
+}
+
+- (void)trackingScrollWillChangeToScrollView:(UIScrollView *)scrollView {
+  MDCFlexibleHeaderScrollViewInfo *info = [_trackedScrollViews objectForKey:scrollView];
+  if (!info) {
+    info = [self fhv_addInsetsToScrollView:scrollView];
+
+    CGPoint offset = scrollView.contentOffset;
+    offset.y -= info.injectedTopContentInset;
+    scrollView.contentOffset = offset;
+  }
+
+  if (_shiftAccumulator >= [self fhv_accumulatorMax]) {
+    // We're shifted off-screen, make sure that this scroll view isn't expecting to show the header.
+
+    CGPoint offset = scrollView.contentOffset;
+    CGFloat rawTopInset = scrollView.contentInset.top - info.injectedTopContentInset;
+    if (offset.y < -rawTopInset) {
+      offset.y = -rawTopInset;
+      scrollView.contentOffset = offset;
+    }
+
+  } else if (self.trackingScrollView.contentOffset.y != scrollView.contentOffset.y &&
+             self.trackingScrollView.contentOffset.y <= 0 && scrollView.contentOffset.y <= 0) {
+    // Our content is expanding the header in both columns, let's match up the content offsets so
+    // that the header's height won't change.
+    CGPoint offset = scrollView.contentOffset;
+    offset.y = self.trackingScrollView.contentOffset.y;
+    scrollView.contentOffset = offset;
+  }
+}
+
+- (void)shiftHeaderOnScreenAnimated:(BOOL)animated {
+  _wantsToBeHidden = NO;
+
+  if (animated) {
+    [self fhv_startDisplayLink];
+  } else {
+    // Remove any offscreen accumulation.
+    _shiftAccumulator = 0;
+    [self fhv_commitAccumulatorToFrame];
+  }
+}
+
+- (void)shiftHeaderOffScreenAnimated:(BOOL)animated {
+  _wantsToBeHidden = YES;
+
+  if (animated) {
+    [self fhv_startDisplayLink];
+  } else {
+    // Add offscreen accumulation equal to this header view's size.
+    _shiftAccumulator = self.fhv_accumulatorMax;
+    [self fhv_commitAccumulatorToFrame];
+  }
+}
+
+- (void)setContentIsTranslucent:(BOOL)contentIsTranslucent {
+  _contentIsTranslucent = contentIsTranslucent;
+
+  // Translucent content means that the status bar shifter should not use snapshotting. Otherwise,
+  // stale visual content under the status bar region may be snapshotted.
+  _statusBarShifter.snapshottingEnabled = !contentIsTranslucent;
+}
+
+@end
+
+@implementation MDCFlexibleHeaderScrollViewInfo
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
new file mode 100644
index 0000000..c8f3fde
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h
@@ -0,0 +1,92 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCFlexibleHeaderView;
+@protocol MDCFlexibleHeaderViewLayoutDelegate;
+
+/**
+ The MDCFlexibleHeaderViewController controller is a simple UIViewController-oriented interface
+ for the flexible header view.
+
+ Note that for this view controller, self.view == self.headerView. This is because this view
+ controller is not meant to take up the full screen. Rather, it should be added as a child view
+ controller within another view controller.
+
+ ### UIScrollViewDelegate
+
+ Instances of this view controller implement the UIScrollViewDelegate methods that must be
+ forwarded to the flexible header view, so if you do not need to process the scroll view events
+ yourself you can set the header view controller instance as your scroll view delegate.
+
+ scrollView.delegate = headerViewController;
+ */
+@interface MDCFlexibleHeaderViewController
+    : UIViewController <UIScrollViewDelegate, UITableViewDelegate>
+
+/** The flexible header view instance that this controller manages. */
+@property(nonatomic, strong, nonnull, readonly) MDCFlexibleHeaderView *headerView;
+
+/** The layout delegate will be notified of any changes to the flexible header view's frame. */
+@property(nonatomic, weak, nullable) id<MDCFlexibleHeaderViewLayoutDelegate> layoutDelegate;
+
+#pragma mark UIViewController methods
+
+/**
+ Returns a Boolean indicating whether the status bar should be hidden or not.
+
+ Must be called by the parent view controller's -prefersStatusBarHidden implementation.
+ */
+- (BOOL)prefersStatusBarHidden;
+
+/**
+ Calculates the status bar style based on the header view's background color.
+
+ Light background colors use the default black status bar and dark background colors use the light
+ status bar. If the header view's background color is not fully-opaque, then this returns
+ UIStatusBarStyleDefault.
+ */
+- (UIStatusBarStyle)preferredStatusBarStyle;
+
+/**
+ Updates the topLayoutGuide to the correct position of a view controller paired with an instance of
+ MDCFlexibleHeaderViewController.
+
+ This method must be called in the |viewWillLayoutSubviews| method of view controller.
+ */
+- (void)updateTopLayoutGuide;
+
+@end
+
+/**
+ An object may conform to this protocol in order to receive layout change events caused by a
+ MDCFlexibleHeaderView.
+ */
+@protocol MDCFlexibleHeaderViewLayoutDelegate <NSObject>
+@required
+
+/**
+ Informs the receiver that the flexible header view's frame has changed.
+
+ The receiver should use the MDCFlexibleHeader scrollPhase APIs in order to react to the frame
+ changes.
+ */
+- (void)flexibleHeaderViewController:
+            (nonnull MDCFlexibleHeaderViewController *)flexibleHeaderViewController
+    flexibleHeaderViewFrameDidChange:(nonnull MDCFlexibleHeaderView *)flexibleHeaderView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m
new file mode 100644
index 0000000..cd2a237
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m
@@ -0,0 +1,250 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderViewController.h"
+
+#import "MDCFlexibleHeaderContainerViewController.h"
+#import "MDCFlexibleHeaderView.h"
+#import "MDFTextAccessibility.h"
+
+static inline BOOL ShouldUseLightStatusBarOnBackgroundColor(UIColor *color) {
+  if (CGColorGetAlpha(color.CGColor) < 1) {
+    return NO;
+  }
+
+  // We assume that the light iOS status text is white and not big enough to be considered "large"
+  // text according to the W3CAG 2.0 spec.
+  return [MDFTextAccessibility textColor:[UIColor whiteColor]
+                 passesOnBackgroundColor:color
+                                 options:MDFTextAccessibilityOptionsNone];
+}
+
+static NSString *const MDCFlexibleHeaderViewControllerHeaderViewKey =
+    @"MDCFlexibleHeaderViewControllerHeaderViewKey";
+static NSString *const MDCFlexibleHeaderViewControllerLayoutDelegateKey =
+    @"MDCFlexibleHeaderViewControllerLayoutDelegateKey";
+
+@interface MDCFlexibleHeaderViewController () <MDCFlexibleHeaderViewDelegate>
+
+/**
+ The current height offset of the flexible header controller with the addition of the current status
+ bar state at any given time.
+
+ This property is used to determine the bottom point of the |flexibleHeaderView| within the window.
+ */
+@property(nonatomic) CGFloat flexibleHeaderViewControllerHeightOffset;
+
+/**
+ The NSLayoutConstraint attached to the flexible header view controller's parentViewController's
+ topLayoutGuide.
+*/
+@property(nonatomic, weak) id topLayoutGuideTopConstraint;
+
+@end
+
+@implementation MDCFlexibleHeaderViewController
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
+  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+  if (self) {
+    [self commonMDCFlexibleHeaderViewControllerInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderViewControllerHeaderViewKey]) {
+      _headerView = [aDecoder decodeObjectForKey:MDCFlexibleHeaderViewControllerHeaderViewKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCFlexibleHeaderViewControllerLayoutDelegateKey]) {
+      _layoutDelegate =
+          [aDecoder decodeObjectForKey:MDCFlexibleHeaderViewControllerLayoutDelegateKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeObject:self.headerView forKey:MDCFlexibleHeaderViewControllerHeaderViewKey];
+  [aCoder encodeConditionalObject:self.layoutDelegate
+                           forKey:MDCFlexibleHeaderViewControllerLayoutDelegateKey];
+}
+
+- (void)commonMDCFlexibleHeaderViewControllerInit {
+  MDCFlexibleHeaderView *headerView =
+      [[MDCFlexibleHeaderView alloc] initWithFrame:[UIScreen mainScreen].bounds];
+  headerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  headerView.delegate = self;
+  _headerView = headerView;
+}
+
+- (void)loadView {
+  self.view = self.headerView;
+}
+
+- (void)willMoveToParentViewController:(UIViewController *)parent {
+  [super willMoveToParentViewController:parent];
+
+  parent.automaticallyAdjustsScrollViewInsets = NO;
+}
+
+- (void)didMoveToParentViewController:(UIViewController *)parent {
+  [super didMoveToParentViewController:parent];
+
+  // The header depends on the tracking scroll view to know how tall it should be.
+  // If there is no tracking scroll view then we have to poke the header into sizing itself.
+  if (!_headerView.trackingScrollView) {
+    [_headerView sizeToFit];
+  } else {
+    [_headerView trackingScrollViewDidScroll];
+  }
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+  [super viewWillAppear:animated];
+
+  for (NSLayoutConstraint *constraint in self.parentViewController.view.constraints) {
+    // Because topLayoutGuide is a readonly property on a viewController we must manipulate
+    // the present one via the NSLayoutConstraint attached to it. Thus we keep reference to it.
+    if (constraint.firstItem == self.parentViewController.topLayoutGuide &&
+        constraint.secondItem == nil) {
+      self.topLayoutGuideTopConstraint = constraint;
+    }
+  }
+
+  // On moving to parentViewController, we calculate the height
+  self.flexibleHeaderViewControllerHeightOffset = [self headerViewControllerHeight];
+
+#if DEBUG
+  NSAssert(![self.parentViewController.parentViewController
+               isKindOfClass:[MDCFlexibleHeaderContainerViewController class]],
+           @"An instance of %@ has been injected into a view controller (%@) that is already"
+           @" wrapped by an instance of %@ - this is not allowed and will cause double headers to"
+           @" appear. Choose to either wrap or inject your view controller (preferring injection"
+           @" where possible).",
+           NSStringFromClass([self class]), NSStringFromClass([self.parentViewController class]),
+           NSStringFromClass([MDCFlexibleHeaderContainerViewController class]));
+#endif
+}
+
+- (UIStatusBarStyle)preferredStatusBarStyle {
+  return (ShouldUseLightStatusBarOnBackgroundColor(_headerView.backgroundColor)
+              ? UIStatusBarStyleLightContent
+              : UIStatusBarStyleDefault);
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _headerView.prefersStatusBarHidden;
+}
+
+// Only include this logic when supporting pre-iOS 8 devices.
+#if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
+                                duration:(NSTimeInterval)duration {
+  [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
+
+  // Check if we're on iOS 8 and above and the new method will be called.
+  if (![UIViewController instancesRespondToSelector:@selector(viewWillTransitionToSize:
+                                                             withTransitionCoordinator:)]) {
+    [_headerView interfaceOrientationWillChange];
+  }
+}
+
+- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
+                                         duration:(NSTimeInterval)duration {
+  [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
+
+  // Check if we're on iOS 8 and above and the new method will be called.
+  if (![UIViewController instancesRespondToSelector:@selector(viewWillTransitionToSize:
+                                                             withTransitionCoordinator:)]) {
+    [_headerView interfaceOrientationIsChanging];
+  }
+}
+
+- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
+  [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
+
+  // Check if we're on iOS 8 and above and the new method will be called.
+  if (![UIViewController instancesRespondToSelector:@selector(viewWillTransitionToSize:
+                                                             withTransitionCoordinator:)]) {
+    [_headerView interfaceOrientationDidChange];
+  }
+}
+#endif  // #if !defined(__IPHONE_8_0) || (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0)
+
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewDidScroll];
+  }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewDidEndDecelerating];
+  }
+}
+
+- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewDidEndDraggingWillDecelerate:decelerate];
+  }
+}
+
+- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
+                     withVelocity:(CGPoint)velocity
+              targetContentOffset:(inout CGPoint *)targetContentOffset {
+  if (scrollView == _headerView.trackingScrollView) {
+    [_headerView trackingScrollViewWillEndDraggingWithVelocity:velocity
+                                           targetContentOffset:targetContentOffset];
+  }
+}
+
+- (void)updateTopLayoutGuide {
+  [self.topLayoutGuideTopConstraint setConstant:self.flexibleHeaderViewControllerHeightOffset];
+}
+
+- (CGFloat)headerViewControllerHeight {
+  CGFloat height =
+      MAX(_headerView.frame.origin.y + _headerView.frame.size.height,
+          _headerView.shiftBehavior == MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar ? 0 : 20);
+  return height;
+}
+
+#pragma mark MDCFlexibleHeaderViewDelegate
+
+- (void)flexibleHeaderViewNeedsStatusBarAppearanceUpdate:(MDCFlexibleHeaderView *)headerView {
+  [self setNeedsStatusBarAppearanceUpdate];
+}
+
+- (void)flexibleHeaderViewFrameDidChange:(MDCFlexibleHeaderView *)headerView {
+  // Whenever the flexibleHeaderView's frame changes, we update the value of the height offset
+  self.flexibleHeaderViewControllerHeightOffset = [self headerViewControllerHeight];
+
+  // We must change the constant of the constraint attached to our parentViewController's
+  // topLayoutGuide to trigger the re-layout of its subviews
+  [self.topLayoutGuideTopConstraint setConstant:self.flexibleHeaderViewControllerHeightOffset];
+
+  [self.layoutDelegate flexibleHeaderViewController:self
+                   flexibleHeaderViewFrameDidChange:headerView];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
new file mode 100644
index 0000000..f8c3ca7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/MaterialFlexibleHeader.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFlexibleHeaderContainerViewController.h"
+#import "MDCFlexibleHeaderView.h"
+#import "MDCFlexibleHeaderViewController.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h
new file mode 100644
index 0000000..964040e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.h
@@ -0,0 +1,109 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCStatusBarShifterDelegate;
+
+/**
+ The status bar shifter is responsible for the management of the status bar's offset as a header
+ view is shifting off-screen.
+
+ This class is not intended to be subclassed.
+ */
+@interface MDCStatusBarShifter : NSObject
+
+#pragma mark Shifting the status bar
+
+/**
+ Provides the status bar shifter with the current desired y offset of the status bar.
+
+ A value of 0 means the status bar is unshifted. Values > 0 shift the status bar by that amount
+ off-screen. Negative values are treated as zero.
+ */
+- (void)setOffset:(CGFloat)offset;
+
+#pragma mark Configuring behavior
+
+/**
+ Whether or not the status bar shifter is enabled.
+
+ If the status bar shifter is disabled midway through shifting the status bar then the shifter
+ will move the status bar to a reasonable location.
+ */
+@property(nonatomic, getter=isEnabled) BOOL enabled;
+
+/**
+ A Boolean value indicating whether this class should use snapshotting when rendering the status
+ bar shift.
+
+ Defaults to YES.
+ */
+@property(nonatomic, getter=isSnapshottingEnabled) BOOL snapshottingEnabled;
+
+#pragma mark Responding to state changes
+
+@property(nonatomic, weak) id<MDCStatusBarShifterDelegate> delegate;
+
+#pragma mark Introspection
+
+/**
+ A Boolean value indicating whether the receiver is able to shift the status bar.
+
+ There are certain scenarios where the status bar shifter won't try to adjust the frame of the
+ status bar. For example, if the status bar is showing the tap-to-return-to-call effect. In these
+ cases this method returns NO.
+ */
+- (BOOL)canUpdateStatusBarFrame;
+
+#pragma mark UIViewController events
+
+/**
+ A Boolean value indicating whether the true status bar should be hidden.
+
+ The implementor of MDCStatusBarShifterDelegate should use this to inform UIKit of the expected
+ status bar visibility via UIViewController::prefersStatusBarHidden.
+ */
+- (BOOL)prefersStatusBarHidden;
+
+/** Must be called when the owning UIViewController's interface orientation is about to change. */
+- (void)interfaceOrientationWillChange;
+
+/** Must be called when the owning UIViewController's interface orientation has changed. */
+- (void)interfaceOrientationDidChange;
+
+@end
+
+/**
+ The MDCStatusBarShifterDelegate protocol allows a delegate to react to changes in the status bar
+ shifter's state.
+ */
+@protocol MDCStatusBarShifterDelegate <NSObject>
+@required
+
+/** Informs the receiver that the preferred status bar visibility has changed. */
+- (void)statusBarShifterNeedsStatusBarAppearanceUpdate:(MDCStatusBarShifter *)statusBarShifter;
+
+/**
+ Informs the receiver that a snapshot view would like to be added to a view hierarchy.
+
+ The receiver is expected to add `view` as a subview. The superview should be shifting off-screen,
+ which will cause the snapshot view to shift off-screen as well.
+ */
+- (void)statusBarShifter:(MDCStatusBarShifter *)statusBarShifter
+    wantsSnapshotViewAdded:(UIView *)view;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.m
new file mode 100644
index 0000000..2383755
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/FlexibleHeader/src/private/MDCStatusBarShifter.m
@@ -0,0 +1,263 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCStatusBarShifter.h"
+
+#import "UIApplication+AppExtensions.h"
+
+static CGFloat kStatusBarExpectedHeight = 20;
+static NSTimeInterval kStatusBarBecomesInvalidAnimationDuration = 0.2;
+
+// If the time changes then we need to invalidate the status bar.
+// This value is the minimum amount of time we'll wait before invalidating the status bar even
+// after the time has changed in an effort to minimize flickering.
+static NSTimeInterval kMinimumNumberOfSecondsToWaitFor = 3;
+
+// Simple state machine for the shifter:
+//          IsReal => IsSnapshot
+//      IsSnapshot => IsReal, InvalidSnapshot
+// InvalidSnapshot => IsReal
+//
+// In other words, once a snapshot becomes invalid it must go through the real state before it can
+// become a snapshot again.
+//
+// The bulk of this state machine is represented in attemptSnapshotState:
+
+typedef NS_ENUM(NSInteger, MDCStatusBarShifterState) {
+  MDCStatusBarShifterStateRealStatusBar,
+  MDCStatusBarShifterStateIsSnapshot,
+  MDCStatusBarShifterStateInvalidSnapshot,
+};
+
+@implementation MDCStatusBarShifter {
+  UIView *_statusBarReplicaView;
+
+  // ivars that can invalidate the status bar
+  CGRect _originalStatusBarFrame;
+  NSTimeInterval _replicaViewTimestamp;
+  NSTimeInterval _secondsRemainingInMinute;
+  NSTimer *_replicaInvalidatorTimer;
+
+  // While our snapshot is invalid we have slightly different status bar visibility.
+  BOOL _prefersStatusBarHiddenWhileInvalid;
+
+  BOOL _prefersStatusBarHidden;
+  MDCStatusBarShifterState _snapshotState;
+}
+
+- (void)dealloc {
+  [_replicaInvalidatorTimer invalidate];
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _enabled = YES;
+    _snapshottingEnabled = YES;
+  }
+  return self;
+}
+
+#pragma mark - Private
+
+// Moves to the invalid state with a status bar animation.
+- (void)invalidateSnapshot {
+  [UIView animateWithDuration:kStatusBarBecomesInvalidAnimationDuration
+                   animations:^{
+                     [self attemptSnapshotState:MDCStatusBarShifterStateInvalidSnapshot];
+                   }];
+}
+
+// Conditions in which the status bar should be invalidated.
+- (BOOL)shouldInvalidateSnapshot {
+  // Frames don't match up
+  if (!CGRectEqualToRect(_statusBarReplicaView.frame, _originalStatusBarFrame)) {
+    return YES;
+  }
+
+  // The time has changed
+  if (([NSDate timeIntervalSinceReferenceDate] - _replicaViewTimestamp) >
+      _secondsRemainingInMinute) {
+    return YES;
+  }
+
+  return NO;
+}
+
+// May not necessarily end in the given state.
+- (void)attemptSnapshotState:(MDCStatusBarShifterState)snapshotState {
+  if (_snapshotState == snapshotState) {
+    // It's likely too good to be true that we're able to stay in the snapshot state, so let's see
+    // if we can invalidate the snapshot in any way.
+    if (_snapshotState == MDCStatusBarShifterStateIsSnapshot && [self shouldInvalidateSnapshot]) {
+      // Frame has become invalid - kill the snapshot.
+      [self invalidateSnapshot];
+    }
+    return;
+  }
+
+  // Don't allow changing from invalid to snapshot without going through "real" first.
+  if (_snapshotState == MDCStatusBarShifterStateInvalidSnapshot &&
+      snapshotState == MDCStatusBarShifterStateIsSnapshot) {
+    return;
+  }
+
+  // Can't go from real => invalid
+  if (_snapshotState == MDCStatusBarShifterStateRealStatusBar &&
+      snapshotState == MDCStatusBarShifterStateInvalidSnapshot) {
+    return;
+  }
+
+  // While disabled, can't leave the real status bar state.
+  if (!_enabled && _snapshotState == MDCStatusBarShifterStateRealStatusBar) {
+    return;
+  }
+
+  // If snapshotting is disabled, then can't go from real => snapshot, but must jump to invalid
+  // state.
+  if (!_snapshottingEnabled && _snapshotState == MDCStatusBarShifterStateRealStatusBar &&
+      snapshotState == MDCStatusBarShifterStateIsSnapshot) {
+    snapshotState = MDCStatusBarShifterStateInvalidSnapshot;
+  }
+
+  [_replicaInvalidatorTimer invalidate];
+
+  _snapshotState = snapshotState;
+
+  // React to changing the state
+  switch (_snapshotState) {
+    case MDCStatusBarShifterStateRealStatusBar: {
+      // Now showing the real status bar. Remove the replica.
+      [_statusBarReplicaView removeFromSuperview];
+      _statusBarReplicaView = nil;
+      self.prefersStatusBarHidden = NO;
+      break;
+    }
+    case MDCStatusBarShifterStateInvalidSnapshot: {
+      // Snapshot is now invalid, show the real status bar.
+      [_statusBarReplicaView removeFromSuperview];
+      _statusBarReplicaView = nil;
+      self.prefersStatusBarHidden = _prefersStatusBarHiddenWhileInvalid;
+      break;
+    }
+    case MDCStatusBarShifterStateIsSnapshot: {
+      // Take a snapshot of the status bar.
+      UIView *snapshotView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
+      UIView *clippingView = [[UIView alloc] init];
+      clippingView.frame =
+          CGRectMake(0, 0, snapshotView.frame.size.width, kStatusBarExpectedHeight);
+      clippingView.autoresizingMask =
+          (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin);
+      clippingView.clipsToBounds = YES;
+      [clippingView addSubview:snapshotView];
+      [self.delegate statusBarShifter:self wantsSnapshotViewAdded:clippingView];
+
+      _statusBarReplicaView = clippingView;
+      _originalStatusBarFrame = clippingView.frame;
+      _replicaViewTimestamp = [NSDate timeIntervalSinceReferenceDate];
+
+      NSCalendar *calendar = [NSCalendar currentCalendar];
+      NSDateComponents *components =
+          [calendar components:NSCalendarUnitSecond fromDate:[NSDate date]];
+      _secondsRemainingInMinute =
+          MAX(kMinimumNumberOfSecondsToWaitFor, (NSTimeInterval)(60 - components.second));
+
+      _replicaInvalidatorTimer = [NSTimer timerWithTimeInterval:_secondsRemainingInMinute
+                                                         target:self
+                                                       selector:@selector(invalidateSnapshot)
+                                                       userInfo:nil
+                                                        repeats:NO];
+      [[NSRunLoop currentRunLoop] addTimer:_replicaInvalidatorTimer forMode:NSRunLoopCommonModes];
+
+      self.prefersStatusBarHidden = YES;
+      break;
+    }
+  }
+}
+
+- (void)setPrefersStatusBarHidden:(BOOL)prefersStatusBarHidden {
+  if (_prefersStatusBarHidden == prefersStatusBarHidden) {
+    return;
+  }
+
+  _prefersStatusBarHidden = prefersStatusBarHidden;
+
+  [self.delegate statusBarShifterNeedsStatusBarAppearanceUpdate:self];
+}
+
+#pragma mark - Public
+
+- (void)setOffset:(CGFloat)offset {
+  if (![self canUpdateStatusBarFrame]) {
+    return;
+  }
+
+  // Bound the status bar range to [0...kStatusBarExpectedHeight].
+  CGFloat statusOffsetY = MIN(kStatusBarExpectedHeight, offset);
+
+  // Adjust the frame of the status bar.
+  if (statusOffsetY > 0) {
+    _prefersStatusBarHiddenWhileInvalid = statusOffsetY >= kStatusBarExpectedHeight;
+
+    if (_snapshotState == MDCStatusBarShifterStateInvalidSnapshot) {
+      // If we're in an invalid state then we have to manage the visibility directly.
+      [UIView animateWithDuration:kStatusBarBecomesInvalidAnimationDuration
+                       animations:^{
+                         self.prefersStatusBarHidden = _prefersStatusBarHiddenWhileInvalid;
+                       }];
+
+    } else {
+      [self attemptSnapshotState:MDCStatusBarShifterStateIsSnapshot];
+    }
+  } else {
+    [self attemptSnapshotState:MDCStatusBarShifterStateRealStatusBar];
+  }
+}
+
+- (void)setEnabled:(BOOL)enabled {
+  if (_enabled == enabled) {
+    return;
+  }
+  _enabled = enabled;
+
+  if (!_enabled) {
+    [UIView animateWithDuration:kStatusBarBecomesInvalidAnimationDuration
+                     animations:^{
+                       [self attemptSnapshotState:MDCStatusBarShifterStateRealStatusBar];
+                     }];
+  }
+}
+
+- (BOOL)canUpdateStatusBarFrame {
+  CGRect statusBarFrame = [[UIApplication mdc_safeSharedApplication] statusBarFrame];
+  CGFloat statusBarHeight = MIN(statusBarFrame.size.width, statusBarFrame.size.height);
+  return ((statusBarHeight == kStatusBarExpectedHeight) || _statusBarReplicaView ||
+          _snapshotState == MDCStatusBarShifterStateInvalidSnapshot);
+}
+
+- (BOOL)prefersStatusBarHidden {
+  return _prefersStatusBarHidden;
+}
+
+- (void)interfaceOrientationWillChange {
+  _statusBarReplicaView.hidden = YES;
+}
+
+- (void)interfaceOrientationDidChange {
+  _statusBarReplicaView.hidden = NO;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
new file mode 100644
index 0000000..e749c70
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.h
@@ -0,0 +1,54 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ The MDCHeaderStackView class lays out a vertical stack of two views.
+
+ Both bars provided to this view must implement sizeThatFits and return their best-fit
+ dimensions.
+
+ # Layout Behavior
+
+ The layout behavior of the two bars is as follows:
+
+ topBar: top aligned, expands to fill all available vertical space not taken up by the bottomBar.
+ bottomBar: bottom aligned.
+
+ If no bottomBar is provided, top bar consumes the entire bounds of the stack view.
+
+ When resized, the top bar will shrink until it reaches its sizeThatFits dimensions.
+ If there is a bottom bar, then at this point the top bar will begin sliding off the top.
+ If there is no bottom bar, then at this point the top bar will stay put.
+
+ At no point in time will either the top or bottom bar shrink below their sizeThatFits height.
+
+ # sizeThatFits Behavior
+
+ sizeThatFits returns the fitted height for bottom bar if available, otherwise it returns the
+ fitted height for topBar. The width will be whatever width was provided.
+ */
+IB_DESIGNABLE
+@interface MDCHeaderStackView : UIView
+
+/** The top bar. Top aligned and vertically expands. */
+@property(nonatomic, strong, nullable) UIView *topBar;
+
+/** The bottom bar. Bottom aligned. */
+@property(nonatomic, strong, nullable) UIView *bottomBar;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.m
new file mode 100644
index 0000000..23cc13a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MDCHeaderStackView.m
@@ -0,0 +1,112 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCHeaderStackView.h"
+
+static NSString *const MDCHeaderStackViewTopBarKey = @"MDCHeaderStackViewTopBarKey";
+static NSString *const MDCHeaderStackViewBottomBarKey = @"MDCHeaderStackViewBottomBarKey";
+
+@implementation MDCHeaderStackView
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCHeaderStackViewTopBarKey]) {
+      _topBar = [aDecoder decodeObjectForKey:MDCHeaderStackViewTopBarKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCHeaderStackViewBottomBarKey]) {
+      _bottomBar = [aDecoder decodeObjectForKey:MDCHeaderStackViewBottomBarKey];
+    }
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  if (self.topBar) {
+    [aCoder encodeObject:self.topBar forKey:MDCHeaderStackViewTopBarKey];
+  }
+  if (self.bottomBar) {
+    [aCoder encodeObject:self.bottomBar forKey:MDCHeaderStackViewBottomBarKey];
+  }
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  if (_bottomBar) {
+    size.height = [_bottomBar sizeThatFits:size].height;
+  } else {
+    size.height = [_topBar sizeThatFits:size].height;
+  }
+  return size;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  CGSize boundsSize = self.bounds.size;
+
+  CGSize topBarSize = [_topBar sizeThatFits:boundsSize];
+  CGSize bottomBarSize = [_bottomBar sizeThatFits:boundsSize];
+
+  CGFloat remainingHeight = boundsSize.height - topBarSize.height - bottomBarSize.height;
+
+  CGRect topBarFrame = CGRectMake(0, 0, topBarSize.width, topBarSize.height);
+  CGRect bottomBarFrame = CGRectMake(0, 0, bottomBarSize.width, bottomBarSize.height);
+
+  if (remainingHeight > 0) {
+    // Expand the top bar to fill the remaining height.
+    topBarFrame.size.height += remainingHeight;
+
+  } else if (remainingHeight < 0) {
+    // Negative value causes the top bar to slide up and away.
+    topBarFrame.origin.y += remainingHeight;
+  }
+  bottomBarFrame.origin.y = CGRectGetMaxY(topBarFrame);
+
+  _topBar.frame = topBarFrame;
+  _bottomBar.frame = bottomBarFrame;
+}
+
+#pragma mark - Public
+
+- (void)setTopBar:(UIView *)topBar {
+  if (_topBar == topBar) {
+    return;
+  }
+
+  [_topBar removeFromSuperview];
+
+  _topBar = topBar;
+
+  [self addSubview:_topBar];
+  [self setNeedsLayout];
+}
+
+- (void)setBottomBar:(UIView *)bottomBar {
+  if (_bottomBar == bottomBar) {
+    return;
+  }
+
+  [_bottomBar removeFromSuperview];
+
+  _bottomBar = bottomBar;
+
+  [self addSubview:_bottomBar];
+  [self setNeedsLayout];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
new file mode 100644
index 0000000..ee74066
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/HeaderStackView/src/MaterialHeaderStackView.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCHeaderStackView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
new file mode 100644
index 0000000..93c0c19
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.h
@@ -0,0 +1,61 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Custom gesture recognizer to observe the various ink response states.
+
+ MDCInkGestureRecognizer is a continuous recognizer that tracks single touches and optionally
+ fails if the touch moves outside the recongizer's view. Multiple touches will cause the
+ recognizer to transition to the UIGestureRecognizerStateCancelled state.
+ */
+@interface MDCInkGestureRecognizer : UIGestureRecognizer
+
+/**
+ Set the distance that causes the recognizer to cancel.
+ */
+@property(nonatomic, assign) CGFloat dragCancelDistance;
+
+/**
+ Set when dragging outside of the view causes the gesture recognizer to cancel.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL cancelOnDragOut;
+
+/**
+ Bounds inside of which the recognizer will recognize ink gestures, relative to self.view.frame.
+
+ If set to CGRectNull (the default), then the recognizer will use self.view.bounds as the target
+ bounds.
+
+ If cancelOnDragOut is YES and the user's touch moves beyond the target bounds inflated by
+ dragCancelDistance then the gesture is cancelled.
+ */
+@property(nonatomic) CGRect targetBounds;
+
+/**
+ Returns the point where the ink starts spreading from.
+
+ @param view View which the point is relative to.
+ */
+- (CGPoint)touchStartLocationInView:(UIView *)view;
+
+/** Returns YES if the touch's current location is still within the target bounds. */
+- (BOOL)isTouchWithinTargetBounds;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.m
new file mode 100644
index 0000000..cb51392
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkGestureRecognizer.m
@@ -0,0 +1,96 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkGestureRecognizer.h"
+
+#import <UIKit/UIGestureRecognizerSubclass.h>
+
+static const CGFloat kInkGestureDefaultDragCancelDistance = 20;
+
+@implementation MDCInkGestureRecognizer {
+  CGPoint _touchStartLocation;
+  CGPoint _touchCurrentLocation;
+  BOOL _cancelOnDragOut;
+}
+
+- (instancetype)initWithTarget:(id)target action:(SEL)action {
+  self = [super initWithTarget:target action:action];
+  if (self) {
+    _cancelOnDragOut = YES;
+    _dragCancelDistance = kInkGestureDefaultDragCancelDistance;
+    _targetBounds = CGRectNull;
+    self.cancelsTouchesInView = NO;
+    self.delaysTouchesEnded = NO;
+  }
+  return self;
+}
+
+- (CGPoint)touchStartLocationInView:(UIView *)view {
+  return [view convertPoint:_touchStartLocation fromView:nil];
+}
+
+- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesBegan:touches withEvent:event];
+  if ([touches count] == 1) {
+    self.state = UIGestureRecognizerStateBegan;
+    _touchStartLocation = [[touches anyObject] locationInView:nil];
+    _touchCurrentLocation = _touchStartLocation;
+  } else {
+    self.state = UIGestureRecognizerStateCancelled;
+  }
+}
+
+- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesMoved:touches withEvent:event];
+  if (self.state == UIGestureRecognizerStateFailed) {
+    return;
+  }
+
+  _touchCurrentLocation = [[touches anyObject] locationInView:nil];
+
+  // Cancel the gesture if it is too far away.
+  if (_cancelOnDragOut && ![self isTouchWithinTargetBounds]) {
+    self.state = UIGestureRecognizerStateCancelled;
+  } else {
+    self.state = UIGestureRecognizerStateChanged;
+  }
+}
+
+- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesEnded:touches withEvent:event];
+  self.state = UIGestureRecognizerStateEnded;
+}
+
+- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
+  [super touchesCancelled:touches withEvent:event];
+  self.state = UIGestureRecognizerStateCancelled;
+}
+
+- (BOOL)isTouchWithinTargetBounds {
+  CGRect targetBounds = [self effectiveTargetBounds];
+  CGRect boundsInWindowCoord = [self.view convertRect:targetBounds toView:nil];
+  boundsInWindowCoord =
+      CGRectInset(boundsInWindowCoord, -_dragCancelDistance, -_dragCancelDistance);
+  return CGRectContainsPoint(boundsInWindowCoord, _touchCurrentLocation);
+}
+
+#pragma mark - Private methods
+
+- (CGRect)effectiveTargetBounds {
+  return CGRectEqualToRect(_targetBounds, CGRectNull) ? self.view.bounds : _targetBounds;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.h
new file mode 100644
index 0000000..100935f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.h
@@ -0,0 +1,186 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCInkGestureRecognizer.h"
+
+@class MDCInkTouchController;
+@class MDCInkView;
+@protocol MDCInkTouchControllerDelegate;
+
+/**
+ MDCInkTouchController associates a MDCInkView with a UIGestureRecognizer to control the spread of
+ the ink.
+
+ Subclasses should avoid overriding the UIGestureRecognizerDelegate gestureRecognizerShouldBegin:
+ and gestureRecognizer:shouldReceiveTouch: methods to avoid breaking
+ MDCInkTouchControllerDelegate.
+
+ **NOTE:** The controller does not keep a strong reference to the view to which it is attaching an
+ ink view.
+ It is expected that the view will keep a strong reference to its own ink controller, or that the
+ view controller controlling the view will keep a strong reference to that view's ink controller.
+ */
+@interface MDCInkTouchController : NSObject <UIGestureRecognizerDelegate>
+
+/** Weak reference to the view that responds to touch events. */
+@property(nonatomic, weak, readonly, nullable) UIView *view;
+
+/**
+ The ink view for clients who do not create their own ink views via the delegate.
+ */
+@property(nonatomic, strong, readonly, nonnull) MDCInkView *defaultInkView;
+
+/** Delegate to extend the behavior of the touch control. */
+@property(nonatomic, weak, nullable) id<MDCInkTouchControllerDelegate> delegate;
+
+/** If YES, the gesture recognizer should delay the start of ink spread. Default is NO. */
+@property(nonatomic, assign) BOOL delaysInkSpread;
+
+/** The distance that causes the recognizer to cancel. Defaults to 20pt. */
+@property(nonatomic, assign) CGFloat dragCancelDistance;
+
+/**
+ Whether dragging outside of the view causes the gesture recognizer to cancel.
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL cancelsOnDragOut;
+
+/**
+ Bounds inside of which the recognizer will recognize ink gestures, relative to self.view.frame.
+
+ If set to CGRectNull (the default), then the recognizer will use self.view.bounds as the target
+ bounds.
+
+ If cancelsOnDragOut is YES and the user's touch moves beyond the target bounds inflated by
+ dragCancelDistance then the gesture is cancelled.
+ */
+@property(nonatomic) CGRect targetBounds;
+
+/** Gesture recognizer used to bind touch events to ink. */
+@property(nonatomic, strong, readonly, nonnull) MDCInkGestureRecognizer *gestureRecognizer;
+
+/** Unavailable, please use initWithView: instead. */
+- (nonnull instancetype)init NS_UNAVAILABLE;
+
+/**
+ Initializes the controller.
+
+ @param view View that responds to touch events for ink.
+ */
+- (nonnull instancetype)initWithView:(nonnull UIView *)view NS_DESIGNATED_INITIALIZER;
+
+/**
+ When called the @c defaultInkView is added to the @c view.
+
+ This method is a no-op when the delegate conforms to @c inkTouchController:inkViewAtTouchLocation:
+ because this is how a client specifies a custom ink view.
+
+ If you want to specify a specific z-index order for your inkView please conform to
+ @c inkTouchController:insertInkView:intoView: and do so there.
+ */
+- (void)addInkView;
+
+/**
+ Cancels all touch processing and dissipates the ink.
+
+ This is useful if your application needs to remove the ink on scrolling, when preparing a view
+ for reuse, etc.
+ */
+- (void)cancelInkTouchProcessing;
+
+/**
+ Returns the ink view at a particular touch location.
+
+ If the delegate responds to @c inkTouchController:inkViewAtLocation: then this method queries it.
+ Otherwise, if @c addInkView has been called and @c location is in the bounds of
+ @c self.defaultView, then that view is returned. If none of these conditions are met, @c nil is
+ returned.
+
+ @param location The query location in the coordinates of @c self.view.
+ @return The ink view at the touch location, or nil.
+*/
+- (MDCInkView *_Nullable)inkViewAtTouchLocation:(CGPoint)location;
+
+@end
+
+/** Delegate methods for MDCInkTouchController. */
+@protocol MDCInkTouchControllerDelegate <NSObject>
+@optional
+
+/**
+ Inserts the ink view into the given view.
+
+ If this method is not implemented, the ink view is added as a subview of the view when the
+ controller's addInkView method is called. Delegates can choose to insert the ink view below the
+ contents as a background view. When inkTouchController:inkViewAtTouchLocation is implemented
+ this method will not be invoked.
+
+ @param inkTouchController The ink touch controller.
+ @param inkView The ink view.
+ @param view The view to add the ink view to.
+ */
+- (void)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+             insertInkView:(nonnull UIView *)inkView
+                  intoView:(nonnull UIView *)view;
+
+/**
+ Returns the ink view to use for a touch located at location in inkTouchController.view.
+
+ If the delegate implements this method, the controller will not create an ink view of its own and
+ inkTouchController:insertInkView:intoView: will not be called. This method allows the delegate
+ to control the creation and reuse of ink views.
+
+ @param inkTouchController The ink touch controller.
+ @param location The touch location in the coords of @c inkTouchController.view.
+ @return An ink view to use at the touch location.
+ */
+- (nullable MDCInkView *)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+                     inkViewAtTouchLocation:(CGPoint)location;
+
+/**
+ Controls whether the ink touch controller should be processing touches.
+
+ The touch controller will query this method to determine if it should start or continue to
+ process touches controlling the ink. Returning NO at the start of a gesture will prevent any ink
+ from being displayed, and returning NO in the middle of a gesture will cancel that gesture and
+ evaporate the ink.
+
+ If not implemented then YES is assumed.
+
+ @param inkTouchController The ink touch controller.
+ @param location The touch location relative to the inkTouchController view.
+ @return YES if the controller should process touches at @c location.
+
+ @see cancelInkTouchProcessing
+ */
+- (BOOL)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+    shouldProcessInkTouchesAtTouchLocation:(CGPoint)location;
+
+/**
+ Notifies the receiver that the ink touch controller did process an ink view at the
+ touch location.
+
+ @param inkTouchController The ink touch controller.
+ @param inkView The ink view.
+ @param location The touch location relative to the inkTouchController superView.
+ */
+- (void)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+         didProcessInkView:(nonnull MDCInkView *)inkView
+           atTouchLocation:(CGPoint)location;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.m
new file mode 100644
index 0000000..66f5315
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkTouchController.m
@@ -0,0 +1,232 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkTouchController.h"
+
+#import "MDCInkView.h"
+
+static const NSTimeInterval kInkTouchDelayInterval = 0.1;
+
+@interface MDCInkTouchController ()
+@property(nonatomic, strong) MDCInkView *addedInkView;
+@property(nonatomic, strong) MDCInkView *defaultInkView;
+@property(nonatomic, assign) BOOL shouldRespondToTouch;
+@property(nonatomic, assign) CGPoint previousLocation;
+@end
+
+@protocol MDCInkTouchControllerLegacyDelegate <NSObject>
+@optional
+
+/**
+ This protocol is private and declares an old method signature that will be removed once legacy code
+ has been migrated to the new delegate protocol.
+ */
+- (BOOL)shouldInkTouchControllerProcessInkTouches:
+        (nonnull MDCInkTouchController *)inkTouchController
+    __deprecated_msg("shouldInkTouchControllerProcessInkTouches has been replaced with "
+                     "inkTouchController:shouldProcessInkTouchesAtTouchLocation.");
+
+@end
+
+@implementation MDCInkTouchController
+
+- (CGFloat)dragCancelDistance {
+  return _gestureRecognizer.dragCancelDistance;
+}
+
+- (void)setDragCancelDistance:(CGFloat)dragCancelDistance {
+  _gestureRecognizer.dragCancelDistance = dragCancelDistance;
+}
+
+- (BOOL)cancelsOnDragOut {
+  return _gestureRecognizer.cancelOnDragOut;
+}
+
+- (void)setCancelsOnDragOut:(BOOL)cancelsOnDragOut {
+  _gestureRecognizer.cancelOnDragOut = cancelsOnDragOut;
+}
+
+- (CGRect)targetBounds {
+  return _gestureRecognizer.targetBounds;
+}
+
+- (void)setTargetBounds:(CGRect)targetBounds {
+  _gestureRecognizer.targetBounds = targetBounds;
+}
+
+- (instancetype)initWithView:(UIView *)view {
+  self = [super init];
+  if (self) {
+    _gestureRecognizer =
+        [[MDCInkGestureRecognizer alloc] initWithTarget:self action:@selector(handleInkGesture:)];
+    _gestureRecognizer.delegate = self;
+
+    _view = view;
+    [_view addGestureRecognizer:_gestureRecognizer];
+
+    _defaultInkView = [[MDCInkView alloc] initWithFrame:view.bounds];
+    _defaultInkView.inkColor = _defaultInkView.defaultInkColor;
+    _defaultInkView.autoresizingMask =
+        UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [_view removeGestureRecognizer:_gestureRecognizer];
+  _gestureRecognizer.delegate = nil;
+}
+
+- (void)addInkView {
+  if (![_delegate respondsToSelector:@selector(inkTouchController:inkViewAtTouchLocation:)]) {
+    _addedInkView = _defaultInkView;
+
+    if ([_delegate respondsToSelector:@selector(inkTouchController:insertInkView:intoView:)]) {
+      [_delegate inkTouchController:self insertInkView:_addedInkView intoView:_view];
+    } else {
+      [_view addSubview:_addedInkView];
+    }
+  }
+}
+
+- (void)cancelInkTouchProcessing {
+  [_addedInkView cancelAllAnimationsAnimated:YES];
+}
+
+- (MDCInkView *_Nullable)inkViewAtTouchLocation:(CGPoint)location {
+  MDCInkView *inkView;
+  if ([_delegate respondsToSelector:@selector(inkTouchController:inkViewAtTouchLocation:)]) {
+    inkView = [_delegate inkTouchController:self inkViewAtTouchLocation:location];
+  } else {
+    CGPoint locationInInkCoords = [self.view convertPoint:location toView:_addedInkView];
+    if ([_addedInkView pointInside:locationInInkCoords withEvent:nil]) {
+      inkView = _addedInkView;
+    }
+  }
+  return inkView;
+}
+
+- (void)handleInkGesture:(MDCInkGestureRecognizer *)recognizer {
+  CGPoint touchLocation = [recognizer locationInView:_view];
+
+  switch (recognizer.state) {
+    case UIGestureRecognizerStateBegan: {
+      if ([_delegate respondsToSelector:@selector(inkTouchController:inkViewAtTouchLocation:)]) {
+        _addedInkView = [_delegate inkTouchController:self inkViewAtTouchLocation:touchLocation];
+        if (!_addedInkView) {
+          return [self cancelInkGestureWithRecognizer:recognizer];
+        }
+        NSAssert([_addedInkView isDescendantOfView:_view],
+                 @"Ink view %@ returned by inkTouchController:inkViewAtTouchLocation: must be a "
+                  "subview of base view %@",
+                 _addedInkView, _view);
+        recognizer.targetBounds = [_addedInkView convertRect:_addedInkView.bounds toView:_view];
+      }
+
+      _shouldRespondToTouch = YES;
+      dispatch_time_t delayTime =
+          dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC * kInkTouchDelayInterval));
+      dispatch_after(_delaysInkSpread ? delayTime : 0, dispatch_get_main_queue(), ^(void) {
+        [self touchBeganAtPoint:[recognizer locationInView:_addedInkView]
+                  touchLocation:touchLocation];
+      });
+      break;
+    }
+    case UIGestureRecognizerStatePossible:  // Ignored
+      break;
+    case UIGestureRecognizerStateChanged: {
+      // Due to changes on iPhone 6s, possibly due to the force touch,
+      // @c UIGestureRecognizerStateChanged constantly fires. However, we do not want to cancel the
+      // ink unless the users moves.
+      if (_shouldRespondToTouch && !CGPointEqualToPoint(touchLocation, _previousLocation)) {
+        _shouldRespondToTouch = NO;
+      }
+      break;
+    }
+    case UIGestureRecognizerStateCancelled:
+      [_addedInkView cancelAllAnimationsAnimated:YES];
+      _shouldRespondToTouch = NO;
+      break;
+    case UIGestureRecognizerStateRecognized:
+      [_addedInkView startTouchEndedAnimationAtPoint:touchLocation completion:nil];
+      _shouldRespondToTouch = NO;
+      break;
+    case UIGestureRecognizerStateFailed:
+      [_addedInkView cancelAllAnimationsAnimated:YES];
+      _shouldRespondToTouch = NO;
+      break;
+  }
+
+  if (_shouldRespondToTouch) {
+    _previousLocation = touchLocation;
+  } else {
+    _previousLocation = CGPointZero;
+  }
+}
+
+- (void)cancelInkGestureWithRecognizer:(MDCInkGestureRecognizer *)recognizer {
+  // To exit, disable the recognizer immediately which forces it to drop out of the current
+  // loop and prevent any state updates. Then re-enable to allow future gesture recognition.
+  recognizer.enabled = NO;
+  recognizer.enabled = YES;
+}
+
+- (void)touchBeganAtPoint:(CGPoint)point touchLocation:(CGPoint)touchLocation {
+  if (_shouldRespondToTouch) {
+    [_addedInkView startTouchBeganAnimationAtPoint:point completion:nil];
+    if ([_delegate
+            respondsToSelector:@selector(inkTouchController:didProcessInkView:atTouchLocation:)]) {
+      [_delegate inkTouchController:self
+                  didProcessInkView:_addedInkView
+                    atTouchLocation:touchLocation];
+    }
+    _shouldRespondToTouch = NO;
+  }
+}
+
+#pragma mark - UIGestureRecognizerDelegate
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+    shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)other {
+  // Subclasses can override this to prioritize another recognizer.
+  return YES;
+}
+
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
+  if ([_delegate respondsToSelector:@selector(inkTouchController:
+                                        shouldProcessInkTouchesAtTouchLocation:)]) {
+    CGPoint touchLocation = [gestureRecognizer locationInView:_view];
+    return [_delegate inkTouchController:self shouldProcessInkTouchesAtTouchLocation:touchLocation];
+  } else if ([_delegate respondsToSelector:@selector(shouldInkTouchControllerProcessInkTouches:)]) {
+    // Please use inkTouchController:shouldProcessInkTouchesAtTouchLocation. The delegate call below
+    // is deprecated and only provided for legacy support.
+    id<MDCInkTouchControllerLegacyDelegate> legacyDelegate =
+        (id<MDCInkTouchControllerLegacyDelegate>)_delegate;
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    return [legacyDelegate shouldInkTouchControllerProcessInkTouches:self];
+#pragma clang diagnostic pop
+  }
+  return YES;
+}
+
+#pragma mark - Deprecations
+
+- (MDCInkView *)inkView {
+  return _defaultInkView;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkView.h
new file mode 100644
index 0000000..6bb87fa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkView.h
@@ -0,0 +1,111 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Completion block signature for all ink animations. */
+typedef void (^MDCInkCompletionBlock)();
+
+/** Ink styles. */
+typedef NS_ENUM(NSInteger, MDCInkStyle) {
+  MDCInkStyleBounded,  /** Ink is clipped to the view's bounds. */
+  MDCInkStyleUnbounded /** Ink is not clipped to the view's bounds. */
+};
+
+/**
+ A UIView that draws and animates the Material Design ink effect for touch interactions.
+
+ There are two kinds of ink:
+
+ Bounded ink: Ink that spreads from a point and is contained in the bounds of a UI element such as a
+ button. The ink is visually clipped to the bounds of the UI element. Bounded ink is the most
+ commonly-used ink in the system. Examples include basic Material buttons, list menu items, and tile
+ grids.
+
+ Unbounded ink: Ink that spreads out from a point "on top" of other UI elements. It typically
+ reaches a maximum circle radius and then fades, unclipped by other UI elements. Typically used
+ when interacting with small UI elements such as navigation bar icons or slider "thumb" controls.
+ Examples include overflow menus, icon toggle buttons, and phone dialer keys.
+
+ Note that the two kinds of ink are designed to have different animation parameters, that is,
+ bounded ink isn't just clipped unbounded ink. Whether the ink is bounded or not depends on the kind
+ of UI element the user is interacting with.
+ */
+@interface MDCInkView : UIView
+
+/**
+ The style of ink for this view. Defaults to MDCInkStyleBounded.
+
+ Changes only affect subsequent animations, not animations in progress.
+ */
+@property(nonatomic, assign) MDCInkStyle inkStyle;
+
+/** The foreground color of the ink. The default value is defaultInkColor. */
+@property(nonatomic, strong, null_resettable) UIColor *inkColor;
+
+/** Default color used for ink if no color is specified. */
+@property(nonatomic, strong, readonly, nonnull) UIColor *defaultInkColor;
+
+/**
+ Maximum radius of the ink. If the radius <= 0 then half the length of the diagonal of self.bounds
+ is used. This value is ignored if @c inkStyle is set to |MDCInkStyleBounded|.
+ */
+@property(nonatomic, assign) CGFloat maxRippleRadius;
+
+/**
+ Use a custom center for the ink splash. If YES, then customInkCenter is used, otherwise the
+ center of self.bounds is used. Default is NO.
+ */
+@property(nonatomic, assign) BOOL usesCustomInkCenter;
+
+/**
+ Custom center for the ink splash in the view’s coordinate system.
+
+ Ignored if usesCustomInkCenter is not set.
+ */
+@property(nonatomic, assign) CGPoint customInkCenter;
+
+/**
+ Start the first part of the "press and release" animation at a particular point.
+
+ The "press and release" animation begins by fading in the ink ripple when this method is called.
+
+ @param point The user interaction position in the view’s coordinate system.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)startTouchBeganAnimationAtPoint:(CGPoint)point
+                             completion:(nullable MDCInkCompletionBlock)completionBlock;
+
+/**
+ Start the second part of the "press and release" animation at a particular point.
+
+ The "press and release" animation ends by completing the ink ripple expansion while fading out when
+ this method is called.
+
+ @param point The user interaction position in the view’s coordinate system.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)startTouchEndedAnimationAtPoint:(CGPoint)point
+                             completion:(nullable MDCInkCompletionBlock)completionBlock;
+
+/**
+ Cancel all animations.
+
+ @param animated If false, remove the animations immediately.
+ */
+- (void)cancelAllAnimationsAnimated:(BOOL)animated;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkView.m
new file mode 100644
index 0000000..01989c8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MDCInkView.m
@@ -0,0 +1,125 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkView.h"
+
+#import "private/MDCInkLayer.h"
+
+@interface MDCInkView ()
+@property(nonatomic, readonly) MDCInkLayer *inkLayer;
+@end
+
+@implementation MDCInkView
+
++ (Class)layerClass {
+  return [MDCInkLayer class];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCInkViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCInkViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCInkViewInit {
+  self.userInteractionEnabled = NO;
+  self.backgroundColor = [UIColor clearColor];
+  self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+  self.inkColor = self.defaultInkColor;
+}
+
+- (void)setInkStyle:(MDCInkStyle)inkStyle {
+  _inkStyle = inkStyle;
+  switch (inkStyle) {
+    case MDCInkStyleBounded:
+      self.inkLayer.masksToBounds = YES;
+      self.inkLayer.bounded = YES;
+      break;
+    case MDCInkStyleUnbounded:
+      self.inkLayer.masksToBounds = NO;
+      self.inkLayer.bounded = NO;
+      break;
+  }
+}
+
+- (void)setInkColor:(UIColor *)inkColor {
+  if (inkColor == nil) {
+    return;
+  }
+  self.inkLayer.inkColor = inkColor;
+}
+
+- (UIColor *)inkColor {
+  return self.inkLayer.inkColor;
+}
+
+- (CGFloat)maxRippleRadius {
+  return self.inkLayer.maxRippleRadius;
+}
+
+- (void)setMaxRippleRadius:(CGFloat)radius {
+  self.inkLayer.maxRippleRadius = radius;
+}
+
+- (BOOL)usesCustomInkCenter {
+  return self.inkLayer.useCustomInkCenter;
+}
+
+- (void)setUsesCustomInkCenter:(BOOL)usesCustomInkCenter {
+  self.inkLayer.useCustomInkCenter = usesCustomInkCenter;
+}
+
+- (CGPoint)customInkCenter {
+  return self.inkLayer.customInkCenter;
+}
+
+- (void)setCustomInkCenter:(CGPoint)customInkCenter {
+  self.inkLayer.customInkCenter = customInkCenter;
+}
+
+- (MDCInkLayer *)inkLayer {
+  return (MDCInkLayer *)self.layer;
+}
+
+- (void)startTouchBeganAnimationAtPoint:(CGPoint)point
+                             completion:(MDCInkCompletionBlock)completionBlock {
+  [self.inkLayer spreadFromPoint:point completion:completionBlock];
+}
+
+- (void)startTouchEndedAnimationAtPoint:(CGPoint)point
+                             completion:(MDCInkCompletionBlock)completionBlock {
+  [self.inkLayer evaporateWithCompletion:completionBlock];
+}
+
+- (void)cancelAllAnimationsAnimated:(BOOL)animated {
+  [self.inkLayer resetAllInk:animated];
+}
+
+- (UIColor *)defaultInkColor {
+  return [[UIColor alloc] initWithWhite:0 alpha:0.06f];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MaterialInk.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MaterialInk.h
new file mode 100644
index 0000000..c73b152
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/MaterialInk.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkGestureRecognizer.h"
+#import "MDCInkTouchController.h"
+#import "MDCInkView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.h
new file mode 100644
index 0000000..a22b14d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.h
@@ -0,0 +1,104 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIKit.h>
+
+/**
+ A Core Animation layer that draws and animates the ink effect.
+
+ Exact behaviour of the ink splash is defined in this sandbox demo: http://go/qinkdemo.
+
+ Quick summary of how the ink ripple works:
+
+ 1. On touch down, blast initiates from the touch point.
+ 2. On touch down hold, it continues to spread, but will gravitate to the center point
+    of the view.
+ 3. On touch up, the ink ripple will lose energy, opacity will start to decrease.
+ */
+@interface MDCInkLayer : CALayer
+
+/** Clips the ripple to the bounds of the layer. */
+@property(nonatomic, assign, getter=isBounded) BOOL bounded;
+
+/** Maximum radius of the ink. No maximum if radius is 0 or less. This value is ignored if
+ @c bounded is set to |YES|.*/
+@property(nonatomic, assign) CGFloat maxRippleRadius;
+
+/** Set the foreground color of the ink. */
+@property(nonatomic, strong) UIColor *inkColor;
+
+/** Spread duration. */
+@property(nonatomic, readonly, assign) NSTimeInterval spreadDuration;
+
+/** Evaporate duration */
+@property(nonatomic, readonly, assign) NSTimeInterval evaporateDuration;
+
+/**
+ Set to YES if the ink layer should be using a custom center.
+ */
+@property(nonatomic, assign) BOOL useCustomInkCenter;
+
+/**
+ Center point which ink gravitates towards.
+
+ Ignored if useCustomInkCenter is not set.
+ */
+@property(nonatomic, assign) CGPoint customInkCenter;
+
+/**
+ Whether linear expansion should be used for the ink, rather than a Quantum curve. Useful for
+ ink which needs to fill the bounds of its view completely and leave those bounds at full speed.
+ */
+@property(nonatomic, assign) BOOL userLinearExpansion;
+
+/**
+ Reset any ink applied to the layer.
+
+ @param animated Enables the ink ripple fade out animation.
+ */
+- (void)resetAllInk:(BOOL)animated;
+
+/**
+ Spreads the ink over the whole view.
+
+ Can be called multiple times which will result in multiple ink ripples.
+
+ @param completionBlock Block called after the completion of the animation.
+ @param point Point at which the ink spreads from.
+ */
+- (void)spreadFromPoint:(CGPoint)point completion:(void (^)())completionBlock;
+
+/**
+ Dissipate ink blast, should be called on touch up.
+
+ If there are multiple ripples at once, the oldest ripple will be evaporated.
+
+ @param completionBlock Block called after the completion of the evaporation.
+ */
+- (void)evaporateWithCompletion:(void (^)())completionBlock;
+
+/**
+ Dissipates the ink blast, but condenses to a point. Used for touch exit or cancel.
+
+ If there are mulitple ripples, the oldest ripple will be evaporated.
+
+ @param point Evaporate the ink towards the point.
+ @param completionBlock Block called after the completion of the evaporation.
+ */
+- (void)evaporateToPoint:(CGPoint)point completion:(void (^)())completionBlock;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.m
new file mode 100644
index 0000000..9d18b4b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Ink/src/private/MDCInkLayer.m
@@ -0,0 +1,596 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCInkLayer.h"
+
+#import <UIKit/UIKit.h>
+
+static inline CGPoint MDCInkLayerInterpolatePoint(CGPoint start,
+                                                  CGPoint end,
+                                                  CGFloat offsetPercent) {
+  CGPoint centerOffsetPoint = CGPointMake(start.x + (end.x - start.x) * offsetPercent,
+                                          start.y + (end.y - start.y) * offsetPercent);
+  return centerOffsetPoint;
+}
+
+static inline CGFloat MDCInkLayerRadiusBounds(CGFloat maxRippleRadius,
+                                              CGFloat inkLayerRectHypotenuse,
+                                              BOOL bounded) {
+  if (maxRippleRadius > 0) {
+#ifdef MDC_BOUNDED_INK_IGNORES_MAX_RIPPLE_RADIUS
+    if (!bounded) {
+      return maxRippleRadius;
+    } else {
+      static dispatch_once_t onceToken;
+      dispatch_once(&onceToken, ^{
+        NSLog(@"Implementation of MDCInkView with |MDCInkStyle| MDCInkStyleBounded and "
+              @"maxRippleRadius has changed.\n\n"
+              @"MDCInkStyleBounded ignores maxRippleRadius. "
+              @"Please use |MDCInkStyle| MDCInkStyleUnbounded to continue using maxRippleRadius. "
+              @"For implementation questions, please email shepj@google.com");
+      });
+      return inkLayerRectHypotenuse;
+    }
+#else
+    return maxRippleRadius;
+#endif
+  } else {
+    return inkLayerRectHypotenuse;
+  }
+}
+
+static inline CGFloat MDCInkLayerRandom() {
+  const uint32_t max_value = 10000;
+  return (CGFloat)arc4random_uniform(max_value + 1) / max_value;
+}
+
+static inline CGPoint MDCInkLayerRectGetCenter(CGRect rect) {
+  return CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
+}
+
+static inline CGFloat MDCInkLayerRectHypotenuse(CGRect rect) {
+  return (CGFloat)hypot(CGRectGetWidth(rect), CGRectGetHeight(rect));
+}
+
+static NSString *const kInkLayerOpacity = @"opacity";
+static NSString *const kInkLayerPosition = @"position";
+static NSString *const kInkLayerScale = @"transform.scale";
+
+// State tracking for ink.
+typedef NS_ENUM(NSInteger, MDCInkRippleState) {
+  kInkRippleNone,
+  kInkRippleSpreading,
+  kInkRippleComplete,
+  kInkRippleCancelled,
+};
+
+@protocol MDCInkLayerRippleDelegate <NSObject>
+
+@optional
+
+- (void)animationDidStop:(CAAnimation *)anim
+              shapeLayer:(CAShapeLayer *)shapeLayer
+                finished:(BOOL)finished;
+
+@end
+
+@interface MDCInkLayerRipple : CAShapeLayer
+
+@property(nonatomic, assign, getter=isAnimationCleared) BOOL animationCleared;
+@property(nonatomic, weak) id<MDCInkLayerRippleDelegate> animationDelegate;
+@property(nonatomic, assign) BOOL bounded;
+@property(nonatomic, weak) CALayer *inkLayer;
+@property(nonatomic, assign) CGFloat radius;
+@property(nonatomic, assign) CGPoint point;
+@property(nonatomic, assign) CGRect targetFrame;
+@property(nonatomic, assign) MDCInkRippleState rippleState;
+@property(nonatomic, strong) UIColor *color;
+
+@end
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCInkLayerRipple () <CAAnimationDelegate>
+@end
+#endif
+
+@implementation MDCInkLayerRipple
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _rippleState = kInkRippleNone;
+    _animationCleared = YES;
+  }
+  return self;
+}
+
+- (void)setupRipple {
+  self.fillColor = self.color.CGColor;
+  CGFloat dim = self.radius * 2.f;
+  self.frame = CGRectMake(0, 0, dim, dim);
+  UIBezierPath *ripplePath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, dim, dim)];
+  self.path = ripplePath.CGPath;
+}
+
+- (void)enter {
+  _rippleState = kInkRippleSpreading;
+  [_inkLayer addSublayer:self];
+  _animationCleared = NO;
+}
+
+- (void)exit {
+  if (_rippleState != kInkRippleCancelled) {
+    _rippleState = kInkRippleComplete;
+  }
+}
+
+- (CAKeyframeAnimation *)opacityAnimWithValues:(NSArray<NSNumber *> *)values
+                                         times:(NSArray<NSNumber *> *)times {
+  CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:kInkLayerOpacity];
+  anim.fillMode = kCAFillModeForwards;
+  anim.keyTimes = times;
+  anim.removedOnCompletion = NO;
+  anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+  anim.values = values;
+  return anim;
+}
+
+- (CAKeyframeAnimation *)positionAnimWithPath:(CGPathRef)path
+                                     duration:(CGFloat)duration
+                               timingFunction:(CAMediaTimingFunction *)timingFunction {
+  CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:kInkLayerPosition];
+  anim.duration = duration;
+  anim.fillMode = kCAFillModeForwards;
+  anim.path = path;
+  anim.removedOnCompletion = NO;
+  anim.timingFunction = timingFunction;
+  return anim;
+}
+
+- (CAKeyframeAnimation *)scaleAnimWithValues:(NSArray<NSNumber *> *)values
+                                       times:(NSArray<NSNumber *> *)times {
+  CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:kInkLayerScale];
+  anim.fillMode = kCAFillModeForwards;
+  anim.keyTimes = times;
+  anim.removedOnCompletion = NO;
+  anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+  anim.values = values;
+  return anim;
+}
+
+- (CAMediaTimingFunction *)logDecelerateEasing {
+  // This bezier curve is an approximation of a log curve.
+  return [[CAMediaTimingFunction alloc] initWithControlPoints:0.157f:0.72f:0.386f:0.987f];
+}
+
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)finished {
+  if (!self.isAnimationCleared) {
+    [self removeFromSuperlayer];
+    [self.animationDelegate animationDidStop:anim shapeLayer:self finished:finished];
+  }
+}
+
+@end
+
+static CGFloat const kInkLayerForegroundBoundedOpacityExitDuration = 0.4f;
+static CGFloat const kInkLayerForegroundBoundedPositionExitDuration = 0.3f;
+static CGFloat const kInkLayerForegroundBoundedRadiusExitDuration = 0.8f;
+static CGFloat const kInkLayerForegroundRadiusGrowthMultiplier = 350.f;
+static CGFloat const kInkLayerForegroundUnboundedEnterDelay = 0.08f;
+static CGFloat const kInkLayerForegroundUnboundedOpacityEnterDuration = 0.12f;
+static CGFloat const kInkLayerForegroundWaveTouchDownAcceleration = 1024.f;
+static CGFloat const kInkLayerForegroundWaveTouchUpAcceleration = 3400.f;
+static NSString *const kInkLayerForegroundOpacityAnim = @"foregroundOpacityAnim";
+static NSString *const kInkLayerForegroundPositionAnim = @"foregroundPositionAnim";
+static NSString *const kInkLayerForegroundScaleAnim = @"foregroundScaleAnim";
+
+@interface MDCInkLayerForegroundRipple : MDCInkLayerRipple
+
+@property(nonatomic, assign) BOOL useCustomInkCenter;
+@property(nonatomic, assign) CGPoint customInkCenter;
+@property(nonatomic, strong) CAKeyframeAnimation *foregroundOpacityAnim;
+@property(nonatomic, strong) CAKeyframeAnimation *foregroundPositionAnim;
+@property(nonatomic, strong) CAKeyframeAnimation *foregroundScaleAnim;
+
+@end
+
+@implementation MDCInkLayerForegroundRipple
+
+- (void)setupRipple {
+  CGFloat random = MDCInkLayerRandom();
+  self.radius = (CGFloat)(0.9f + random * 0.1f) * kInkLayerForegroundRadiusGrowthMultiplier;
+  [super setupRipple];
+}
+
+- (void)enterWithCompletion:(void (^)())completionBlock {
+  [super enter];
+
+  if (self.bounded) {
+    _foregroundOpacityAnim = [self opacityAnimWithValues:@[ @0 ] times:@[ @0 ]];
+    _foregroundScaleAnim = [self scaleAnimWithValues:@[ @0 ] times:@[ @0 ]];
+  } else {
+    _foregroundOpacityAnim = [self opacityAnimWithValues:@[ @0, @1 ] times:@[ @0, @1 ]];
+    _foregroundOpacityAnim.duration = kInkLayerForegroundUnboundedOpacityEnterDuration;
+
+    CGFloat duration = (CGFloat)sqrt(self.radius / kInkLayerForegroundWaveTouchDownAcceleration);
+    _foregroundScaleAnim =
+        [self scaleAnimWithValues:@[ @0, @1 ]
+                            times:@[ @(kInkLayerForegroundUnboundedEnterDelay), @1 ]];
+    _foregroundScaleAnim.duration = duration;
+
+    CGFloat xOffset = self.targetFrame.origin.x - self.inkLayer.frame.origin.x;
+    CGFloat yOffset = self.targetFrame.origin.y - self.inkLayer.frame.origin.y;
+
+    UIBezierPath *movePath = [UIBezierPath bezierPath];
+    CGPoint startPoint = CGPointMake(self.point.x + xOffset, self.point.y + yOffset);
+    CGPoint endPoint = MDCInkLayerRectGetCenter(self.targetFrame);
+    if (self.useCustomInkCenter) {
+      endPoint = self.customInkCenter;
+    }
+    endPoint = CGPointMake(endPoint.x + xOffset, endPoint.y + yOffset);
+    [movePath moveToPoint:startPoint];
+    [movePath addLineToPoint:endPoint];
+
+    CAMediaTimingFunction *linearTimingFunction =
+        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+    _foregroundPositionAnim = [self positionAnimWithPath:movePath.CGPath
+                                                duration:duration
+                                          timingFunction:linearTimingFunction];
+    _foregroundPositionAnim.keyTimes = @[ @(kInkLayerForegroundUnboundedEnterDelay), @1 ];
+    [self addAnimation:_foregroundPositionAnim forKey:kInkLayerForegroundPositionAnim];
+  }
+
+  [CATransaction begin];
+  if (completionBlock) {
+    __weak MDCInkLayerForegroundRipple *weakSelf = self;
+    [CATransaction setCompletionBlock:^{
+      MDCInkLayerForegroundRipple *strongSelf = weakSelf;
+      if (strongSelf.rippleState != kInkRippleCancelled) {
+        completionBlock();
+      }
+    }];
+  }
+  [self addAnimation:_foregroundOpacityAnim forKey:kInkLayerForegroundOpacityAnim];
+  [self addAnimation:_foregroundScaleAnim forKey:kInkLayerForegroundScaleAnim];
+  [CATransaction commit];
+}
+
+- (void)exit:(BOOL)animated {
+  self.rippleState = kInkRippleCancelled;
+  [self exit:animated completion:nil];
+}
+
+- (void)exit:(BOOL)animated completion:(void (^)())completionBlock {
+  [super exit];
+
+  if (!animated) {
+    [self removeAllAnimations];
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    self.opacity = 0;
+    [CATransaction commit];
+    return;
+  }
+
+  if (self.bounded) {
+    _foregroundOpacityAnim.values = @[ @1, @0 ];
+    _foregroundOpacityAnim.duration = kInkLayerForegroundBoundedOpacityExitDuration;
+
+    // Bounded ripples move slightly towards the center of the tap target. Unbounded ripples
+    // move to the center of the tap target.
+
+    CGFloat xOffset = self.targetFrame.origin.x - self.inkLayer.frame.origin.x;
+    CGFloat yOffset = self.targetFrame.origin.y - self.inkLayer.frame.origin.y;
+
+    CGPoint startPoint = CGPointMake(self.point.x + xOffset, self.point.y + yOffset);
+    CGPoint endPoint = MDCInkLayerRectGetCenter(self.targetFrame);
+    if (self.useCustomInkCenter) {
+      endPoint = self.customInkCenter;
+    }
+    endPoint = CGPointMake(endPoint.x + xOffset, endPoint.y + yOffset);
+    CGPoint centerOffsetPoint = MDCInkLayerInterpolatePoint(startPoint, endPoint, 0.3f);
+    UIBezierPath *movePath = [UIBezierPath bezierPath];
+    [movePath moveToPoint:startPoint];
+    [movePath addLineToPoint:centerOffsetPoint];
+
+    _foregroundPositionAnim =
+        [self positionAnimWithPath:movePath.CGPath
+                          duration:kInkLayerForegroundBoundedPositionExitDuration
+                    timingFunction:[self logDecelerateEasing]];
+    _foregroundScaleAnim.values = @[ @0, @1 ];
+    _foregroundScaleAnim.keyTimes = @[ @0, @1 ];
+    _foregroundScaleAnim.duration = kInkLayerForegroundBoundedRadiusExitDuration;
+  } else {
+    NSNumber *opacityVal = [self.presentationLayer valueForKeyPath:kInkLayerOpacity];
+    if (!opacityVal) {
+      opacityVal = [NSNumber numberWithFloat:0];
+    }
+    CGFloat adjustedDuration = kInkLayerForegroundBoundedPositionExitDuration;
+    CGFloat normOpacityVal = opacityVal.floatValue;
+    CGFloat opacityDuration = normOpacityVal / 3.f;
+    _foregroundOpacityAnim.values = @[ opacityVal, @0 ];
+    _foregroundOpacityAnim.duration = opacityDuration + adjustedDuration;
+
+    NSNumber *scaleVal = [self.presentationLayer valueForKeyPath:kInkLayerScale];
+    if (!scaleVal) {
+      scaleVal = [NSNumber numberWithFloat:0];
+    }
+    CGFloat unboundedDuration = (CGFloat)sqrt(((1.f - scaleVal.floatValue) * self.radius) /
+                                              (kInkLayerForegroundWaveTouchDownAcceleration +
+                                               kInkLayerForegroundWaveTouchUpAcceleration));
+    _foregroundPositionAnim.duration = unboundedDuration + adjustedDuration;
+    _foregroundScaleAnim.values = @[ scaleVal, @1 ];
+    _foregroundScaleAnim.duration = unboundedDuration + adjustedDuration;
+  }
+
+  _foregroundOpacityAnim.keyTimes = @[ @0, @1 ];
+  if (_foregroundOpacityAnim.duration < _foregroundScaleAnim.duration) {
+    _foregroundScaleAnim.delegate = self;
+  } else {
+    _foregroundOpacityAnim.delegate = self;
+  }
+
+  _foregroundOpacityAnim.timingFunction =
+      [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+  _foregroundPositionAnim.timingFunction = [self logDecelerateEasing];
+  _foregroundScaleAnim.timingFunction = [self logDecelerateEasing];
+
+  [CATransaction begin];
+  if (completionBlock) {
+    __weak MDCInkLayerForegroundRipple *weakSelf = self;
+    [CATransaction setCompletionBlock:^{
+      MDCInkLayerForegroundRipple *strongSelf = weakSelf;
+      if (strongSelf.rippleState != kInkRippleCancelled) {
+        completionBlock();
+      }
+    }];
+  }
+  [self addAnimation:_foregroundOpacityAnim forKey:kInkLayerForegroundOpacityAnim];
+  [self addAnimation:_foregroundPositionAnim forKey:kInkLayerForegroundPositionAnim];
+  [self addAnimation:_foregroundScaleAnim forKey:kInkLayerForegroundScaleAnim];
+  [CATransaction commit];
+}
+
+- (void)removeAllAnimations {
+  [super removeAllAnimations];
+  _foregroundOpacityAnim = nil;
+  _foregroundPositionAnim = nil;
+  _foregroundScaleAnim = nil;
+  self.animationCleared = YES;
+}
+
+@end
+
+static CGFloat const kInkLayerBackgroundOpacityEnterDuration = 0.6f;
+static CGFloat const kInkLayerBackgroundBaseOpacityExitDuration = 0.48f;
+static CGFloat const kInkLayerBackgroundFastEnterDuration = 0.12f;
+static NSString *const kInkLayerBackgroundOpacityAnim = @"backgroundOpacityAnim";
+
+@interface MDCInkLayerBackgroundRipple : MDCInkLayerRipple
+
+@property(nonatomic, strong) CAKeyframeAnimation *backgroundOpacityAnim;
+
+@end
+
+@implementation MDCInkLayerBackgroundRipple
+
+- (void)enter {
+  [super enter];
+  _backgroundOpacityAnim = [self opacityAnimWithValues:@[ @0, @1 ] times:@[ @0, @1 ]];
+  _backgroundOpacityAnim.duration = kInkLayerBackgroundOpacityEnterDuration;
+  [self addAnimation:_backgroundOpacityAnim forKey:kInkLayerBackgroundOpacityAnim];
+}
+
+- (void)exit:(BOOL)animated {
+  [super exit];
+
+  if (!animated) {
+    [self removeAllAnimations];
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    self.opacity = 0;
+    [CATransaction commit];
+    return;
+  }
+
+  NSNumber *opacityVal = [self.presentationLayer valueForKeyPath:kInkLayerOpacity];
+  if (!opacityVal) {
+    opacityVal = [NSNumber numberWithFloat:0];
+  }
+  CGFloat duration = kInkLayerBackgroundBaseOpacityExitDuration;
+  if (self.bounded) {
+    // The end (tap release) animation should continue at the opacity level of the start animation.
+    CGFloat enterDuration = (1 - opacityVal.floatValue / 1) * kInkLayerBackgroundFastEnterDuration;
+    duration += enterDuration;
+    _backgroundOpacityAnim = [self opacityAnimWithValues:@[ opacityVal, @1, @0 ]
+                                                   times:@[ @0, @(enterDuration / duration), @1 ]];
+  } else {
+    _backgroundOpacityAnim = [self opacityAnimWithValues:@[ opacityVal, @0 ] times:@[ @0, @1 ]];
+  }
+  _backgroundOpacityAnim.duration = duration;
+  _backgroundOpacityAnim.delegate = self;
+  [self addAnimation:_backgroundOpacityAnim forKey:kInkLayerBackgroundOpacityAnim];
+}
+
+- (void)removeAllAnimations {
+  [super removeAllAnimations];
+  _backgroundOpacityAnim = nil;
+  self.animationCleared = YES;
+}
+
+@end
+
+@interface MDCInkLayer () <MDCInkLayerRippleDelegate>
+
+/**
+ Reset the bottom-most ink applied to the layer with a completion handler to be called on completion
+ if applicable.
+
+ @param animated Enables the ink ripple fade out animation.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)resetBottomInk:(BOOL)animated completion:(void (^)())completionBlock;
+
+/**
+ Reset the bottom-most ink applied to the layer with a completion handler to be called on completion
+ if applicable.
+
+ @param animated Enables the ink ripple fade out animation.
+ @param point Evaporate the ink towards the point.
+ @param completionBlock Block called after the completion of the animation.
+ */
+- (void)resetBottomInk:(BOOL)animated toPoint:(CGPoint)point completion:(void (^)())completionBlock;
+
+@property(nonatomic, strong) CAShapeLayer *compositeRipple;
+@property(nonatomic, strong) NSMutableArray<MDCInkLayerForegroundRipple *> *foregroundRipples;
+@property(nonatomic, strong) NSMutableArray<MDCInkLayerBackgroundRipple *> *backgroundRipples;
+
+@end
+
+@implementation MDCInkLayer
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    self.masksToBounds = YES;
+    _bounded = YES;
+    _compositeRipple = [CAShapeLayer layer];
+    _foregroundRipples = [NSMutableArray array];
+    _backgroundRipples = [NSMutableArray array];
+    [self addSublayer:_compositeRipple];
+  }
+  return self;
+}
+
+- (void)layoutSublayers {
+  [super layoutSublayers];
+  _compositeRipple.frame = self.frame;
+  CGFloat radius = MDCInkLayerRadiusBounds(_maxRippleRadius,
+                                           MDCInkLayerRectHypotenuse(self.bounds) / 2.f, _bounded);
+
+  CGRect rippleFrame =
+      CGRectMake(-(radius * 2.f - self.bounds.size.width) / 2.f,
+                 -(radius * 2.f - self.bounds.size.height) / 2.f, radius * 2.f, radius * 2.f);
+  _compositeRipple.frame = rippleFrame;
+  CGRect rippleBounds = CGRectMake(0, 0, radius * 2.f, radius * 2.f);
+  CAShapeLayer *rippleMaskLayer = [CAShapeLayer layer];
+  UIBezierPath *ripplePath = [UIBezierPath bezierPathWithOvalInRect:rippleBounds];
+  rippleMaskLayer.path = ripplePath.CGPath;
+  _compositeRipple.mask = rippleMaskLayer;
+}
+
+- (void)resetAllInk:(BOOL)animated {
+  if (self.foregroundRipples.count > 0) {
+    [self.foregroundRipples makeObjectsPerformSelector:@selector(exit:)];
+  }
+  if (self.backgroundRipples.count > 0) {
+    [self.backgroundRipples makeObjectsPerformSelector:@selector(exit:)];
+  }
+}
+
+- (void)resetBottomInk:(BOOL)animated completion:(void (^)())completionBlock {
+  if (self.foregroundRipples.count > 0) {
+    [[self.foregroundRipples objectAtIndex:(self.foregroundRipples.count - 1)]
+              exit:animated
+        completion:completionBlock];
+  }
+  if (self.backgroundRipples.count > 0) {
+    [[self.backgroundRipples objectAtIndex:(self.backgroundRipples.count - 1)] exit:animated];
+  }
+}
+
+- (void)resetBottomInk:(BOOL)animated
+               toPoint:(CGPoint)point
+            completion:(void (^)())completionBlock {
+  if (self.foregroundRipples.count > 0) {
+    MDCInkLayerForegroundRipple *foregroundRipple =
+        [self.foregroundRipples objectAtIndex:(self.foregroundRipples.count - 1)];
+    foregroundRipple.point = point;
+    [foregroundRipple exit:animated completion:completionBlock];
+  }
+  if (self.backgroundRipples.count > 0) {
+    [[self.backgroundRipples objectAtIndex:(self.backgroundRipples.count - 1)] exit:animated];
+  }
+}
+
+#pragma mark - Properties
+
+- (void)spreadFromPoint:(CGPoint)point completion:(void (^)())completionBlock {
+  // Create a mask layer before drawing the ink using the superlayer's shadowPath
+  // if it exists. This helps the FAB when it is not rectangular.
+  if (self.masksToBounds && self.superlayer.shadowPath) {
+    CAShapeLayer *mask = [CAShapeLayer layer];
+    mask.path = self.superlayer.shadowPath;
+    mask.fillColor = [UIColor whiteColor].CGColor;
+    self.mask = mask;
+  } else {
+    self.mask = nil;
+  }
+
+  CGFloat radius = MDCInkLayerRadiusBounds(_maxRippleRadius,
+                                           MDCInkLayerRectHypotenuse(self.bounds) / 2.f, _bounded);
+
+  MDCInkLayerBackgroundRipple *backgroundRipple = [[MDCInkLayerBackgroundRipple alloc] init];
+  backgroundRipple.inkLayer = _compositeRipple;
+  backgroundRipple.targetFrame = self.bounds;
+  backgroundRipple.point = point;
+  backgroundRipple.color = self.inkColor;
+  backgroundRipple.radius = radius;
+  backgroundRipple.bounded = self.bounded;
+  backgroundRipple.animationDelegate = self;
+  [backgroundRipple setupRipple];
+
+  MDCInkLayerForegroundRipple *foregroundRipple = [[MDCInkLayerForegroundRipple alloc] init];
+  foregroundRipple.inkLayer = _compositeRipple;
+  foregroundRipple.targetFrame = self.bounds;
+  foregroundRipple.point = point;
+  foregroundRipple.color = self.inkColor;
+  foregroundRipple.radius = radius;
+  foregroundRipple.bounded = self.bounded;
+  foregroundRipple.animationDelegate = self;
+  foregroundRipple.useCustomInkCenter = self.useCustomInkCenter;
+  foregroundRipple.customInkCenter = self.customInkCenter;
+  [foregroundRipple setupRipple];
+
+  [backgroundRipple enter];
+  [self.backgroundRipples addObject:backgroundRipple];
+  [foregroundRipple enterWithCompletion:completionBlock];
+  [self.foregroundRipples addObject:foregroundRipple];
+}
+
+- (void)evaporateWithCompletion:(void (^)())completionBlock {
+  [self resetBottomInk:YES completion:completionBlock];
+}
+
+- (void)evaporateToPoint:(CGPoint)point completion:(void (^)())completionBlock {
+  [self resetBottomInk:YES toPoint:point completion:completionBlock];
+}
+
+#pragma mark - MDCInkLayerRippleDelegate
+
+- (void)animationDidStop:(CAAnimation *)anim
+              shapeLayer:(CAShapeLayer *)shapeLayer
+                finished:(BOOL)finished {
+  [shapeLayer removeAllAnimations];
+
+  if ([shapeLayer isMemberOfClass:[MDCInkLayerForegroundRipple class]]) {
+    [self.foregroundRipples removeObject:(MDCInkLayerForegroundRipple *)shapeLayer];
+  } else if ([shapeLayer isMemberOfClass:[MDCInkLayerBackgroundRipple class]]) {
+    [self.backgroundRipples removeObject:(MDCInkLayerBackgroundRipple *)shapeLayer];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
new file mode 100644
index 0000000..a3e07da
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.h
@@ -0,0 +1,194 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCButtonBarDelegate;
+
+/** Specifies the title alignment of the |MDCNavigationBar|. */
+typedef NS_ENUM(NSInteger, MDCNavigationBarTitleAlignment) {
+  /** Aligns the title to the center of the NavigationBar. */
+  MDCNavigationBarTitleAlignmentCenter,
+  /** Aligns the title to the left/leading of the NavigationBar. */
+  MDCNavigationBarTitleAlignmentLeading
+};
+
+/**
+ This protocol defines all of the properties on UINavigationItem that can be listened to by
+ MDCNavigationBar.
+ */
+@protocol MDCUINavigationItemObservables <NSObject>
+@required
+
+@property(nonatomic, copy, nullable) NSString *title;
+@property(nonatomic, strong, nullable) UIView *titleView;
+@property(nonatomic) BOOL hidesBackButton;
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leftBarButtonItems;
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *rightBarButtonItems;
+@property(nonatomic) BOOL leftItemsSupplementBackButton;
+@property(nonatomic, strong, nullable) UIBarButtonItem *leftBarButtonItem;
+@property(nonatomic, strong, nullable) UIBarButtonItem *rightBarButtonItem;
+
+@end
+
+@class MDCNavigationBar;
+
+/**
+  The MDCNavigationBarTextColorAccessibilityMutator class creates an external object with which to
+  work on an instance of a Material Navigation Bar to activate and ensure accessibility on its title
+  and buttons.
+
+  ### Dependencies
+
+  Material NavigationBarTextColorAccessibilityMutator depends on the Navigation Bar material
+  component and MDFTextAccessibility Framework.
+  */
+
+@interface MDCNavigationBarTextColorAccessibilityMutator : NSObject
+
+/**
+ Initializes and returns a newly created accessibility mutator
+ */
+- (nonnull instancetype)init;
+
+/**
+  Mutates title text color and navigation items' tint colors based on background color of
+  navigation bar.
+  */
+- (void)mutate:(nonnull MDCNavigationBar *)navBar;
+
+@end
+
+/**
+ The MDCNavigationBar class is a view consisting of a leading and trailing button bar, title label,
+ and an optional title view.
+
+ This view is not designed to have subviews added to it except via through its declared properties
+ (e.g. titleView).
+ */
+IB_DESIGNABLE
+@interface MDCNavigationBar : UIView
+
+#pragma mark Behavior
+
+/* Title displayed in the bar if titleView is unset. */
+@property(nonatomic, copy, nullable) NSString *title;
+
+/**
+ The title view layout differs from the traditional behavior of UINavigationBar.
+
+ Due to MDCNavigationBar being able to expand vertically, the titleView's height is updated to match
+ any changes in the MDCNavigationBar's height.
+
+ You may wish to create a container view that is able to manage subview layout if your situation
+ requires it.
+ */
+@property(nonatomic, strong, nullable) UIView *titleView;
+
+/**
+ Display attributes for the titleView's title text.
+
+ Setting this property will render an NSAttributedString with the assigned attributes across the
+ entire text.
+ */
+@property(nonatomic, copy, nullable)
+    NSDictionary<NSString *, id> *titleTextAttributes UI_APPEARANCE_SELECTOR;
+
+/** The back button to be displayed, if any. */
+@property(nonatomic, strong, nullable) UIBarButtonItem *backItem;
+
+/*  If YES, this navigation bar will hide the back button. */
+@property(nonatomic) BOOL hidesBackButton;
+
+/* Use these properties to set multiple items in a navigation bar.
+ The single properties (leadingBarButtonItem and trailingBarButtonItem) refer to the first item in
+ the respective array of items.
+
+ NOTE: You'll achieve the best results if you use either the singular properties or the plural
+ properties consistently and don't try to mix them.
+
+   leadingBarButtonItems are placed in the navigation bar from the leading edge to the trailing edge
+ with the first item in the list at the leading outside edge and leading aligned.
+   trailingBarButtonItems are placed from the trailing edge to the leading edge with the first item
+ in the list at the trailing outside edge and trailing aligned.
+ */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leadingBarButtonItems;
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *trailingBarButtonItems;
+
+/* By default, the leadingItemsSupplementBackButton property is NO. In this case, the back button is
+ not drawn and the leading item or items replace it. If you would like the leading items to appear
+ in addition to the back button (as opposed to instead of it) set leadingItemsSupplementBackButton
+ to YES.
+ */
+@property(nonatomic) BOOL leadingItemsSupplementBackButton;
+
+/*
+ Use these when you want to display a custom leading or trailing item in this navigation bar.
+ A custom leading item replaces the regular back button unless you set
+ leadingItemsSupplementBackButton to YES.
+ */
+@property(nonatomic, strong, nullable) UIBarButtonItem *leadingBarButtonItem;
+@property(nonatomic, strong, nullable) UIBarButtonItem *trailingBarButtonItem;
+
+/**
+ The horizontal text alignment of the navigation bar title. Defaults to
+ MDCNavigationBarTitleAlignmentLeading.
+ */
+@property(nonatomic) MDCNavigationBarTitleAlignment titleAlignment;
+
+#pragma mark Observing UINavigationItem instances
+
+/**
+ Begin observing changes to the provided navigation item.
+
+ Only one navigation item instance can be observed at a time. Observing a second navigation item
+ will stop observation of the first navigation item.
+
+ Once execution returns from this method the receiver's state will match that of the newly-observed
+ navigation item.
+
+ The observed navigation item is strongly held.
+ */
+- (void)observeNavigationItem:(nonnull UINavigationItem *)navigationItem;
+
+/**
+ Stop observing changes to the previously-observed navigation item.
+
+ Does nothing if no navigation item is being observed.
+ */
+- (void)unobserveNavigationItem;
+
+#pragma mark UINavigationItem interface matching
+
+/* Equivalent to leadingBarButtonItems. */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *leftBarButtonItems;
+
+/* Equivalent to trailingBarButtonItems. */
+@property(nonatomic, copy, nullable) NSArray<UIBarButtonItem *> *rightBarButtonItems;
+
+/* Equivalent to leadingBarButtonItem. */
+@property(nonatomic, strong, nullable) UIBarButtonItem *leftBarButtonItem;
+
+/* Equivalent to trailingBarButtonItem. */
+@property(nonatomic, strong, nullable) UIBarButtonItem *rightBarButtonItem;
+
+/* Equivalent to leadingItemsSupplementBackButton. */
+@property(nonatomic) BOOL leftItemsSupplementBackButton;
+
+/** The text alignment of the navigation bar title. Defaults to NSTextAlignmentLeft. */
+@property(nonatomic) NSTextAlignment textAlignment __deprecated_msg("Use titleAlignment instead.");
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.m
new file mode 100644
index 0000000..c40c3f1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MDCNavigationBar.m
@@ -0,0 +1,722 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCNavigationBar.h"
+
+#import "MDFTextAccessibility.h"
+#import "MaterialButtonBar.h"
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+#import <objc/runtime.h>
+
+static inline CGFloat Ceil(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return ceil(value);
+#else
+  return ceilf(value);
+#endif
+}
+
+static inline CGFloat Floor(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return floor(value);
+#else
+  return floorf(value);
+#endif
+}
+
+static const CGFloat kNavigationBarDefaultHeight = 56;
+static const CGFloat kNavigationBarPadDefaultHeight = 64;
+static const UIEdgeInsets kTextInsets = {16, 16, 16, 16};
+static const UIEdgeInsets kTextPadInsets = {20, 16, 20, 16};
+
+// KVO contexts
+static char *const kKVOContextMDCNavigationBar = "kKVOContextMDCNavigationBar";
+
+static NSArray<NSString *> *MDCNavigationBarNavigationItemKVOPaths(void) {
+  static dispatch_once_t onceToken;
+  static NSArray<NSString *> *forwardingKeyPaths = nil;
+  dispatch_once(&onceToken, ^{
+    NSMutableArray<NSString *> *keyPaths = [NSMutableArray array];
+
+    Protocol *headerProtocol = @protocol(MDCUINavigationItemObservables);
+    unsigned int count = 0;
+    objc_property_t *propertyList = protocol_copyPropertyList(headerProtocol, &count);
+    if (propertyList) {
+      for (unsigned int ix = 0; ix < count; ++ix) {
+        [keyPaths addObject:[NSString stringWithFormat:@"%s", property_getName(propertyList[ix])]];
+      }
+      free(propertyList);
+    }
+
+    // Ensure that the plural bar button item key paths are listened to last, otherwise the
+    // non-plural variant will cause the extra bar button items to be lost. Fun!
+    NSArray<NSString *> *orderedKeyPaths = @[
+      NSStringFromSelector(@selector(leftBarButtonItems)),
+      NSStringFromSelector(@selector(rightBarButtonItems))
+    ];
+    [keyPaths removeObjectsInArray:orderedKeyPaths];
+    [keyPaths addObjectsFromArray:orderedKeyPaths];
+
+    forwardingKeyPaths = keyPaths;
+  });
+  return forwardingKeyPaths;
+}
+
+static NSString *const MDCNavigationBarTitleKey = @"MDCNavigationBarTitleKey";
+static NSString *const MDCNavigationBarTitleViewKey = @"MDCNavigationBarTitleViewKey";
+static NSString *const MDCNavigationBarTitleTextAttributesKey =
+    @"MDCNavigationBarTitleTextAttributesKey";
+static NSString *const MDCNavigationBarBackItemKey = @"MDCNavigationBarBackItemKey";
+static NSString *const MDCNavigationBarHidesBackButtonKey = @"MDCNavigationBarHidesBackButtonKey";
+static NSString *const MDCNavigationBarLeadingBarItemsKey = @"MDCNavigationBarLeadingBarItemsKey";
+static NSString *const MDCNavigationBarTrailingBarItemsKey = @"MDCNavigationBarTrailingBarItemsKey";
+static NSString *const MDCNavigationBarLeadingButtonSupplementsBackButtonKey =
+    @"MDCNavigationBarLeadingButtonSupplementsBackButtonKey";
+static NSString *const MDCNavigationBarTitleAlignmentKey = @"MDCNavigationBarTitleAlignmentKey";
+
+@implementation MDCNavigationBarTextColorAccessibilityMutator
+
+- (nonnull instancetype)init {
+  self = [super init];
+  return self;
+}
+
+- (void)mutate:(MDCNavigationBar *)navBar {
+  // Determine what is the appropriate background color
+  UIColor *backgroundColor = navBar.backgroundColor;
+  if (!backgroundColor) {
+    return;
+  }
+
+  // Update title label color based on navigationBar backgroundColor
+  NSMutableDictionary *textAttr =
+      [NSMutableDictionary dictionaryWithDictionary:[navBar titleTextAttributes]];
+  UIColor *textColor =
+      [MDFTextAccessibility textColorOnBackgroundColor:backgroundColor
+                                       targetTextAlpha:1.0
+                                                  font:[textAttr objectForKey:NSFontAttributeName]];
+  [textAttr setObject:textColor forKey:NSForegroundColorAttributeName];
+  [navBar setTitleTextAttributes:textAttr];
+
+  // Update button's tint color based on navigationBar backgroundColor
+  navBar.tintColor = textColor;
+}
+
+@end
+
+/**
+ Indiana Jones style placeholder view for UINavigationBar. Ownership of UIBarButtonItem.customView
+ and UINavigationItem.titleView are normally transferred to UINavigationController but we plan to
+ steal them away. In order to avoid crashing during KVO updates, we steal the view away and
+ replace it with a sandbag view.
+ */
+@interface MDCNavigationBarSandbagView : UIView
+@end
+
+@implementation MDCNavigationBarSandbagView
+@end
+
+@interface MDCNavigationBar (PrivateAPIs)
+
+- (UILabel *)titleLabel;
+- (MDCButtonBar *)leadingButtonBar;
+- (MDCButtonBar *)trailingButtonBar;
+
+@end
+
+@implementation MDCNavigationBar {
+  id _observedNavigationItemLock;
+  UINavigationItem *_observedNavigationItem;
+
+  UILabel *_titleLabel;
+
+  MDCButtonBar *_leadingButtonBar;
+  MDCButtonBar *_trailingButtonBar;
+
+  __weak UIViewController *_watchingViewController;
+}
+
+@synthesize leadingBarButtonItems = _leadingBarButtonItems;
+@synthesize trailingBarButtonItems = _trailingBarButtonItems;
+@synthesize hidesBackButton = _hidesBackButton;
+@synthesize leadingItemsSupplementBackButton = _leadingItemsSupplementBackButton;
+@synthesize titleView = _titleView;
+
+- (void)dealloc {
+  [self setObservedNavigationItem:nil];
+}
+
+- (void)commonMDCNavigationBarInit {
+  _observedNavigationItemLock = [[NSObject alloc] init];
+
+  _titleLabel = [[UILabel alloc] init];
+  _titleLabel.font = [MDCTypography titleFont];
+  _titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader;
+  _titleLabel.textAlignment = NSTextAlignmentCenter;
+  _leadingButtonBar = [[MDCButtonBar alloc] init];
+  _leadingButtonBar.layoutPosition = MDCButtonBarLayoutPositionLeading;
+  _trailingButtonBar = [[MDCButtonBar alloc] init];
+  _trailingButtonBar.layoutPosition = MDCButtonBarLayoutPositionTrailing;
+
+  [self addSubview:_titleLabel];
+  [self addSubview:_leadingButtonBar];
+  [self addSubview:_trailingButtonBar];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCNavigationBarInit];
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleKey]) {
+      self.title = [aDecoder decodeObjectForKey:MDCNavigationBarTitleKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleViewKey]) {
+      self.titleView = [aDecoder decodeObjectForKey:MDCNavigationBarTitleViewKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleTextAttributesKey]) {
+      self.titleTextAttributes =
+          [aDecoder decodeObjectForKey:MDCNavigationBarTitleTextAttributesKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarBackItemKey]) {
+      self.backItem = [aDecoder decodeObjectForKey:MDCNavigationBarBackItemKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarHidesBackButtonKey]) {
+      self.hidesBackButton = [aDecoder decodeBoolForKey:MDCNavigationBarHidesBackButtonKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarLeadingBarItemsKey]) {
+      self.leadingBarButtonItems = [aDecoder decodeObjectForKey:MDCNavigationBarLeadingBarItemsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTrailingBarItemsKey]) {
+      self.trailingBarButtonItems =
+          [aDecoder decodeObjectForKey:MDCNavigationBarTrailingBarItemsKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarLeadingButtonSupplementsBackButtonKey]) {
+      self.leadingItemsSupplementBackButton =
+          [aDecoder decodeBoolForKey:MDCNavigationBarLeadingButtonSupplementsBackButtonKey];
+    }
+
+    if ([aDecoder containsValueForKey:MDCNavigationBarTitleAlignmentKey]) {
+      self.titleAlignment = [aDecoder decodeIntegerForKey:MDCNavigationBarTitleAlignmentKey];
+    }
+  }
+  return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCNavigationBarInit];
+  }
+  return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+
+  if (self.title) {
+    [aCoder encodeObject:self.title forKey:MDCNavigationBarTitleKey];
+  }
+
+  if (self.titleView) {
+    [aCoder encodeObject:self.titleView forKey:MDCNavigationBarTitleViewKey];
+  }
+
+  if (self.titleTextAttributes) {
+    [aCoder encodeObject:self.titleTextAttributes forKey:MDCNavigationBarTitleTextAttributesKey];
+  }
+
+  if (self.backItem) {
+    [aCoder encodeObject:self.backItem forKey:MDCNavigationBarBackItemKey];
+  }
+
+  [aCoder encodeBool:self.hidesBackButton forKey:MDCNavigationBarHidesBackButtonKey];
+
+  if (self.leadingBarButtonItems && self.leadingBarButtonItems.count > 0) {
+    [aCoder encodeObject:self.leadingBarButtonItems forKey:MDCNavigationBarLeadingBarItemsKey];
+  }
+
+  if (self.trailingBarButtonItems && self.trailingBarButtonItems.count > 0) {
+    [aCoder encodeObject:self.trailingBarButtonItems forKey:MDCNavigationBarTrailingBarItemsKey];
+  }
+
+  [aCoder encodeBool:self.leadingItemsSupplementBackButton
+              forKey:MDCNavigationBarLeadingButtonSupplementsBackButtonKey];
+  [aCoder encodeInteger:self.titleAlignment forKey:MDCNavigationBarTitleAlignmentKey];
+}
+
+#pragma mark Accessibility
+
+- (NSArray<__kindof UIView *> *)accessibilityElements {
+  return @[ _leadingButtonBar, self.titleView ?: _titleLabel, _trailingButtonBar ];
+}
+
+- (BOOL)isAccessibilityElement {
+  return NO;
+}
+
+- (NSInteger)accessibilityElementCount {
+  return self.accessibilityElements.count;
+}
+
+- (id)accessibilityElementAtIndex:(NSInteger)index {
+  return self.accessibilityElements[index];
+}
+
+- (NSInteger)indexOfAccessibilityElement:(id)element {
+  return [self.accessibilityElements indexOfObject:element];
+}
+
+#pragma mark UIView Overrides
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  CGSize leadingButtonBarSize = [_leadingButtonBar sizeThatFits:self.bounds.size];
+  CGRect leadingButtonBarFrame =
+      CGRectMake(0, self.bounds.origin.y, leadingButtonBarSize.width, leadingButtonBarSize.height);
+  _leadingButtonBar.frame = MDCRectFlippedForRTL(leadingButtonBarFrame, self.bounds.size.width,
+                                                 self.mdc_effectiveUserInterfaceLayoutDirection);
+
+  CGSize trailingButtonBarSize = [_trailingButtonBar sizeThatFits:self.bounds.size];
+  CGRect trailingButtonBarFrame =
+      CGRectMake(self.bounds.size.width - trailingButtonBarSize.width, self.bounds.origin.y,
+                 trailingButtonBarSize.width, trailingButtonBarSize.height);
+  _trailingButtonBar.frame = MDCRectFlippedForRTL(trailingButtonBarFrame, self.bounds.size.width,
+                                                  self.mdc_effectiveUserInterfaceLayoutDirection);
+
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+  UIEdgeInsets textInsets = isPad ? kTextPadInsets : kTextInsets;
+
+  CGRect textFrame = UIEdgeInsetsInsetRect(self.bounds, textInsets);
+  textFrame.origin.x += _leadingButtonBar.frame.size.width;
+  textFrame.size.width -= _leadingButtonBar.frame.size.width + _trailingButtonBar.frame.size.width;
+
+  NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
+  paraStyle.lineBreakMode = _titleLabel.lineBreakMode;
+
+  NSDictionary<NSString *, id> *attributes =
+      @{NSFontAttributeName : _titleLabel.font, NSParagraphStyleAttributeName : paraStyle};
+
+  CGSize titleSize = [_titleLabel.text boundingRectWithSize:textFrame.size
+                                                    options:NSStringDrawingTruncatesLastVisibleLine
+                                                 attributes:attributes
+                                                    context:NULL]
+                         .size;
+  titleSize.width = Ceil(titleSize.width);
+  titleSize.height = Ceil(titleSize.height);
+  CGRect titleFrame = CGRectMake(textFrame.origin.x, 0, titleSize.width, titleSize.height);
+  titleFrame = MDCRectFlippedForRTL(titleFrame, self.bounds.size.width,
+                                    self.mdc_effectiveUserInterfaceLayoutDirection);
+  UIControlContentVerticalAlignment titleVerticalAlignment = UIControlContentVerticalAlignmentTop;
+  CGRect alignedFrame = [self mdc_frameAlignedVertically:titleFrame
+                                            withinBounds:textFrame
+                                               alignment:titleVerticalAlignment];
+  _titleLabel.frame =
+      [self mdc_frameAlignedHorizontally:alignedFrame alignment:self.titleAlignment];
+  self.titleView.frame = textFrame;
+
+  // Button and title label alignment
+
+  CGFloat titleTextRectHeight =
+      [_titleLabel textRectForBounds:_titleLabel.bounds limitedToNumberOfLines:0].size.height;
+
+  if (_titleLabel.hidden || titleTextRectHeight <= 0) {
+    _leadingButtonBar.buttonTitleBaseline = 0;
+    _trailingButtonBar.buttonTitleBaseline = 0;
+  } else {
+    // Assumes that the title is center-aligned vertically.
+    CGFloat titleTextOriginY = (_titleLabel.frame.size.height - titleTextRectHeight) / 2;
+    CGFloat titleTextHeight = titleTextOriginY + titleTextRectHeight + _titleLabel.font.descender;
+    CGFloat titleBaseline = _titleLabel.frame.origin.y + titleTextHeight;
+    _leadingButtonBar.buttonTitleBaseline = titleBaseline;
+    _trailingButtonBar.buttonTitleBaseline = titleBaseline;
+  }
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  CGSize intrinsicContentSize = [self intrinsicContentSize];
+  return CGSizeMake(size.width, intrinsicContentSize.height);
+}
+
+- (CGSize)intrinsicContentSize {
+  const BOOL isPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad;
+  CGFloat height = (isPad ? kNavigationBarPadDefaultHeight : kNavigationBarDefaultHeight);
+  return CGSizeMake(UIViewNoIntrinsicMetric, height);
+}
+
+- (MDCNavigationBarTitleAlignment)titleAlignment {
+  return [MDCNavigationBar titleAlignmentFromTextAlignment:_titleLabel.textAlignment];
+}
+
+- (void)setTitleAlignment:(MDCNavigationBarTitleAlignment)titleAlignment {
+  _titleLabel.textAlignment = [MDCNavigationBar textAlignmentFromTitleAlignment:titleAlignment];
+  [self setNeedsLayout];
+}
+
+#pragma mark Private
+
++ (NSTextAlignment)textAlignmentFromTitleAlignment:(MDCNavigationBarTitleAlignment)titleAlignment {
+  switch (titleAlignment) {
+    case MDCNavigationBarTitleAlignmentCenter:
+      return NSTextAlignmentCenter;
+      break;
+    default:
+      NSAssert(NO, @"titleAlignment not understood: %li", (long)titleAlignment);
+    // Intentional fall through logic
+    case MDCNavigationBarTitleAlignmentLeading:
+      return NSTextAlignmentNatural;
+      break;
+  }
+}
+
++ (MDCNavigationBarTitleAlignment)titleAlignmentFromTextAlignment:(NSTextAlignment)textAlignment {
+  switch (textAlignment) {
+    default:
+      NSAssert(NO, @"textAlignment not supported: %li", (long)textAlignment);
+    // Intentional fall through logic
+    case NSTextAlignmentNatural:
+    case NSTextAlignmentLeft:
+      return MDCNavigationBarTitleAlignmentLeading;
+      break;
+    case NSTextAlignmentCenter:
+      return MDCNavigationBarTitleAlignmentCenter;
+      break;
+  }
+}
+
+- (UILabel *)titleLabel {
+  return _titleLabel;
+}
+
+- (MDCButtonBar *)leadingButtonBar {
+  return _leadingButtonBar;
+}
+
+- (MDCButtonBar *)trailingButtonBar {
+  return _trailingButtonBar;
+}
+
+#pragma mark KVO
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context {
+  if (context == kKVOContextMDCNavigationBar) {
+    void (^mainThreadWork)(void) = ^{
+      @synchronized(self->_observedNavigationItemLock) {
+        if (object != _observedNavigationItem) {
+          return;
+        }
+
+        [self setValue:[object valueForKey:keyPath] forKey:keyPath];
+      }
+    };
+
+    // Ensure that UIKit modifications occur on the main thread.
+    if ([NSThread isMainThread]) {
+      mainThreadWork();
+    } else {
+      [[NSOperationQueue mainQueue] addOperationWithBlock:mainThreadWork];
+    }
+
+  } else {
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+  }
+}
+
+#pragma mark Layout
+
+- (CGRect)mdc_frameAlignedVertically:(CGRect)frame
+                        withinBounds:(CGRect)bounds
+                           alignment:(UIControlContentVerticalAlignment)alignment {
+  switch (alignment) {
+    case UIControlContentVerticalAlignmentBottom:
+      return CGRectMake(frame.origin.x, CGRectGetMaxY(bounds) - frame.size.height, frame.size.width,
+                        frame.size.height);
+
+    case UIControlContentVerticalAlignmentCenter: {
+      CGFloat centeredY = Floor((bounds.size.height - frame.size.height) / 2) + bounds.origin.y;
+      return CGRectMake(frame.origin.x, centeredY, frame.size.width, frame.size.height);
+    }
+
+    case UIControlContentVerticalAlignmentTop: {
+      return CGRectMake(frame.origin.x, bounds.origin.y, frame.size.width, frame.size.height);
+    }
+
+    case UIControlContentVerticalAlignmentFill: {
+      return bounds;
+    }
+  }
+}
+
+- (CGRect)mdc_frameAlignedHorizontally:(CGRect)frame
+                             alignment:(MDCNavigationBarTitleAlignment)alignment {
+  switch (alignment) {
+    case MDCNavigationBarTitleAlignmentCenter:
+      return CGRectMake(CGRectGetMaxX(self.bounds) / 2 - frame.size.width / 2, frame.origin.y,
+                        frame.size.width, frame.size.height);
+
+    case MDCNavigationBarTitleAlignmentLeading:
+      return CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
+  }
+}
+
+- (NSArray<UIBarButtonItem *> *)mdc_buttonItemsForLeadingBar {
+  if (!self.leadingItemsSupplementBackButton && self.leadingBarButtonItems.count > 0) {
+    return self.leadingBarButtonItems;
+  }
+
+  NSMutableArray<UIBarButtonItem *> *buttonItems = [NSMutableArray array];
+  if (self.backItem && !self.hidesBackButton) {
+    [buttonItems addObject:self.backItem];
+  }
+  [buttonItems addObjectsFromArray:self.leadingBarButtonItems];
+  return buttonItems;
+}
+
+#pragma mark Colors
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  // Tint color should only modify interactive elements
+  _leadingButtonBar.tintColor = self.tintColor;
+  _trailingButtonBar.tintColor = self.tintColor;
+}
+
+#pragma mark Public
+
+- (void)setTitle:(NSString *)title {
+  // |self.titleTextAttributes| can only be set if |title| is set
+  if (self.titleTextAttributes && title.length > 0) {
+    _titleLabel.attributedText =
+        [[NSAttributedString alloc] initWithString:title attributes:_titleTextAttributes];
+  } else {
+    _titleLabel.text = title;
+  }
+  [self setNeedsLayout];
+}
+
+- (NSString *)title {
+  return _titleLabel.text;
+}
+
+- (void)setTitleView:(UIView *)titleView {
+  if (self.titleView == titleView) {
+    return;
+  }
+  // Ignore sandbag KVO events
+  if ([_observedNavigationItem.titleView isKindOfClass:[MDCNavigationBarSandbagView class]]) {
+    return;
+  }
+  [self.titleView removeFromSuperview];
+  _titleView = titleView;
+  [self addSubview:_titleView];
+
+  _titleLabel.hidden = _titleView != nil;
+
+  [self setNeedsLayout];
+
+  // Swap in the sandbag (so that UINavigationController won't steal our view)
+  if (titleView) {
+    _observedNavigationItem.titleView = [[MDCNavigationBarSandbagView alloc] init];
+  } else if (_observedNavigationItem.titleView) {
+    _observedNavigationItem.titleView = nil;
+  }
+}
+
+- (void)setTitleTextAttributes:(NSDictionary<NSString *, id> *)titleTextAttributes {
+  // If title dictionary is equivalent, no need to make changes
+  if ([_titleTextAttributes isEqualToDictionary:titleTextAttributes]) {
+    return;
+  }
+
+  // Copy attributes dictionary
+  _titleTextAttributes = [titleTextAttributes copy];
+  if (_titleLabel) {
+    // |_titleTextAttributes| can only be set if |self.title| is set
+    if (_titleTextAttributes && self.title.length > 0) {
+      // Set label text as newly created attributed string with attributes if non-nil
+      _titleLabel.attributedText =
+          [[NSAttributedString alloc] initWithString:self.title attributes:_titleTextAttributes];
+    } else {
+      // Otherwise set titleLabel text property
+      _titleLabel.text = self.title;
+    }
+    [self setNeedsLayout];
+  }
+}
+
+- (void)setLeadingBarButtonItems:(NSArray<UIBarButtonItem *> *)leadingBarButtonItems {
+  _leadingBarButtonItems = [leadingBarButtonItems copy];
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setTrailingBarButtonItems:(NSArray<UIBarButtonItem *> *)trailingBarButtonItems {
+  _trailingBarButtonItems = [trailingBarButtonItems copy];
+  _trailingButtonBar.items = _trailingBarButtonItems;
+  [self setNeedsLayout];
+}
+
+- (void)setLeadingBarButtonItem:(UIBarButtonItem *)leadingBarButtonItem {
+  self.leadingBarButtonItems = leadingBarButtonItem ? @[ leadingBarButtonItem ] : nil;
+}
+
+- (UIBarButtonItem *)leadingBarButtonItem {
+  return [self.leadingBarButtonItems firstObject];
+}
+
+- (void)setTrailingBarButtonItem:(UIBarButtonItem *)trailingBarButtonItem {
+  self.trailingBarButtonItems = trailingBarButtonItem ? @[ trailingBarButtonItem ] : nil;
+}
+
+- (UIBarButtonItem *)trailingBarButtonItem {
+  return [self.trailingBarButtonItems firstObject];
+}
+
+- (void)setBackBarButtonItem:(UIBarButtonItem *)backBarButtonItem {
+  self.backItem = backBarButtonItem;
+}
+
+- (UIBarButtonItem *)backBarButtonItem {
+  return self.backItem;
+}
+
+- (void)setBackItem:(UIBarButtonItem *)backItem {
+  if (_backItem == backItem) {
+    return;
+  }
+  _backItem = backItem;
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setHidesBackButton:(BOOL)hidesBackButton {
+  if (_hidesBackButton == hidesBackButton) {
+    return;
+  }
+  _hidesBackButton = hidesBackButton;
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setLeadingItemsSupplementBackButton:(BOOL)leadingItemsSupplementBackButton {
+  if (_leadingItemsSupplementBackButton == leadingItemsSupplementBackButton) {
+    return;
+  }
+  _leadingItemsSupplementBackButton = leadingItemsSupplementBackButton;
+  _leadingButtonBar.items = [self mdc_buttonItemsForLeadingBar];
+  [self setNeedsLayout];
+}
+
+- (void)setObservedNavigationItem:(UINavigationItem *)navigationItem {
+  @synchronized(_observedNavigationItemLock) {
+    if (navigationItem == _observedNavigationItem) {
+      return;
+    }
+
+    NSArray<NSString *> *keyPaths = MDCNavigationBarNavigationItemKVOPaths();
+    for (NSString *keyPath in keyPaths) {
+      [_observedNavigationItem removeObserver:self
+                                   forKeyPath:keyPath
+                                      context:kKVOContextMDCNavigationBar];
+    }
+
+    _observedNavigationItem = navigationItem;
+
+    NSKeyValueObservingOptions options =
+        (NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial);
+    for (NSString *keyPath in keyPaths) {
+      [_observedNavigationItem addObserver:self
+                                forKeyPath:keyPath
+                                   options:options
+                                   context:kKVOContextMDCNavigationBar];
+    }
+  }
+}
+
+- (void)observeNavigationItem:(UINavigationItem *)navigationItem {
+  [self setObservedNavigationItem:navigationItem];
+}
+
+- (void)unobserveNavigationItem {
+  [self setObservedNavigationItem:nil];
+}
+
+#pragma mark UINavigationItem interface matching
+
+- (NSArray<UIBarButtonItem *> *)leftBarButtonItems {
+  return self.leadingBarButtonItems;
+}
+
+- (void)setLeftBarButtonItems:(NSArray<UIBarButtonItem *> *)leftBarButtonItems {
+  self.leadingBarButtonItems = leftBarButtonItems;
+}
+
+- (NSArray<UIBarButtonItem *> *)rightBarButtonItems {
+  return self.trailingBarButtonItems;
+}
+
+- (void)setRightBarButtonItems:(NSArray<UIBarButtonItem *> *)rightBarButtonItems {
+  self.trailingBarButtonItems = rightBarButtonItems;
+}
+
+- (UIBarButtonItem *)leftBarButtonItem {
+  return self.leadingBarButtonItem;
+}
+
+- (void)setLeftBarButtonItem:(UIBarButtonItem *)leftBarButtonItem {
+  self.leadingBarButtonItem = leftBarButtonItem;
+}
+
+- (UIBarButtonItem *)rightBarButtonItem {
+  return self.trailingBarButtonItem;
+}
+
+- (void)setRightBarButtonItem:(UIBarButtonItem *)rightBarButtonItem {
+  self.trailingBarButtonItem = rightBarButtonItem;
+}
+
+- (BOOL)leftItemsSupplementBackButton {
+  return self.leadingItemsSupplementBackButton;
+}
+
+- (void)setLeftItemsSupplementBackButton:(BOOL)leftItemsSupplementBackButton {
+  self.leadingItemsSupplementBackButton = leftItemsSupplementBackButton;
+}
+
+#pragma mark deprecated
+
+- (void)setTextAlignment:(NSTextAlignment)textAlignment {
+  [self setTitleAlignment:[MDCNavigationBar titleAlignmentFromTextAlignment:textAlignment]];
+}
+
+- (NSTextAlignment)textAlignment {
+  return [MDCNavigationBar textAlignmentFromTitleAlignment:self.titleAlignment];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
new file mode 100644
index 0000000..f116c9d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/NavigationBar/src/MaterialNavigationBar.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCNavigationBar.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
new file mode 100644
index 0000000..23b988c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.h
@@ -0,0 +1,48 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Subclasses UIWindow to allow overlays to cover all content.
+
+ Overlays will be the full size of the screen, or when multitasking use all available screen space,
+ and will be rotated as appropriate based on device orientation. For performance, owners of overlay
+ views should set the @c hidden property to YES when the overlay is not in use.
+ */
+@interface MDCOverlayWindow : UIWindow
+
+/**
+ Notifies the window that the given overlay view should be shown.
+
+ Overlay owners must call this method to ensure that the overlay is actually displayed over the
+ window's primary content.
+
+ @param overlay The overlay being displayed.
+ @param level The UIWindowLevel to display the overlay on.
+ */
+- (void)activateOverlay:(UIView *)overlay withLevel:(UIWindowLevel)level;
+
+/**
+ Notifies the window that the given overlay is no longer active.
+
+ Overlay owners should still hide their overlay before calling this method.
+
+ @param overlay The overlay being displayed.
+ */
+- (void)deactivateOverlay:(UIView *)overlay;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.m
new file mode 100644
index 0000000..ef88d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MDCOverlayWindow.m
@@ -0,0 +1,282 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayWindow.h"
+
+#import <objc/runtime.h>
+
+#import "UIApplication+AppExtensions.h"
+
+/**
+ A container view for overlay views.
+
+ Used by MDCOverlayWindow, overlay views are added to the overlay window container when
+ @c activateOverlay is called and removed from the overlay window when @c deactivateOverlay is
+ called.
+ */
+@interface MDCOverlayWindowContainerView : UIView
+@end
+
+@interface MDCOverlayWindow ()
+
+@property(nonatomic, strong) NSMutableArray *overlays;
+@property(nonatomic, strong) MDCOverlayWindowContainerView *overlayView;
+
+// Forward declaration so that MDCOverlayWindowContainerView can call this method.
+- (void)noteOverlayRemoved:(UIView *)overlay;
+
+@end
+
+@implementation MDCOverlayWindowContainerView
+
+- (void)willRemoveSubview:(UIView *)subview {
+  [super willRemoveSubview:subview];
+
+  MDCOverlayWindow *window = (MDCOverlayWindow *)self.window;
+  [window noteOverlayRemoved:subview];
+}
+
+// Only allow a tap if it explicitly hit one of the overlays. Otherwise, behave as if this view
+// doesn't exist at all.
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
+  UIView *hitView = [super hitTest:point withEvent:event];
+  return hitView == self ? nil : hitView;
+}
+
+@end
+
+@implementation MDCOverlayWindow
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    [self commonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonInit];
+  }
+  return self;
+}
+
+- (void)commonInit {
+  self.backgroundColor = [UIColor clearColor];
+
+  _overlays = [[NSMutableArray alloc] init];
+
+  _overlayView = [[MDCOverlayWindowContainerView alloc] initWithFrame:self.bounds];
+  _overlayView.autoresizingMask =
+      (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+  _overlayView.backgroundColor = [UIColor clearColor];
+  [self addSubview:_overlayView];
+
+  NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+  [nc addObserver:self
+         selector:@selector(handleRotationNotification:)
+             name:UIApplicationWillChangeStatusBarOrientationNotification
+           object:nil];
+
+  // Set a sane initial position.
+  [self updateOverlayViewForOrientation:[[UIApplication mdc_safeSharedApplication]
+                                            statusBarOrientation]];
+
+  // Set a sane hidden state.
+  [self updateOverlayHiddenState];
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark - Rotation
+
+- (void)updateOverlayViewForOrientation:(UIInterfaceOrientation)orientation {
+  // On iOS 8, the window orientation is corrected logically after transforms, so there is
+  // no need to apply this transform correction like we do for iOS 7 and below.
+  BOOL hasFixedCoordinateSpace = NO;
+  UIScreen *screen = [UIScreen mainScreen];
+  hasFixedCoordinateSpace = [screen respondsToSelector:@selector(fixedCoordinateSpace)];
+
+  if (!hasFixedCoordinateSpace) {
+    CGAffineTransform transform = CGAffineTransformIdentity;
+    BOOL swapBounds = NO;
+
+    switch (orientation) {
+      case UIInterfaceOrientationLandscapeLeft:
+        transform = CGAffineTransformMakeRotation((CGFloat)-M_PI_2);
+        swapBounds = YES;
+        break;
+      case UIInterfaceOrientationLandscapeRight:
+        transform = CGAffineTransformMakeRotation((CGFloat)M_PI_2);
+        swapBounds = YES;
+        break;
+      case UIInterfaceOrientationPortraitUpsideDown:
+        transform = CGAffineTransformMakeRotation((CGFloat)M_PI);
+        break;
+      case UIInterfaceOrientationPortrait:
+      default:
+        break;
+    }
+
+    CGRect bounds = self.bounds;
+
+    if (swapBounds) {
+      bounds = CGRectMake(0, 0, bounds.size.height, bounds.size.width);
+    }
+    self.overlayView.bounds = bounds;
+    self.overlayView.transform = transform;
+    [self.overlayView layoutIfNeeded];
+  }
+}
+
+// This method is called within an animation block, so we simply need to update the overlay view.
+- (void)handleRotationNotification:(NSNotification *)notification {
+  UIInterfaceOrientation orientation =
+      [notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
+  [self updateOverlayViewForOrientation:orientation];
+}
+
+#pragma mark - Window positioning
+
+// Regardless of what was added to this window, ensure that the overlay view is on top.
+- (void)didAddSubview:(UIView *)subview {
+  [super didAddSubview:subview];
+
+  [self bringSubviewToFront:self.overlayView];
+}
+
+#pragma mark - Overlay Activation
+
+- (void)updateOverlayHiddenState {
+  BOOL hasOverlays = [self.overlays count] > 0;
+  self.overlayView.hidden = !hasOverlays;
+  [self updateAccessibilityIsModal];
+}
+
+- (void)updateAccessibilityIsModal {
+  BOOL containsModal = NO;
+  for (UIView *overlay in self.overlays) {
+    if (overlay.accessibilityViewIsModal) {
+      containsModal = YES;
+      break;
+    }
+  }
+  self.overlayView.accessibilityViewIsModal = containsModal;
+}
+
+- (void)noteOverlayRemoved:(UIView *)overlay {
+  if (!overlay) {
+    return;
+  }
+
+  // If the overlay argument wasn't managed by us, don't do anything when it goes away.
+  if (![self.overlays containsObject:overlay]) {
+    return;
+  }
+
+  // Clean up the level information stored on the view.
+  [self removeLevelForOverlay:overlay];
+
+  // Stop tracking the overlay view.
+  [self.overlays removeObject:overlay];
+
+  // Show or hide ourself as needed.
+  [self updateOverlayHiddenState];
+}
+
+- (void)activateOverlay:(UIView *)overlay withLevel:(UIWindowLevel)level {
+  if (!overlay) {
+    return;
+  }
+
+  // Make sure the that the overlay is out of the view hierarchy, even our own (if this is a
+  // re-activation with a new level). If @c overlay is already in the overlay view, then this call
+  // will take care of cleaning up @c self.overlays, by way of @c noteOverlayRemoved:.
+  [overlay removeFromSuperview];
+
+  // Default to adding the overlay at the very end (on top) of all the other overlays. We'll check
+  // the existing overlays to see if this one needs to go in before.
+  __block NSUInteger insertionIndex = self.overlays.count;
+
+  // Because @c self.overlays is already sorted by level, we can pick the first index which has a
+  // level larger than @c level.
+  [self.overlays enumerateObjectsUsingBlock:^(UIView *existing, NSUInteger idx, BOOL *stop) {
+    UIWindowLevel existingLevel = [self windowLevelForOverlay:existing];
+    if (level < existingLevel) {
+      insertionIndex = idx;
+      *stop = YES;
+    }
+  }];
+
+  // Make sure that the overlay is as large as the overlay container view before adding it.
+  overlay.bounds = self.overlayView.bounds;
+  overlay.center = CGPointMake(CGRectGetMidX(overlay.bounds), CGRectGetMidY(overlay.bounds));
+  overlay.translatesAutoresizingMaskIntoConstraints = YES;
+  overlay.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
+  [self setLevel:level forOverlay:overlay];
+  [self.overlayView insertSubview:overlay atIndex:insertionIndex];
+  [self.overlays insertObject:overlay atIndex:insertionIndex];
+
+  [self updateOverlayHiddenState];
+}
+
+- (void)deactivateOverlay:(UIView *)overlay {
+  if (!overlay) {
+    return;
+  }
+
+  // If the overlay wasn't managed by us, don't do anything to deactivate it.
+  if (![self.overlays containsObject:overlay]) {
+    return;
+  }
+
+  // If @c overlay is already in the overlay view, then this call will take care of cleaning up
+  // @c self.overlays by way of @c noteOverlayRemoved:.
+  [overlay removeFromSuperview];
+}
+
+#pragma mark - Level Storage
+
+static char kLevelKey;
+
+- (UIWindowLevel)windowLevelForOverlay:(UIView *)overlay {
+  NSNumber *levelObject = objc_getAssociatedObject(self, &kLevelKey);
+  return [levelObject floatValue];
+}
+
+- (void)setLevel:(UIWindowLevel)level forOverlay:(UIView *)overlay {
+  NSNumber *levelObject = @(level);
+  objc_setAssociatedObject(overlay, &kLevelKey, levelObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+- (void)removeLevelForOverlay:(UIView *)overlay {
+  objc_setAssociatedObject(overlay, &kLevelKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
new file mode 100644
index 0000000..75d2373
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/OverlayWindow/src/MaterialOverlayWindow.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayWindow.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.h
new file mode 100644
index 0000000..723772c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.h
@@ -0,0 +1,129 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ A Material page control.
+
+ This control is designed to be a drop-in replacement for UIPageControl, but adhering to the
+ Material Design specifications for animation and layout.
+
+ The UIControlEventValueChanged control event is sent when the user changes the current page.
+
+ ### UIScrollViewDelegate
+
+ In order for the Page Control to respond correctly to scroll events set the scrollView.delegate to
+ your pageControl:
+
+   scrollView.delegate = pageControl;
+
+ or forward the UIScrollViewDelegate methods:
+
+   @c scrollViewDidScroll:
+   @c scrollViewDidEndDecelerating:
+   @c scrollViewDidEndScrollingAnimation:
+
+ */
+@interface MDCPageControl : UIControl <UIScrollViewDelegate>
+
+#pragma mark Managing the page
+
+/**
+ The number of page indicators in the control.
+
+ Negative values are clamped to 0.
+
+ The default value is 0.
+ */
+@property(nonatomic) NSInteger numberOfPages;
+
+/**
+ The current page indicator of the control.
+
+ See setCurrentPage:animated: for animated version.
+
+ Values outside the possible range are clamped within [0, numberOfPages-1].
+
+ The default value is 0.
+ */
+@property(nonatomic) NSInteger currentPage;
+
+/**
+ Sets the current page indicator of the control.
+
+ @param currentPage Index of the desired page indicator. Values outside the possible range are
+                    clamped within [0, numberOfPages-1].
+ @param animated    YES the change will be animated; otherwise, NO.
+ */
+- (void)setCurrentPage:(NSInteger)currentPage animated:(BOOL)animated;
+
+/**
+ A Boolean value that controls whether the page control is hidden when there is only one page.
+
+ The default value is NO.
+ */
+@property(nonatomic) BOOL hidesForSinglePage;
+
+#pragma mark Configuring the page colors
+
+/** The color of the non-current page indicators. */
+@property(nonatomic, strong, nullable) UIColor *pageIndicatorTintColor UI_APPEARANCE_SELECTOR;
+
+/** The color of the current page indicator. */
+@property(nonatomic, strong, nullable)
+    UIColor *currentPageIndicatorTintColor UI_APPEARANCE_SELECTOR;
+
+#pragma mark Configuring the page behavior
+
+/**
+ A Boolean value that controls when the current page is displayed.
+
+ If enabled, user interactions that cause the current page to change will not be visually
+ reflected until -updateCurrentPageDisplay is called.
+
+ The default value is NO.
+ */
+@property(nonatomic) BOOL defersCurrentPageDisplay;
+
+/**
+ Updates the page indicator to the current page.
+
+ This method is ignored if defersCurrentPageDisplay is NO.
+ */
+- (void)updateCurrentPageDisplay;
+
+#pragma mark Resizing the control
+
+/**
+ Returns the size required to accommodate the given number of pages.
+
+ @param pageCount The number of pages for which an estimated size should be returned.
+ */
+- (CGSize)sizeForNumberOfPages:(NSInteger)pageCount;
+
+#pragma mark UIScrollView interface
+
+/** The owner must call this to inform the control that scrolling has occurred. */
+- (void)scrollViewDidScroll:(nonnull UIScrollView *)scrollView;
+
+/** The owner must call this when the scrollView has ended its deleration. */
+- (void)scrollViewDidEndDecelerating:(nonnull UIScrollView *)scrollView;
+
+/** The owner must call this when the scrollView has ended its scrolling animation. */
+- (void)scrollViewDidEndScrollingAnimation:(nonnull UIScrollView *)scrollView;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.m
new file mode 100644
index 0000000..193101e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MDCPageControl.m
@@ -0,0 +1,520 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControl.h"
+
+#import "private/MDCPageControlIndicator.h"
+#import "private/MDCPageControlTrackLayer.h"
+#import "private/MaterialPageControlStrings.h"
+#import "private/MaterialPageControlStrings_table.h"
+
+#import <tgmath.h>
+
+// The Bundle for string resources.
+static NSString *const kMaterialPageControlBundle = @"MaterialPageControl.bundle";
+
+// The keypath for the content offset of a scrollview.
+static NSString *const kMaterialPageControlScrollViewContentOffset = @"bounds.origin";
+
+// Matches native UIPageControl minimum height.
+static const CGFloat kPageControlMinimumHeight = 37.0f;
+
+// Matches native UIPageControl indicator radius.
+static const CGFloat kPageControlIndicatorRadius = 3.5f;
+
+// Matches native UIPageControl indicator spacing margin.
+static const CGFloat kPageControlIndicatorMargin = kPageControlIndicatorRadius * 2.5;
+
+// Delay for revealing indicators staggered towards current page indicator.
+static const NSTimeInterval kPageControlIndicatorShowDelay = 0.04f;
+
+// Default indicator opacity.
+static const CGFloat kPageControlIndicatorDefaultOpacity = 0.5f;
+
+// Default white level for current page indicator color.
+static const CGFloat kPageControlCurrentPageIndicatorWhiteColor = 0.38f;
+
+// Default white level for page indicator color.
+static const CGFloat kPageControlPageIndicatorWhiteColor = 0.62f;
+
+// Normalize to [0,1] range.
+static inline CGFloat normalizeValue(CGFloat value, CGFloat minRange, CGFloat maxRange) {
+  CGFloat diff = maxRange - minRange;
+  return (diff > 0) ? ((value - minRange) / diff) : 0;
+}
+
+@implementation MDCPageControl {
+  UIView *_containerView;
+  NSMutableArray<MDCPageControlIndicator *> *_indicators;
+  NSMutableArray<NSValue *> *_indicatorPositions;
+  MDCPageControlIndicator *_animatedIndicator;
+  MDCPageControlTrackLayer *_trackLayer;
+  CGFloat _trackLength;
+  BOOL _isDeferredScrolling;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCPageControlInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCPageControlInit];
+  }
+  return self;
+}
+
+- (void)commonMDCPageControlInit {
+  CGFloat radius = kPageControlIndicatorRadius;
+  CGFloat topEdge = (CGFloat)(floor(CGRectGetHeight(self.bounds) - (radius * 2)) / 2);
+  CGRect containerFrame = CGRectMake(0, topEdge, CGRectGetWidth(self.bounds), radius * 2);
+  _containerView = [[UIView alloc] initWithFrame:containerFrame];
+
+  _trackLayer = [[MDCPageControlTrackLayer alloc] initWithRadius:radius];
+  [_containerView.layer addSublayer:_trackLayer];
+  _containerView.autoresizingMask =
+      UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin |
+      UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
+  [self addSubview:_containerView];
+
+  // Defaults.
+  _currentPage = 0;
+  _currentPageIndicatorTintColor =
+      [UIColor colorWithWhite:kPageControlCurrentPageIndicatorWhiteColor alpha:1];
+  _pageIndicatorTintColor = [UIColor colorWithWhite:kPageControlPageIndicatorWhiteColor alpha:1];
+
+  UITapGestureRecognizer *tapGestureRecognizer =
+      [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
+  [self addGestureRecognizer:tapGestureRecognizer];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  if (_hidesForSinglePage && [_indicators count] == 1) {
+    self.hidden = YES;
+    return;
+  }
+  self.hidden = NO;
+  for (MDCPageControlIndicator *indicator in _indicators) {
+    NSInteger indicatorIndex = [_indicators indexOfObject:indicator];
+    if (indicatorIndex == _currentPage) {
+      indicator.hidden = YES;
+    }
+    indicator.color = _pageIndicatorTintColor;
+  }
+  _animatedIndicator.color = _currentPageIndicatorTintColor;
+  _trackLayer.trackColor = _pageIndicatorTintColor;
+
+  // TODO(cjcox): Add back in RTL once we get the view category ready.
+  // This view must be mirrored by flipping instead of relayout, because we want to mirror
+  // the view itself, not its subviews.
+  //  if ([self class] == [MDCPageControl class]) {
+  //    [self mdc_flipViewForRTL];
+  //  }
+}
+
+- (void)setNumberOfPages:(NSInteger)numberOfPages {
+  _numberOfPages = MAX(0, numberOfPages);
+  _currentPage = MAX(0, MIN(_numberOfPages - 1, _currentPage));
+  [self resetControl];
+}
+
+- (void)setCurrentPage:(NSInteger)currentPage {
+  [self setCurrentPage:currentPage animated:NO];
+}
+
+- (void)setCurrentPage:(NSInteger)currentPage animated:(BOOL)animated {
+  [self setCurrentPage:currentPage animated:animated duration:0];
+}
+- (void)setCurrentPage:(NSInteger)currentPage
+              animated:(BOOL)animated
+              duration:(NSTimeInterval)duration {
+  currentPage = MAX(0, MIN(_numberOfPages - 1, currentPage));
+  NSInteger previousPage = _currentPage;
+  BOOL shouldReverse = (previousPage > currentPage);
+  _currentPage = currentPage;
+
+  if (animated) {
+    // Draw and extend track.
+    CGPoint startPoint = [_indicatorPositions[previousPage] CGPointValue];
+    CGPoint endPoint = [_indicatorPositions[currentPage] CGPointValue];
+    if (shouldReverse) {
+      startPoint = [_indicatorPositions[currentPage] CGPointValue];
+      endPoint = [_indicatorPositions[previousPage] CGPointValue];
+    }
+
+    // Remove track and reveal hidden indicators staggered towards current page indicator. Reveal
+    // indicators in reverse if scrolling to left.
+    void (^completionBlock)() = ^{
+      // We are using the delay to increase the time between the end of the extension of the track
+      // ahead of the dots movement and the contraction of the track under the dot at the
+      // destination.
+      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(duration * NSEC_PER_SEC)),
+                     dispatch_get_main_queue(), ^{
+                       [_trackLayer removeTrackTowardsPoint:shouldReverse ? startPoint : endPoint
+                                                 completion:^{
+                                                   // Once track is removed, reveal indicators once
+                                                   // more to ensure
+                                                   // no hidden indicators remain.
+                                                   [self revealIndicatorsReversed:shouldReverse];
+                                                 }];
+                       [self revealIndicatorsReversed:shouldReverse];
+                     });
+    };
+
+    [_trackLayer drawAndExtendTrackFromStartPoint:startPoint
+                                       toEndPoint:endPoint
+                                       completion:completionBlock];
+  } else {
+    // If not animated, simply move indicator to new position and reset track.
+    CGPoint point = [_indicatorPositions[currentPage] CGPointValue];
+    [_animatedIndicator updateIndicatorTransformX:point.x - kPageControlIndicatorRadius];
+    [_trackLayer resetAtPoint:point];
+
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    [_indicators[previousPage] setHidden:NO];
+    [CATransaction commit];
+  }
+}
+
+- (void)setHidesForSinglePage:(BOOL)hidesForSinglePage {
+  _hidesForSinglePage = hidesForSinglePage;
+  [self setNeedsLayout];
+}
+
+- (CGSize)sizeForNumberOfPages:(NSInteger)pageCount {
+  CGFloat radius = kPageControlIndicatorRadius;
+  CGFloat margin = kPageControlIndicatorMargin;
+  CGFloat width = pageCount * ((radius * 2) + margin) - margin;
+  CGFloat height = MAX(kPageControlMinimumHeight, radius * 2);
+  return CGSizeMake(width, height);
+}
+
+- (BOOL)isPageIndexValid:(NSInteger)nextPage {
+  // Returns YES if next page is within bounds of page control. Otherwise NO.
+  return (nextPage >= 0 && nextPage < _numberOfPages);
+}
+
+#pragma mark - UIView(UIViewGeometry)
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return [self sizeForNumberOfPages:_numberOfPages];
+}
+
+#pragma mark - Colors
+
+- (void)setPageIndicatorTintColor:(UIColor *)pageIndicatorTintColor {
+  _pageIndicatorTintColor = pageIndicatorTintColor;
+  [self setNeedsLayout];
+}
+
+- (void)setCurrentPageIndicatorTintColor:(UIColor *)currentPageIndicatorTintColor {
+  _currentPageIndicatorTintColor = currentPageIndicatorTintColor;
+  [self setNeedsLayout];
+}
+
+#pragma mark - Scrolling
+
+- (NSInteger)scrolledPageNumber:(UIScrollView *)scrollView {
+  // Returns paged index of scrollView.
+  NSInteger unboundedPageNumber = lround(scrollView.contentOffset.x / scrollView.frame.size.width);
+  return MAX(0, MIN(_numberOfPages - 1, unboundedPageNumber));
+}
+
+- (CGFloat)scrolledPercentage:(UIScrollView *)scrollView {
+  // Returns scrolled percentage of scrollView from 0 to 1. If the scrollView has bounced past
+  // the edge of its content, it will return either a negative value or value above 1.
+  return normalizeValue(scrollView.contentOffset.x, 0,
+                        scrollView.contentSize.width - scrollView.frame.size.width);
+}
+
+#pragma mark - UIScrollViewDelegate Observers
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+  CGFloat scrolledPercentage = [self scrolledPercentage:scrollView];
+
+  // Detect if we are getting called from an animation block
+  if ([scrollView.layer.animationKeys containsObject:kMaterialPageControlScrollViewContentOffset]) {
+    CAAnimation *animation =
+        [scrollView.layer animationForKey:kMaterialPageControlScrollViewContentOffset];
+
+    // If the animation block has a delay it translates to the beginTime of the CAAnimation. We need
+    // to ensure that we delay our animation of the page control to keep in sync with the animation
+    // of the scrollView.contentOffset.
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animation.beginTime * NSEC_PER_SEC)),
+                   dispatch_get_main_queue(), ^{
+                     NSInteger currentPage = [self scrolledPageNumber:scrollView];
+                     [self setCurrentPage:currentPage animated:YES duration:animation.duration];
+
+                     CGFloat transformX = scrolledPercentage * _trackLength;
+                     [_animatedIndicator updateIndicatorTransformX:transformX
+                                                          animated:YES
+                                                          duration:animation.duration
+                                               mediaTimingFunction:animation.timingFunction];
+                   });
+
+  } else if (scrolledPercentage >= 0 && scrolledPercentage <= 1) {
+    // Update active indicator position.
+    CGFloat transformX = scrolledPercentage * _trackLength;
+    if (!_isDeferredScrolling) {
+      [_animatedIndicator updateIndicatorTransformX:transformX];
+    }
+
+    // Determine endpoints for drawing track depending on direction scrolled.
+    NSInteger scrolledPageNumber = [self scrolledPageNumber:scrollView];
+    CGPoint startPoint = [_indicatorPositions[scrolledPageNumber] CGPointValue];
+    CGPoint endPoint = startPoint;
+    CGFloat radius = kPageControlIndicatorRadius;
+    if (transformX > startPoint.x - radius) {
+      endPoint = [_indicatorPositions[scrolledPageNumber + 1] CGPointValue];
+    } else if (transformX < startPoint.x - radius) {
+      startPoint = [_indicatorPositions[scrolledPageNumber - 1] CGPointValue];
+    }
+
+    if (scrollView.isDragging) {
+      // Draw or extend track.
+      if (_trackLayer.isTrackHidden) {
+        [_trackLayer drawTrackFromStartPoint:startPoint toEndPoint:endPoint];
+      } else {
+        [_trackLayer extendTrackFromStartPoint:startPoint toEndPoint:endPoint];
+      }
+    }
+
+    // Hide indicators to be shown with animated reveal once track is removed.
+    if (!_isDeferredScrolling) {
+      [_indicators[scrolledPageNumber] setHidden:YES];
+    }
+  }
+}
+
+- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
+  // Remove track towards current active indicator position.
+  NSInteger scrolledPageNumber = [self scrolledPageNumber:scrollView];
+  CGPoint point = [_indicatorPositions[scrolledPageNumber] CGPointValue];
+  BOOL shouldReverse = (_currentPage > scrolledPageNumber);
+  BOOL sendAction = (_currentPage != scrolledPageNumber);
+  _currentPage = scrolledPageNumber;
+
+  [_trackLayer removeTrackTowardsPoint:point
+                            completion:^{
+                              // Animate hidden indicators once more when completed to ensure all
+                              // indicators
+                              // have been revealed.
+                              [self revealIndicatorsReversed:shouldReverse];
+                            }];
+
+  // Animate hidden indicators staggered towards current page indicator. Show indicators
+  // in reverse if scrolling to left.
+  [self revealIndicatorsReversed:shouldReverse];
+
+  // Send notification if new scrolled page.
+  if (sendAction) {
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
+  _isDeferredScrolling = NO;
+  NSInteger scrolledPageNumber = [self scrolledPageNumber:scrollView];
+  BOOL shouldReverse = (_currentPage > scrolledPageNumber);
+  _currentPage = scrolledPageNumber;
+  [self revealIndicatorsReversed:shouldReverse];
+}
+
+#pragma mark - Indicators
+
+- (void)revealIndicatorsReversed:(BOOL)reversed {
+  // Animate hidden indicators staggered with delay.
+  NSArray<MDCPageControlIndicator *> *indicators =
+      reversed ? [[_indicators reverseObjectEnumerator] allObjects] : _indicators;
+  NSInteger count = 0;
+  for (MDCPageControlIndicator *indicator in indicators) {
+    // Determine if this is the current page indicator.
+    NSInteger indicatorIndex = [indicators indexOfObject:indicator];
+    if (reversed) {
+      indicatorIndex = [indicators count] - 1 - indicatorIndex;
+    }
+    BOOL isCurrentPageIndicator = indicatorIndex == _currentPage;
+
+    // Reveal indicators if hidden and not current page indicator.
+    if (indicator.isHidden && !isCurrentPageIndicator) {
+      dispatch_time_t popTime = dispatch_time(
+          DISPATCH_TIME_NOW, (int64_t)(kPageControlIndicatorShowDelay * count * NSEC_PER_SEC));
+      dispatch_after(popTime, dispatch_get_main_queue(), ^{
+        [indicator revealIndicator];
+      });
+      count++;
+    }
+  }
+}
+
+#pragma mark - UIGestureRecognizer
+
+- (void)handleTapGesture:(UITapGestureRecognizer *)gesture {
+  CGPoint touchPoint = [gesture locationInView:self];
+  BOOL willDecrement = touchPoint.x < CGRectGetMidX(self.bounds);
+  NSInteger nextPage;
+  if (willDecrement) {
+    nextPage = _currentPage - 1;
+  } else {
+    nextPage = _currentPage + 1;
+  }
+
+  // Quit if scrolling past bounds.
+  if ([self isPageIndexValid:nextPage]) {
+    if (_defersCurrentPageDisplay) {
+      _isDeferredScrolling = YES;
+      _currentPage = nextPage;
+    } else {
+      [self setCurrentPage:nextPage animated:YES];
+    }
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+- (void)updateCurrentPageDisplay {
+  // If _defersCurrentPageDisplay = YES, then update control only when this method is called.
+  if (_defersCurrentPageDisplay && [self isPageIndexValid:_currentPage]) {
+    [self setCurrentPage:_currentPage];
+
+    // Reset hidden state of indicators.
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    for (int i = 0; i < _numberOfPages; i++) {
+      MDCPageControlIndicator *indicator = _indicators[i];
+      indicator.hidden = (i == _currentPage) ? YES : NO;
+    }
+    [CATransaction commit];
+  }
+}
+
+#pragma mark - Accessibility
+
+- (BOOL)isAccessibilityElement {
+  return YES;
+}
+
+- (NSString *)accessibilityLabel {
+  return
+      [[self class] pageControlAccessibilityLabelWithPage:_currentPage + 1 ofPages:_numberOfPages];
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  return UIAccessibilityTraitAdjustable;
+}
+
+- (void)accessibilityIncrement {
+  // Quit if scrolling past bounds.
+  NSInteger nextPage = _currentPage + 1;
+  if ([self isPageIndexValid:nextPage]) {
+    [self setCurrentPage:nextPage animated:YES];
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    [self accessibilityLabel]);
+  }
+}
+
+- (void)accessibilityDecrement {
+  // Quit if scrolling past bounds.
+  NSInteger nextPage = _currentPage - 1;
+  if ([self isPageIndexValid:nextPage]) {
+    [self setCurrentPage:nextPage animated:YES];
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    [self accessibilityLabel]);
+  }
+}
+
+#pragma mark - Private
+
+- (void)resetControl {
+  // Clear indicators.
+  for (CALayer *layer in [_containerView.layer.sublayers copy]) {
+    if (layer != _trackLayer) {
+      [layer removeFromSuperlayer];
+    }
+  }
+  _indicators = [NSMutableArray arrayWithCapacity:_numberOfPages];
+  _indicatorPositions = [NSMutableArray arrayWithCapacity:_numberOfPages];
+
+  // Create indicators.
+  CGFloat radius = kPageControlIndicatorRadius;
+  CGFloat margin = kPageControlIndicatorMargin;
+  for (int i = 0; i < _numberOfPages; i++) {
+    CGFloat offsetX = i * (margin + (radius * 2));
+    CGFloat offsetY = radius;
+    CGPoint center = CGPointMake(offsetX + radius, offsetY);
+    MDCPageControlIndicator *indicator =
+        [[MDCPageControlIndicator alloc] initWithCenter:center radius:radius];
+    indicator.opacity = kPageControlIndicatorDefaultOpacity;
+    [_containerView.layer addSublayer:indicator];
+    [_indicators addObject:indicator];
+    [_indicatorPositions addObject:[NSValue valueWithCGPoint:indicator.position]];
+  }
+
+  // Resize container view to keep indicators centered.
+  CGFloat frameWidth = _containerView.frame.size.width;
+  CGSize controlSize = [self sizeForNumberOfPages:_numberOfPages];
+  _containerView.frame = CGRectInset(_containerView.frame, (frameWidth - controlSize.width) / 2, 0);
+  _trackLength = CGRectGetWidth(_containerView.frame) - (radius * 2);
+
+  // Add animated indicator that will travel freely across the container. Its transform will be
+  // updated by calling its -updateIndicatorTransformX method.
+  CGPoint center = CGPointMake(radius, radius);
+  _animatedIndicator = [[MDCPageControlIndicator alloc] initWithCenter:center radius:radius];
+  [_containerView.layer addSublayer:_animatedIndicator];
+
+  [self setNeedsLayout];
+}
+
+#pragma mark - Strings
+
++ (NSString *)pageControlAccessibilityLabelWithPage:(NSInteger)currentPage
+                                            ofPages:(NSInteger)ofPages {
+  NSString *key = kMaterialPageControlStringTable[kStr_MaterialPageControlAccessibilityLabel];
+  NSString *localizedString = NSLocalizedStringFromTableInBundle(
+      key, kMaterialPageControlStringsTableName, [self bundle], @"page {number} of {total number}");
+  return [NSString localizedStringWithFormat:localizedString, currentPage, ofPages];
+}
+
+#pragma mark - Resource bundle
+
++ (NSBundle *)bundle {
+  static NSBundle *bundle = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    bundle = [NSBundle bundleWithPath:[self bundlePathWithName:kMaterialPageControlBundle]];
+  });
+
+  return bundle;
+}
+
++ (NSString *)bundlePathWithName:(NSString *)bundleName {
+  // In iOS 8+, we could be included by way of a dynamic framework, and our resource bundles may
+  // not be in the main .app bundle, but rather in a nested framework, so figure out where we live
+  // and use that as the search location.
+  NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+  NSString *resourcePath = [(nil == bundle ? [NSBundle mainBundle] : bundle)resourcePath];
+  return [resourcePath stringByAppendingPathComponent:bundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.bundle/Resources/en.lproj/MaterialPageControl.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.bundle/Resources/en.lproj/MaterialPageControl.strings
new file mode 100644
index 0000000..973bb5b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.bundle/Resources/en.lproj/MaterialPageControl.strings
@@ -0,0 +1,2 @@
+/* Accessibility label for page control. Example: "page 1 of 4". */
+"MaterialPageControlAccessibilityLabel" = "page %1$zd of %2$zd";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.h
new file mode 100644
index 0000000..b488b9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/MaterialPageControl.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControl.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h
new file mode 100644
index 0000000..54660df
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.h
@@ -0,0 +1,61 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIKit.h>
+
+/**
+ This shape layer provides a circular indicator denoting a page in a page control.
+
+ @internal
+ */
+@interface MDCPageControlIndicator : CAShapeLayer
+
+/** The color of the indicator. */
+@property(nonatomic, strong) UIColor *color;
+
+/**
+ Default initializer.
+
+ @param center The layer position for this indicator.
+ @param radius The radius of this indicator circle.
+ */
+- (instancetype)initWithCenter:(CGPoint)center radius:(CGFloat)radius NS_DESIGNATED_INITIALIZER;
+
+/** Reveals the indicator by scaling from zero to full size while fading in. */
+- (void)revealIndicator;
+
+/**
+ Updates the indicator transform.x property along the track by the designated percentage.
+
+ @param transformX The transform.x value.
+ */
+- (void)updateIndicatorTransformX:(CGFloat)transformX;
+
+/**
+ Updates the indicator transform.x property along the track by the designated percentage.
+
+ @param transformX The transform.x value.
+ @param animated The whether to animate the change.
+ @param duration The duration of the animation.
+ @param timingFunction The timing function to use when animating the value.
+ */
+- (void)updateIndicatorTransformX:(CGFloat)transformX
+                         animated:(BOOL)animated
+                         duration:(NSTimeInterval)duration
+              mediaTimingFunction:(CAMediaTimingFunction *)timingFunction;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.m
new file mode 100644
index 0000000..79cba9a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlIndicator.m
@@ -0,0 +1,104 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControlIndicator.h"
+
+static const NSTimeInterval kPageControlIndicatorAnimationDuration = 0.3;
+static NSString *const kPageControlIndicatorAnimationKey = @"fadeInScaleUp";
+
+@implementation MDCPageControlIndicator {
+  BOOL _isAnimating;
+}
+
+- (instancetype)initWithCenter:(CGPoint)center radius:(CGFloat)radius {
+  self = [super init];
+  if (self) {
+    self.frame = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
+    self.path = [self circlePathWithRadius:radius];
+    self.zPosition = 1;
+  }
+  return self;
+}
+
+- (void)setColor:(UIColor *)color {
+  // Override here to disable implicit layer animation.
+  _color = color;
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  CGColorRef cgColor = _color.CGColor;
+  self.fillColor = cgColor;
+  [super setOpacity:(float)CGColorGetAlpha(cgColor)];
+  [CATransaction commit];
+}
+
+- (void)setOpacity:(float)opacity {
+  // Override here to disable implicit layer animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  [super setOpacity:opacity];
+  [CATransaction commit];
+}
+
+- (void)revealIndicator {
+  // Scale indicator from zero to full size while fading in.
+  CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
+  scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.0, 0.0, 0.0)];
+  scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
+
+  CABasicAnimation *fadeAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+  fadeAnimation.fromValue = @(0);
+  fadeAnimation.toValue = @(self.opacity);
+
+  CAAnimationGroup *group = [CAAnimationGroup animation];
+  group.duration = kPageControlIndicatorAnimationDuration;
+  group.fillMode = kCAFillModeForwards;
+  group.removedOnCompletion = YES;
+  group.animations = @[ scaleAnimation, fadeAnimation ];
+  [self addAnimation:group forKey:kPageControlIndicatorAnimationKey];
+
+  // Default value.
+  self.hidden = NO;
+}
+
+- (void)updateIndicatorTransformX:(CGFloat)transformX
+                         animated:(BOOL)animated
+                         duration:(NSTimeInterval)duration
+              mediaTimingFunction:(CAMediaTimingFunction *)timingFunction {
+  [CATransaction begin];
+  [CATransaction setDisableActions:!animated];
+  [CATransaction setAnimationDuration:duration];
+  [CATransaction setAnimationTimingFunction:timingFunction];
+  self.transform = CATransform3DMakeTranslation(transformX, 0, 0);
+  [CATransaction commit];
+}
+
+- (void)updateIndicatorTransformX:(CGFloat)transformX {
+  // Disable animation of this transform.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  self.transform = CATransform3DMakeTranslation(transformX, 0, 0);
+  [CATransaction commit];
+}
+
+#pragma mark - Private
+
+- (CGPathRef)circlePathWithRadius:(CGFloat)radius {
+  return [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, radius * 2, radius * 2)
+                                    cornerRadius:radius]
+      .CGPath;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h
new file mode 100644
index 0000000..ddddcc7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.h
@@ -0,0 +1,87 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+#import <UIKit/UIKit.h>
+
+/**
+ This shape layer provides a rounded rectangular track on which a page indicator can travel
+ between subsequent indicators. The track animates on appearance, removal, and when its
+ end points are updated.
+
+ @internal
+ */
+@interface MDCPageControlTrackLayer : CAShapeLayer
+
+/** The color of the indicator track. */
+@property(nonatomic, strong) UIColor *trackColor;
+
+/** A Boolean value indicating whether the track is hidden. */
+@property(nonatomic, readonly, getter=isTrackHidden) BOOL trackHidden;
+
+/**
+ Default initializer.
+
+ @param radius The radius of this indicator and track edges.
+ */
+- (instancetype)initWithRadius:(CGFloat)radius NS_DESIGNATED_INITIALIZER;
+
+/**
+ Draws a track with animation from the startpoint to endpoint.
+
+ @param startPoint The start point of the track.
+ @param endPoint The end point of the track.
+ */
+- (void)drawTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint;
+
+/**
+ Extends the visible track with animation to encompass the startpoint and endpoint.
+
+ @param startPoint The start point of the track.
+ @param endPoint The end point of the track.
+ */
+- (void)extendTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint;
+
+/**
+ Draws a track and extends it with animation to encompass the startpoint and endpoint. This
+ method should be called when an immediate track needs to be drawn and extended without
+ waiting for the draw animation. A typical use case is when called programmatically as
+ opposed to user gesture driven.
+
+ @param startPoint The start point of the track.
+ @param endPoint The end point of the track.
+ @param completion A block to execute when the presentation is finished.
+ */
+- (void)drawAndExtendTrackFromStartPoint:(CGPoint)startPoint
+                              toEndPoint:(CGPoint)endPoint
+                              completion:(void (^)())completion;
+
+/**
+ Removes the track with animation towards the designated point.
+
+ @param point The point the track should animate towards.
+ @param completion A block to execute when the presentation is finished.
+ */
+- (void)removeTrackTowardsPoint:(CGPoint)point completion:(void (^)())completion;
+
+/**
+ Resets the track with animation to the designated point.
+
+ @param point The point the track should be set to.
+ */
+- (void)resetAtPoint:(CGPoint)point;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.m
new file mode 100644
index 0000000..ae195c9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MDCPageControlTrackLayer.m
@@ -0,0 +1,286 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPageControlTrackLayer.h"
+
+static const NSTimeInterval kPageControlAnimationDuration = 0.2;
+static const NSInteger kPageControlKeyframeCount = 2;
+static NSString *const kPageControlAnimationKeyDraw = @"drawTrack";
+
+@implementation MDCPageControlTrackLayer {
+  CGFloat _radius;
+  CGPoint _startPoint, _endPoint, _midPoint;
+  BOOL _isAnimating;
+}
+
+- (instancetype)initWithRadius:(CGFloat)radius {
+  self = [super init];
+  if (self) {
+    _trackHidden = YES;
+    _radius = radius;
+    self.cornerRadius = radius;
+  }
+  return self;
+}
+
+- (void)setTrackColor:(UIColor *)trackColor {
+  _trackColor = trackColor;
+  self.fillColor = trackColor.CGColor;
+  self.backgroundColor = trackColor.CGColor;
+}
+
+#pragma mark - Draw/Extend Track
+
+- (void)drawTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint {
+  if (_isAnimating || !_trackHidden || [self isPointZero:startPoint] ||
+      [self isPointZero:endPoint]) {
+    return;
+  }
+
+  // First reset track frame.
+  [self resetTrackFrame];
+
+  _isAnimating = YES;
+  _startPoint = startPoint;
+  _endPoint = endPoint;
+  _midPoint = [self midPointFromPoint:startPoint toPoint:endPoint];
+  [self resetHidden:NO];
+
+  [CATransaction begin];
+  [CATransaction setCompletionBlock:^{
+    // After drawn, remove animation and update track frame.
+    [self removeAnimationForKey:kPageControlAnimationKeyDraw];
+    [self updateTrackFrameWithAnimation:NO completion:nil];
+    _trackHidden = NO;
+    _isAnimating = NO;
+  }];
+
+  // Get animation keyframes.
+  NSMutableArray<UIBezierPath *> *values = [NSMutableArray array];
+  for (NSInteger i = 0; i < kPageControlKeyframeCount; i++) {
+    [values addObject:(id)[self pathAtKeyframe:i]];
+  }
+
+  // Add animation path.
+  CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"path"];
+  animation.duration = kPageControlAnimationDuration;
+  animation.removedOnCompletion = NO;
+  animation.fillMode = kCAFillModeForwards;
+  animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
+  animation.values = values;
+  [self addAnimation:animation forKey:kPageControlAnimationKeyDraw];
+  [CATransaction commit];
+}
+
+- (void)extendTrackFromStartPoint:(CGPoint)startPoint toEndPoint:(CGPoint)endPoint {
+  if (_trackHidden || [self isPointZero:startPoint] || [self isPointZero:endPoint]) {
+    return;
+  }
+
+  // Extend track to encompass minimum startPoint and maximum endPoint.
+  _startPoint = (startPoint.x < _startPoint.x) ? startPoint : _startPoint;
+  _endPoint = (endPoint.x > _endPoint.x) ? endPoint : _endPoint;
+  [self updateTrackFrameWithAnimation:YES completion:nil];
+}
+
+- (void)drawAndExtendTrackFromStartPoint:(CGPoint)startPoint
+                              toEndPoint:(CGPoint)endPoint
+                              completion:(void (^)())completion {
+  _trackHidden = NO;
+  if ([self isPointZero:_startPoint]) {
+    // If no previous start point, first set frame without animation.
+    _startPoint = startPoint;
+    _endPoint = endPoint;
+    [self updateTrackFrameWithAnimation:NO
+                             completion:^{
+                               [self updateTrackFrameWithAnimation:YES
+                                                        completion:^{
+                                                          if (completion) {
+                                                            completion();
+                                                          }
+                                                        }];
+                             }];
+  } else {
+    // Previous startPoint exists, therefore animate to new start and end points.
+    _startPoint = startPoint;
+    _endPoint = endPoint;
+    [self updateTrackFrameWithAnimation:YES
+                             completion:^{
+                               if (completion) {
+                                 completion();
+                               }
+                             }];
+  }
+}
+
+- (void)updateTrackFrameWithAnimation:(BOOL)animated completion:(void (^)())completion {
+  // Set track frame without implicit animation.
+  [self resetHidden:NO];
+  [CATransaction begin];
+  [CATransaction setDisableActions:!animated];
+  [CATransaction setCompletionBlock:^{
+    if (completion) {
+      completion();
+    }
+  }];
+  self.frame = CGRectMake(_startPoint.x - _radius, _startPoint.y - _radius,
+                          _endPoint.x - _startPoint.x + (_radius * 2), _radius * 2);
+  [CATransaction commit];
+}
+
+- (void)resetTrackFrame {
+  // Reset track frame without implicit animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  self.frame = CGRectZero;
+  [CATransaction commit];
+}
+
+- (void)resetHidden:(BOOL)hidden {
+  // Reset hidden without implicit animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  self.hidden = hidden;
+  [CATransaction commit];
+}
+
+#pragma mark - Remove Track
+
+- (void)removeTrackTowardsPoint:(CGPoint)point completion:(void (^)())completion {
+  // Animate the track removal towards a single point.
+  _startPoint = point;
+  _endPoint = point;
+  [self updateTrackFrameWithAnimation:YES
+                           completion:^{
+                             [self reset];
+                             if (completion) {
+                               completion();
+                             }
+                           }];
+}
+
+- (void)resetAtPoint:(CGPoint)point {
+  // Resets the track at single point without animation.
+  _startPoint = point;
+  _endPoint = point;
+  [self updateTrackFrameWithAnimation:NO
+                           completion:^{
+                             [self reset];
+                           }];
+}
+
+- (void)reset {
+  // Reset track frame without implicit animation.
+  [CATransaction begin];
+  [CATransaction setDisableActions:YES];
+  [self removeAllAnimations];
+  _isAnimating = NO;
+  _trackHidden = YES;
+  [self resetHidden:YES];
+  [CATransaction commit];
+}
+
+#pragma mark - Private
+
+- (CGPoint)midPointFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
+  // Returns midpoint between two points.
+  return CGPointMake((fromPoint.x + toPoint.x) / 2, (fromPoint.y + toPoint.y) / 2);
+}
+
+- (CGPathRef)pathAtKeyframe:(NSInteger)keyframe {
+  // Generates bezier path keyframes that can be animated forward and in reverse.
+  CGFloat r = _radius;
+  CGFloat d = _radius * 2;
+  UIBezierPath *bezierPath = UIBezierPath.bezierPath;
+
+  if (keyframe == 0) {
+    // Create circles at start and end points.
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_startPoint];
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_endPoint];
+
+    // Create an arc from top of startpoint circle to midpoint.
+    [bezierPath
+        moveToPoint:[self pointOnCircleWithRadius:r angleInDegrees:300.0f origin:_startPoint]];
+    [bezierPath addQuadCurveToPoint:_midPoint controlPoint:CGPointMake(_midPoint.x - r / 2, r)];
+
+    // Create an arc from midpoint to top of endpoint circle.
+    [bezierPath
+        addQuadCurveToPoint:[self pointOnCircleWithRadius:r angleInDegrees:240.0f origin:_endPoint]
+               controlPoint:CGPointMake(_midPoint.x + r / 2, r)];
+
+    // Create a line from top of endpoint circle to bottom of endpoint circle.
+    [bezierPath
+        addLineToPoint:[self pointOnCircleWithRadius:r angleInDegrees:120.0f origin:_endPoint]];
+
+    // Create an arc from bottom of endpoint circle to midpoint.
+    [bezierPath addQuadCurveToPoint:_midPoint controlPoint:CGPointMake(_midPoint.x + r / 2, r)];
+
+    // Create an arc from midpoint to bottom of startpoint circle.
+    [bezierPath
+        addQuadCurveToPoint:[self pointOnCircleWithRadius:r angleInDegrees:60.0f origin:_startPoint]
+               controlPoint:CGPointMake(_midPoint.x - r / 2, r)];
+
+    // Create line from bottom of startpoint circle to top of startpoint circle.
+    [bezierPath
+        addLineToPoint:[self pointOnCircleWithRadius:r angleInDegrees:300.0f origin:_startPoint]];
+
+    // Close path.
+    [bezierPath closePath];
+
+  } else if (keyframe == 1) {
+    // Creates rectangular path from startpoint to endpoint with rounded ends.
+    // Requires same number of paths as previous keyframe to animate properly.
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_startPoint];
+    [self addRoundedEndpontToBezierPath:bezierPath atPoint:_endPoint];
+    [bezierPath moveToPoint:CGPointMake(_startPoint.x, 0)];
+    [bezierPath addLineToPoint:CGPointMake(_midPoint.x, 0)];
+    [bezierPath addLineToPoint:CGPointMake(_endPoint.x, 0)];
+    [bezierPath addLineToPoint:CGPointMake(_endPoint.x, d)];
+    [bezierPath addLineToPoint:CGPointMake(_midPoint.x, d)];
+    [bezierPath addLineToPoint:CGPointMake(_startPoint.x, d)];
+    [bezierPath closePath];
+  }
+  return bezierPath.CGPath;
+}
+
+- (void)addRoundedEndpontToBezierPath:(UIBezierPath *)bezierPath atPoint:(CGPoint)point {
+  // Creates a closed circle at designated point.
+  [bezierPath moveToPoint:CGPointMake(point.x, _radius * 2)];
+  [bezierPath addArcWithCenter:point
+                        radius:_radius
+                    startAngle:0
+                      endAngle:[self degreesToRadians:360]
+                     clockwise:YES];
+}
+
+- (CGPoint)pointOnCircleWithRadius:(CGFloat)radius
+                    angleInDegrees:(CGFloat)angleInDegrees
+                            origin:(CGPoint)origin {
+  // Returns a point along a circles edge at given angle.
+  CGFloat locationX = (CGFloat)(radius * cos([self degreesToRadians:angleInDegrees])) + origin.x;
+  CGFloat locationY = (CGFloat)(radius * sin([self degreesToRadians:angleInDegrees])) + origin.y;
+  return CGPointMake(locationX, locationY);
+}
+
+- (CGFloat)degreesToRadians:(CGFloat)degrees {
+  return degrees * (CGFloat)M_PI / 180.0f;
+}
+
+- (BOOL)isPointZero:(CGPoint)point {
+  return CGPointEqualToPoint(point, CGPointZero);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h
new file mode 100644
index 0000000..0c54d17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings.h
@@ -0,0 +1,24 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// GENERATED CODE: DO NOT EDIT BY HAND
+// GENERATED FROM:
+// ./PageControl/GoogleKitPageControl.bundle/Resources/en.lproj/GoogleKitPageControl.strings
+// GENERATED BY: //depot/google3/googlemac/iPhone/Shared/Tools/generate_string_tables.py
+
+typedef enum {
+  kStr_MaterialPageControlAccessibilityLabel = 0,
+} MaterialPageControlStringId;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h
new file mode 100644
index 0000000..2314001
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/PageControl/src/private/MaterialPageControlStrings_table.h
@@ -0,0 +1,31 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// GENERATED CODE: DO NOT EDIT BY HAND
+// GENERATED FROM:
+// ./PageControl/GoogleKitPageControl.bundle/Resources/en.lproj/GoogleKitPageControl.strings
+// GENERATED BY: //depot/google3/googlemac/iPhone/Shared/Tools/generate_string_tables.py
+
+// A table of string keys to look-up localized strings in the bundle.
+// This table is to be indexed using the generated enum.
+
+static NSString *const kMaterialPageControlStringTable[] = {
+    @"MaterialPageControlAccessibilityLabel",  // page %1$zd of %2$zd
+};
+#define kNumMaterialPageControlStrings 1
+#define kMaterialControlStringsOffset 0
+#define kMaterialPageControlStringsEnd 10000
+static NSString *const kMaterialPageControlStringsTableName = @"MaterialPageControl";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.h
new file mode 100644
index 0000000..78507dc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.h
@@ -0,0 +1,212 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** The name of the tint 50 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint50Name;
+
+/** The name of the tint 100 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint100Name;
+
+/** The name of the tint 200 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint200Name;
+
+/** The name of the tint 300 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint300Name;
+
+/** The name of the tint 400 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint400Name;
+
+/** The name of the tint 500 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint500Name;
+
+/** The name of the tint 600 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint600Name;
+
+/** The name of the tint 700 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint700Name;
+
+/** The name of the tint 800 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint800Name;
+
+/** The name of the tint 900 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteTint900Name;
+
+/** The name of the accent 100 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent100Name;
+
+/** The name of the accent 200 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent200Name;
+
+/** The name of the accent 400 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent400Name;
+
+/** The name of the accent 700 color when creating a custom palette. */
+CG_EXTERN const NSString *_Nonnull MDCPaletteAccent700Name;
+
+/**
+ A palette of Material colors.
+
+ Material palettes have a set of named tint colors and an optional set of named accent colors. This
+ class provides access to the pre-defined set of Material palettes. MDCPalette objects are
+ immutable; it is safe to use them from multiple threads in your app.
+
+ @see https://www.google.com/design/spec/style/color.html#color-color-palette
+ */
+@interface MDCPalette : NSObject
+
+/** The red palette. */
++ (nonnull MDCPalette *)redPalette;
+
+/** The pink palette. */
++ (nonnull MDCPalette *)pinkPalette;
+
+/** The purple palette. */
++ (nonnull MDCPalette *)purplePalette;
+
+/** The deep purple palette. */
++ (nonnull MDCPalette *)deepPurplePalette;
+
+/** The indigo palette. */
++ (nonnull MDCPalette *)indigoPalette;
+
+/** The blue palette. */
++ (nonnull MDCPalette *)bluePalette;
+
+/** The light blue palette. */
++ (nonnull MDCPalette *)lightBluePalette;
+
+/** The cyan palette. */
++ (nonnull MDCPalette *)cyanPalette;
+
+/** The teal palette. */
++ (nonnull MDCPalette *)tealPalette;
+
+/** The green palette. */
++ (nonnull MDCPalette *)greenPalette;
+
+/** The light green palette. */
++ (nonnull MDCPalette *)lightGreenPalette;
+
+/** The lime palette. */
++ (nonnull MDCPalette *)limePalette;
+
+/** The yellow palette. */
++ (nonnull MDCPalette *)yellowPalette;
+
+/** The amber palette. */
++ (nonnull MDCPalette *)amberPalette;
+
+/** The orange palette. */
++ (nonnull MDCPalette *)orangePalette;
+
+/** The deep orange palette. */
++ (nonnull MDCPalette *)deepOrangePalette;
+
+/** The brown palette (no accents). */
++ (nonnull MDCPalette *)brownPalette;
+
+/** The grey palette (no accents). */
++ (nonnull MDCPalette *)greyPalette;
+
+/** The blue grey palette (no accents). */
++ (nonnull MDCPalette *)blueGreyPalette;
+
+/**
+ Returns a palette generated from a single target 500 tint color.
+
+ TODO(ajsecord): Document the algorithm used to generate the palette.
+
+ @param target500Color The target "500" color in the palette.
+ @return A palette generated with a 500 color matching the target color.
+ */
++ (nonnull instancetype)paletteGeneratedFromColor:(nonnull UIColor *)target500Color;
+
+/**
+ Returns a palette with a custom set of tints and accents.
+
+ The tints dictionary must have values for each key matching MDCPaletteTint.*Name. The accents
+ dictionary, if specified, may have entries for each key matching MDCPaletteAccent.*Name. Missing
+ accent values will cause an assert in debug mode and will return +[UIColor clearColor] in release
+ mode when the corresponding property is acccessed.
+
+ @param tints A dictionary mapping MDCPaletteTint.*Name keys to UIColors.
+ @param accents An optional dictionary mapping MDCPaletteAccent.*Name keys to UIColors.
+ @return An palette containing the custom colors.
+ */
++ (nonnull instancetype)paletteWithTints:(nonnull NSDictionary<const NSString *, UIColor *> *)tints
+                                 accents:
+                                     (nullable NSDictionary<const NSString *, UIColor *> *)accents;
+
+/**
+ Returns an initialized palette object with a custom set of tints and accents.
+
+ The tints dictionary must have values for each key matching MDCPaletteTint.*Name. The accents
+ dictionary, if specified, may have entries for each key matching MDCPaletteAccent.*Name. Missing
+ accent values will cause an assert in debug mode and will return +[UIColor clearColor] in release
+ mode when the corresponding property is acccessed.
+
+ @param tints A dictionary mapping MDCPaletteTint.*Name keys to UIColors.
+ @param accents An optional dictionary mapping MDCPaletteAccent.*Name keys to UIColors.
+ @return An initialized MDCPalette object containing the custom colors.
+ */
+- (nonnull instancetype)initWithTints:(nonnull NSDictionary<const NSString *, UIColor *> *)tints
+                              accents:(nullable NSDictionary<const NSString *, UIColor *> *)accents;
+
+/** The 50 tint color, the lightest tint of the palette. */
+@property(nonatomic, nonnull, readonly) UIColor *tint50;
+
+/** The 100 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint100;
+
+/** The 200 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint200;
+
+/** The 300 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint300;
+
+/** The 400 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint400;
+
+/** The 500 tint color, the representative tint of the palette. */
+@property(nonatomic, nonnull, readonly) UIColor *tint500;
+
+/** The 600 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint600;
+
+/** The 700 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint700;
+
+/** The 800 tint color. */
+@property(nonatomic, nonnull, readonly) UIColor *tint800;
+
+/** The 900 tint color, the darkest tint of the palette. */
+@property(nonatomic, nonnull, readonly) UIColor *tint900;
+
+/** The A100 accent color, the lightest accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent100;
+
+/** The A200 accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent200;
+
+/** The A400 accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent400;
+
+/** The A700 accent color, the darkest accent color. */
+@property(nonatomic, nullable, readonly) UIColor *accent700;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.m
new file mode 100644
index 0000000..4a713fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MDCPalettes.m
@@ -0,0 +1,654 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPalettes.h"
+#import "private/MDCPaletteExpansions.h"
+#import "private/MDCPaletteNames.h"
+
+const NSString *MDCPaletteTint50Name = MDC_PALETTE_TINT_50_INTERNAL_NAME;
+const NSString *MDCPaletteTint100Name = MDC_PALETTE_TINT_100_INTERNAL_NAME;
+const NSString *MDCPaletteTint200Name = MDC_PALETTE_TINT_200_INTERNAL_NAME;
+const NSString *MDCPaletteTint300Name = MDC_PALETTE_TINT_300_INTERNAL_NAME;
+const NSString *MDCPaletteTint400Name = MDC_PALETTE_TINT_400_INTERNAL_NAME;
+const NSString *MDCPaletteTint500Name = MDC_PALETTE_TINT_500_INTERNAL_NAME;
+const NSString *MDCPaletteTint600Name = MDC_PALETTE_TINT_600_INTERNAL_NAME;
+const NSString *MDCPaletteTint700Name = MDC_PALETTE_TINT_700_INTERNAL_NAME;
+const NSString *MDCPaletteTint800Name = MDC_PALETTE_TINT_800_INTERNAL_NAME;
+const NSString *MDCPaletteTint900Name = MDC_PALETTE_TINT_900_INTERNAL_NAME;
+const NSString *MDCPaletteAccent100Name = MDC_PALETTE_ACCENT_100_INTERNAL_NAME;
+const NSString *MDCPaletteAccent200Name = MDC_PALETTE_ACCENT_200_INTERNAL_NAME;
+const NSString *MDCPaletteAccent400Name = MDC_PALETTE_ACCENT_400_INTERNAL_NAME;
+const NSString *MDCPaletteAccent700Name = MDC_PALETTE_ACCENT_700_INTERNAL_NAME;
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *ColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+@interface MDCPalette () {
+  NSDictionary<const NSString *, UIColor *> *_tints;
+  NSDictionary<const NSString *, UIColor *> *_accents;
+}
+
+@end
+
+@implementation MDCPalette
+
++ (MDCPalette *)redPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFEBEE),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFCDD2),
+      MDCPaletteTint200Name : ColorFromRGB(0xEF9A9A),
+      MDCPaletteTint300Name : ColorFromRGB(0xE57373),
+      MDCPaletteTint400Name : ColorFromRGB(0xEF5350),
+      MDCPaletteTint500Name : ColorFromRGB(0xF44336),
+      MDCPaletteTint600Name : ColorFromRGB(0xE53935),
+      MDCPaletteTint700Name : ColorFromRGB(0xD32F2F),
+      MDCPaletteTint800Name : ColorFromRGB(0xC62828),
+      MDCPaletteTint900Name : ColorFromRGB(0xB71C1C)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFF8A80),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFF5252),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFF1744),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xD50000)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)pinkPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFCE4EC),
+      MDCPaletteTint100Name : ColorFromRGB(0xF8BBD0),
+      MDCPaletteTint200Name : ColorFromRGB(0xF48FB1),
+      MDCPaletteTint300Name : ColorFromRGB(0xF06292),
+      MDCPaletteTint400Name : ColorFromRGB(0xEC407A),
+      MDCPaletteTint500Name : ColorFromRGB(0xE91E63),
+      MDCPaletteTint600Name : ColorFromRGB(0xD81B60),
+      MDCPaletteTint700Name : ColorFromRGB(0xC2185B),
+      MDCPaletteTint800Name : ColorFromRGB(0xAD1457),
+      MDCPaletteTint900Name : ColorFromRGB(0x880E4F)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFF80AB),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFF4081),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xF50057),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xC51162)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)purplePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xF3E5F5),
+      MDCPaletteTint100Name : ColorFromRGB(0xE1BEE7),
+      MDCPaletteTint200Name : ColorFromRGB(0xCE93D8),
+      MDCPaletteTint300Name : ColorFromRGB(0xBA68C8),
+      MDCPaletteTint400Name : ColorFromRGB(0xAB47BC),
+      MDCPaletteTint500Name : ColorFromRGB(0x9C27B0),
+      MDCPaletteTint600Name : ColorFromRGB(0x8E24AA),
+      MDCPaletteTint700Name : ColorFromRGB(0x7B1FA2),
+      MDCPaletteTint800Name : ColorFromRGB(0x6A1B9A),
+      MDCPaletteTint900Name : ColorFromRGB(0x4A148C)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xEA80FC),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xE040FB),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xD500F9),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xAA00FF)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)deepPurplePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xEDE7F6),
+      MDCPaletteTint100Name : ColorFromRGB(0xD1C4E9),
+      MDCPaletteTint200Name : ColorFromRGB(0xB39DDB),
+      MDCPaletteTint300Name : ColorFromRGB(0x9575CD),
+      MDCPaletteTint400Name : ColorFromRGB(0x7E57C2),
+      MDCPaletteTint500Name : ColorFromRGB(0x673AB7),
+      MDCPaletteTint600Name : ColorFromRGB(0x5E35B1),
+      MDCPaletteTint700Name : ColorFromRGB(0x512DA8),
+      MDCPaletteTint800Name : ColorFromRGB(0x4527A0),
+      MDCPaletteTint900Name : ColorFromRGB(0x311B92)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xB388FF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x7C4DFF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x651FFF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x6200EA)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)indigoPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE8EAF6),
+      MDCPaletteTint100Name : ColorFromRGB(0xC5CAE9),
+      MDCPaletteTint200Name : ColorFromRGB(0x9FA8DA),
+      MDCPaletteTint300Name : ColorFromRGB(0x7986CB),
+      MDCPaletteTint400Name : ColorFromRGB(0x5C6BC0),
+      MDCPaletteTint500Name : ColorFromRGB(0x3F51B5),
+      MDCPaletteTint600Name : ColorFromRGB(0x3949AB),
+      MDCPaletteTint700Name : ColorFromRGB(0x303F9F),
+      MDCPaletteTint800Name : ColorFromRGB(0x283593),
+      MDCPaletteTint900Name : ColorFromRGB(0x1A237E)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x8C9EFF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x536DFE),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x3D5AFE),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x304FFE)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)bluePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE3F2FD),
+      MDCPaletteTint100Name : ColorFromRGB(0xBBDEFB),
+      MDCPaletteTint200Name : ColorFromRGB(0x90CAF9),
+      MDCPaletteTint300Name : ColorFromRGB(0x64B5F6),
+      MDCPaletteTint400Name : ColorFromRGB(0x42A5F5),
+      MDCPaletteTint500Name : ColorFromRGB(0x2196F3),
+      MDCPaletteTint600Name : ColorFromRGB(0x1E88E5),
+      MDCPaletteTint700Name : ColorFromRGB(0x1976D2),
+      MDCPaletteTint800Name : ColorFromRGB(0x1565C0),
+      MDCPaletteTint900Name : ColorFromRGB(0x0D47A1)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x82B1FF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x448AFF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x2979FF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x2962FF)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)lightBluePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE1F5FE),
+      MDCPaletteTint100Name : ColorFromRGB(0xB3E5FC),
+      MDCPaletteTint200Name : ColorFromRGB(0x81D4FA),
+      MDCPaletteTint300Name : ColorFromRGB(0x4FC3F7),
+      MDCPaletteTint400Name : ColorFromRGB(0x29B6F6),
+      MDCPaletteTint500Name : ColorFromRGB(0x03A9F4),
+      MDCPaletteTint600Name : ColorFromRGB(0x039BE5),
+      MDCPaletteTint700Name : ColorFromRGB(0x0288D1),
+      MDCPaletteTint800Name : ColorFromRGB(0x0277BD),
+      MDCPaletteTint900Name : ColorFromRGB(0x01579B)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x80D8FF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x40C4FF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x00B0FF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x0091EA)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)cyanPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE0F7FA),
+      MDCPaletteTint100Name : ColorFromRGB(0xB2EBF2),
+      MDCPaletteTint200Name : ColorFromRGB(0x80DEEA),
+      MDCPaletteTint300Name : ColorFromRGB(0x4DD0E1),
+      MDCPaletteTint400Name : ColorFromRGB(0x26C6DA),
+      MDCPaletteTint500Name : ColorFromRGB(0x00BCD4),
+      MDCPaletteTint600Name : ColorFromRGB(0x00ACC1),
+      MDCPaletteTint700Name : ColorFromRGB(0x0097A7),
+      MDCPaletteTint800Name : ColorFromRGB(0x00838F),
+      MDCPaletteTint900Name : ColorFromRGB(0x006064)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0x84FFFF),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x18FFFF),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x00E5FF),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x00B8D4)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)tealPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE0F2F1),
+      MDCPaletteTint100Name : ColorFromRGB(0xB2DFDB),
+      MDCPaletteTint200Name : ColorFromRGB(0x80CBC4),
+      MDCPaletteTint300Name : ColorFromRGB(0x4DB6AC),
+      MDCPaletteTint400Name : ColorFromRGB(0x26A69A),
+      MDCPaletteTint500Name : ColorFromRGB(0x009688),
+      MDCPaletteTint600Name : ColorFromRGB(0x00897B),
+      MDCPaletteTint700Name : ColorFromRGB(0x00796B),
+      MDCPaletteTint800Name : ColorFromRGB(0x00695C),
+      MDCPaletteTint900Name : ColorFromRGB(0x004D40)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xA7FFEB),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x64FFDA),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x1DE9B6),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x00BFA5)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)greenPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xE8F5E9),
+      MDCPaletteTint100Name : ColorFromRGB(0xC8E6C9),
+      MDCPaletteTint200Name : ColorFromRGB(0xA5D6A7),
+      MDCPaletteTint300Name : ColorFromRGB(0x81C784),
+      MDCPaletteTint400Name : ColorFromRGB(0x66BB6A),
+      MDCPaletteTint500Name : ColorFromRGB(0x4CAF50),
+      MDCPaletteTint600Name : ColorFromRGB(0x43A047),
+      MDCPaletteTint700Name : ColorFromRGB(0x388E3C),
+      MDCPaletteTint800Name : ColorFromRGB(0x2E7D32),
+      MDCPaletteTint900Name : ColorFromRGB(0x1B5E20)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xB9F6CA),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0x69F0AE),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x00E676),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x00C853)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)lightGreenPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xF1F8E9),
+      MDCPaletteTint100Name : ColorFromRGB(0xDCEDC8),
+      MDCPaletteTint200Name : ColorFromRGB(0xC5E1A5),
+      MDCPaletteTint300Name : ColorFromRGB(0xAED581),
+      MDCPaletteTint400Name : ColorFromRGB(0x9CCC65),
+      MDCPaletteTint500Name : ColorFromRGB(0x8BC34A),
+      MDCPaletteTint600Name : ColorFromRGB(0x7CB342),
+      MDCPaletteTint700Name : ColorFromRGB(0x689F38),
+      MDCPaletteTint800Name : ColorFromRGB(0x558B2F),
+      MDCPaletteTint900Name : ColorFromRGB(0x33691E)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xCCFF90),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xB2FF59),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0x76FF03),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0x64DD17)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)limePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xF9FBE7),
+      MDCPaletteTint100Name : ColorFromRGB(0xF0F4C3),
+      MDCPaletteTint200Name : ColorFromRGB(0xE6EE9C),
+      MDCPaletteTint300Name : ColorFromRGB(0xDCE775),
+      MDCPaletteTint400Name : ColorFromRGB(0xD4E157),
+      MDCPaletteTint500Name : ColorFromRGB(0xCDDC39),
+      MDCPaletteTint600Name : ColorFromRGB(0xC0CA33),
+      MDCPaletteTint700Name : ColorFromRGB(0xAFB42B),
+      MDCPaletteTint800Name : ColorFromRGB(0x9E9D24),
+      MDCPaletteTint900Name : ColorFromRGB(0x827717)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xF4FF81),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xEEFF41),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xC6FF00),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xAEEA00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)yellowPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFFDE7),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFF9C4),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFF59D),
+      MDCPaletteTint300Name : ColorFromRGB(0xFFF176),
+      MDCPaletteTint400Name : ColorFromRGB(0xFFEE58),
+      MDCPaletteTint500Name : ColorFromRGB(0xFFEB3B),
+      MDCPaletteTint600Name : ColorFromRGB(0xFDD835),
+      MDCPaletteTint700Name : ColorFromRGB(0xFBC02D),
+      MDCPaletteTint800Name : ColorFromRGB(0xF9A825),
+      MDCPaletteTint900Name : ColorFromRGB(0xF57F17)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFFFF8D),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFFFF00),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFFEA00),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xFFD600)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)amberPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFF8E1),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFECB3),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFE082),
+      MDCPaletteTint300Name : ColorFromRGB(0xFFD54F),
+      MDCPaletteTint400Name : ColorFromRGB(0xFFCA28),
+      MDCPaletteTint500Name : ColorFromRGB(0xFFC107),
+      MDCPaletteTint600Name : ColorFromRGB(0xFFB300),
+      MDCPaletteTint700Name : ColorFromRGB(0xFFA000),
+      MDCPaletteTint800Name : ColorFromRGB(0xFF8F00),
+      MDCPaletteTint900Name : ColorFromRGB(0xFF6F00)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFFE57F),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFFD740),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFFC400),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xFFAB00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)orangePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFFF3E0),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFE0B2),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFCC80),
+      MDCPaletteTint300Name : ColorFromRGB(0xFFB74D),
+      MDCPaletteTint400Name : ColorFromRGB(0xFFA726),
+      MDCPaletteTint500Name : ColorFromRGB(0xFF9800),
+      MDCPaletteTint600Name : ColorFromRGB(0xFB8C00),
+      MDCPaletteTint700Name : ColorFromRGB(0xF57C00),
+      MDCPaletteTint800Name : ColorFromRGB(0xEF6C00),
+      MDCPaletteTint900Name : ColorFromRGB(0xE65100)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFFD180),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFFAB40),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFF9100),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xFF6D00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)deepOrangePalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFBE9E7),
+      MDCPaletteTint100Name : ColorFromRGB(0xFFCCBC),
+      MDCPaletteTint200Name : ColorFromRGB(0xFFAB91),
+      MDCPaletteTint300Name : ColorFromRGB(0xFF8A65),
+      MDCPaletteTint400Name : ColorFromRGB(0xFF7043),
+      MDCPaletteTint500Name : ColorFromRGB(0xFF5722),
+      MDCPaletteTint600Name : ColorFromRGB(0xF4511E),
+      MDCPaletteTint700Name : ColorFromRGB(0xE64A19),
+      MDCPaletteTint800Name : ColorFromRGB(0xD84315),
+      MDCPaletteTint900Name : ColorFromRGB(0xBF360C)
+    }
+                                  accents:@{
+                                    MDCPaletteAccent100Name : ColorFromRGB(0xFF9E80),
+                                    MDCPaletteAccent200Name : ColorFromRGB(0xFF6E40),
+                                    MDCPaletteAccent400Name : ColorFromRGB(0xFF3D00),
+                                    MDCPaletteAccent700Name : ColorFromRGB(0xDD2C00)
+                                  }];
+  });
+  return palette;
+}
+
++ (MDCPalette *)brownPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xEFEBE9),
+      MDCPaletteTint100Name : ColorFromRGB(0xD7CCC8),
+      MDCPaletteTint200Name : ColorFromRGB(0xBCAAA4),
+      MDCPaletteTint300Name : ColorFromRGB(0xA1887F),
+      MDCPaletteTint400Name : ColorFromRGB(0x8D6E63),
+      MDCPaletteTint500Name : ColorFromRGB(0x795548),
+      MDCPaletteTint600Name : ColorFromRGB(0x6D4C41),
+      MDCPaletteTint700Name : ColorFromRGB(0x5D4037),
+      MDCPaletteTint800Name : ColorFromRGB(0x4E342E),
+      MDCPaletteTint900Name : ColorFromRGB(0x3E2723)
+    }
+                                  accents:nil];
+  });
+  return palette;
+}
+
++ (MDCPalette *)greyPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xFAFAFA),
+      MDCPaletteTint100Name : ColorFromRGB(0xF5F5F5),
+      MDCPaletteTint200Name : ColorFromRGB(0xEEEEEE),
+      MDCPaletteTint300Name : ColorFromRGB(0xE0E0E0),
+      MDCPaletteTint400Name : ColorFromRGB(0xBDBDBD),
+      MDCPaletteTint500Name : ColorFromRGB(0x9E9E9E),
+      MDCPaletteTint600Name : ColorFromRGB(0x757575),
+      MDCPaletteTint700Name : ColorFromRGB(0x616161),
+      MDCPaletteTint800Name : ColorFromRGB(0x424242),
+      MDCPaletteTint900Name : ColorFromRGB(0x212121)
+    }
+                                  accents:nil];
+  });
+  return palette;
+}
+
++ (MDCPalette *)blueGreyPalette {
+  static MDCPalette *palette;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    palette = [[self alloc] initWithTints:@{
+      MDCPaletteTint50Name : ColorFromRGB(0xECEFF1),
+      MDCPaletteTint100Name : ColorFromRGB(0xCFD8DC),
+      MDCPaletteTint200Name : ColorFromRGB(0xB0BEC5),
+      MDCPaletteTint300Name : ColorFromRGB(0x90A4AE),
+      MDCPaletteTint400Name : ColorFromRGB(0x78909C),
+      MDCPaletteTint500Name : ColorFromRGB(0x607D8B),
+      MDCPaletteTint600Name : ColorFromRGB(0x546E7A),
+      MDCPaletteTint700Name : ColorFromRGB(0x455A64),
+      MDCPaletteTint800Name : ColorFromRGB(0x37474F),
+      MDCPaletteTint900Name : ColorFromRGB(0x263238)
+    }
+                                  accents:nil];
+  });
+  return palette;
+}
+
++ (instancetype)paletteGeneratedFromColor:(nonnull UIColor *)target500Color {
+  NSArray *tintNames = @[
+    MDCPaletteTint50Name, MDCPaletteTint100Name, MDCPaletteTint200Name, MDCPaletteTint300Name,
+    MDCPaletteTint400Name, MDCPaletteTint500Name, MDCPaletteTint600Name, MDCPaletteTint700Name,
+    MDCPaletteTint800Name, MDCPaletteTint900Name, MDCPaletteAccent100Name, MDCPaletteAccent200Name,
+    MDCPaletteAccent400Name, MDCPaletteAccent700Name
+  ];
+
+  NSMutableDictionary *tints = [[NSMutableDictionary alloc] init];
+  for (NSString *name in tintNames) {
+    [tints setObject:MDCPaletteTintFromTargetColor(target500Color, name) forKey:name];
+  }
+
+  NSArray *accentNames = @[
+    MDCPaletteAccent100Name, MDCPaletteAccent200Name, MDCPaletteAccent400Name,
+    MDCPaletteAccent700Name
+  ];
+  NSMutableDictionary *accents = [[NSMutableDictionary alloc] init];
+  for (NSString *name in accentNames) {
+    [accents setObject:MDCPaletteAccentFromTargetColor(target500Color, name) forKey:name];
+  }
+
+  return [self paletteWithTints:tints accents:accents];
+}
+
++ (instancetype)paletteWithTints:(NSDictionary<NSString *, UIColor *> *)tints
+                         accents:(NSDictionary<NSString *, UIColor *> *)accents {
+  return [[self alloc] initWithTints:tints accents:accents];
+}
+
+- (instancetype)initWithTints:(NSDictionary<const NSString *, UIColor *> *)tints
+                      accents:(NSDictionary<const NSString *, UIColor *> *)accents {
+  self = [super init];
+  if (self) {
+    _accents = accents ? [accents copy] : @{};
+
+    // Check if all the accent colors are present.
+    NSDictionary<const NSString *, UIColor *> *allTints = tints;
+    NSMutableSet<const NSString *> *requiredTintKeys =
+        [NSMutableSet setWithSet:[[self class] requiredTintKeys]];
+    [requiredTintKeys minusSet:[NSSet setWithArray:[tints allKeys]]];
+    if ([requiredTintKeys count] != 0) {
+      NSAssert(NO, @"Missing accent colors for the following keys: %@.", requiredTintKeys);
+      NSMutableDictionary<const NSString *, UIColor *> *replacementTints =
+          [NSMutableDictionary dictionaryWithDictionary:_accents];
+      for (NSString *tintKey in requiredTintKeys) {
+        [replacementTints setObject:[UIColor clearColor] forKey:tintKey];
+      }
+      allTints = replacementTints;
+    }
+
+    _tints = [allTints copy];
+  }
+  return self;
+}
+
+- (UIColor *)tint50 {
+  return _tints[MDCPaletteTint50Name];
+}
+
+- (UIColor *)tint100 {
+  return _tints[MDCPaletteTint100Name];
+}
+
+- (UIColor *)tint200 {
+  return _tints[MDCPaletteTint200Name];
+}
+
+- (UIColor *)tint300 {
+  return _tints[MDCPaletteTint300Name];
+}
+
+- (UIColor *)tint400 {
+  return _tints[MDCPaletteTint400Name];
+}
+
+- (UIColor *)tint500 {
+  return _tints[MDCPaletteTint500Name];
+}
+
+- (UIColor *)tint600 {
+  return _tints[MDCPaletteTint600Name];
+}
+
+- (UIColor *)tint700 {
+  return _tints[MDCPaletteTint700Name];
+}
+
+- (UIColor *)tint800 {
+  return _tints[MDCPaletteTint800Name];
+}
+
+- (UIColor *)tint900 {
+  return _tints[MDCPaletteTint900Name];
+}
+
+- (UIColor *)accent100 {
+  return _accents[MDCPaletteAccent100Name];
+}
+
+- (UIColor *)accent200 {
+  return _accents[MDCPaletteAccent200Name];
+}
+
+- (UIColor *)accent400 {
+  return _accents[MDCPaletteAccent400Name];
+}
+
+- (UIColor *)accent700 {
+  return _accents[MDCPaletteAccent700Name];
+}
+
+#pragma mark - Private methods
+
++ (nonnull NSSet<const NSString *> *)requiredTintKeys {
+  return [NSSet setWithArray:@[
+    MDCPaletteTint50Name, MDCPaletteTint100Name, MDCPaletteTint200Name, MDCPaletteTint300Name,
+    MDCPaletteTint400Name, MDCPaletteTint500Name, MDCPaletteTint600Name, MDCPaletteTint700Name,
+    MDCPaletteTint800Name, MDCPaletteTint900Name
+  ]];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MaterialPalettes.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MaterialPalettes.h
new file mode 100644
index 0000000..fa83aec
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/MaterialPalettes.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPalettes.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h
new file mode 100644
index 0000000..3a92cc9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+UIColor* _Nonnull MDCPaletteTintFromTargetColor(UIColor* _Nonnull targetColor,
+                                                NSString* _Nonnull tintName);
+
+UIColor* _Nonnull MDCPaletteAccentFromTargetColor(UIColor* _Nonnull targetColor,
+                                                  NSString* _Nonnull accentName);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.m
new file mode 100644
index 0000000..c9ac33c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteExpansions.m
@@ -0,0 +1,206 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#include "MDCPaletteExpansions.h"
+
+#include <Foundation/Foundation.h>
+
+#import "MDCPaletteNames.h"
+
+// Observed saturation ranges for tints 50, 500, 900.
+static const CGFloat kSaturation50Min = 0.06f;
+static const CGFloat kSaturation50Max = 0.12f;
+static const CGFloat kSaturation500Min = 0.60f;
+static const CGFloat kSaturation500Max = 1.00f;
+static const CGFloat kSaturation900Min = 0.70f;
+static const CGFloat kSaturation900Max = 1.00f;
+
+// Minimum value of saturation to consider a color "colorless" (e.g. white/black/grey).
+static const CGFloat kSaturationMinThreshold = 1 / 256.0f;
+
+// A small value for comparing floating point numbers that is appropriate for color components.
+static const CGFloat kComponentEpsilon = 0.5f / 256.0f;
+
+// Observed brightness ranges for tints 50, 500, 900.
+static const CGFloat kBrightness50Min = 0.95f;
+static const CGFloat kBrightness50Max = 1.00f;
+static const CGFloat kBrightness500Min = 0.50f;
+static const CGFloat kBrightness500Max = 1.00f;
+
+// Observed quadratic brightness coefficients for tints >= 500.
+static const CGFloat kBrightnessQuadracticCoeff = -0.00642857142857143f;
+static const CGFloat kBrightnessLinearCoeff = -0.03585714285714282f;
+
+// Median saturation and brightness values for A100, A200, A400, A700.
+static const CGFloat kAccentSaturation[4] = {0.49f, 0.75f, 1.00f, 1.00f};
+static const CGFloat kAccentBrightness[4] = {1.00f, 1.00f, 1.00f, 0.92f};
+
+// Ordered indices of each of the tints/accents.
+static const int kQTMColorTint50Index = 0;
+static const int kQTMColorTint100Index = 1;
+static const int kQTMColorTint200Index = 2;
+static const int kQTMColorTint300Index = 3;
+static const int kQTMColorTint400Index = 4;
+static const int kQTMColorTint500Index = 5;
+static const int kQTMColorTint600Index = 6;
+static const int kQTMColorTint700Index = 7;
+static const int kQTMColorTint800Index = 8;
+static const int kQTMColorTint900Index = 9;
+static const int kQTMColorAccent100Index = 10;
+static const int kQTMColorAccent200Index = 11;
+static const int kQTMColorAccent400Index = 12;
+static const int kQTMColorAccent700Index = 13;
+
+/** Returns a value Clamped to the range [min, max]. */
+static inline CGFloat Clamp(CGFloat value, CGFloat min, CGFloat max) {
+  if (value < min) {
+    return min;
+  } else if (value > max) {
+    return max;
+  } else {
+    return value;
+  }
+}
+
+/** Returns the linear interpolation of [min, max] at value. */
+static inline CGFloat Lerp(CGFloat value, CGFloat min, CGFloat max) {
+  return (1 - value) * min + value * max;
+}
+
+/** Returns the value t such that Lerp(t, min, max) == value. */
+static inline CGFloat InvLerp(CGFloat value, CGFloat min, CGFloat max) {
+  return (value - min) / (max - min);
+}
+
+/**
+ Returns "component > value", but accounting for floating point mathematics. The component is
+ expected to be between [0,255].
+ */
+static inline BOOL IsComponentGreaterThanValue(CGFloat component, CGFloat value) {
+  return component + kComponentEpsilon > value;
+}
+
+static void ColorToHSB(UIColor *_Nonnull color, CGFloat hsb[4]) {
+  // Pre-iOS 8 would not convert greyscale colors to HSB.
+  if (![color getHue:&hsb[0] saturation:&hsb[1] brightness:&hsb[2] alpha:&hsb[3]]) {
+    // Greyscale colors have hue and saturation of zero.
+    hsb[0] = 0;
+    hsb[1] = 0;
+    if (![color getWhite:&hsb[2] alpha:&hsb[3]]) {
+      NSCAssert(NO, @"Could not extract HSB from target color %@", color);
+      hsb[2] = 0;
+      hsb[3] = 0;
+    }
+  }
+}
+
+/** Return the ordered index of a tint/accent by name. */
+static int NameToIndex(NSString *_Nonnull name) {
+  static NSDictionary *map = nil;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    map = @{
+      MDC_PALETTE_TINT_50_INTERNAL_NAME : @(kQTMColorTint50Index),
+      MDC_PALETTE_TINT_100_INTERNAL_NAME : @(kQTMColorTint100Index),
+      MDC_PALETTE_TINT_200_INTERNAL_NAME : @(kQTMColorTint200Index),
+      MDC_PALETTE_TINT_300_INTERNAL_NAME : @(kQTMColorTint300Index),
+      MDC_PALETTE_TINT_400_INTERNAL_NAME : @(kQTMColorTint400Index),
+      MDC_PALETTE_TINT_500_INTERNAL_NAME : @(kQTMColorTint500Index),
+      MDC_PALETTE_TINT_600_INTERNAL_NAME : @(kQTMColorTint600Index),
+      MDC_PALETTE_TINT_700_INTERNAL_NAME : @(kQTMColorTint700Index),
+      MDC_PALETTE_TINT_800_INTERNAL_NAME : @(kQTMColorTint800Index),
+      MDC_PALETTE_TINT_900_INTERNAL_NAME : @(kQTMColorTint900Index),
+      MDC_PALETTE_ACCENT_100_INTERNAL_NAME : @(kQTMColorAccent100Index),
+      MDC_PALETTE_ACCENT_200_INTERNAL_NAME : @(kQTMColorAccent200Index),
+      MDC_PALETTE_ACCENT_400_INTERNAL_NAME : @(kQTMColorAccent400Index),
+      MDC_PALETTE_ACCENT_700_INTERNAL_NAME : @(kQTMColorAccent700Index)
+    };
+  });
+
+  NSNumber *index = map[name];
+  if (index) {
+    return [index intValue];
+  } else {
+    NSCAssert(NO, @"%@ is not a valid tint/accent name.", name);
+    return kQTMColorTint500Index;
+  }
+}
+
+UIColor *MDCPaletteTintFromTargetColor(UIColor *targetColor, NSString *tintName) {
+  NSCAssert(MDCPaletteIsTintOrAccentName(tintName), @"Invalid tint/accent name %@.", tintName);
+  int tint = NameToIndex(tintName);
+
+  CGFloat hsb[4];
+  ColorToHSB(targetColor, hsb);
+
+  // Saturation: select a saturation curve from the input saturation, unless the saturation is so
+  // low to be considered 'colorless', e.g. white/black/grey, in which case skip this step.
+  CGFloat saturation = hsb[1];
+  CGFloat t;
+  if (IsComponentGreaterThanValue(hsb[1], kSaturationMinThreshold)) {
+    // Limit saturation to observed values.
+    hsb[1] = Clamp(hsb[1], kSaturation500Min, kSaturation500Max);
+
+    t = InvLerp(hsb[1], kSaturation500Min, kSaturation500Max);
+    if (tint <= kQTMColorTint500Index) {
+      CGFloat saturation50 = Lerp(t, kSaturation50Min, kSaturation50Max);
+      CGFloat u = InvLerp(tint, kQTMColorTint50Index, kQTMColorTint500Index);
+      saturation = Lerp(u, saturation50, hsb[1]);
+    } else {
+      CGFloat saturation900 = Lerp(t, kSaturation900Min, kSaturation900Max);
+      CGFloat u = InvLerp(tint, kQTMColorTint500Index, kQTMColorTint900Index);
+      saturation = Lerp(u, hsb[1], saturation900);
+    }
+  }
+
+  // Brightness: select a brightness curve from the input brightness.
+  CGFloat brightness;
+
+  // Limit brightness to observed values.
+  hsb[2] = Clamp(hsb[2], kBrightness500Min, kBrightness500Max);
+  t = InvLerp(hsb[2], kBrightness500Min, kBrightness500Max);
+
+  // The tints 50-500 are nice and linear.
+  if (tint <= kQTMColorTint500Index) {
+    CGFloat brightness50 = Lerp(t, kBrightness50Min, kBrightness50Max);
+    CGFloat u = InvLerp(tint, kQTMColorTint50Index, kQTMColorTint500Index);
+    brightness = Lerp(u, brightness50, hsb[2]);
+
+    // The tints > 500 fall off roughly quadratically.
+  } else {
+    CGFloat u = tint - kQTMColorTint500Index;
+    brightness = hsb[2] + kBrightnessQuadracticCoeff * u * u + kBrightnessLinearCoeff * u;
+  }
+
+  return [UIColor colorWithHue:hsb[0] saturation:saturation brightness:brightness alpha:1];
+}
+
+UIColor *MDCPaletteAccentFromTargetColor(UIColor *targetColor, NSString *accentName) {
+  NSCAssert(MDCPaletteIsTintOrAccentName(accentName), @"Invalid tint/accent name %@.", accentName);
+  int accent = NameToIndex(accentName);
+
+  CGFloat hsb[4];
+  ColorToHSB(targetColor, hsb);
+
+  int index = accent - kQTMColorAccent100Index;
+  NSCAssert(index >= 0 && index < 4, @"Invalid accent index %i", (int)accent);
+
+  CGFloat saturation = IsComponentGreaterThanValue(hsb[1], kSaturationMinThreshold)
+                           ? kAccentSaturation[index]
+                           : hsb[1];
+  CGFloat brightness = kAccentBrightness[index];
+  return [UIColor colorWithHue:hsb[0] saturation:saturation brightness:brightness alpha:1];
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h
new file mode 100644
index 0000000..58a3cc2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.h
@@ -0,0 +1,58 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License")
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/*
+ The string values of the names of the tints and accents are required in two places:
+   - in the definitions of the API names (such as MDCPaletteTint500Name)
+   - in the private implementation, for example, to check incoming strings are correct.
+
+ We can't have both the public and the private implementations depending on each other, since that
+ would cause a dependency loop. The normal solution to a dependency loop is to factor out the
+ common part into a new "unit" and have both of the original implementations depend on this new
+ unit. In this case, the string values would get factored out into the new unit.
+
+ However, the code in question is initializing constant data (the strings), the definitions must use
+ compile-time constants. For example, if we factored out the string values as "internal" names, the
+ following would still not work because the initialization doesn't use compile-time constants.
+
+ ```objective-c
+ static const NSString *MDCPaletteTint500Name = MDCPaletteTint500InternalName;
+ ```
+
+ To get around this, we instead drop down a level and define the strings in the preprocessor, so
+ that the compiler still sees compile-time constants. This has the downside of possibly duplicating
+ strings if the compiler can't optimize string storage across compilation units.
+ */
+
+#import <Foundation/Foundation.h>
+
+#define MDC_PALETTE_TINT_50_INTERNAL_NAME @"50"
+#define MDC_PALETTE_TINT_100_INTERNAL_NAME @"100"
+#define MDC_PALETTE_TINT_200_INTERNAL_NAME @"200"
+#define MDC_PALETTE_TINT_300_INTERNAL_NAME @"300"
+#define MDC_PALETTE_TINT_400_INTERNAL_NAME @"400"
+#define MDC_PALETTE_TINT_500_INTERNAL_NAME @"500"
+#define MDC_PALETTE_TINT_600_INTERNAL_NAME @"600"
+#define MDC_PALETTE_TINT_700_INTERNAL_NAME @"700"
+#define MDC_PALETTE_TINT_800_INTERNAL_NAME @"800"
+#define MDC_PALETTE_TINT_900_INTERNAL_NAME @"900"
+#define MDC_PALETTE_ACCENT_100_INTERNAL_NAME @"A100"
+#define MDC_PALETTE_ACCENT_200_INTERNAL_NAME @"A200"
+#define MDC_PALETTE_ACCENT_400_INTERNAL_NAME @"A400"
+#define MDC_PALETTE_ACCENT_700_INTERNAL_NAME @"A700"
+
+/** Return YES if a string is one of the pre-defined tint/accent names. */
+BOOL MDCPaletteIsTintOrAccentName(NSString* _Nonnull name);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.m
new file mode 100644
index 0000000..620fb3e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Palettes/src/private/MDCPaletteNames.m
@@ -0,0 +1,34 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License")
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCPaletteNames.h"
+
+BOOL MDCPaletteIsTintOrAccentName(NSString* _Nonnull name) {
+  return [name isEqualToString:MDC_PALETTE_TINT_50_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_100_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_200_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_300_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_400_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_500_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_600_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_700_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_800_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_TINT_900_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_100_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_200_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_400_INTERNAL_NAME] ||
+         [name isEqualToString:MDC_PALETTE_ACCENT_700_INTERNAL_NAME];
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.h
new file mode 100644
index 0000000..3c01c65
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.h
@@ -0,0 +1,91 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** The animation mode when animating backward progress. */
+typedef NS_ENUM(NSInteger, MDCProgressViewBackwardAnimationMode) {
+
+  /** Animate negative progress by resetting to 0 and then animating to the new value. */
+  MDCProgressViewBackwardAnimationModeReset,
+
+  /** Animate negative progress by animating from the current value. */
+  MDCProgressViewBackwardAnimationModeAnimate
+};
+
+/**
+ A Material linear determinate progress view.
+
+ See https://www.google.com/design/spec/components/progress-activity.html
+ */
+IB_DESIGNABLE
+@interface MDCProgressView : UIView
+
+/**
+ The color shown for the portion of the progress view that is filled.
+
+ The default is a blue color. When changed, the trackTintColor is reset.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *progressTintColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The color shown for the portion of the progress view that is not filled.
+
+ The default is a light version of the current progressTintColor.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *trackTintColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The current progress.
+
+ The current progress is represented by a floating-point value between 0.0 and 1.0, inclusive, where
+ 1.0 indicates the completion of the task. The default value is 0.0. Values less than 0.0 and
+ greater than 1.0 are pinned to those limits.
+ To animate progress changes, use -setProgress:animated:completion:.
+ */
+@property(nonatomic, assign) float progress;
+
+/**
+ The backward progress animation mode.
+
+ When animating progress which is lower than the current progress value, this mode
+ will determine which animation to use. The default is MDCProgressViewBackwardAnimationModeReset.
+ */
+@property(nonatomic, assign) MDCProgressViewBackwardAnimationMode backwardProgressAnimationMode;
+
+/**
+ Adjusts the current progress, optionally animating the change.
+
+ @param progress The progress to set.
+ @param animated Whether the change should be animated.
+ @param completion The completion block executed at the end of the animation.
+ */
+- (void)setProgress:(float)progress
+           animated:(BOOL)animated
+         completion:(void (^__nullable)(BOOL finished))completion;
+
+/**
+ Changes the hidden state, optionally animating the change.
+
+ @param hidden The hidden state to set.
+ @param animated Whether the change should be animated.
+ @param completion The completion block executed at the end of the animation.
+ */
+- (void)setHidden:(BOOL)hidden
+         animated:(BOOL)animated
+       completion:(void (^__nullable)(BOOL finished))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.m
new file mode 100644
index 0000000..705a5ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MDCProgressView.m
@@ -0,0 +1,292 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCProgressView.h"
+
+#import <tgmath.h>
+
+#import "MaterialRTL.h"
+
+// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t MDCProgressViewDefaultTintColor = 0x2196F3;
+
+// The ratio by which to desaturate the progress tint color to obtain the default track tint color.
+static const CGFloat MDCProgressViewTrackColorDesaturation = 0.3f;
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+static const NSTimeInterval MDCProgressViewAnimationDuration = 0.25;
+
+@interface MDCProgressView ()
+@property(nonatomic, strong) UIView *progressView;
+@property(nonatomic, strong) UIView *trackView;
+@property(nonatomic) BOOL animatingHide;
+// A UIProgressView to return the same format for the accessibility value. For example, when
+// progress is 0.497, it reports "fifty per cent".
+@property(nonatomic, readonly) UIProgressView *accessibilityProgressView;
+@end
+
+@implementation MDCProgressView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCProgressViewInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCProgressViewInit];
+  }
+  return self;
+}
+
+- (void)commonMDCProgressViewInit {
+  self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
+  self.backgroundColor = [UIColor clearColor];
+  self.clipsToBounds = YES;
+  self.isAccessibilityElement = YES;
+
+  _backwardProgressAnimationMode = MDCProgressViewBackwardAnimationModeReset;
+
+  _trackView = [[UIView alloc] initWithFrame:self.frame];
+  _trackView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+  [self addSubview:_trackView];
+
+  _progressView = [[UIView alloc] initWithFrame:CGRectZero];
+  [self addSubview:_progressView];
+
+  _progressView.backgroundColor = [[self class] defaultProgressTintColor];
+  _trackView.backgroundColor =
+      [[self class] defaultTrackTintColorForProgressTintColor:_progressView.backgroundColor];
+}
+
+- (void)willMoveToSuperview:(UIView *)superview {
+  [super willMoveToSuperview:superview];
+  [NSObject cancelPreviousPerformRequestsWithTarget:self];
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // Don't update the views when the hide animation is in progress.
+  if (!self.animatingHide) {
+    [self updateProgressView];
+    [self updateTrackView];
+  }
+}
+
+- (UIColor *)progressTintColor {
+  return self.progressView.backgroundColor;
+}
+
+- (void)setProgressTintColor:(UIColor *)progressTintColor {
+  if (progressTintColor == nil) {
+    progressTintColor = [[self class] defaultProgressTintColor];
+  }
+  self.progressView.backgroundColor = progressTintColor;
+}
+
+- (UIColor *)trackTintColor {
+  return self.trackView.backgroundColor;
+}
+
+- (void)setTrackTintColor:(UIColor *)trackTintColor {
+  if (trackTintColor == nil) {
+    trackTintColor =
+        [[self class] defaultTrackTintColorForProgressTintColor:self.progressTintColor];
+  }
+  self.trackView.backgroundColor = trackTintColor;
+}
+
+- (void)setProgress:(float)progress {
+  if (progress > 1)
+    progress = 1;
+  if (progress < 0)
+    progress = 0;
+  _progress = progress;
+  [self accessibilityValueDidChange];
+  [self setNeedsLayout];
+}
+
+- (void)setProgress:(float)progress
+           animated:(BOOL)animated
+         completion:(void (^__nullable)(BOOL finished))completion {
+  if (progress < self.progress &&
+      self.backwardProgressAnimationMode == MDCProgressViewBackwardAnimationModeReset) {
+    self.progress = 0;
+    [self updateProgressView];
+  }
+
+  self.progress = progress;
+  [UIView animateWithDuration:animated ? [[self class] animationDuration] : 0
+                        delay:0
+                      options:[[self class] animationOptions]
+                   animations:^{
+                     [self updateProgressView];
+                   }
+                   completion:completion];
+}
+
+- (void)setHidden:(BOOL)hidden {
+  [super setHidden:hidden];
+  UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, hidden ? nil : self);
+}
+
+- (void)setHidden:(BOOL)hidden
+         animated:(BOOL)animated
+       completion:(void (^__nullable)(BOOL finished))completion {
+  if (hidden == self.hidden) {
+    if (completion) {
+      completion(YES);
+    }
+    return;
+  }
+
+  void (^animations)(void);
+
+  if (hidden) {
+    self.animatingHide = YES;
+    animations = ^{
+      CGFloat y = CGRectGetHeight(self.bounds);
+
+      CGRect trackViewFrame = self.trackView.frame;
+      trackViewFrame.origin.y = y;
+      trackViewFrame.size.height = 0;
+      self.trackView.frame = trackViewFrame;
+
+      CGRect progressViewFrame = self.progressView.frame;
+      progressViewFrame.origin.y = y;
+      progressViewFrame.size.height = 0;
+      self.progressView.frame = progressViewFrame;
+    };
+  } else {
+    self.hidden = NO;
+    animations = ^{
+      self.trackView.frame = self.bounds;
+
+      CGRect progressViewFrame = self.progressView.frame;
+      progressViewFrame.origin.y = 0;
+      progressViewFrame.size.height = CGRectGetHeight(self.bounds);
+      self.progressView.frame = progressViewFrame;
+    };
+  }
+
+  [UIView animateWithDuration:animated ? [[self class] animationDuration] : 0
+                        delay:0
+                      options:[[self class] animationOptions]
+                   animations:animations
+                   completion:^(BOOL finished) {
+                     if (hidden) {
+                       self.animatingHide = NO;
+                       self.hidden = YES;
+                     }
+                     if (completion)
+                       completion(finished);
+                   }];
+}
+
+#pragma mark Accessibility
+
+- (UIProgressView *)accessibilityProgressView {
+  // Accessibility values are determined by querying a UIProgressView set to the same value as our
+  // MDCProgressView.
+  static UIProgressView *accessibilityProgressView;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    accessibilityProgressView = [[UIProgressView alloc] init];
+  });
+
+  return accessibilityProgressView;
+}
+
+- (NSString *)accessibilityValue {
+  self.accessibilityProgressView.progress = self.progress;
+  return self.accessibilityProgressView.accessibilityValue;
+}
+
+- (void)accessibilityValueDidChange {
+  // Store a strong reference to self until the end of the method. Indeed,
+  // a previous -performSelector:withObject:afterDelay: might be the last thing
+  // to retain self, so calling +cancelPreviousPerformRequestsWithTarget: might
+  // deallocate self.
+  MDCProgressView *strongSelf = self;
+  // Cancel unprocessed announcements and replace them with the most up-to-date
+  // value. That way, they don't overlap and don't spam the user.
+  [NSObject cancelPreviousPerformRequestsWithTarget:strongSelf
+                                           selector:@selector(announceAccessibilityValueChange)
+                                             object:nil];
+  // Schedule a new announcement.
+  [strongSelf performSelector:@selector(announceAccessibilityValueChange)
+                   withObject:nil
+                   afterDelay:1];
+}
+
+- (void)announceAccessibilityValueChange {
+  if ([self accessibilityElementIsFocused]) {
+    UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                    [self accessibilityValue]);
+  }
+}
+
+#pragma mark Private
+
++ (NSTimeInterval)animationDuration {
+  return MDCProgressViewAnimationDuration;
+}
+
++ (UIViewAnimationOptions)animationOptions {
+  // Since the animation is fake, using a linear interpolation avoids the speeding up and slowing
+  // down that repeated easing in and out causes.
+  return UIViewAnimationOptionCurveLinear;
+}
+
++ (UIColor *)defaultProgressTintColor {
+  return MDCColorFromRGB(MDCProgressViewDefaultTintColor);
+}
+
++ (UIColor *)defaultTrackTintColorForProgressTintColor:(UIColor *)progressTintColor {
+  CGFloat hue, saturation, brightness, alpha;
+  if ([progressTintColor getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
+    CGFloat newSaturation = MIN(saturation * MDCProgressViewTrackColorDesaturation, 1.0f);
+    return [UIColor colorWithHue:hue saturation:newSaturation brightness:brightness alpha:alpha];
+  }
+  return [UIColor clearColor];
+}
+
+- (void)updateProgressView {
+  // Update progressView with the current progress value.
+  CGFloat progressWidth = ceil(self.progress * CGRectGetWidth(self.bounds));
+  CGRect progressFrame = CGRectMake(0, 0, progressWidth, CGRectGetHeight(self.bounds));
+  self.progressView.frame = MDCRectFlippedForRTL(progressFrame, CGRectGetWidth(self.bounds),
+                                                 self.mdc_effectiveUserInterfaceLayoutDirection);
+}
+
+- (void)updateTrackView {
+  const CGSize size = self.bounds.size;
+  self.trackView.frame = self.hidden ? CGRectMake(0.0, size.height, size.width, 0.0) : self.bounds;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MaterialProgressView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MaterialProgressView.h
new file mode 100644
index 0000000..9c844f6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ProgressView/src/MaterialProgressView.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCProgressView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
new file mode 100644
index 0000000..10c620a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.h
@@ -0,0 +1,83 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <CoreGraphics/CoreGraphics.h>
+
+/** The shadow elevation of the app bar. */
+CG_EXTERN const CGFloat MDCShadowElevationAppBar;
+
+/** The shadow elevation of a card in its picked up state. */
+CG_EXTERN const CGFloat MDCShadowElevationCardPickedUp;
+
+/** The shadow elevation of a card in its resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationCardResting;
+
+/** The shadow elevation of dialogs. */
+CG_EXTERN const CGFloat MDCShadowElevationDialog;
+
+/** The shadow elevation of the floating action button in its pressed state. */
+CG_EXTERN const CGFloat MDCShadowElevationFABPressed;
+
+/** The shadow elevation of the floating action button in its resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationFABResting;
+
+/** The shadow elevation of a menu. */
+CG_EXTERN const CGFloat MDCShadowElevationMenu;
+
+/** The shadow elevation of a modal bottom sheet. */
+CG_EXTERN const CGFloat MDCShadowElevationModalBottomSheet;
+
+/** The shadow elevation of the navigation drawer. */
+CG_EXTERN const CGFloat MDCShadowElevationNavDrawer;
+
+/** No shadow elevation at all. */
+CG_EXTERN const CGFloat MDCShadowElevationNone;
+
+/** The shadow elevation of a picker. */
+CG_EXTERN const CGFloat MDCShadowElevationPicker;
+
+/** The shadow elevation of the quick entry in the scrolled state. */
+CG_EXTERN const CGFloat MDCShadowElevationQuickEntry;
+
+/** The shadow elevation of the quick entry in the resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationQuickEntryResting;
+
+/** The shadow elevation of a raised button in the pressed state. */
+CG_EXTERN const CGFloat MDCShadowElevationRaisedButtonPressed;
+
+/** The shadow elevation of a raised button in the resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationRaisedButtonResting;
+
+/** The shadow elevation of a refresh indicator. */
+CG_EXTERN const CGFloat MDCShadowElevationRefresh;
+
+/** The shadow elevation of the right drawer. */
+CG_EXTERN const CGFloat MDCShadowElevationRightDrawer;
+
+/** The shadow elevation of the search bar in the resting state. */
+CG_EXTERN const CGFloat MDCShadowElevationSearchBarResting;
+
+/** The shadow elevation of the search bar in the scrolled state. */
+CG_EXTERN const CGFloat MDCShadowElevationSearchBarScrolled;
+
+/** The shadow elevation of the snackbar. */
+CG_EXTERN const CGFloat MDCShadowElevationSnackbar;
+
+/** The shadow elevation of a sub menu (+1 for each additional sub menu). */
+CG_EXTERN const CGFloat MDCShadowElevationSubMenu;
+
+/** The shadow elevation of a switch. */
+CG_EXTERN const CGFloat MDCShadowElevationSwitch;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.m
new file mode 100644
index 0000000..182f951
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MDCShadowElevations.m
@@ -0,0 +1,40 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowElevations.h"
+
+const CGFloat MDCShadowElevationAppBar = 4.f;
+const CGFloat MDCShadowElevationCardPickedUp = 8.f;
+const CGFloat MDCShadowElevationCardResting = 2.f;
+const CGFloat MDCShadowElevationDialog = 24.f;
+const CGFloat MDCShadowElevationFABPressed = 12.f;
+const CGFloat MDCShadowElevationFABResting = 6.f;
+const CGFloat MDCShadowElevationMenu = 8.f;
+const CGFloat MDCShadowElevationModalBottomSheet = 16.f;
+const CGFloat MDCShadowElevationNavDrawer = 16.f;
+const CGFloat MDCShadowElevationNone = 0;
+const CGFloat MDCShadowElevationPicker = 24.f;
+const CGFloat MDCShadowElevationQuickEntry = 3.f;
+const CGFloat MDCShadowElevationQuickEntryResting = 2.f;
+const CGFloat MDCShadowElevationRaisedButtonPressed = 8.f;
+const CGFloat MDCShadowElevationRaisedButtonResting = 2.f;
+const CGFloat MDCShadowElevationRefresh = 3.f;
+const CGFloat MDCShadowElevationRightDrawer = 16.f;
+const CGFloat MDCShadowElevationSearchBarResting = 2.f;
+const CGFloat MDCShadowElevationSearchBarScrolled = 3.f;
+const CGFloat MDCShadowElevationSnackbar = 6.f;
+const CGFloat MDCShadowElevationSubMenu = 9.f;
+const CGFloat MDCShadowElevationSwitch = 1.f;
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
new file mode 100644
index 0000000..3a62377
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowElevations/src/MaterialShadowElevations.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowElevations.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
new file mode 100644
index 0000000..7fe6b46
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.h
@@ -0,0 +1,78 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Metrics of the Material shadow effect.
+
+ These can be used if you require your own shadow implementation but want to match the material
+ spec.
+ */
+@interface MDCShadowMetrics : NSObject
+@property(nonatomic, readonly) CGFloat topShadowRadius;
+@property(nonatomic, readonly) CGSize topShadowOffset;
+@property(nonatomic, readonly) float topShadowOpacity;
+@property(nonatomic, readonly) CGFloat bottomShadowRadius;
+@property(nonatomic, readonly) CGSize bottomShadowOffset;
+@property(nonatomic, readonly) float bottomShadowOpacity;
+
+/**
+ The shadow metrics for manually creating shadows given an elevation.
+
+ @param elevation The shadow's elevation in points.
+ @return The shadow metrics.
+ */
++ (nonnull MDCShadowMetrics *)metricsWithElevation:(CGFloat)elevation;
+@end
+
+/**
+ The Material shadow effect.
+
+ @see
+ https://www.google.com/design/spec/what-is-material/elevation-shadows.html#elevation-shadows-shadows
+
+ Consider rasterizing your MDCShadowLayer if your view will not generally be animating or
+ changing size. If you need to animate a rasterized MDCShadowLayer, disable rasterization first.
+
+ For example, if self's layerClass is MDCShadowLayer, you might introduce the following code:
+
+     self.layer.shouldRasterize = YES;
+     self.layer.rasterizationScale = [UIScreen mainScreen].scale;
+ */
+@interface MDCShadowLayer : CALayer
+
+/**
+ The elevation of the layer in points.
+
+ The higher the elevation, the more spread out the shadow is. This is distinct from the layer's
+ zPosition which can be used to order overlapping layers, but will have no affect on the size of
+ the shadow.
+
+ Negative values act as if zero were specified.
+ */
+@property(nonatomic, assign) CGFloat elevation;
+
+/**
+ Whether to apply the "cutout" shadow layer mask.
+
+ If enabled, then a mask is created to ensure the interior, non-shadow part of the layer is visible.
+
+ Default is YES. Not animatable.
+ */
+@property(nonatomic, getter=isShadowMaskEnabled, assign) BOOL shadowMaskEnabled;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.m
new file mode 100644
index 0000000..ef690ee
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MDCShadowLayer.m
@@ -0,0 +1,353 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowLayer.h"
+
+static const CGFloat kShadowElevationDialog = 24.0;
+static const float kKeyShadowOpacity = 0.26f;
+static const float kAmbientShadowOpacity = 0.08f;
+
+static NSString *const MDCShadowLayerElevationKey = @"MDCShadowLayerElevationKey";
+static NSString *const MDCShadowLayerShadowMaskEnabledKey = @"MDCShadowLayerShadowMaskEnabledKey";
+
+@implementation MDCShadowMetrics
+
++ (MDCShadowMetrics *)metricsWithElevation:(CGFloat)elevation {
+  if (0.0 < elevation) {
+    return [[MDCShadowMetrics alloc] initWithElevation:elevation];
+  } else {
+    return [MDCShadowMetrics emptyShadowMetrics];
+  }
+}
+
+- (MDCShadowMetrics *)initWithElevation:(CGFloat)elevation {
+  self = [super init];
+  if (self) {
+    _topShadowRadius = [MDCShadowMetrics ambientShadowBlur:elevation];
+    _topShadowOffset = CGSizeMake(0.0, 0.0);
+    _topShadowOpacity = kAmbientShadowOpacity;
+    _bottomShadowRadius = [MDCShadowMetrics keyShadowBlur:elevation];
+    _bottomShadowOffset = CGSizeMake(0.0, [MDCShadowMetrics keyShadowYOff:elevation]);
+    _bottomShadowOpacity = kKeyShadowOpacity;
+  }
+  return self;
+}
+
++ (MDCShadowMetrics *)emptyShadowMetrics {
+  static MDCShadowMetrics *emptyShadowMetrics;
+  static dispatch_once_t once;
+  dispatch_once(&once, ^{
+    emptyShadowMetrics = [[MDCShadowMetrics alloc] init];
+    emptyShadowMetrics->_topShadowRadius = (CGFloat)0.0;
+    emptyShadowMetrics->_topShadowOffset = CGSizeMake(0.0, 0.0);
+    emptyShadowMetrics->_topShadowOpacity = 0.0f;
+    emptyShadowMetrics->_bottomShadowRadius = (CGFloat)0.0;
+    emptyShadowMetrics->_bottomShadowOffset = CGSizeMake(0.0, 0.0);
+    emptyShadowMetrics->_bottomShadowOpacity = 0.0f;
+  });
+
+  return emptyShadowMetrics;
+}
+
++ (CGFloat)ambientShadowBlur:(CGFloat)points {
+  CGFloat blur = 0.889544f * points - 0.003701f;
+  return blur;
+}
+
++ (CGFloat)keyShadowBlur:(CGFloat)points {
+  CGFloat blur = 0.666920f * points - 0.001648f;
+  return blur;
+}
+
++ (CGFloat)keyShadowYOff:(CGFloat)points {
+  CGFloat yOff = 1.23118f * points - 0.03933f;
+  return yOff;
+}
+
+@end
+
+@interface MDCShadowLayer ()
+
+@property(nonatomic, strong) CAShapeLayer *topShadow;
+@property(nonatomic, strong) CAShapeLayer *bottomShadow;
+
+@end
+
+@implementation MDCShadowLayer
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _elevation = 0;
+    _shadowMaskEnabled = YES;
+
+    [self commonMDCShadowLayerInit];
+  }
+  return self;
+}
+
+- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    if ([aDecoder containsValueForKey:MDCShadowLayerElevationKey]) {
+      _elevation = (CGFloat)[aDecoder decodeDoubleForKey:MDCShadowLayerElevationKey];
+    }
+    if ([aDecoder containsValueForKey:MDCShadowLayerShadowMaskEnabledKey]) {
+      _shadowMaskEnabled = [aDecoder decodeBoolForKey:MDCShadowLayerShadowMaskEnabledKey];
+    }
+
+    [self commonMDCShadowLayerInit];
+  }
+  return self;
+}
+
+/**
+ commonMDCShadowLayerInit creates additional layers based on the values of _elevation and
+ _shadowMaskEnabled.
+ */
+- (void)commonMDCShadowLayerInit {
+  _bottomShadow = [CAShapeLayer layer];
+  _bottomShadow.backgroundColor = [UIColor clearColor].CGColor;
+  _bottomShadow.shadowColor = [UIColor blackColor].CGColor;
+  [self addSublayer:_bottomShadow];
+
+  _topShadow = [CAShapeLayer layer];
+  _topShadow.backgroundColor = [UIColor clearColor].CGColor;
+  _topShadow.shadowColor = [UIColor blackColor].CGColor;
+  [self addSublayer:_topShadow];
+
+  // Setup shadow layer state based off _elevation and _shadowMaskEnabled
+  MDCShadowMetrics *shadowMetrics = [MDCShadowMetrics metricsWithElevation:_elevation];
+  _topShadow.shadowOffset = shadowMetrics.topShadowOffset;
+  _topShadow.shadowRadius = shadowMetrics.topShadowRadius;
+  _topShadow.shadowOpacity = shadowMetrics.topShadowOpacity;
+  _bottomShadow.shadowOffset = shadowMetrics.bottomShadowOffset;
+  _bottomShadow.shadowRadius = shadowMetrics.bottomShadowRadius;
+  _bottomShadow.shadowOpacity = shadowMetrics.bottomShadowOpacity;
+
+  // TODO(#1021): We shouldn't be calling property accessors in an init method.
+  if (_shadowMaskEnabled) {
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+  }
+}
+
+// TODO(#993): Implement missing initWithLayer:
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+  [super encodeWithCoder:aCoder];
+  [aCoder encodeDouble:_elevation forKey:MDCShadowLayerElevationKey];
+  [aCoder encodeBool:_shadowMaskEnabled forKey:MDCShadowLayerShadowMaskEnabledKey];
+  // Additional state is calculated at deserialization time based on _elevation and
+  // _shadowMaskEnabled so we don't need to store them.
+}
+
+- (void)layoutSublayers {
+  [super layoutSublayers];
+  [self commonLayoutSublayers];
+}
+
+- (void)setBounds:(CGRect)bounds {
+  BOOL sizeChanged = !CGSizeEqualToSize(self.bounds.size, bounds.size);
+  [super setBounds:bounds];
+  if (sizeChanged) {
+    // Invalidate our shadow paths.
+    _bottomShadow.shadowPath = nil;
+    _topShadow.shadowPath = nil;
+    [self setNeedsLayout];
+  }
+}
+
+#pragma mark - CALayer change monitoring.
+
+/** Returns a shadowPath based on the layer properties. */
+- (UIBezierPath *)defaultShadowPath {
+  CGFloat cornerRadius = self.cornerRadius;
+  if (0.0 < cornerRadius) {
+    return [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:cornerRadius];
+  }
+  return [UIBezierPath bezierPathWithRect:self.bounds];
+}
+
+- (void)setShadowPath:(CGPathRef)shadowPath {
+  super.shadowPath = shadowPath;
+  _topShadow.shadowPath = shadowPath;
+  _bottomShadow.shadowPath = shadowPath;
+  if (_shadowMaskEnabled) {
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+  }
+}
+
+- (void)setShadowColor:(CGColorRef)shadowColor {
+  super.shadowColor = shadowColor;
+  _topShadow.shadowColor = shadowColor;
+  _bottomShadow.shadowColor = shadowColor;
+}
+
+#pragma mark - shouldRasterize forwarding
+
+- (void)setShouldRasterize:(BOOL)shouldRasterize {
+  [super setShouldRasterize:shouldRasterize];
+  _topShadow.shouldRasterize = shouldRasterize;
+  _bottomShadow.shouldRasterize = shouldRasterize;
+}
+
+#pragma mark - Shadow Spread
+
+// Returns how far aware the shadow is spread from the edge of the layer.
++ (CGSize)shadowSpreadForElevation:(CGFloat)elevation {
+  MDCShadowMetrics *metrics = [MDCShadowMetrics metricsWithElevation:elevation];
+
+  CGSize shadowSpread = CGSizeZero;
+  shadowSpread.width = MAX(metrics.topShadowRadius, metrics.bottomShadowRadius) +
+                       MAX(metrics.topShadowOffset.width, metrics.bottomShadowOffset.width);
+  shadowSpread.height = MAX(metrics.topShadowRadius, metrics.bottomShadowRadius) +
+                        MAX(metrics.topShadowOffset.height, metrics.bottomShadowOffset.height);
+
+  return shadowSpread;
+}
+
+#pragma mark - Pseudo Shadow Masks
+
+- (void)setShadowMaskEnabled:(BOOL)shadowMaskEnabled {
+  _shadowMaskEnabled = shadowMaskEnabled;
+  if (_shadowMaskEnabled) {
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+  } else {
+    _topShadow.mask = nil;
+    _bottomShadow.mask = nil;
+  }
+}
+
+// Creates a layer mask that has a hole cut inside so that the original contents
+// of the view is no obscured by the shadow the top/bottom pseudo shadow layers
+// cast.
+- (CAShapeLayer *)shadowLayerMaskForLayer:(CALayer *)layer {
+  CAShapeLayer *maskLayer = [CAShapeLayer layer];
+
+  CGSize shadowSpread = [MDCShadowLayer shadowSpreadForElevation:kShadowElevationDialog];
+  CGRect bounds = layer.bounds;
+  CGRect maskRect = CGRectInset(bounds, -shadowSpread.width * 2, -shadowSpread.height * 2);
+
+  UIBezierPath *path = [UIBezierPath bezierPathWithRect:maskRect];
+  UIBezierPath *innerPath = nil;
+  if (self.shadowPath != nil) {
+    innerPath = [UIBezierPath bezierPathWithCGPath:(_Nonnull CGPathRef)self.shadowPath];
+  } else if (self.cornerRadius > 0) {
+    innerPath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.cornerRadius];
+  } else {
+    innerPath = [UIBezierPath bezierPathWithRect:self.bounds];
+  }
+  [path appendPath:innerPath];
+  [path setUsesEvenOddFillRule:YES];
+
+  maskLayer.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
+  maskLayer.bounds = maskRect;
+  maskLayer.path = path.CGPath;
+  maskLayer.fillRule = kCAFillRuleEvenOdd;
+  maskLayer.fillColor = [UIColor blackColor].CGColor;
+  return maskLayer;
+}
+
+- (void)setElevation:(CGFloat)elevation {
+  _elevation = elevation;
+  MDCShadowMetrics *shadowMetrics = [MDCShadowMetrics metricsWithElevation:elevation];
+  [self setMetrics:shadowMetrics];
+}
+
+- (void)setMetrics:(MDCShadowMetrics *)shadowMetrics {
+  CABasicAnimation *topOffsetAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOffset"];
+  topOffsetAnimation.fromValue = nil;
+  topOffsetAnimation.toValue = [NSValue valueWithCGSize:shadowMetrics.topShadowOffset];
+
+  CABasicAnimation *bottomOffsetAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOffset"];
+  bottomOffsetAnimation.fromValue = nil;
+  bottomOffsetAnimation.toValue = [NSValue valueWithCGSize:shadowMetrics.bottomShadowOffset];
+
+  CABasicAnimation *topRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"shadowRadius"];
+  topRadiusAnimation.fromValue = nil;
+  topRadiusAnimation.toValue = @(shadowMetrics.topShadowRadius);
+
+  CABasicAnimation *bottomRadiusAnimation = [CABasicAnimation animationWithKeyPath:@"shadowRadius"];
+  bottomRadiusAnimation.fromValue = nil;
+  bottomRadiusAnimation.toValue = @(shadowMetrics.bottomShadowRadius);
+
+  CABasicAnimation *topOpacityAnimation = [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
+  topOpacityAnimation.fromValue = nil;
+  topOpacityAnimation.toValue = @(shadowMetrics.topShadowOpacity);
+
+  CABasicAnimation *bottomOpacityAnimation =
+      [CABasicAnimation animationWithKeyPath:@"shadowOpacity"];
+  bottomOpacityAnimation.fromValue = nil;
+  bottomOpacityAnimation.toValue = @(shadowMetrics.bottomShadowOpacity);
+
+  // Group all animations together.
+  CAAnimationGroup *topAnimations = [CAAnimationGroup animation];
+  topAnimations.animations = @[ topOffsetAnimation, topRadiusAnimation, topOpacityAnimation ];
+
+  CAAnimationGroup *bottomAnimations = [CAAnimationGroup animation];
+  bottomAnimations.animations =
+      @[ bottomOffsetAnimation, bottomRadiusAnimation, bottomOpacityAnimation ];
+
+  [_topShadow removeAllAnimations];
+  [_bottomShadow removeAllAnimations];
+  [_topShadow addAnimation:topAnimations forKey:nil];
+  [_bottomShadow addAnimation:bottomAnimations forKey:nil];
+
+  // Set the final animation value in to the model layer.
+  _topShadow.shadowOffset = shadowMetrics.topShadowOffset;
+  _topShadow.shadowRadius = shadowMetrics.topShadowRadius;
+  _topShadow.shadowOpacity = shadowMetrics.topShadowOpacity;
+  _bottomShadow.shadowOffset = shadowMetrics.bottomShadowOffset;
+  _bottomShadow.shadowRadius = shadowMetrics.bottomShadowRadius;
+  _bottomShadow.shadowOpacity = shadowMetrics.bottomShadowOpacity;
+}
+
+#pragma mark - Private
+
+- (void)commonLayoutSublayers {
+  CGRect bounds = self.bounds;
+
+  _bottomShadow.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
+  _bottomShadow.bounds = bounds;
+  _topShadow.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
+  _topShadow.bounds = bounds;
+
+  if (_shadowMaskEnabled) {
+    _bottomShadow.mask = [self shadowLayerMaskForLayer:_bottomShadow];
+    _topShadow.mask = [self shadowLayerMaskForLayer:_topShadow];
+  }
+  // Enforce shadowPaths because otherwise no shadows can be drawn. If a shadowPath
+  // is already set, use that, otherwise fallback to just a regular rect because path.
+  if (!_bottomShadow.shadowPath) {
+    if (self.shadowPath) {
+      _bottomShadow.shadowPath = self.shadowPath;
+    } else {
+      _bottomShadow.shadowPath = [self defaultShadowPath].CGPath;
+    }
+  }
+  if (!_topShadow.shadowPath) {
+    if (self.shadowPath) {
+      _topShadow.shadowPath = self.shadowPath;
+    } else {
+      _topShadow.shadowPath = [self defaultShadowPath].CGPath;
+    }
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
new file mode 100644
index 0000000..baf9ce6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/ShadowLayer/src/MaterialShadowLayer.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCShadowLayer.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MDCSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MDCSlider.h
new file mode 100644
index 0000000..018e462
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MDCSlider.h
@@ -0,0 +1,196 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@protocol MDCSliderDelegate;
+
+/**
+ A Material slider.
+
+ @see https://www.google.com/design/spec/components/sliders.html for full details.
+
+ Differences between UISlider and MDCSlider:
+   Does not have api to
+     set right and left icons
+     set the thumb image
+     set the right and left track images (if you wanted a custom track)
+     set the right (background track) color
+   Same features
+     set color for thumb via @c thumbColor
+     set color of track via @c trackColor
+   New features
+     making the slider a snap to discrete values via @c numberOfDiscreteValues.
+ */
+IB_DESIGNABLE
+@interface MDCSlider : UIControl <NSSecureCoding>
+
+/** The delegate for the slider. */
+@property(nullable, nonatomic, weak) id<MDCSliderDelegate> delegate;
+
+/**
+ The color of the cursor (thumb) and filled in portion of the track (left side).
+
+ Default color is blue.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *color;
+
+/*
+ The color of the unfilled track that the cursor moves along (right side).
+
+ Default color is gray.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *trackBackgroundColor;
+
+/**
+ The number of discrete values that the slider can take.
+
+ If greater than or equal to 2, the thumb will snap to the nearest discrete value when the user
+ lifts their finger or taps. The discrete values are evenly spaced between the @c minimumValue and
+ @c maximumValue. If 0 or 1, the slider's value will not change when the user releases the thumb.
+
+ The default value is zero.
+ */
+@property(nonatomic, assign) NSUInteger numberOfDiscreteValues;
+
+/**
+ The value of the slider.
+
+ To animate from the current value to the new value, instead use @see setValue:animated:. The value
+ will be clamped between @c minimumValue and @c maximumValue. Setting the value will not send an
+ action message.
+
+ The default value of this property is 0.
+ */
+@property(nonatomic, assign) CGFloat value;
+
+/**
+ Set the value of the slider, allowing you to animate the change visually.
+
+ If animated is YES, the thumb is animated into its new position. Setting the value does not
+ result in an action message being sent.
+
+ @param value The value to set the slider to.
+ @param animated If YES, the thumb will animate to its new position.
+ */
+- (void)setValue:(CGFloat)value animated:(BOOL)animated;
+
+/**
+ The minimum value of the slider.
+
+ If you change the value of this property and the @c value of the receiver is below the new minimum,
+ the current value will be adjusted to match the new minimum value.
+ If you change the value of this property and @c maximumValue of the receiver is below the new
+ minimum, the @c maximumValue will also be set to this new minimum value.
+
+ The default value of this property is 0.0.
+ */
+@property(nonatomic, assign) CGFloat minimumValue;
+
+/**
+ The maximum value of the slider.
+
+ If you change the value of this property and the @c value of the receiver is above the new maximum,
+ the current value will be adjusted to match the new maximum value.
+ If you change the value of this property and @c minimumValue of the receiver is above the new
+ maximum, the @c minimumValue will also be set to this new maximum value.
+
+ The default value of this property is 1.0.
+ */
+@property(nonatomic, assign) CGFloat maximumValue;
+
+/**
+ Indicates  whether changes in the slider's value generate continuous update events.
+
+ If YES, the slider sends update events continuously to the associated target's action method.
+ If NO, the slider only sends an action event when the user releases the slider's thumb control to
+ set the final value.
+
+ The default value of this property is YES.
+ */
+@property(nonatomic, assign, getter=isContinuous) BOOL continuous;
+
+/**
+ The value from which the filled part of the track is anchored. If set to a value between
+ minimumValue and maximumValue, then the filled/colored part of the track extends from the
+ trackAnchorValue to the thumb. Values beyond the minimum/maximum values are effectively capped.
+
+ The default value is -CGFLOAT_MAX, so the filled part of the track extends from the minimum value
+ to the thumb.
+ */
+@property(nonatomic, assign) CGFloat filledTrackAnchorValue;
+
+/**
+ Whether or not to show the numeric value label when dragging a discrete slider. If YES, consider
+ implementing MDCSliderDelegate's @c -slider:displayedStringForValue: method to customize the string
+ displayed for each discrete value.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign) BOOL shouldDisplayDiscreteValueLabel;
+
+/**
+ Whether or not the thumb view should be a hollow circle when at the minimum value. For sliders
+ where the minimum value indicates that the associated property is off (for example a volume slider
+ where a value of 0 = muted), this should be set to YES. In cases where this doesn't make sense (for
+ instance a scrubber of an audio or video file), this should be set to NO.
+
+ Defaults to YES.
+ */
+@property(nonatomic, assign, getter=isThumbHollowAtStart) BOOL thumbHollowAtStart;
+
+@end
+
+/** MDCSlider delegate which allows setting custom behavior. */
+@protocol MDCSliderDelegate <NSObject>
+@optional
+
+/**
+ Called when the user taps on the MDCSlider.
+
+ If not implemented, the MDCSlider will always be allowed to jump to any value.
+ */
+- (BOOL)slider:(nonnull MDCSlider *)slider shouldJumpToValue:(CGFloat)value;
+
+/**
+ For discrete sliders, called when the slider is determining the string label to display for a given
+ discrete value.
+
+ If not implemented, or if no slider delegate is specified, the slider defaults to displaying the
+ value rounded to the closest relevant digit. For instance, 0.50000 would become "0.5"
+
+ Override this to provide custom behavior, for instance if your slider deals in percentages, the
+ above example could become "50%"
+
+ @param slider The MDCSlider sender.
+ @param value The value whose label needs to be calculated.
+ */
+- (nonnull NSString *)slider:(nonnull MDCSlider *)slider displayedStringForValue:(CGFloat)value;
+
+/**
+ Used to determine what string value should be used as the accessibility string for a given value.
+
+ If not implemented, or if no slider delegate is specified, the slider defaults to how filled the
+ slider is, as a percentage. Override this method to provide custom behavior, and when implementing,
+ you may want to also implement @c -slider:displayedStringForValue: to ensure consistency between
+ the displayed value and the accessibility label.
+
+ @param slider The MDCSlider sender.
+ @param value The value whose accessibility label needs to be calculated.
+ */
+- (nonnull NSString *)slider:(nonnull MDCSlider *)slider accessibilityLabelForValue:(CGFloat)value;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MDCSlider.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MDCSlider.m
new file mode 100644
index 0000000..ee831e1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MDCSlider.m
@@ -0,0 +1,343 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSlider.h"
+#import "private/MDCSlider_Subclassable.h"
+
+#import "MaterialThumbTrack.h"
+
+static const CGFloat kSliderDefaultWidth = 100.0f;
+static const CGFloat kSliderFrameHeight = 27.0f;
+static const CGFloat kSliderMinTouchSize = 48.0f;
+static const CGFloat kSliderThumbRadius = 6.0f;
+static const CGFloat kSliderAccessibilityIncrement = 0.1f;  // Matches UISlider's percent increment.
+static const CGFloat kSliderLightThemeTrackAlpha = 0.26f;
+
+// Blue 500 from http://www.google.com/design/spec/style/color.html#color-color-palette .
+static const uint32_t MDCBlueColor = 0x2196F3;
+
+// Creates a UIColor from a 24-bit RGB color encoded as an integer.
+static inline UIColor *MDCColorFromRGB(uint32_t rgbValue) {
+  return [UIColor colorWithRed:((CGFloat)((rgbValue & 0xFF0000) >> 16)) / 255
+                         green:((CGFloat)((rgbValue & 0x00FF00) >> 8)) / 255
+                          blue:((CGFloat)((rgbValue & 0x0000FF) >> 0)) / 255
+                         alpha:1];
+}
+
+@interface MDCSlider () <MDCThumbTrackDelegate>
+
+@end
+
+@implementation MDCSlider
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCSliderInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCSliderInit];
+  }
+  return self;
+}
+
+- (void)commonMDCSliderInit {
+  _thumbTrack =
+      [[MDCThumbTrack alloc] initWithFrame:self.bounds onTintColor:[[self class] defaultColor]];
+  _thumbTrack.delegate = self;
+  _thumbTrack.disabledTrackHasThumbGaps = YES;
+  _thumbTrack.trackEndsAreInset = YES;
+  _thumbTrack.thumbRadius = kSliderThumbRadius;
+  _thumbTrack.thumbIsSmallerWhenDisabled = YES;
+  _thumbTrack.thumbIsHollowAtStart = YES;
+  _thumbTrack.thumbGrowsWhenDragging = YES;
+  _thumbTrack.shouldDisplayInk = NO;
+  _thumbTrack.shouldDisplayDiscreteDots = YES;
+  _thumbTrack.shouldDisplayDiscreteValueLabel = YES;
+  _thumbTrack.trackOffColor = [[self class] defaultTrackOffColor];
+  _thumbTrack.thumbDisabledColor = [[self class] defaultDisabledColor];
+  _thumbTrack.trackDisabledColor = [[self class] defaultDisabledColor];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackValueChanged:)
+        forControlEvents:UIControlEventValueChanged];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchDown:)
+        forControlEvents:UIControlEventTouchDown];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchUpInside:)
+        forControlEvents:UIControlEventTouchUpInside];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchUpOutside:)
+        forControlEvents:UIControlEventTouchUpOutside];
+  [_thumbTrack addTarget:self
+                  action:@selector(thumbTrackTouchCanceled:)
+        forControlEvents:UIControlEventTouchCancel];
+  [self addSubview:_thumbTrack];
+}
+
+#pragma mark - ThumbTrack passthrough methods
+
+- (void)setTrackBackgroundColor:(UIColor *)trackBackgroundColor {
+  _thumbTrack.trackOffColor = trackBackgroundColor ?: [[self class] defaultTrackOffColor];
+  ;
+}
+
+- (UIColor *)trackBackgroundColor {
+  return _thumbTrack.trackOffColor;
+}
+
+- (void)setColor:(UIColor *)color {
+  _thumbTrack.primaryColor = color ?: [[self class] defaultColor];
+}
+
+- (UIColor *)color {
+  return _thumbTrack.primaryColor;
+}
+
+- (NSUInteger)numberOfDiscreteValues {
+  return _thumbTrack.numDiscreteValues;
+}
+
+- (void)setNumberOfDiscreteValues:(NSUInteger)numberOfDiscreteValues {
+  _thumbTrack.numDiscreteValues = numberOfDiscreteValues;
+}
+
+- (BOOL)isContinuous {
+  return _thumbTrack.continuousUpdateEvents;
+}
+
+- (void)setContinuous:(BOOL)continuous {
+  _thumbTrack.continuousUpdateEvents = continuous;
+}
+
+- (CGFloat)value {
+  return _thumbTrack.value;
+}
+
+- (void)setValue:(CGFloat)value {
+  _thumbTrack.value = value;
+}
+
+- (void)setValue:(CGFloat)value animated:(BOOL)animated {
+  [_thumbTrack setValue:value animated:animated];
+}
+
+- (CGFloat)minimumValue {
+  return _thumbTrack.minimumValue;
+}
+
+- (void)setMinimumValue:(CGFloat)minimumValue {
+  _thumbTrack.minimumValue = minimumValue;
+}
+
+- (CGFloat)maximumValue {
+  return _thumbTrack.maximumValue;
+}
+
+- (void)setMaximumValue:(CGFloat)maximumValue {
+  _thumbTrack.maximumValue = maximumValue;
+}
+
+- (CGFloat)filledTrackAnchorValue {
+  return _thumbTrack.filledTrackAnchorValue;
+}
+
+- (void)setFilledTrackAnchorValue:(CGFloat)filledTrackAnchorValue {
+  _thumbTrack.filledTrackAnchorValue = filledTrackAnchorValue;
+}
+
+- (BOOL)shouldDisplayDiscreteValueLabel {
+  return _thumbTrack.shouldDisplayDiscreteValueLabel;
+}
+
+- (void)setShouldDisplayDiscreteValueLabel:(BOOL)shouldDisplayDiscreteValueLabel {
+  _thumbTrack.shouldDisplayDiscreteValueLabel = shouldDisplayDiscreteValueLabel;
+}
+
+- (BOOL)isThumbHollowAtStart {
+  return _thumbTrack.thumbIsHollowAtStart;
+}
+
+- (void)setThumbHollowAtStart:(BOOL)thumbHollowAtStart {
+  _thumbTrack.thumbIsHollowAtStart = thumbHollowAtStart;
+}
+
+#pragma mark - MDCThumbTrackDelegate methods
+
+- (NSString *)thumbTrack:(MDCThumbTrack *)thumbTrack stringForValue:(CGFloat)value {
+  if ([_delegate respondsToSelector:@selector(slider:displayedStringForValue:)]) {
+    return [_delegate slider:self displayedStringForValue:value];
+  }
+
+  // Default behavior
+
+  static dispatch_once_t onceToken;
+  static NSNumberFormatter *numberFormatter;
+  dispatch_once(&onceToken, ^{
+    numberFormatter = [[NSNumberFormatter alloc] init];
+    numberFormatter.maximumFractionDigits = 3;
+    numberFormatter.minimumIntegerDigits = 1;  // To get 0.5 instead of .5
+  });
+  return [numberFormatter stringFromNumber:@(value)];
+}
+
+- (BOOL)thumbTrack:(MDCThumbTrack *)thumbTrack shouldJumpToValue:(CGFloat)value {
+  return ![_delegate respondsToSelector:@selector(slider:shouldJumpToValue:)] ||
+         [_delegate slider:self shouldJumpToValue:value];
+}
+
+#pragma mark - UIControl methods
+
+- (void)setEnabled:(BOOL)enabled {
+  [super setEnabled:enabled];
+  _thumbTrack.enabled = enabled;
+}
+
+- (BOOL)isTracking {
+  return _thumbTrack.isTracking;
+}
+
+#pragma mark - UIView methods
+
+- (CGSize)intrinsicContentSize {
+  return CGSizeMake(kSliderDefaultWidth, kSliderFrameHeight);
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  CGFloat dx = MIN(0, kSliderThumbRadius - kSliderMinTouchSize / 2);
+  CGFloat dy = MIN(0, (self.bounds.size.height - kSliderMinTouchSize) / 2);
+  CGRect rect = CGRectInset(self.bounds, dx, dy);
+  return CGRectContainsPoint(rect, point);
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  _thumbTrack.frame = self.bounds;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  CGSize result = self.bounds.size;
+  result.height = kSliderFrameHeight;
+  return result;
+}
+
+#pragma mark - Accessibility
+
+- (BOOL)isAccessibilityElement {
+  return YES;
+}
+
+- (NSString *)accessibilityValue {
+  if ([_delegate respondsToSelector:@selector(slider:accessibilityLabelForValue:)]) {
+    return [_delegate slider:self accessibilityLabelForValue:self.value];
+  }
+
+  // Default behavior
+
+  static dispatch_once_t onceToken;
+  static NSNumberFormatter *numberFormatter;
+  dispatch_once(&onceToken, ^{
+    numberFormatter = [[NSNumberFormatter alloc] init];
+    numberFormatter.numberStyle = NSNumberFormatterPercentStyle;
+  });
+  CGFloat percentage = (self.value - self.minimumValue) / (self.maximumValue - self.minimumValue);
+  return [numberFormatter stringFromNumber:@(percentage)];
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+  // Adding UIAccessibilityTraitAdjustable also causes an iOS accessibility hint to be spoken:
+  // "Swipe up or down with one finger to adjust the value."
+  UIAccessibilityTraits traits = super.accessibilityTraits | UIAccessibilityTraitAdjustable;
+  if (!self.enabled) {
+    traits |= UIAccessibilityTraitNotEnabled;
+  }
+  return traits;
+}
+
+- (void)accessibilityIncrement {
+  if (self.enabled) {
+    CGFloat range = self.maximumValue - self.minimumValue;
+    CGFloat newValue = self.value + kSliderAccessibilityIncrement * range;
+    [_thumbTrack setValue:newValue
+                     animated:NO
+        animateThumbAfterMove:NO
+                userGenerated:YES
+                   completion:NULL];
+
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+- (void)accessibilityDecrement {
+  if (self.enabled) {
+    CGFloat range = self.maximumValue - self.minimumValue;
+    CGFloat newValue = self.value - kSliderAccessibilityIncrement * range;
+    [_thumbTrack setValue:newValue
+                     animated:NO
+        animateThumbAfterMove:NO
+                userGenerated:YES
+                   completion:NULL];
+
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+  }
+}
+
+#pragma mark - NSSecureCoding
+
++ (BOOL)supportsSecureCoding {
+  return YES;
+}
+
+#pragma mark - Private
+
+- (void)thumbTrackValueChanged:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventValueChanged];
+}
+
+- (void)thumbTrackTouchDown:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchDown];
+}
+
+- (void)thumbTrackTouchUpInside:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchUpInside];
+}
+
+- (void)thumbTrackTouchUpOutside:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
+}
+
+- (void)thumbTrackTouchCanceled:(MDCThumbTrack *)thumbTrack {
+  [self sendActionsForControlEvents:UIControlEventTouchCancel];
+}
+
++ (UIColor *)defaultColor {
+  return MDCColorFromRGB(MDCBlueColor);
+}
+
++ (UIColor *)defaultTrackOffColor {
+  return [[UIColor blackColor] colorWithAlphaComponent:kSliderLightThemeTrackAlpha];
+}
+
++ (UIColor *)defaultDisabledColor {
+  return [[UIColor blackColor] colorWithAlphaComponent:kSliderLightThemeTrackAlpha];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MaterialSlider.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MaterialSlider.h
new file mode 100644
index 0000000..310f828
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/MaterialSlider.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSlider.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h
new file mode 100644
index 0000000..87e5dd0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Slider/src/private/MDCSlider_Subclassable.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSlider.h"
+
+@class MDCThumbTrack;
+
+/**
+ Import this header in order to properly subclass MDCSlider including access to the internal thumb
+ track.
+ */
+@interface MDCSlider () {
+ @protected
+  /**
+   The underlying thumb track backing the slider.
+   */
+  MDCThumbTrack *_thumbTrack;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
new file mode 100644
index 0000000..0bcc4a6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.h
@@ -0,0 +1,125 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCSnackbarMessage;
+@protocol MDCSnackbarSuspensionToken;
+
+/**
+ Provides a means of displaying an unobtrusive message to the user.
+
+ The style and location of the message can vary depending on the configuration of the message to be
+ shown. This class will queue repeated calls to @c showMessage: and show them at the appropriate
+ time, once previous messages have been dismissed. This class is thread-safe as long as the messages
+ given to MDCSnackbarManager are not mutated after being passed to @c showMessage:
+
+ Snackbars prefer an application's main window is a subclass of @c MDCOverlayWindow. When a standard
+ UIWindow is used an attempt is made to find the top-most view controller in the view hierarchy.
+ */
+@interface MDCSnackbarManager : NSObject
+
+/**
+ Shows @c message to the user, in a style consistent with the data contained in @c message.
+
+ For messages with the same category, the firing of completion blocks has a guaranteed FIFO
+ ordering. Ordering between completion blocks of different categories is not guaranteed. This method
+ is safe to call from any thread.
+ */
++ (void)showMessage:(MDCSnackbarMessage *)message;
+
+/**
+ MDCSnackbarManager will display the messages in this view.
+
+ Call this method to choose where in the view hierarchy snackbar messages will be presented. It is
+ only necessary to provide a host view if the default behavior is unable to find one on it's own,
+ most commonly when using MDCSnackbarManager inside an application extension. By default, if you use
+ MDCSnackbarManager without calling @c setPresentationHostView, the manager will attempt to find a
+ suitable view by stepping through the application windows. Explicitly providing a host view is only
+ required if you need to manually manage the view hierarchy, or are inside a UIApplication
+ extension.
+
+ @note This method must be called from the main thread.
+ @note Calling setPresentationHostView will not change the parent of the currently visible message.
+ */
++ (void)setPresentationHostView:(UIView *)hostView;
+
+/**
+ Bypasses showing the messages of the given @c category.
+
+ Completion blocks are called, but the UI won't show any queued messages and will dismiss any
+ messages for the @c category. Calling this method with @c nil will dismiss all messages. This
+ method is safe to call from any thread.
+ */
++ (void)dismissAndCallCompletionBlocksWithCategory:(NSString *)category;
+
+/**
+ How far from the bottom of the screen messages are displayed.
+
+ If called within an animation block, the change will be animated.
+
+ @note This method must be called from the main thread.
+ @note This is meant for apps which have a navigation element such as a tab bar, which cannot
+ move and should not be obscured.
+ */
++ (void)setBottomOffset:(CGFloat)offset;
+
+#pragma mark Suspending
+
+/**
+ Suspends the display of all messages.
+
+ Any messages currently on screen will remain on screen (and dismiss normally). During this time any
+ incoming messages will be queued as normal.
+
+ @return A token suitable for use in {@c +[MDCSnackbarManager resumeWithToken:]}. Letting this
+ object deallocate is equivalent to calling {@c +[MDCSnackbarManager resumeMessagesWithToken:]}.
+ */
++ (id<MDCSnackbarSuspensionToken>)suspendAllMessages;
+
+/**
+ Suspends the display of all messages in a given category.
+
+ Any messages currently on screen will remain on screen (and dismiss normally). During this time any
+ incoming messages in this category will be queued as normal.
+
+ @param category The category for which message display will be suspended. Should not be nil.
+ @return A token suitable for use in {@c +[MDCSnackbarManager resumeMessagesWithToken:]}.
+ Letting this object dealloc is equivalent to calling
+ {@c +[MDCSnackbarManager resumeMessagesWithToken:]}.
+ */
++ (id<MDCSnackbarSuspensionToken>)suspendMessagesWithCategory:(NSString *)category;
+
+/**
+ Resumes the display of messages once there are no outstanding suspension tokens.
+
+ The provided token is invalidated and becomes useless.
+
+ @param token The suspension token to invalidate.
+ */
++ (void)resumeMessagesWithToken:(id<MDCSnackbarSuspensionToken>)token;
+
+@end
+
+/**
+ A suspension token is returned when messages are suspended by the snackbar manager.
+
+ Messages are suppressed while a suspension token is kept in memory. Messages will resume being
+ displayed when the suspension token is released or when the suspension token is passed to
+ @c resumeMessagesWithToken.
+ */
+@protocol MDCSnackbarSuspensionToken <NSObject>
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.m
new file mode 100644
index 0000000..9c71e23
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarManager.m
@@ -0,0 +1,575 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarManager.h"
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
+#import "MaterialOverlayWindow.h"
+#import "UIApplication+AppExtensions.h"
+#import "private/MDCSnackbarMessageInternal.h"
+#import "private/MDCSnackbarMessageViewInternal.h"
+#import "private/MDCSnackbarOverlayView.h"
+
+/** Test whether any of the accessibility elements of a view is focused */
+static BOOL UIViewHasFocusedAccessibilityElement(UIView *view) {
+  for (NSInteger i = 0; i < [view accessibilityElementCount]; i++) {
+    id accessibilityElement = [view accessibilityElementAtIndex:i];
+    if ([accessibilityElement accessibilityElementIsFocused]) {
+      return YES;
+    }
+  }
+  return NO;
+};
+
+@class MDCSnackbarManagerSuspensionToken;
+
+/**
+ Special category representing all messages.
+ */
+static NSString *const kAllMessagesCategory = @"$$___ALL_MESSAGES___$$";
+
+/**
+ The 'actual' snackbar manager which will take care of showing/hiding snackbar messages.
+ */
+@interface MDCSnackbarManagerInternal : NSObject
+
+/**
+ The list of messages waiting to be displayed.
+ */
+@property(nonatomic) NSMutableArray *pendingMessages;
+
+/**
+ The current suspension tokens.
+
+ @note: Keys are the message category, or the all messages category. Values are sets of suspension
+        tokens.
+ */
+@property(nonatomic) NSMutableDictionary<NSString *, NSMutableSet<NSUUID *> *> *suspensionTokens;
+
+/**
+ The view which will host our snackbar messages.
+ */
+@property(nonatomic) MDCSnackbarOverlayView *overlayView;
+
+/**
+ The view which contains the overlayView.
+ */
+@property(nonatomic) UIView *presentationHostView;
+
+/**
+ The currently-showing snackbar.
+ */
+@property(nonatomic) MDCSnackbarMessageView *currentSnackbar;
+
+/**
+ Whether or not we are currently showing a message.
+ */
+@property(nonatomic) BOOL showingMessage;
+
+@end
+
+@interface MDCSnackbarManagerSuspensionToken : NSObject <MDCSnackbarSuspensionToken>
+
+/**
+ The unique identifier for this token.
+ */
+@property(nonatomic, readonly) NSUUID *identifier;
+
+/**
+ The category string associated with this token.
+ */
+@property(nonatomic) NSString *category;
+
+@end
+
+@implementation MDCSnackbarManagerInternal
+
++ (MDCSnackbarManagerInternal *)sharedInstance {
+  static MDCSnackbarManagerInternal *manager = nil;
+  static dispatch_once_t onceToken;
+
+  dispatch_once(&onceToken, ^{
+    manager = [[MDCSnackbarManagerInternal alloc] init];
+  });
+
+  return manager;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _pendingMessages = [[NSMutableArray alloc] init];
+    _suspensionTokens = [NSMutableDictionary dictionary];
+    _overlayView = [[MDCSnackbarOverlayView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+  }
+  return self;
+}
+
+#pragma mark - Message Displaying
+
+/**
+ Determines whether or not a message is eligible to be shown based on the snackbar manager's current
+ configuration.
+
+ @note This method should ensure that messages in the same category are not shown out of order.
+ */
+- (BOOL)shouldShowMessageRightNowMainThread:(MDCSnackbarMessage *)message {
+  // If there are outstanding suspension tokens for all messages (not just specific categories),
+  // then hold off on displaying.
+  if ([self allMessagesSuspendedMainThread]) {
+    return NO;
+  }
+
+  // If there is an outstanding suspension token for this message category, then hold off on
+  // displaying.
+  if (message.category != nil && [self categorySuspended:message.category]) {
+    return NO;
+  }
+
+  return YES;
+}
+
+- (MDCSnackbarMessage *)dequeueNextShowableMessageMainThread {
+  // NOTE: In pathological cases, the iteration through the pending messages can be an O(n)
+  //       operation. Though we expect `n` to be low, to protect against needless iteration we'll
+  //       do a quick check to see if message displaying is completely suspended.
+  if ([self allMessagesSuspendedMainThread]) {
+    return nil;
+  }
+
+  __block NSUInteger messageIndex = NSNotFound;
+  [self.pendingMessages
+      enumerateObjectsUsingBlock:^(MDCSnackbarMessage *message, NSUInteger idx, BOOL *stop) {
+        if ([self shouldShowMessageRightNowMainThread:message]) {
+          messageIndex = idx;
+          *stop = YES;
+        }
+      }];
+
+  if (messageIndex != NSNotFound) {
+    MDCSnackbarMessage *message = self.pendingMessages[messageIndex];
+    [self.pendingMessages removeObjectAtIndex:messageIndex];
+
+    return message;
+  }
+
+  return nil;
+}
+
+// Dequeues and schedules the display of a particular message.
+- (void)showNextMessageIfNecessaryMainThread {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  if (self.pendingMessages.count == 0) {
+    return;
+  }
+
+  if (!self.showingMessage) {
+    MDCSnackbarMessage *message = [self dequeueNextShowableMessageMainThread];
+
+    if (message != nil) {
+      self.showingMessage = YES;
+      [self displaySnackbarViewForMessage:message];
+    }
+  }
+}
+
+// This method should only be called from within @c showNextMessageIfNecessaryMainThread.
+- (void)displaySnackbarViewForMessage:(MDCSnackbarMessage *)message {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  __block MDCSnackbarMessageView *snackbarView = nil;
+
+  // Guard against the timer firing and trying to dismiss us multiple times.
+  __block BOOL shouldDismiss = YES;
+  MDCSnackbarMessageDismissHandler dismissHandler =
+      ^(BOOL userInitiated, MDCSnackbarMessageAction *action) {
+        // Because we start a timer to dismiss the snackbar once it is on screen, there exists the
+        // potential to try and dismiss the snackbar view multiple times, say if the user taps on
+        // the snackbar (dismissal one) and then the timer fires (dismissal two). This check ensures
+        // that the dismissal logic will only fire one time for a given Snackbar view.
+        if (shouldDismiss) {
+          shouldDismiss = NO;
+
+          // If the user
+          [self hideSnackbarViewReally:snackbarView withAction:action userPrompted:userInitiated];
+        }
+      };
+
+  Class viewClass = [message viewClass];
+  snackbarView = [[viewClass alloc] initWithMessage:message dismissHandler:dismissHandler];
+  self.currentSnackbar = snackbarView;
+
+  self.overlayView.accessibilityViewIsModal = ![self isSnackbarTransient:snackbarView];
+  self.overlayView.hidden = NO;
+  [self activateOverlay:self.overlayView];
+
+  // Once the Snackbar has finished animating on screen, start the automatic dismiss timeout, but
+  // only if the user isn't running VoiceOver.
+  [self.overlayView
+      showSnackbarView:snackbarView
+              animated:YES
+            completion:^{
+              if ([self isSnackbarTransient:snackbarView]) {
+                snackbarView.accessibilityElementsHidden = YES;
+                UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification,
+                                                message.voiceNotificationText);
+
+              } else {
+                UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification,
+                                                snackbarView);
+              }
+
+              if ([self isSnackbarTransient:snackbarView]) {
+                __weak MDCSnackbarMessageView *weakSnackbarView = snackbarView;
+                dispatch_time_t popTime =
+                    dispatch_time(DISPATCH_TIME_NOW, (int64_t)(message.duration * NSEC_PER_SEC));
+                dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
+                  MDCSnackbarMessageView *strongSnackbarView = weakSnackbarView;
+                  BOOL hasVoiceOverFocus = UIAccessibilityIsVoiceOverRunning() &&
+                                           UIViewHasFocusedAccessibilityElement(strongSnackbarView);
+                  if (strongSnackbarView && !hasVoiceOverFocus) {
+                    // Mimic the user tapping on the snackbar.
+                    [strongSnackbarView dismissWithAction:nil userInitiated:NO];
+                  }
+                });
+              }
+            }];
+}
+
+- (void)hideSnackbarViewReally:(MDCSnackbarMessageView *)snackbarView
+                    withAction:(MDCSnackbarMessageAction *)action
+                  userPrompted:(BOOL)userPrompted {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  // Mark the snackbar as being in the process of dismissal.
+  snackbarView.dismissing = YES;
+
+  MDCSnackbarMessage *message = snackbarView.message;
+
+  // Fire off the button action, if necessary. Always call the message's completion handler.
+  [message
+      executeActionHandler:action
+                completion:^{
+                  [message executeCompletionHandlerWithUserInteraction:userPrompted completion:nil];
+                }];
+
+  [self.overlayView dismissSnackbarViewAnimated:YES
+                                     completion:^{
+                                       self.overlayView.hidden = YES;
+                                       [self deactivateOverlay:self.overlayView];
+
+                                       // If VoiceOver had been enabled and the snackbarView was
+                                       // transient, the snackbar was just announced (layout was not
+                                       // reported as changed) so there is no need to post a layout
+                                       // change here.
+                                       if (![self isSnackbarTransient:snackbarView]) {
+                                         UIAccessibilityPostNotification(
+                                             UIAccessibilityLayoutChangedNotification, nil);
+                                       }
+
+                                       self.currentSnackbar = nil;
+
+                                       // Now that the snackbar view is offscreen, we can allow more
+                                       // messages to be shown.
+                                       self.showingMessage = NO;
+                                       [self showNextMessageIfNecessaryMainThread];
+                                     }];
+}
+
+#pragma mark - Helper methods
+
+- (BOOL)isSnackbarTransient:(MDCSnackbarMessageView *)snackbarView {
+  if (UIAccessibilityIsVoiceOverRunning()) {
+    return ![snackbarView shouldWaitForDismissalDuringVoiceover];
+  }
+
+  return YES;
+}
+
+#pragma mark - Overlay Activation
+
+- (void)activateOverlay:(UIView *)overlay {
+  UIWindow *window = [self bestGuessWindow];
+  UIView *targetView = nil;
+
+  if (self.presentationHostView) {
+    targetView = self.presentationHostView;
+  } else if ([window isKindOfClass:[MDCOverlayWindow class]]) {
+    // If the application's window is an overlay window, take advantage of it. Otherwise, just add
+    // our overlay view into the main view controller's hierarchy.
+    MDCOverlayWindow *overlayWindow = (MDCOverlayWindow *)window;
+    [overlayWindow activateOverlay:overlay withLevel:UIWindowLevelNormal];
+  } else {
+    // Find the most top view controller to display overlay.
+    UIViewController *topViewController = [window rootViewController];
+    while ([topViewController presentedViewController]) {
+      topViewController = [topViewController presentedViewController];
+    }
+    targetView = [topViewController view];
+  }
+
+  if (targetView) {
+    overlay.frame = targetView.bounds;
+    overlay.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+    overlay.translatesAutoresizingMaskIntoConstraints = YES;
+
+    [targetView addSubview:overlay];
+  }
+}
+
+- (UIWindow *)bestGuessWindow {
+  UIApplication *application = [UIApplication mdc_safeSharedApplication];
+
+  // Check all of the windows in existence for an overlay window, because that's what we prefer to
+  // present in.
+  for (UIWindow *window in application.windows) {
+    if ([window isKindOfClass:[MDCOverlayWindow class]]) {
+      return window;
+    }
+  }
+
+  // Next see if the application's delegate declares a window. That's a good indicator of it being
+  // the 'main' window for an application.
+  if ([application.delegate respondsToSelector:@selector(window)]) {
+    id potentialWindow = application.delegate.window;
+    if (potentialWindow != nil) {
+      return potentialWindow;
+    }
+  }
+
+  // Default to the key window, since we couldn't find anything better.
+  return [[UIApplication mdc_safeSharedApplication] keyWindow];
+}
+
+- (void)deactivateOverlay:(UIView *)overlay {
+  UIWindow *window = [[UIApplication mdc_safeSharedApplication] keyWindow];
+  if ([window isKindOfClass:[MDCOverlayWindow class]]) {
+    MDCOverlayWindow *overlayWindow = (MDCOverlayWindow *)window;
+    [overlayWindow deactivateOverlay:overlay];
+  } else {
+    [overlay removeFromSuperview];
+  }
+}
+
+#pragma mark - Public API
+
+// Must be called from the main thread only.
+- (void)showMessageMainThread:(MDCSnackbarMessage *)message {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  // Dismiss and call the completion block for all the messages from the same category.
+  [self dismissAndCallCompletionBlocksOnMainThreadWithCategory:message.category];
+
+  // Add the new message to the queue, the call to @c showNextMessageIfNecessaryMainThread will take
+  // care of getting it on screen. At this moment, @c message is the only message of its category
+  // in @c _sPendingMessages.
+  [self.pendingMessages addObject:message];
+
+  // Pulse the UI as needed.
+  [self showNextMessageIfNecessaryMainThread];
+}
+
+- (void)dismissAndCallCompletionBlocksOnMainThreadWithCategory:(NSString *)categoryToDismiss {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  // Make sure that if there is a snackbar on screen, it does not belong to the current category.
+  if (self.currentSnackbar != nil && !self.currentSnackbar.dismissing) {
+    MDCSnackbarMessage *currentMessage = self.currentSnackbar.message;
+
+    if (!categoryToDismiss || [currentMessage.category isEqualToString:categoryToDismiss]) {
+      // Mimic the user tapping on the Snackbar. This will trigger the display of other messages,
+      // but because the dismissal animations happen on the main thread, we can modify
+      // @c _sPendingMessages in this cycle of the runloop without fear of the dismiss
+      // animation interfering.
+      [self.currentSnackbar dismissWithAction:nil userInitiated:NO];
+    }
+  }
+
+  // Now that we've ensured that the currently showing snackbar has been taken care of, we can go
+  // through pending messages and fire off their completion blocks as we remove them from the
+  // queue.
+  NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
+  [self.pendingMessages
+      enumerateObjectsUsingBlock:^(MDCSnackbarMessage *pendingMessage, NSUInteger idx, BOOL *stop) {
+        if (!categoryToDismiss || [pendingMessage.category isEqualToString:categoryToDismiss]) {
+          // Mark the message for removal from the pending messages list.
+          [indexesToRemove addIndex:idx];
+
+          // Notify the outside world that this snackbar has been completed.
+          [pendingMessage executeCompletionHandlerWithUserInteraction:NO completion:nil];
+        }
+      }];
+
+  // Make sure the queued up messages aren't shown.
+  if ([indexesToRemove count]) {
+    [self.pendingMessages removeObjectsAtIndexes:indexesToRemove];
+  }
+}
+
+#pragma mark - Suspend/Resume
+
+/**
+ Returns YES if message display is completely suspended.
+ */
+- (BOOL)allMessagesSuspendedMainThread {
+  NSMutableSet *allMessageSuspensions = self.suspensionTokens[kAllMessagesCategory];
+  if (allMessageSuspensions.count > 0) {
+    return YES;
+  }
+  return NO;
+}
+
+/**
+ Returns YES if message display is suspended for the given category.
+ */
+- (BOOL)categorySuspended:(NSString *)category {
+  NSMutableSet *thisCategorySuspensions = self.suspensionTokens[category];
+  if (thisCategorySuspensions.count > 0) {
+    return YES;
+  }
+  return NO;
+}
+
+- (void)addSuspensionIdentifierMainThread:(NSUUID *)identifier forCategory:(NSString *)category {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  NSMutableSet *tokens = self.suspensionTokens[category];
+  if (tokens == nil) {
+    tokens = [NSMutableSet set];
+    self.suspensionTokens[category] = tokens;
+  }
+
+  [tokens addObject:identifier];
+}
+
+- (void)removeSuspensionIdentifierMainThread:(NSUUID *)identifier forCategory:(NSString *)category {
+  // Ensure that this method is called on the main thread.
+  NSAssert([NSThread isMainThread], @"Method is not called on main thread.");
+
+  NSMutableSet *tokens = self.suspensionTokens[category];
+  [tokens removeObject:identifier];
+
+  // If that was the last token for this category, do some cleanup.
+  if (tokens != nil && tokens.count == 0) {
+    [self.suspensionTokens removeObjectForKey:category];
+  }
+
+  // We may have removed the last suspend, so trigger a display.
+  [self showNextMessageIfNecessaryMainThread];
+}
+
+@end
+
+#pragma mark - Public API
+
+@implementation MDCSnackbarManager
+
++ (void)showMessage:(MDCSnackbarMessage *)inputMessage {
+  if (!inputMessage) {
+    return;
+  }
+
+  // Snag a copy now, we'll use that internally.
+  MDCSnackbarMessage *message = [inputMessage copy];
+
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager showMessageMainThread:message];
+  });
+}
+
++ (void)setPresentationHostView:(UIView *)hostView {
+  NSAssert([NSThread isMainThread], @"setPresentationHostView must be called on main thread.");
+
+  MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+  manager.presentationHostView = hostView;
+}
+
++ (void)dismissAndCallCompletionBlocksWithCategory:(NSString *)category {
+  // Snag a copy now, we'll use that internally.
+  NSString *categoryToDismiss = [category copy];
+
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager dismissAndCallCompletionBlocksOnMainThreadWithCategory:categoryToDismiss];
+  });
+}
+
++ (void)setBottomOffset:(CGFloat)offset {
+  NSAssert([NSThread isMainThread], @"setBottomOffset must be called on main thread.");
+
+  MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+  manager.overlayView.bottomOffset = offset;
+}
+
+#pragma mark - Suspension
+
++ (id<MDCSnackbarSuspensionToken>)suspendMessagesWithCategory:(NSString *)category {
+  MDCSnackbarManagerSuspensionToken *token = [[MDCSnackbarManagerSuspensionToken alloc] init];
+  token.category = category;
+
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager addSuspensionIdentifierMainThread:token.identifier forCategory:token.category];
+  });
+
+  return token;
+}
+
++ (id<MDCSnackbarSuspensionToken>)suspendAllMessages {
+  return [self suspendMessagesWithCategory:kAllMessagesCategory];
+}
+
++ (void)handleInvalidatedIdentifier:(NSUUID *)identifier forCategory:(NSString *)category {
+  // Ensure that all of our work happens on the main thread.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    MDCSnackbarManagerInternal *manager = [MDCSnackbarManagerInternal sharedInstance];
+    [manager removeSuspensionIdentifierMainThread:identifier forCategory:category];
+  });
+}
+
++ (void)resumeMessagesWithToken:(id<MDCSnackbarSuspensionToken>)inToken {
+  if (![inToken isKindOfClass:[MDCSnackbarManagerSuspensionToken class]]) {
+    return;
+  }
+
+  MDCSnackbarManagerSuspensionToken *token = (MDCSnackbarManagerSuspensionToken *)inToken;
+  [self handleInvalidatedIdentifier:token.identifier forCategory:token.category];
+}
+
+@end
+
+@implementation MDCSnackbarManagerSuspensionToken
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    _identifier = [NSUUID UUID];
+  }
+  return self;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
new file mode 100644
index 0000000..0ee02c9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.h
@@ -0,0 +1,165 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCSnackbarMessageAction;
+
+/**
+ Called when a message is finished displaying, regardless of whether or not buttons were tapped.
+ */
+typedef void (^MDCSnackbarMessageCompletionHandler)(BOOL userInitiated);
+
+/**
+ Called when the button in the snackbar is tapped.
+ */
+typedef void (^MDCSnackbarMessageActionHandler)(void);
+
+/**
+ Maximum duration allowed for a MDCSnackbarMessage.
+
+ Set to 10 seconds. If longer durations are necessary than this value consider creating a custom UI
+ for your use case.
+ */
+extern const NSTimeInterval MDCSnackbarMessageDurationMax;
+
+/**
+ Bold style attribute that can be used in attributed text.
+
+ This attribute can be set over any range of @c attributedText and that text will have the proper
+ font applied.
+ */
+extern NSString *const MDCSnackbarMessageBoldAttributeName;
+
+/**
+ Represents a message to unobtrusively show to the user.
+
+ A snackbar message provides brief feedback about an operation. Messages are passed to the snackbar
+ manager to be displayed.
+
+ Snackbars prefer an application's main window is a subclass of @c MDCOverlayWindow. When a standard
+ UIWindow is used an attempt is made to find the top-most view controller in the view hierarchy.
+ */
+@interface MDCSnackbarMessage : NSObject <NSCopying, UIAccessibilityIdentification>
+
+/**
+ Returns a MDCSnackbarMessage with its text initialized.
+
+ @param text The text to display in the message.
+ @return An initialized MDCSnackbarMessage object with @c text.
+ */
++ (instancetype)messageWithText:(NSString *)text;
+
+/**
+ Returns a MDCSnackbarMessage with its attributed text initialized.
+
+ @param attributedText The attributed text to display in the message.
+ @return An initialized MDCSnackbarMessage object with @c attributedText.
+ */
++ (instancetype)messageWithAttributedText:(NSAttributedString *)attributedText;
+
+/**
+ The primary text of the message.
+
+ Either @c text or @c attributedText must be set.
+ */
+@property(nonatomic, copy) NSString *text;
+
+/**
+ The primary text of the message with styling.
+
+ Any attributes supported by UIKit may be set, though font and color will be overridden by the
+ snackbar. Either @c text or @c attributedText must be set.
+ */
+@property(nonatomic, copy) NSAttributedString *attributedText;
+
+/**
+ Optional button to show along with the rest of the message.
+
+ A MDCSnackbarMessageAction is displayed as a button on the snackbar. If no action is set no button
+ will appear on the Snackbar.
+ */
+@property(nonatomic, strong) MDCSnackbarMessageAction *action;
+
+/**
+ The color used for button text on the snackbar in normal state.
+
+ Default is white.
+ */
+@property(nonatomic, strong) UIColor *buttonTextColor;
+
+/**
+ The color used for button text on the snackbar in highlighted state.
+
+ Default is white.
+ */
+@property(nonatomic, strong) UIColor *highlightedButtonTextColor;
+
+/**
+ How long the message should be displayed.
+
+ Defaults to 4 seconds and can be set up to the maximum duration defined by
+ @c MDCSnackbarMessageDurationMax. Any value set above this limit will use the maximum duration.
+ */
+@property(nonatomic, assign) NSTimeInterval duration;
+
+/**
+ Called when a message is finished displaying.
+
+ The message completion handler is called regardless of whether or not buttons were tapped and is
+ always called on the main thread.
+ */
+@property(nonatomic, copy) MDCSnackbarMessageCompletionHandler completionHandler;
+
+/**
+ The category of messages to which a message belongs.
+
+ Default is nil. If set, only the last message of this category will be shown, any currently
+ showing or pending messages in this category will be dismissed as if the user had directly tapped
+ the snackbar.
+ */
+@property(nonatomic, copy) NSString *category;
+
+/**
+ Redeclaration from UIAccessibility to make clear that this class supports accessibility labels.
+ */
+@property(nonatomic, copy) NSString *accessibilityLabel;
+
+/**
+ Text that should be read when the message appears on screen and VoiceOver is enabled.
+ */
+@property(nonatomic, readonly) NSString *voiceNotificationText;
+
+@end
+
+/**
+ Represents a button in a MDCSnackbarMessage.
+ */
+@interface MDCSnackbarMessageAction : NSObject <UIAccessibilityIdentification, NSCopying>
+
+/**
+ The title text on the button.
+ */
+@property(nonatomic, copy) NSString *title;
+
+/**
+ Called when the button in the snackbar is tapped.
+
+ Always called on the main thread.
+ */
+@property(nonatomic, copy) MDCSnackbarMessageActionHandler handler;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.m
new file mode 100644
index 0000000..0ad9f7a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessage.m
@@ -0,0 +1,165 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
+#import "private/MDCSnackbarMessageInternal.h"
+
+static const NSTimeInterval kDefaultDuration = 4.0f;
+
+const NSTimeInterval MDCSnackbarMessageDurationMax = 10;
+NSString *const MDCSnackbarMessageBoldAttributeName = @"MDCSnackbarMessageBoldAttributeName";
+
+@interface MDCSnackbarMessage ()
+
+@property(nonatomic, readonly, strong) dispatch_queue_t targetQueue;
+
+@property(nonatomic, assign) BOOL hasSetTextAlignment;
+
+@end
+
+@implementation MDCSnackbarMessage
+
+@synthesize accessibilityIdentifier;
+@dynamic text;
+
++ (instancetype)messageWithText:(NSString *)text {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  message.text = text;
+  return message;
+}
+
++ (instancetype)messageWithAttributedText:(NSAttributedString *)attributedText {
+  MDCSnackbarMessage *message = [[MDCSnackbarMessage alloc] init];
+  message.attributedText = attributedText;
+  return message;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _duration = kDefaultDuration;
+  }
+  return self;
+}
+
+- (Class)viewClass {
+  return [MDCSnackbarMessageView class];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  MDCSnackbarMessage *copy = [[[self class] alloc] init];
+  copy.attributedText = self.attributedText;
+  copy.duration = self.duration;
+  copy.category = self.category;
+  copy.accessibilityLabel = self.accessibilityLabel;
+  copy.buttonTextColor = self.buttonTextColor;
+  copy.highlightedButtonTextColor = self.highlightedButtonTextColor;
+
+  // Unfortunately there's not really a concept of 'copying' a block (in the same way you would copy
+  // a string, for example). A block's pointer is immutable once it is created and copied to the
+  // heap, so we're pretty safe just using the same block.
+  copy.completionHandler = self.completionHandler;
+  copy.action = self.action;
+
+  return copy;
+}
+
+- (dispatch_queue_t)targetQueue {
+  return dispatch_get_main_queue();
+}
+
+#pragma mark Text
+
+- (void)setText:(NSString *)text {
+  self.attributedText = [[NSAttributedString alloc] initWithString:[text copy]];
+}
+
+- (NSString *)text {
+  return [self.attributedText string];
+}
+
+#pragma mark - Duration
+
+- (void)setDuration:(NSTimeInterval)duration {
+  NSAssert(duration <= MDCSnackbarMessageDurationMax,
+           @"Duration %g is longer than the maximum allowed: %g.", duration,
+           MDCSnackbarMessageDurationMax);
+  _duration = MIN(MDCSnackbarMessageDurationMax, duration);
+}
+
+#pragma mark - A11y
+
+- (NSString *)voiceNotificationText {
+  if ([self.accessibilityLabel length]) {
+    return self.accessibilityLabel;
+  } else {
+    return self.text;
+  }
+}
+
+#pragma mark - Internal
+
+- (void)executeCompletionHandlerWithUserInteraction:(BOOL)userInteraction
+                                         completion:(void (^)(void))completion {
+  if (self.completionHandler) {
+    dispatch_async(self.targetQueue, ^{
+      self.completionHandler(userInteraction);
+      if (completion) {
+        completion();
+      }
+    });
+  } else {
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+- (void)executeActionHandler:(MDCSnackbarMessageAction *)action
+                  completion:(void (^)(void))completion {
+  if (!action || !action.handler) {
+    if (completion) {
+      completion();
+    }
+    return;
+  }
+
+  // Fire off the action handler.
+  dispatch_async(self.targetQueue, ^{
+    action.handler();
+    if (completion) {
+      completion();
+    }
+  });
+}
+
+@end
+
+@implementation MDCSnackbarMessageAction
+
+@synthesize accessibilityIdentifier;
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  MDCSnackbarMessageAction *copy = [[[self class] alloc] init];
+  copy.title = self.title;
+  copy.handler = self.handler;  // See the comment on @c completionHandler above.
+  copy.accessibilityIdentifier = self.accessibilityIdentifier;
+
+  return copy;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
new file mode 100644
index 0000000..8649a8f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Class which provides the default implementation of a snackbar.
+ */
+@interface MDCSnackbarMessageView : UIView
+
+/**
+ The color for the background of the snackbar message view.
+ */
+@property(nonatomic, strong, nullable)
+    UIColor *snackbarMessageViewBackgroundColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The color for the shadow color for the snackbar message view.
+ */
+@property(nonatomic, strong, nullable)
+    UIColor *snackbarMessageViewShadowColor UI_APPEARANCE_SELECTOR;
+
+/**
+ The color for the message text in the snackbar message view.
+ */
+@property(nonatomic, strong, nullable) UIColor *snackbarMessageViewTextColor UI_APPEARANCE_SELECTOR;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.m
new file mode 100644
index 0000000..606ea39
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MDCSnackbarMessageView.m
@@ -0,0 +1,809 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <QuartzCore/QuartzCore.h>
+
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialButtons.h"
+#import "MaterialTypography.h"
+#import "private/MDCSnackbarMessageViewInternal.h"
+#import "private/MDCSnackbarOverlayView.h"
+
+NSString *const MDCSnackbarMessageTitleAutomationIdentifier =
+    @"MDCSnackbarMessageTitleAutomationIdentifier";
+NSString *const MDCSnackbarMessageViewTitleA11yHint = @"Double-tap to dismiss.";
+
+static inline UIColor *MDCRGBAColor(uint8_t r, uint8_t g, uint8_t b, float a) {
+  return [UIColor colorWithRed:(r) / 255.0f green:(g) / 255.0f blue:(b) / 255.0f alpha:(a)];
+}
+
+/**
+ The thickness of the snackbar border.
+ */
+static const CGFloat kBorderWidth = 0;
+
+/**
+ Shadow coloring.
+ */
+static const CGFloat kShadowAlpha = 0.24f;
+static const CGSize kShadowOffset = (CGSize){0.0, 1.0};
+static const CGFloat kShadowSpread = 1.0f;
+
+/**
+ The radius of the corners.
+ */
+static const CGFloat kCornerRadius = 0;
+
+/**
+ Padding between the edges of the snackbar and any content.
+ */
+static UIEdgeInsets kContentMargin = (UIEdgeInsets){18.0, 24.0, 18.0, 24.0};
+
+/**
+ Padding between the image and the main title.
+ */
+static const CGFloat kTitleImagePadding = 8.0f;
+
+/**
+ Padding between the main title and the first button.
+ */
+static const CGFloat kTitleButtonPadding = 8.0f;
+
+/**
+ Padding on the edges of the buttons.
+ */
+static const CGFloat kButtonPadding = 5.0f;
+
+/**
+ The width of the snackbar.
+ */
+static const CGFloat kMinimumViewWidth_iPad = 288.0f;
+static const CGFloat kMaximumViewWidth_iPad = 568.0f;
+static const CGFloat kMinimumViewWidth_iPhone = 320.0f;
+static const CGFloat kMaximumViewWidth_iPhone = 320.0f;
+
+/**
+ The minimum height of the snackbar.
+ */
+static const CGFloat kMinimumHeight = 48.0f;
+
+/**
+ Each button will have a tag indexed starting from this value.
+ */
+static const NSInteger kButtonTagStart = 20000;
+
+/**
+ The ink radius of the action button.
+ */
+static const CGFloat kButtonInkRadius = 64.0f;
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCSnackbarMessageView () <CAAnimationDelegate>
+@end
+#endif
+
+@interface MDCSnackbarMessageView ()
+
+/**
+ Holds the icon for the image.
+ */
+@property(nonatomic, strong) UIImageView *imageView;
+
+/**
+ Holds the button views.
+ */
+@property(nonatomic, strong) NSArray *buttons;
+
+/**
+ Holds the text label for the main message.
+ */
+@property(nonatomic, strong) UILabel *label;
+
+/**
+ The constraints managing this view.
+ */
+@property(nonatomic, strong) NSArray *viewConstraints;
+
+/**
+ The view containing all of the visual content. Inset by @c kBorderWidth from the view.
+ */
+@property(nonatomic, strong) UIControl *containerView;
+
+/**
+ The view containing all of the buttons.
+ */
+@property(nonatomic, strong) UIView *buttonView;
+
+/**
+ The view containing the title and image views.
+ */
+@property(nonatomic, strong) UIView *contentView;
+
+/**
+ Holds onto the dismissal handler, called when the snackbar should dismiss due to user interaction.
+ */
+@property(nonatomic, copy) MDCSnackbarMessageDismissHandler dismissalHandler;
+
+@end
+
+@interface MDCSnackbarMessageViewButton : MDCFlatButton
+@end
+
+@implementation MDCSnackbarMessageViewButton
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.inkMaxRippleRadius = kButtonInkRadius;
+    self.inkColor = [UIColor colorWithWhite:1 alpha:0.06f];
+    self.inkStyle = MDCInkStyleUnbounded;
+  }
+  return self;
+}
+
+@end
+
+@implementation MDCSnackbarMessageView
+
++ (void)initialize {
+  [[self appearance] setSnackbarMessageViewShadowColor:MDCRGBAColor(0x00, 0x00, 0x00, 1.0f)];
+  [[self appearance] setSnackbarMessageViewBackgroundColor:MDCRGBAColor(0x32, 0x32, 0x32, 1.0f)];
+  [[self appearance] setSnackbarMessageViewTextColor:MDCRGBAColor(0xFF, 0xFF, 0xFF, 1.0f)];
+}
+
+- (void)dismissWithAction:(MDCSnackbarMessageAction *)action userInitiated:(BOOL)userInitiated {
+  if (self.dismissalHandler) {
+    self.dismissalHandler(userInitiated, action);
+
+    // In case our dismissal handler has a reference to us, release the block.
+    self.dismissalHandler = nil;
+  }
+}
+
+#pragma mark - Subclass overrides
+
++ (BOOL)requiresConstraintBasedLayout {
+  return YES;
+}
+
+- (CGFloat)minimumWidth {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? kMinimumViewWidth_iPad
+                                                              : kMinimumViewWidth_iPhone;
+}
+
+- (CGFloat)maximumWidth {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? kMaximumViewWidth_iPad
+                                                              : kMaximumViewWidth_iPhone;
+}
+
+#pragma mark - Styling the view
+
+- (UIColor *)snackbarButtonTextColor {
+  return MDCRGBAColor(0xFF, 0xFF, 0xFF, 0.6f);
+}
+
+- (UIColor *)snackbarButtonTextColorHighlighted {
+  return MDCRGBAColor(0xFF, 0xFF, 0xFF, 1.0f);
+}
+
+- (UIColor *)snackbarSeparatorColor {
+  return MDCRGBAColor(0xFF, 0xFF, 0xFF, 0.5f);
+}
+
+- (void)setSnackbarMessageViewBackgroundColor:(UIColor *)snackbarMessageViewBackgroundColor {
+  _snackbarMessageViewBackgroundColor = snackbarMessageViewBackgroundColor;
+  _containerView.backgroundColor = snackbarMessageViewBackgroundColor;
+}
+
+- (void)setSnackbarShadowColor:(UIColor *)snackbarMessageViewShadowColor {
+  _snackbarMessageViewShadowColor = snackbarMessageViewShadowColor;
+  self.layer.shadowColor = snackbarMessageViewShadowColor.CGColor;
+}
+
+- (void)setSnackbarMessageViewTextColor:(UIColor *)snackbarMessageViewTextColor {
+  _snackbarMessageViewTextColor = snackbarMessageViewTextColor;
+  self.label.textColor = _snackbarMessageViewTextColor;
+}
+
+- (void)addColorToMessageLabel:(UIColor *)color {
+  NSMutableAttributedString *messageString = [_label.attributedText mutableCopy];
+  [messageString addAttributes:@{
+    NSForegroundColorAttributeName : color,
+  }
+                         range:NSMakeRange(0, messageString.length)];
+  _label.attributedText = messageString;
+}
+
+- (instancetype)initWithMessage:(MDCSnackbarMessage *)message
+                 dismissHandler:(MDCSnackbarMessageDismissHandler)handler {
+  self = [super init];
+  if (self) {
+    _message = message;
+    _dismissalHandler = [handler copy];
+
+    self.backgroundColor = [UIColor clearColor];
+    self.layer.cornerRadius = kCornerRadius;
+    self.layer.shadowColor = _snackbarMessageViewShadowColor.CGColor;
+    self.layer.shadowOpacity = kShadowAlpha;
+    self.layer.shadowOffset = kShadowOffset;
+    self.layer.shadowRadius = kShadowSpread;
+
+    // Borders are drawn inside of the bounds of a layer. Because our border is translucent, we need
+    // to have a view with transparent background and border only (@c self). Inside will be a
+    // content view that has the dark grey color.
+    _containerView = [[UIControl alloc] init];
+    [self addSubview:_containerView];
+
+    [_containerView setTranslatesAutoresizingMaskIntoConstraints:NO];
+    _containerView.backgroundColor = _snackbarMessageViewBackgroundColor;
+    _containerView.layer.cornerRadius = kCornerRadius;
+    _containerView.layer.masksToBounds = YES;
+
+    // Listen for taps on the background of the view.
+    [_containerView addTarget:self
+                       action:@selector(handleBackgroundTapped:)
+             forControlEvents:UIControlEventTouchUpInside];
+
+    UISwipeGestureRecognizer *swipeRightGesture =
+        [[UISwipeGestureRecognizer alloc] initWithTarget:self
+                                                  action:@selector(handleBackgroundSwipedRight:)];
+    [swipeRightGesture setDirection:UISwipeGestureRecognizerDirectionRight];
+    [_containerView addGestureRecognizer:swipeRightGesture];
+
+    UISwipeGestureRecognizer *swipeLeftGesture =
+        [[UISwipeGestureRecognizer alloc] initWithTarget:self
+                                                  action:@selector(handleBackgroundSwipedLeft:)];
+    [swipeRightGesture setDirection:UISwipeGestureRecognizerDirectionLeft];
+    [_containerView addGestureRecognizer:swipeLeftGesture];
+
+    _contentView = [[UIView alloc] init];
+    [_contentView setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [_containerView addSubview:_contentView];
+    _contentView.userInteractionEnabled = NO;
+
+    _buttonView = [[UIView alloc] init];
+    [_buttonView setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [_containerView addSubview:_buttonView];
+
+    // Set up the title label.
+    _label = [[UILabel alloc] initWithFrame:CGRectZero];
+    [_contentView addSubview:_label];
+
+    NSMutableAttributedString *messageString = [message.attributedText mutableCopy];
+
+    // Find any of the bold attributes in the string, and set the proper font for those ranges.
+    // Use NSAttributedStringEnumerationLongestEffectiveRangeNotRequired as opposed to 0, otherwise
+    // it will only work if bold text is in the end.
+    [messageString
+        enumerateAttribute:MDCSnackbarMessageBoldAttributeName
+                   inRange:NSMakeRange(0, messageString.length)
+                   options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
+                usingBlock:^(id value, NSRange range, BOOL *stop) {
+                  UIFont *font = [MDCTypography body1Font];
+                  if ([value boolValue]) {
+                    font = [MDCTypography body2Font];
+                  }
+                  [messageString setAttributes:@{ NSFontAttributeName : font } range:range];
+                }];
+
+    // Apply 'global' attributes along the whole string.
+    _label.backgroundColor = [UIColor clearColor];
+    _label.textAlignment = NSTextAlignmentNatural;
+    _label.attributedText = messageString;
+    _label.numberOfLines = 0;
+    [_label setTranslatesAutoresizingMaskIntoConstraints:NO];
+    [_label setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh
+                                            forAxis:UILayoutConstraintAxisHorizontal];
+    [_label setContentHuggingPriority:UILayoutPriorityDefaultLow
+                              forAxis:UILayoutConstraintAxisHorizontal];
+
+    // For VoiceOver purposes, the label is the primary 'button' for dismissing the snackbar, so
+    // we'll make sure the label looks like a button.
+    _label.accessibilityTraits = UIAccessibilityTraitButton;
+    _label.accessibilityIdentifier = MDCSnackbarMessageTitleAutomationIdentifier;
+    _label.accessibilityHint = MDCSnackbarMessageViewTitleA11yHint;
+
+    // If an accessibility label was set on the message model object, use that instead of the text
+    // in the label.
+    if ([message.accessibilityLabel length]) {
+      _label.accessibilityLabel = message.accessibilityLabel;
+    }
+
+    // Figure out how much horizontal space the main text needs, in order to decide if the buttons
+    // are laid out horizontally or vertically.
+    __block CGFloat availableTextWidth = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad
+                                             ? kMaximumViewWidth_iPad
+                                             : kMaximumViewWidth_iPhone;
+
+    // Take into account the content padding.
+    availableTextWidth -= (kContentMargin.left + kContentMargin.right);
+
+    // If there are buttons, account for the padding between the title and the buttons.
+    if (message.action) {
+      availableTextWidth -= kTitleButtonPadding;
+    }
+
+    UIColor *textColor = [self snackbarButtonTextColor];
+    UIColor *textColorHighlighted = [self snackbarButtonTextColorHighlighted];
+
+    _label.textColor = textColor;
+
+    if (message.buttonTextColor) {
+      textColor = message.buttonTextColor;
+    }
+
+    if (message.highlightedButtonTextColor) {
+      textColorHighlighted = message.highlightedButtonTextColor;
+    }
+
+    NSDictionary *buttonAttributes = @{
+      NSFontAttributeName : [MDCTypography buttonFont],
+      NSForegroundColorAttributeName : textColor,
+    };
+
+    NSDictionary *buttonHighlightedAttributes = @{
+      NSFontAttributeName : [MDCTypography buttonFont],
+      NSForegroundColorAttributeName : textColorHighlighted,
+    };
+
+    // Add buttons to the view. We'll use this opportunity to determine how much space a button will
+    // need, to inform the layout direction.
+    NSMutableArray *actions = [NSMutableArray array];
+    if (message.action) {
+      UIView *buttonView = [[UIView alloc] init];
+      [buttonView setTranslatesAutoresizingMaskIntoConstraints:NO];
+      [_buttonView addSubview:buttonView];
+
+      UIButton *button = [[MDCSnackbarMessageViewButton alloc] init];
+      [button setTranslatesAutoresizingMaskIntoConstraints:NO];
+      button.tag = kButtonTagStart;
+      [buttonView addSubview:button];
+
+      // Style the text in the button.
+      NSAttributedString *buttonText =
+          [[NSAttributedString alloc] initWithString:message.action.title
+                                          attributes:buttonAttributes];
+      NSAttributedString *buttonHighlightedText =
+          [[NSAttributedString alloc] initWithString:message.action.title
+                                          attributes:buttonHighlightedAttributes];
+      button.titleLabel.numberOfLines = 1;
+      button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
+      button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
+      button.contentEdgeInsets = UIEdgeInsetsMake(0, kButtonPadding, 0, kButtonPadding);
+
+      // Set up the button's accessibility values.
+      button.accessibilityIdentifier = message.action.accessibilityIdentifier;
+      [button setAttributedTitle:buttonText forState:UIControlStateNormal];
+      [button setAttributedTitle:buttonHighlightedText forState:UIControlStateHighlighted];
+
+      if (message.buttonTextColor) {
+        [button setTitleColor:textColor forState:UIControlStateNormal];
+      }
+
+      // Make sure the button doesn't get too compressed.
+      [button setContentCompressionResistancePriority:UILayoutPriorityRequired
+                                              forAxis:UILayoutConstraintAxisHorizontal];
+      [button setContentHuggingPriority:UILayoutPriorityDefaultHigh
+                                forAxis:UILayoutConstraintAxisHorizontal];
+      [button addTarget:self
+                    action:@selector(handleButtonTapped:)
+          forControlEvents:UIControlEventTouchUpInside];
+
+      availableTextWidth -= [buttonText size].width;
+      availableTextWidth -= 2 * kButtonPadding;
+
+      [actions addObject:buttonView];
+    }
+
+    self.buttons = actions;
+  }
+
+  return self;
+}
+
+- (BOOL)shouldWaitForDismissalDuringVoiceover {
+  return self.message.action != nil;
+}
+
+#pragma mark - Constraints and layout
+
+- (void)updateConstraints {
+  [super updateConstraints];
+
+  if (self.viewConstraints) {
+    return;
+  }
+
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  [constraints addObjectsFromArray:[self containerViewConstraints]];
+  [constraints addObjectsFromArray:[self contentViewConstraints]];
+  [constraints addObjectsFromArray:[self horizontalButtonLayoutConstraints]];
+
+  [self addConstraints:constraints];
+  self.viewConstraints = constraints;
+}
+
+/**
+ Provides constraints to pin the container view to the size of the snackbar, inset by
+ @c kBorderWidth. Also positions the content view and button view inside of the container view.
+ */
+- (NSArray *)containerViewConstraints {
+  NSDictionary *metrics = @{
+    @"kBorderMargin" : @(kBorderWidth),
+    @"kBottomMargin" : @(kContentMargin.bottom),
+    @"kLeftMargin" : @(kContentMargin.left),
+    @"kRightMargin" : @(kContentMargin.right),
+    @"kTitleImagePadding" : @(kTitleImagePadding),
+    @"kTopMargin" : @(kContentMargin.top),
+    @"kTitleButtonPadding" : @(kTitleButtonPadding),
+  };
+  NSDictionary *views = @{
+    @"container" : self.containerView,
+    @"content" : self.contentView,
+    @"buttons" : self.buttonView,
+  };
+
+  BOOL hasButtons = (self.buttons.count > 0);
+
+  NSString *formatString = nil;  // Scratch variable.
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  // Pin the left and right edges of the container view to the snackbar.
+  formatString = @"H:|-(==kBorderMargin)-[container]-(==kBorderMargin)-|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the top and bottom edges of the container view to the snackbar.
+  formatString = @"V:|-(==kBorderMargin)-[container]-(==kBorderMargin)-|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the content to the top of the container view.
+  formatString = @"V:|-(==kTopMargin)-[content]";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the content view to the left side of the container.
+  formatString = @"H:|-(==kLeftMargin)-[content]";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // If there are no buttons, or the buttons are below the main content, then the content view
+  // should be pinned to the right side of the container. If there are horizontal buttons, the
+  // leftmost button will take care of positioning the trailing edge of the label view.
+
+  // If there are no buttons, then go ahead and pin the content view to the bottom of the
+  // container view.
+  if (!hasButtons) {
+    formatString = @"V:[content]-(==kBottomMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  }
+
+  if (!hasButtons) {
+    // There is nothing to the right of the content, so go ahead and pin it to the trailing edge of
+    // the container view.
+    formatString = @"H:[content]-(==kRightMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  } else {  // This is a horizontal layout, and there are buttons present.
+    // Align the content and buttons horizontally.
+    formatString = @"H:[content]-(==kTitleButtonPadding)-[buttons]-(==kRightMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // The buttons should take up the entire height of the container view.
+    formatString = @"V:|[buttons]|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // Pin the content to the bottom of the container view, since there's nothing below.
+    formatString = @"V:[content]-(==kBottomMargin)-|";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  }
+
+  return constraints;
+}
+
+/**
+ Provides constraints for the image view and label within the content view.
+ */
+- (NSArray *)contentViewConstraints {
+  NSDictionary *metrics = @{
+    @"kBottomMargin" : @(kContentMargin.bottom),
+    @"kLeftMargin" : @(kContentMargin.left),
+    @"kRightMargin" : @(kContentMargin.right),
+    @"kTitleImagePadding" : @(kTitleImagePadding),
+    @"kTopMargin" : @(kContentMargin.top),
+  };
+
+  NSMutableDictionary *views = [NSMutableDictionary dictionary];
+  views[@"label"] = self.label;
+  if (self.imageView) {
+    views[@"imageView"] = self.imageView;
+  }
+
+  NSString *formatString = nil;  // Scratch variable.
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  // The label should take up the entire height of the content view.
+  formatString = @"V:|[label]|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  // Pin the label to the trailing edge of the content view.
+  formatString = @"H:[label]|";
+  [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                           options:0
+                                                                           metrics:metrics
+                                                                             views:views]];
+
+  if (self.imageView) {
+    // Constrain the image view to be no taller than @c kMaximumImageSize.
+    formatString = @"V:[imageView(<=kMaximumImageSize)]";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // Vertically center the image view within the content view.
+    [constraints addObject:[NSLayoutConstraint constraintWithItem:self.imageView
+                                                        attribute:NSLayoutAttributeCenterY
+                                                        relatedBy:NSLayoutRelationEqual
+                                                           toItem:self.contentView
+                                                        attribute:NSLayoutAttributeCenterY
+                                                       multiplier:1.0
+                                                         constant:0]];
+
+    // Constrain the image view to be no wider than @c kMaximumImageSize, and pin it to the leading
+    // edge of the content view. Pin the label to the trailing edge of the image.
+    formatString = @"H:|[imageView(<=kMaximumImageSize)]-(==kTitleImagePadding)-[label]";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  } else {
+    formatString = @"H:|[label]";
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+  }
+
+  return constraints;
+}
+
+/**
+ Provides constraints positioning the buttons horizontally within the button container.
+ */
+- (NSArray *)horizontalButtonLayoutConstraints {
+  NSMutableArray *constraints = [NSMutableArray array];
+
+  NSDictionary *metrics = @{
+    @"kLeftMargin" : @(kContentMargin.left),
+    @"kRightMargin" : @(kContentMargin.right),
+    @"kTopMargin" : @(kContentMargin.top),
+    @"kBottomMargin" : @(kContentMargin.bottom),
+    @"kTitleImagePadding" : @(kTitleImagePadding),
+    @"kBorderMargin" : @(kBorderWidth),
+    @"kTitleButtonPadding" : @(kTitleButtonPadding),
+    @"kButtonPadding" : @(kButtonPadding),
+  };
+
+  __block UIView *previousButton = nil;
+  [self.buttons enumerateObjectsUsingBlock:^(UIView *button, NSUInteger idx, BOOL *stop) {
+    // Convenience dictionary of views.
+    NSMutableDictionary *views = [NSMutableDictionary dictionary];
+    views[@"buttonContainer"] = button;
+    views[@"button"] = [button viewWithTag:kButtonTagStart + idx];
+    if (previousButton) {
+      views[@"previousButton"] = previousButton;
+    }
+
+    // In a horizontal layout, the button takes on the height of the snackbar.
+    [constraints
+        addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[buttonContainer]|"
+                                                                    options:0
+                                                                    metrics:metrics
+                                                                      views:views]];
+
+    // Pin the button to the height of its container.
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[button]|"
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    // Pin the button to the width of its container.
+    [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[button]|"
+                                                                             options:0
+                                                                             metrics:metrics
+                                                                               views:views]];
+
+    if (idx == 0) {
+      // The first button should be pinned to the leading edge of the button view.
+      [constraints addObjectsFromArray:[NSLayoutConstraint
+                                           constraintsWithVisualFormat:@"H:|[buttonContainer]"
+                                                               options:0
+                                                               metrics:metrics
+                                                                 views:views]];
+    }
+
+    if (idx == ([self.buttons count] - 1)) {
+      // The last button should be pinned to the trailing edge of the button view.
+      [constraints addObjectsFromArray:[NSLayoutConstraint
+                                           constraintsWithVisualFormat:@"H:[buttonContainer]|"
+                                                               options:0
+                                                               metrics:metrics
+                                                                 views:views]];
+    }
+
+    if (previousButton) {
+      // If there was a button before this one, pin this one to it.
+      NSString *formatString = @"H:[previousButton]-(==kButtonPadding)-[buttonContainer]";
+      [constraints addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:formatString
+                                                                               options:0
+                                                                               metrics:metrics
+                                                                                 views:views]];
+    }
+  }];
+
+  return constraints;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  // As our layout changes, make sure that the shadow path is kept up-to-date.
+  UIBezierPath *path =
+      [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:kCornerRadius];
+  self.layer.shadowPath = path.CGPath;
+}
+
+#pragma mark - Sizing
+
+- (CGSize)intrinsicContentSize {
+  CGFloat height = 0;
+
+  // Figure out which of the elements is tallest, and use that for calculating our preferred height.
+  // Images are forced to be no bigger than @c kMaximumImageSize.
+  height = MAX(height, self.label.intrinsicContentSize.height);
+
+  // Make sure that content margins are included in our calculation.
+  height += kContentMargin.top + kContentMargin.bottom;
+
+  // Make sure that the height of the image and text is larger than the minimum height;
+  height = MAX(kMinimumHeight, height);
+
+  return CGSizeMake(UIViewNoIntrinsicMetric, height);
+}
+
+#pragma mark - Event Handlers
+
+- (void)handleBackgroundSwipedRight:(UIButton *)sender {
+  CABasicAnimation *translationAnimation =
+      [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
+  translationAnimation.toValue = [NSNumber numberWithDouble:-self.frame.size.width];
+  translationAnimation.duration = MDCSnackbarTransitionDuration;
+  translationAnimation.timingFunction =
+      [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionTranslateOffScreen];
+  translationAnimation.delegate = self;
+  translationAnimation.fillMode = kCAFillModeForwards;
+  translationAnimation.removedOnCompletion = NO;
+  [self.layer addAnimation:translationAnimation forKey:@"transform.translation.x"];
+}
+
+- (void)handleBackgroundSwipedLeft:(UIButton *)sender {
+  CABasicAnimation *translationAnimation =
+      [CABasicAnimation animationWithKeyPath:@"transform.translation.x"];
+  translationAnimation.toValue = [NSNumber numberWithDouble:self.frame.size.width];
+  translationAnimation.duration = MDCSnackbarTransitionDuration;
+  translationAnimation.timingFunction =
+      [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionTranslateOffScreen];
+  translationAnimation.delegate = self;
+  translationAnimation.fillMode = kCAFillModeForwards;
+  translationAnimation.removedOnCompletion = NO;
+  [self.layer addAnimation:translationAnimation forKey:@"transform.translation.x"];
+}
+
+- (void)handleBackgroundTapped:(UIButton *)sender {
+  [self dismissWithAction:nil userInitiated:YES];
+}
+
+- (void)handleButtonTapped:(UIButton *)sender {
+  [self dismissWithAction:self.message.action userInitiated:YES];
+}
+
+- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
+  if (flag) {
+    [self dismissWithAction:nil userInitiated:YES];
+  }
+}
+
+#pragma mark - Accessibility
+
+// Override regular accessibility element ordering and ensure label
+// is read first before any buttons, if they exist.
+- (NSInteger)accessibilityElementCount {
+  return 1 + [self.buttons count];
+}
+
+- (id)accessibilityElementAtIndex:(NSInteger)index {
+  if (index == 0) {
+    return _label;
+  }
+  return [self.buttons objectAtIndex:(index - 1)];
+}
+
+- (NSInteger)indexOfAccessibilityElement:(id)element {
+  if (element == _label) {
+    return 0;
+  }
+
+  NSInteger buttonIndex = [self.buttons indexOfObject:element];
+  if (buttonIndex == NSNotFound) {
+    return NSNotFound;
+  }
+  return buttonIndex + 1;
+}
+
+#pragma mark - Animation
+
+- (void)animateContentOpacityFrom:(CGFloat)fromOpacity
+                               to:(CGFloat)toOpacity
+                         duration:(NSTimeInterval)duration
+                   timingFunction:(CAMediaTimingFunction *)timingFunction {
+  [CATransaction begin];
+
+  CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
+  opacityAnimation.duration = duration;
+  opacityAnimation.fromValue = @(fromOpacity);
+  opacityAnimation.toValue = @(toOpacity);
+  opacityAnimation.timingFunction = timingFunction;
+
+  // The text and the button do not share a common view that can be animated independently of the
+  // background color, so just animate them both independently here. If this becomes more
+  // complicated, refactor to add a containing view for both and animate that.
+  [self.contentView.layer addAnimation:opacityAnimation forKey:@"opacity"];
+  [self.buttonView.layer addAnimation:opacityAnimation forKey:@"opacity"];
+
+  [CATransaction commit];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MaterialSnackbar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
new file mode 100644
index 0000000..700adbb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/MaterialSnackbar.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarManager.h"
+#import "MDCSnackbarMessage.h"
+#import "MDCSnackbarMessageView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h
new file mode 100644
index 0000000..c51c075
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageInternal.h
@@ -0,0 +1,51 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCSnackbarMessage.h"
+
+/**
+ Internal-only methods used by MDCSnackbarMessage and MDCSnackbarManager.
+ */
+@interface MDCSnackbarMessage ()
+
+/**
+ The class of the view which should be instantiated in order to show this message.
+
+ The class returned by this method must be a subclass of MDCSnackbarMessageView.
+ */
+- (Class)viewClass;
+
+/**
+ Executes @c self.completionhandler on the main thread.
+
+ @c completion is called after @c self.completionHandler has executed. If @c self.completionHandler
+ is nil, then @c completion fires immediately from the calling thread.
+ */
+- (void)executeCompletionHandlerWithUserInteraction:(BOOL)userInteraction
+                                         completion:(void (^)(void))completion;
+
+/**
+ Given @c action, which must be in @c self.actions, this method will call the action handler on
+ @c self.targetQueue.
+
+ @c completion is called after the handler has executed. If @c action.handler is nil, then
+ @c completion fires immediately from the calling thread. Passing a nil @c action will immediately
+ call @c completion.
+ */
+- (void)executeActionHandler:(MDCSnackbarMessageAction *)action
+                  completion:(void (^)(void))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h
new file mode 100644
index 0000000..40e9598
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h
@@ -0,0 +1,88 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+@class MDCSnackbarMessage;
+@class MDCSnackbarMessageAction;
+
+/**
+ Called by the snackbar message view when the user interacts with the snackbar view.
+
+ @c userInitiated indicates whether or not the handler is being called due to direct user
+ interaction. @c action, if non-nil, indicates that the user chose to execute a specific action.
+ */
+typedef void (^MDCSnackbarMessageDismissHandler)(BOOL userInitiated,
+                                                 MDCSnackbarMessageAction *_Nullable action);
+
+@interface MDCSnackbarMessageView ()
+
+/**
+ If the user has tapped on the snackbar or if @c dismissWithAction:userInitiated: has been called.
+ */
+@property(nonatomic, getter=isDismissing) BOOL dismissing;
+
+/**
+ The minimum width of the snackbar.
+ */
+@property(nonatomic, readonly) CGFloat minimumWidth;
+
+/**
+ The maximum width of the snackbar.
+ */
+@property(nonatomic, readonly) CGFloat maximumWidth;
+
+/**
+ Convenience pointer to the message used to create the view.
+ */
+@property(nonatomic, nullable, readonly, strong) MDCSnackbarMessage *message;
+/**
+ Creates a snackbar view to display @c message.
+
+ The view will call @c handler when the user has interacted with the snackbar view in such a way
+ that it needs to be dismissed prior to its timer-based dismissal time.
+ */
+- (_Nonnull instancetype)initWithMessage:(MDCSnackbarMessage *_Nullable)message
+                          dismissHandler:(MDCSnackbarMessageDismissHandler _Nullable)handler;
+
+/**
+ Dismisses the message view.
+
+ Does not call the message's completion handler or any action handler. Must be called from the main
+ thread.
+
+ @param action The action that prompted the dismissal.
+ @param userInitiated Whether or not this is a user-initiated dismissal or a programmatic one.
+ */
+- (void)dismissWithAction:(MDCSnackbarMessageAction *_Nullable)action
+            userInitiated:(BOOL)userInitiated;
+
+/**
+ When VoiceOver is enabled the view should wait for user action before dismissing.
+
+ Default is YES.
+ */
+- (BOOL)shouldWaitForDismissalDuringVoiceover;
+
+/**
+ Animate the opacity text and button content.
+
+ Creates and commits a CATransaction to perform the animation.
+ */
+- (void)animateContentOpacityFrom:(CGFloat)fromOpacity
+                               to:(CGFloat)toOpacity
+                         duration:(NSTimeInterval)duration
+                   timingFunction:(CAMediaTimingFunction *_Nullable)timingFunction;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h
new file mode 100644
index 0000000..e4526e6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.h
@@ -0,0 +1,65 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCSnackbarMessageView;
+
+/** The identifier reported for the snackbar. */
+OBJC_EXTERN NSString *const MDCSnackbarOverlayIdentifier;
+
+/** The time it takes to show or hide the snackbar. */
+OBJC_EXTERN NSTimeInterval const MDCSnackbarTransitionDuration;
+
+/**
+ Custom overlay view for displaying snackbars.
+ */
+@interface MDCSnackbarOverlayView : UIView
+
+/**
+ Designated initializer.
+
+ Creates an overlay view which utilizes @c watcher to get its keyboard position information.
+ */
+- (instancetype)initWithFrame:(CGRect)frame;
+
+/**
+ Shows the snackbar view with the most appropriate animation.
+
+ @param snackbarView The snackbar view to display.
+ @param animated Whether or not the show should be animated.
+ @param completion A block to execute when the presentation is finished.
+ */
+- (void)showSnackbarView:(MDCSnackbarMessageView *)snackbarView
+                animated:(BOOL)animated
+              completion:(void (^)(void))completion;
+
+/**
+ Dismisses the currently showing snackbar view.
+
+ @param animated Whether or not the dismiss should be animated.
+ @param completion A block to execute when the dismissal is finished.
+ */
+- (void)dismissSnackbarViewAnimated:(BOOL)animated completion:(void (^)(void))completion;
+
+/**
+ How far from the bottom of the screen should snackbars be presented.
+
+ If set inside of an animation block, the change will animate.
+ */
+@property(nonatomic) CGFloat bottomOffset;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.m
new file mode 100644
index 0000000..1a0cca0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Snackbar/src/private/MDCSnackbarOverlayView.m
@@ -0,0 +1,661 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+#import "MDCSnackbarOverlayView.h"
+
+#import "MDCSnackbarMessageView.h"
+#import "MDCSnackbarMessageViewInternal.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialKeyboardWatcher.h"
+#import "MaterialOverlays.h"
+#import "UIApplication+AppExtensions.h"
+
+NSString *const MDCSnackbarOverlayIdentifier = @"MDCSnackbar";
+
+// The time it takes to show or hide the snackbar.
+NSTimeInterval const MDCSnackbarTransitionDuration = 0.5f;
+
+// How far from the bottom of the screen should the snackbar be.
+static const CGFloat MDCSnackbarBottomMargin_iPhone = 0;
+static const CGFloat MDCSnackbarBottomMargin_iPad = 0;
+
+// How far from the sides of the screen should the snackbar be.
+static const CGFloat MDCSnackbarSideMargin_iPhone = 0;
+static const CGFloat MDCSnackbarSideMargin_iPad = 24.0f;
+
+// The maximum height of the snackbar.
+static const CGFloat kMaximumHeight = 80.0f;
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCSnackbarOverlayView () <CAAnimationDelegate>
+@end
+#endif
+
+@interface MDCSnackbarOverlayView ()
+
+/**
+ The snackbar view to show. Setting this property simply puts the snackbar view into the window
+ hierarchy and installs constraints which will keep it pinned to the bottom of the screen.
+ */
+@property(nonatomic) MDCSnackbarMessageView *snackbarView;
+
+/**
+ The object which will notify us of changes in the keyboard position.
+ */
+@property(nonatomic) MDCKeyboardWatcher *watcher;
+
+/**
+ The layout constraint which determines the bottom of the containing view. Setting the constant
+ to a negative value will cause snackbars to appear from a point above the bottom of the screen.
+ */
+@property(nonatomic) NSLayoutConstraint *bottomConstraint;
+
+/**
+ The view which actually houses the snackbar. This view is sized to be the same width and height as
+ ourselves, except offset from the bottom, based on the keyboard height as well as any user-set
+ content offsets.
+ */
+@property(nonatomic) UIView *containingView;
+
+/**
+ Whether or not we are triggering a layout change ourselves. This is to distinguish when our bounds
+ are changing due to rotation rather than us adding/removing a snackbar.
+ */
+@property(nonatomic) BOOL manualLayoutChange;
+
+/**
+ If we received a rotation event, this is the duration that should be used.
+ */
+@property(nonatomic) NSTimeInterval rotationDuration;
+
+/**
+ The constraint used to pin the bottom of the snackbar to the bottom of the screen.
+ */
+@property(nonatomic) NSLayoutConstraint *snackbarOnscreenConstraint;
+
+/**
+ The constraint used to pin the top of the snackbar to the bottom of the screen.
+ */
+@property(nonatomic) NSLayoutConstraint *snackbarOffscreenConstraint;
+
+@end
+
+@implementation MDCSnackbarOverlayView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+
+  MDCKeyboardWatcher *watcher = [MDCKeyboardWatcher sharedKeyboardWatcher];
+
+  if (self) {
+    _watcher = watcher;
+    _containingView = [[UIView alloc] initWithFrame:frame];
+    _containingView.translatesAutoresizingMaskIntoConstraints = NO;
+    _containingView.clipsToBounds = YES;
+    [self addSubview:_containingView];
+
+    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillShow:)
+               name:MDCKeyboardWatcherKeyboardWillShowNotification
+             object:watcher];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillBeHidden:)
+               name:MDCKeyboardWatcherKeyboardWillHideNotification
+             object:watcher];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillChangeFrame:)
+               name:MDCKeyboardWatcherKeyboardWillChangeFrameNotification
+             object:watcher];
+
+    [nc addObserver:self
+           selector:@selector(willRotate:)
+               name:UIApplicationWillChangeStatusBarOrientationNotification
+             object:nil];
+
+    [nc addObserver:self
+           selector:@selector(didRotate:)
+               name:UIApplicationDidChangeStatusBarOrientationNotification
+             object:nil];
+
+    [self setupContainerConstraints];
+  }
+  return self;
+}
+
+/**
+ Installs constraints for the ever-present container view.
+
+ @note These constraints remain installed for the life of the overlay view, whereas the
+       constraints installed in @c setsnackbarView: come and go with the current snackbar.
+ */
+- (void)setupContainerConstraints {
+  [self addConstraint:[NSLayoutConstraint constraintWithItem:_containingView
+                                                   attribute:NSLayoutAttributeLeading
+                                                   relatedBy:NSLayoutRelationEqual
+                                                      toItem:self
+                                                   attribute:NSLayoutAttributeLeading
+                                                  multiplier:1.0
+                                                    constant:0]];
+
+  [self addConstraint:[NSLayoutConstraint constraintWithItem:_containingView
+                                                   attribute:NSLayoutAttributeTrailing
+                                                   relatedBy:NSLayoutRelationEqual
+                                                      toItem:self
+                                                   attribute:NSLayoutAttributeTrailing
+                                                  multiplier:1.0
+                                                    constant:0]];
+
+  [self addConstraint:[NSLayoutConstraint constraintWithItem:_containingView
+                                                   attribute:NSLayoutAttributeTop
+                                                   relatedBy:NSLayoutRelationEqual
+                                                      toItem:self
+                                                   attribute:NSLayoutAttributeTop
+                                                  multiplier:1.0
+                                                    constant:0]];
+
+  self.bottomConstraint = [NSLayoutConstraint constraintWithItem:_containingView
+                                                       attribute:NSLayoutAttributeBottom
+                                                       relatedBy:NSLayoutRelationEqual
+                                                          toItem:self
+                                                       attribute:NSLayoutAttributeBottom
+                                                      multiplier:1.0
+                                                        constant:-[self dynamicBottomMargin]];
+  [self addConstraint:self.bottomConstraint];
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+/**
+ The bottom margin which is dependent on the keyboard and application-wide settings, and may
+ change at any time during runtime.
+ */
+- (CGFloat)dynamicBottomMargin {
+  CGFloat keyboardHeight = self.watcher.keyboardOffset;
+  CGFloat userHeight = self.bottomOffset;
+
+  return MAX(keyboardHeight, userHeight);
+}
+
+/**
+ The bottom margin which is dependent on device type and cannot change.
+ */
+- (CGFloat)staticBottomMargin {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? MDCSnackbarBottomMargin_iPad
+                                                              : MDCSnackbarBottomMargin_iPhone;
+}
+
+- (CGFloat)sideMargin {
+  return UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? MDCSnackbarSideMargin_iPad
+                                                              : MDCSnackbarSideMargin_iPhone;
+}
+
+- (void)setSnackbarView:(MDCSnackbarMessageView *)snackbarView {
+  if (_snackbarView != snackbarView) {
+    [_snackbarView removeFromSuperview];
+    _snackbarView = snackbarView;
+
+    CGFloat bottomMargin = [self staticBottomMargin];
+    CGFloat sideMargin = [self sideMargin];
+
+    BOOL fullWidth = UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad;
+
+    UIView *container = self.containingView;
+
+    if (snackbarView) {
+      [container addSubview:snackbarView];
+
+      // Pin the snackbar to the bottom of the screen.
+      [snackbarView setTranslatesAutoresizingMaskIntoConstraints:NO];
+
+      [container addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                            attribute:NSLayoutAttributeCenterX
+                                                            relatedBy:NSLayoutRelationEqual
+                                                               toItem:container
+                                                            attribute:NSLayoutAttributeCenterX
+                                                           multiplier:1.0
+                                                             constant:0]];
+
+      if (fullWidth) {
+        [container addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                              attribute:NSLayoutAttributeWidth
+                                                              relatedBy:NSLayoutRelationEqual
+                                                                 toItem:container
+                                                              attribute:NSLayoutAttributeWidth
+                                                             multiplier:1.0
+                                                               constant:-2 * sideMargin]];
+      } else {
+        // If not full width, ensure that it doesn't get any larger than our own width.
+        [container
+            addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                       attribute:NSLayoutAttributeWidth
+                                                       relatedBy:NSLayoutRelationLessThanOrEqual
+                                                          toItem:container
+                                                       attribute:NSLayoutAttributeWidth
+                                                      multiplier:1.0
+                                                        constant:-2 * sideMargin]];
+
+        // Also ensure that it doesn't get any smaller than its own minimum width.
+        [container
+            addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                       attribute:NSLayoutAttributeWidth
+                                                       relatedBy:NSLayoutRelationGreaterThanOrEqual
+                                                          toItem:nil
+                                                       attribute:NSLayoutAttributeNotAnAttribute
+                                                      multiplier:1.0
+                                                        constant:[snackbarView minimumWidth]]];
+
+        // Also ensure that it doesn't get any larger than its own maximum width.
+        [container
+            addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                       attribute:NSLayoutAttributeWidth
+                                                       relatedBy:NSLayoutRelationLessThanOrEqual
+                                                          toItem:nil
+                                                       attribute:NSLayoutAttributeNotAnAttribute
+                                                      multiplier:1.0
+                                                        constant:[snackbarView maximumWidth]]];
+      }
+
+      // Always pin the snackbar to the bottom of the container.
+      _snackbarOnscreenConstraint = [NSLayoutConstraint constraintWithItem:snackbarView
+                                                                 attribute:NSLayoutAttributeBottom
+                                                                 relatedBy:NSLayoutRelationEqual
+                                                                    toItem:container
+                                                                 attribute:NSLayoutAttributeBottom
+                                                                multiplier:1.0
+                                                                  constant:-bottomMargin];
+      _snackbarOnscreenConstraint.active = NO;  // snackbar starts off-screen.
+      _snackbarOnscreenConstraint.priority = UILayoutPriorityDefaultHigh;
+      [container addConstraint:_snackbarOnscreenConstraint];
+
+      _snackbarOffscreenConstraint = [NSLayoutConstraint constraintWithItem:snackbarView
+                                                                  attribute:NSLayoutAttributeTop
+                                                                  relatedBy:NSLayoutRelationEqual
+                                                                     toItem:container
+                                                                  attribute:NSLayoutAttributeBottom
+                                                                 multiplier:1.0
+                                                                   constant:-bottomMargin];
+      _snackbarOffscreenConstraint.active = YES;
+      [container addConstraint:_snackbarOffscreenConstraint];
+
+      // Always limit the height of the snackbar.
+      [container
+          addConstraint:[NSLayoutConstraint constraintWithItem:snackbarView
+                                                     attribute:NSLayoutAttributeHeight
+                                                     relatedBy:NSLayoutRelationLessThanOrEqual
+                                                        toItem:nil
+                                                     attribute:NSLayoutAttributeNotAnAttribute
+                                                    multiplier:1.0
+                                                      constant:kMaximumHeight]];
+    }
+  }
+}
+
+// All we care about is whether or not we tapped on the snackbar view. Everything else should pass
+// through to other windows. Only ask the snackbar view if the given point belongs, and ignore all
+// other touches.
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  BOOL result = NO;
+
+  if (self.snackbarView) {
+    CGPoint snackbarPoint = [self convertPoint:point toView:self.snackbarView];
+    result = [self.snackbarView pointInside:snackbarPoint withEvent:event];
+  }
+
+  return result;
+}
+
+- (void)triggerSnackbarLayoutChange {
+  self.manualLayoutChange = YES;
+  [self layoutIfNeeded];
+  self.manualLayoutChange = NO;
+}
+
+- (CGRect)snackbarRectInScreenCoordinates {
+  if (self.snackbarView == nil) {
+    return CGRectNull;
+  }
+
+  UIWindow *window = self.snackbarView.window;
+  if (window == nil) {
+    return CGRectNull;
+  }
+
+  UIScreen *screen = window.screen;
+  if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
+    return [self.snackbarView convertRect:self.snackbarView.bounds
+                        toCoordinateSpace:screen.fixedCoordinateSpace];
+  }
+
+  CGRect snackbarWindowFrame =
+      [window convertRect:self.snackbarView.bounds fromView:self.snackbarView];
+  CGRect snackbarScreenFrame = [window convertRect:snackbarWindowFrame toWindow:nil];
+  return snackbarScreenFrame;
+}
+
+#pragma mark - Presentation/Dismissal
+
+- (void)showSnackbarView:(MDCSnackbarMessageView *)snackbarView
+                animated:(BOOL)animated
+              completion:(void (^)(void))completion {
+  self.snackbarView = snackbarView;  // Install the snackbar.
+
+  if (animated) {
+    [self slideInMessageView:snackbarView completion:completion];
+  } else {
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+- (void)dismissSnackbarViewAnimated:(BOOL)animated completion:(void (^)(void))completion {
+  if (animated) {
+    [self slideOutMessageView:self.snackbarView
+                   completion:^{
+                     self.snackbarView = nil;  // Uninstall the snackbar
+
+                     if (completion) {
+                       completion();
+                     }
+                   }];
+  } else {
+    self.snackbarView = nil;
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+#pragma mark - Fade Animation
+
+- (void)fadeInsnackbarView:(MDCSnackbarMessageView *)snackbarView
+                completion:(void (^)(void))completion {
+  snackbarView.alpha = 0;
+
+  // Make sure that the snackbar has been properly sized before fading in.
+  [self triggerSnackbarLayoutChange];
+
+  void (^animations)(void) = ^{
+    self.snackbarView.alpha = 1.0;
+  };
+  void (^realCompletion)(BOOL) = ^(BOOL finished) {
+    if (completion) {
+      completion();
+    }
+  };
+
+  UIViewAnimationCurve curve = UIViewAnimationCurveEaseInOut;
+  CAMediaTimingFunction *function = nil;
+
+  MDCAnimationTimingFunction materialCurve = MDCAnimationTimingFunctionEaseOut;
+  function = [CAMediaTimingFunction mdc_functionWithType:materialCurve];
+
+  [MDCSnackbarOverlayView animateWithDuration:MDCSnackbarTransitionDuration
+                                        curve:materialCurve
+                                   animations:animations
+                                   completion:realCompletion];
+
+  // Notify the overlay system.
+  [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                            duration:MDCSnackbarTransitionDuration
+                               curve:curve
+                      timingFunction:function];
+}
+
+#pragma mark - Slide Animation
+
+- (void)slideMessageView:(MDCSnackbarMessageView *)snackbarView
+                onscreen:(BOOL)onscreen
+      fromContentOpacity:(CGFloat)fromContentOpacity
+        toContentOpacity:(CGFloat)toContentOpacity
+              completion:(void (^)(void))completion {
+  // Prepare to move the snackbar.
+  _snackbarOnscreenConstraint.active = onscreen;
+  _snackbarOffscreenConstraint.active = !onscreen;
+  [_containingView setNeedsUpdateConstraints];
+
+  CAMediaTimingFunction *timingFunction =
+      [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionEaseInOut];
+  [CATransaction begin];
+  [CATransaction setAnimationTimingFunction:timingFunction];
+
+  // We use UIView animation inside a CATransaction in order to use the custom animation curve.
+  [UIView animateWithDuration:MDCSnackbarTransitionDuration
+      delay:0
+      options:UIViewAnimationOptionCurveEaseInOut
+      animations:^{
+        // Trigger snackbar animation.
+        [_containingView layoutIfNeeded];
+      }
+      completion:^(BOOL finished) {
+        if (completion) {
+          completion();
+        }
+      }];
+
+  [snackbarView animateContentOpacityFrom:fromContentOpacity
+                                       to:toContentOpacity
+                                 duration:MDCSnackbarTransitionDuration
+                           timingFunction:timingFunction];
+  [CATransaction commit];
+
+  // Notify the overlay system.
+  [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                            duration:MDCSnackbarTransitionDuration
+                               curve:0
+                      timingFunction:timingFunction];
+}
+
+- (void)slideInMessageView:(MDCSnackbarMessageView *)snackbarView
+                completion:(void (^)(void))completion {
+  // Make sure that the snackbar has been properly sized to calculate the translation value.
+  [self triggerSnackbarLayoutChange];
+
+  [self slideMessageView:snackbarView
+                onscreen:YES
+      fromContentOpacity:0
+        toContentOpacity:1
+              completion:completion];
+}
+
+- (void)slideOutMessageView:(MDCSnackbarMessageView *)snackbarView
+                 completion:(void (^)(void))completion {
+  // Make sure that the snackbar has been properly sized to calculate the translation value.
+  [self triggerSnackbarLayoutChange];
+
+  [self slideMessageView:snackbarView
+                onscreen:NO
+      fromContentOpacity:1
+        toContentOpacity:0
+              completion:completion];
+}
+
+#pragma mark - Keyboard Notifications
+
+- (void)updatesnackbarPositionWithKeyboardUserInfo:(NSDictionary *)userInfo {
+  // Always set the bottom constraint, even if there isn't a snackbar currently displayed.
+  void (^updateBlock)(void) = ^{
+    self.bottomConstraint.constant = -[self dynamicBottomMargin];
+    [self triggerSnackbarLayoutChange];
+  };
+
+  if (self.snackbarView) {
+    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
+    UIViewAnimationCurve curve =
+        [userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
+    UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState | curve << 16;
+
+    [UIView animateWithDuration:duration
+                          delay:0
+                        options:options
+                     animations:updateBlock
+                     completion:nil];
+
+    // Notify the overlay system that a change is happening.
+    [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                              duration:duration
+                                 curve:curve
+                        timingFunction:nil];
+  } else {
+    updateBlock();
+  }
+}
+
+- (void)keyboardWillShow:(NSNotification *)notification {
+  [self updatesnackbarPositionWithKeyboardUserInfo:[notification userInfo]];
+}
+
+- (void)keyboardWillBeHidden:(NSNotification *)notification {
+  [self updatesnackbarPositionWithKeyboardUserInfo:[notification userInfo]];
+}
+
+- (void)keyboardWillChangeFrame:(NSNotification *)notification {
+  [self updatesnackbarPositionWithKeyboardUserInfo:[notification userInfo]];
+}
+
+#pragma mark - Bottom Offset
+
+- (void)setBottomOffset:(CGFloat)bottomOffset {
+  if (_bottomOffset != bottomOffset) {
+    _bottomOffset = bottomOffset;
+
+    self.bottomConstraint.constant = -[self dynamicBottomMargin];
+    [self triggerSnackbarLayoutChange];
+  }
+}
+
+#pragma mark - Rotation
+
+- (void)handleRotation {
+  if (self.snackbarView != nil) {
+    [self notifyOverlayChangeWithFrame:[self snackbarRectInScreenCoordinates]
+                              duration:self.rotationDuration
+                                 curve:UIViewAnimationCurveEaseInOut
+                        timingFunction:nil];
+  }
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  if (!self.manualLayoutChange && self.rotationDuration > 0) {
+    [self handleRotation];
+  }
+}
+
+- (void)willRotate:(NSNotification *)notification {
+  UIApplication *application = [UIApplication mdc_safeSharedApplication];
+  UIInterfaceOrientation currentOrientation = application.statusBarOrientation;
+  UIInterfaceOrientation targetOrientation =
+      [notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
+
+  NSTimeInterval duration = application.statusBarOrientationAnimationDuration;
+
+  // If this is a landscape->landscape or portrait->portrait rotation, then double the duration.
+  BOOL currentIsLandscape = UIInterfaceOrientationIsLandscape(currentOrientation);
+  BOOL targetIsLandscape = UIInterfaceOrientationIsLandscape(targetOrientation);
+  if (currentIsLandscape == targetIsLandscape) {
+    duration = 2 * duration;
+  }
+
+  self.rotationDuration = duration;
+
+  // On iOS 7, the layout of this overlay view will have already occurred by the time the will
+  // rotation notification is posted. In that event, we need to report rotation here. Opting to
+  // check for version using the UIDevice string methods because we need to perform this check even
+  // if the app was compiled on an iOS 7 SDK and is running on an iOS 8 device.
+  NSString *version = [[UIDevice currentDevice] systemVersion];
+  if ([version compare:@"8.0" options:NSNumericSearch] == NSOrderedAscending) {
+    [self handleRotation];
+  }
+}
+
+- (void)didRotate:(NSNotification *)notification {
+  // The UIApplicationDidChangeStatusBarOrientationNotification happens pretty much immediately
+  // after the willRotate notification, before any layouts are changed. By delaying this until the
+  // next runloop, any rotation-related layout changes will occur, and we can know that they were
+  // due to rotation.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    self.rotationDuration = -1;
+  });
+}
+
+#pragma mark - Overlay Support
+
+- (void)notifyOverlayChangeWithFrame:(CGRect)frame
+                            duration:(NSTimeInterval)duration
+                               curve:(UIViewAnimationCurve)curve
+                      timingFunction:(CAMediaTimingFunction *)timingFunction {
+  NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:@{
+    MDCOverlayIdentifierKey : MDCSnackbarOverlayIdentifier,
+    MDCOverlayFrameKey : [NSValue valueWithCGRect:frame],
+    MDCOverlayTransitionDurationKey : @(duration),
+  }];
+
+  if (duration > 0) {
+    if (timingFunction != nil) {
+      userInfo[MDCOverlayTransitionTimingFunctionKey] = timingFunction;
+    } else {
+      userInfo[MDCOverlayTransitionCurveKey] = @(curve);
+    }
+  }
+
+  // Notify the overlay system that a change is happening
+  [[NSNotificationCenter defaultCenter] postNotificationName:MDCOverlayDidChangeNotification
+                                                      object:nil
+                                                    userInfo:userInfo];
+}
+
+#pragma mark - UIAccessibilityAction
+
+- (BOOL)accessibilityPerformEscape {
+  if (self.snackbarView) {
+    [self.snackbarView dismissWithAction:nil userInitiated:YES];
+    return YES;
+  } else {
+    return NO;
+  }
+}
+
+#pragma mark - Timing functions
+
+static void WrapWithTimingFunctionForCurve(MDCAnimationTimingFunction mediaTiming,
+                                           void (^block)(void)) {
+  [CATransaction begin];
+  [CATransaction
+      setAnimationTimingFunction:[CAMediaTimingFunction mdc_functionWithType:mediaTiming]];
+  block();
+  [CATransaction commit];
+}
+
++ (void)animateWithDuration:(NSTimeInterval)duration
+                      curve:(MDCAnimationTimingFunction)curve
+                 animations:(void (^)(void))animations
+                 completion:(void (^)(BOOL finished))completion {
+  WrapWithTimingFunctionForCurve(curve, ^{
+    [UIView animateWithDuration:duration animations:animations completion:completion];
+  });
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.h
new file mode 100644
index 0000000..701cd43
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.h
@@ -0,0 +1,154 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCTabBarAlignment.h"
+#import "MDCTabBarItemAppearance.h"
+
+@class MDCTabBarItem;
+@protocol MDCTabBarDelegate;
+
+/**
+ A material tab bar for switching between views of grouped content.
+
+ Clients are responsible for responding to changes to the selected tab and updating the selected
+ tab as necessary.
+
+ Note: This class is not intended to be subclassed.
+
+ @see https://www.google.com/design/spec/components/tabs.html
+ */
+IB_DESIGNABLE
+@interface MDCTabBar : UIView
+
+/** Return the desired height for the tab bar given an item appearance. */
++ (CGFloat)defaultHeightForItemAppearance:(MDCTabBarItemAppearance)appearance;
+
+/**
+ Items displayed in the tab bar.
+
+ If the new items do not contain the currently selected item, the selection will be reset to nil.
+ Changes to this property are not animated.
+ */
+@property(nonatomic, copy, nonnull) NSArray<UITabBarItem *> *items;
+
+/**
+ The currently selected item. Setting to nil will clear the selection.
+
+ Changes to `selectedItem` are not animated.
+ */
+@property(nonatomic, strong, nullable) UITabBarItem *selectedItem;
+
+/** The tab bar's delegate. */
+@property(nonatomic, weak, nullable) IBOutlet id<MDCTabBarDelegate> delegate;
+
+/**
+ Tint color for the tab bar, which determines the color of the tab indicator bar. If
+ selectedItemTintColor is nil, tintColor also affects tinting of selected item titles and images.
+ */
+@property(nonatomic, strong, null_resettable) UIColor *tintColor;
+
+/**
+ Tint color for selected items. If nil, selected items will be tinted using the tab bar's
+ inherited tintColor instead. Default: Opaque white.
+ */
+@property(nonatomic, nullable) UIColor *selectedItemTintColor UI_APPEARANCE_SELECTOR;
+
+/** Tint color for unselected items. Default: Semi-transparent white. */
+@property(nonatomic, nonnull) UIColor *unselectedItemTintColor UI_APPEARANCE_SELECTOR;
+
+/** Ink color for taps on tab bar items. Default: Semi-transparent white. */
+@property(nonatomic, nonnull) UIColor *inkColor UI_APPEARANCE_SELECTOR;
+
+/**
+ Tint color to apply to the tab bar background.
+
+ If nil, the receiver uses the default background appearance. Default: nil.
+ */
+@property(nonatomic, nullable) UIColor *barTintColor UI_APPEARANCE_SELECTOR;
+
+/**
+ Horizontal alignment of tabs within the tab bar. Changes are not animated. Default alignment is
+ MDCTabBarAlignmentLeading.
+ */
+@property(nonatomic) MDCTabBarAlignment alignment;
+
+/**
+ Appearance of tabs within the tab bar. Changes are not animated. Default appearance is
+ MDCTabBarItemAppearanceTitles.
+ */
+@property(nonatomic) MDCTabBarItemAppearance itemAppearance;
+
+/**
+ Indicates if all tab titles should be uppercased for display. If NO, item titles will be
+ displayed verbatim.
+
+ Default is YES and is recommended whenever possible.
+ */
+@property(nonatomic) BOOL displaysUppercaseTitles;
+
+/**
+ Select an item with optional animation. Setting to nil will clear the selection.
+
+ `selectedItem` must be nil or in `items`.
+ */
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem animated:(BOOL)animated;
+
+/** Updates the alignment with optional animation. */
+- (void)setAlignment:(MDCTabBarAlignment)alignment animated:(BOOL)animated;
+
+@end
+
+#pragma mark -
+
+/** Accessibility-related methods on MDCTabBar. */
+@interface MDCTabBar (MDCAccessibility)
+
+/**
+ Get the accessibility element representing the given item. Returns nil if item is not in `items`
+ or if the item is not on screen.
+
+ The accessibility element returned from this method may be used as the focused element after a
+ run loop iteration.
+ */
+- (nullable id)accessibilityElementForItem:(nonnull UITabBarItem *)item;
+
+@end
+
+#pragma mark -
+
+/**
+ Delegate protocol for MDCTabBar. Clients may implement this protocol to receive notifications of
+ selection changes in the tab bar.
+ */
+@protocol MDCTabBarDelegate <NSObject>
+
+@optional
+
+/**
+ Called before the selected item changes by user action. This method is not called for programmatic
+ changes to the tab bar's selected item.
+ */
+- (void)tabBar:(nonnull MDCTabBar *)tabBar willSelectItem:(nonnull UITabBarItem *)item;
+
+/**
+ Called when the selected item changes by user action. This method is not called for programmatic
+ changes to the tab bar's selected item.
+ */
+- (void)tabBar:(nonnull MDCTabBar *)tabBar didSelectItem:(nonnull UITabBarItem *)item;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.m
new file mode 100644
index 0000000..77659de
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBar.m
@@ -0,0 +1,311 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCTabBar.h"
+
+#import "MaterialInk.h"
+#import "MaterialTypography.h"
+#import "private/MDCItemBar.h"
+#import "private/MDCItemBarAlignment.h"
+#import "private/MDCItemBarStyle.h"
+
+/// Padding between image and title in points, according to the spec.
+static const CGFloat kImageTitleSpecPadding = 10;
+
+/// Adjustment added to spec measurements to compensate for internal paddings.
+static const CGFloat kImageTitlePaddingAdjustment = -3;
+
+// Heights based on the spec: https://www.google.com/design/spec/components/tabs.html
+
+/// Height for image-only tab bars, in points.
+static const CGFloat kImageOnlyBarHeight = 48;
+
+/// Height for image-only tab bars, in points.
+static const CGFloat kTitleOnlyBarHeight = 48;
+
+/// Height for image-and-title tab bars, in points.
+static const CGFloat kTitledImageBarHeight = 72;
+
+static MDCTabBarAlignment MDCTabBarAlignmentForItemBarAlignment(MDCItemBarAlignment alignment) {
+  switch (alignment) {
+    case MDCItemBarAlignmentCenter:
+      return MDCTabBarAlignmentCenter;
+
+    case MDCItemBarAlignmentLeading:
+      return MDCTabBarAlignmentLeading;
+
+    case MDCItemBarAlignmentJustified:
+      return MDCTabBarAlignmentJustified;
+
+    case MDCItemBarAlignmentCenterSelected:
+      return MDCTabBarAlignmentCenterSelected;
+  }
+
+  NSCAssert(0, @"Invalid alignment value %zd", alignment);
+  return MDCTabBarAlignmentLeading;
+}
+
+static MDCItemBarAlignment MDCItemBarAlignmentForTabBarAlignment(MDCTabBarAlignment alignment) {
+  switch (alignment) {
+    case MDCTabBarAlignmentCenter:
+      return MDCItemBarAlignmentCenter;
+
+    case MDCTabBarAlignmentLeading:
+      return MDCItemBarAlignmentLeading;
+
+    case MDCTabBarAlignmentJustified:
+      return MDCItemBarAlignmentJustified;
+
+    case MDCTabBarAlignmentCenterSelected:
+      return MDCItemBarAlignmentCenterSelected;
+  }
+
+  NSCAssert(0, @"Invalid alignment value %zd", alignment);
+  return MDCItemBarAlignmentLeading;
+}
+
+@interface MDCTabBar () <MDCItemBarDelegate>
+@end
+
+@implementation MDCTabBar {
+  /// Item bar responsible for displaying the actual tab bar content.
+  MDCItemBar *_itemBar;
+}
+// Inherit UIView's tintColor logic.
+@dynamic tintColor;
+
+#pragma mark - Initialization
+
++ (void)initialize {
+  [[[self class] appearance] setSelectedItemTintColor:[UIColor whiteColor]];
+  [[[self class] appearance] setUnselectedItemTintColor:[UIColor colorWithWhite:1.0 alpha:0.7f]];
+  [[[self class] appearance] setInkColor:[UIColor colorWithWhite:1.0 alpha:0.7f]];
+  [[[self class] appearance] setBarTintColor:nil];
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonMDCTabBarInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonMDCTabBarInit];
+  }
+  return self;
+}
+
+- (void)commonMDCTabBarInit {
+  _itemAppearance = MDCTabBarItemAppearanceTitles;
+  _displaysUppercaseTitles = YES;
+
+  // Create item bar.
+  _itemBar = [[MDCItemBar alloc] initWithFrame:self.bounds];
+  _itemBar.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+  _itemBar.delegate = self;
+  _itemBar.alignment = MDCItemBarAlignmentLeading;
+  [self addSubview:_itemBar];
+
+  [self updateItemBarStyle];
+}
+
+#pragma mark - Public
+
++ (CGFloat)defaultHeightForItemAppearance:(MDCTabBarItemAppearance)appearance {
+  return [MDCItemBar defaultHeightForStyle:[self defaultStyleForItemAppearance:appearance]];
+}
+
+- (NSArray<UITabBarItem *> *)items {
+  return _itemBar.items;
+}
+
+- (void)setItems:(NSArray<UITabBarItem *> *)items {
+  [_itemBar setItems:items];
+}
+
+- (UITabBarItem *)selectedItem {
+  return _itemBar.selectedItem;
+}
+
+- (void)setSelectedItem:(UITabBarItem *)selectedItem {
+  [_itemBar setSelectedItem:selectedItem];
+}
+
+- (void)setSelectedItem:(UITabBarItem *)selectedItem animated:(BOOL)animated {
+  [_itemBar setSelectedItem:selectedItem animated:animated];
+}
+
+- (void)setBarTintColor:(UIColor *)barTintColor {
+  if (_barTintColor != barTintColor && ![_barTintColor isEqual:barTintColor]) {
+    _barTintColor = barTintColor;
+
+    // Update background color.
+    _itemBar.backgroundColor = barTintColor;
+  }
+}
+
+- (void)setInkColor:(UIColor *)inkColor {
+  if (_inkColor != inkColor && ![_inkColor isEqual:inkColor]) {
+    _inkColor = inkColor;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (MDCTabBarAlignment)alignment {
+  return MDCTabBarAlignmentForItemBarAlignment(_itemBar.alignment);
+}
+
+- (void)setAlignment:(MDCTabBarAlignment)alignment {
+  [_itemBar setAlignment:MDCItemBarAlignmentForTabBarAlignment(alignment)];
+}
+
+- (void)setAlignment:(MDCTabBarAlignment)alignment animated:(BOOL)animated {
+  [_itemBar setAlignment:MDCItemBarAlignmentForTabBarAlignment(alignment) animated:animated];
+}
+
+- (void)setItemAppearance:(MDCTabBarItemAppearance)itemAppearance {
+  if (itemAppearance != _itemAppearance) {
+    _itemAppearance = itemAppearance;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (void)setSelectedItemTintColor:(UIColor *)selectedItemTintColor {
+  if (_selectedItemTintColor != selectedItemTintColor &&
+      ![_selectedItemTintColor isEqual:selectedItemTintColor]) {
+    _selectedItemTintColor = selectedItemTintColor;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (void)setUnselectedItemTintColor:(UIColor *)unselectedItemTintColor {
+  if (_unselectedItemTintColor != unselectedItemTintColor &&
+      ![_unselectedItemTintColor isEqual:unselectedItemTintColor]) {
+    _unselectedItemTintColor = unselectedItemTintColor;
+
+    [self updateItemBarStyle];
+  }
+}
+
+- (void)setDisplaysUppercaseTitles:(BOOL)displaysUppercaseTitles {
+  if (displaysUppercaseTitles != _displaysUppercaseTitles) {
+    _displaysUppercaseTitles = displaysUppercaseTitles;
+
+    [self updateItemBarStyle];
+  }
+}
+
+#pragma mark - MDCItemBarDelegate
+
+- (void)itemBar:(MDCItemBar *)itemBar didSelectItem:(UITabBarItem *)item {
+  id<MDCTabBarDelegate> delegate = self.delegate;
+  if ([delegate respondsToSelector:@selector(tabBar:didSelectItem:)]) {
+    [delegate tabBar:self didSelectItem:item];
+  }
+}
+
+- (void)itemBar:(MDCItemBar *)itemBar willSelectItem:(UITabBarItem *)item {
+  id<MDCTabBarDelegate> delegate = self.delegate;
+  if ([delegate respondsToSelector:@selector(tabBar:willSelectItem:)]) {
+    [delegate tabBar:self willSelectItem:item];
+  }
+}
+
+#pragma mark - UIView
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  [self updateItemBarStyle];
+}
+
+- (CGSize)intrinsicContentSize {
+  return _itemBar.intrinsicContentSize;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  return [_itemBar sizeThatFits:size];
+}
+
+#pragma mark - Private
+
++ (MDCItemBarStyle *)defaultStyleForItemAppearance:(MDCTabBarItemAppearance)appearance {
+  MDCItemBarStyle *style = [[MDCItemBarStyle alloc] init];
+
+  style.shouldDisplaySelectionIndicator = YES;
+  style.shouldGrowOnSelection = NO;
+  style.titleFont = [MDCTypography buttonFont];
+  style.inkStyle = MDCInkStyleBounded;
+  style.titleImagePadding = (kImageTitleSpecPadding + kImageTitlePaddingAdjustment);
+
+  BOOL displayImage = NO;
+  BOOL displayTitle = NO;
+  CGFloat defaultHeight = 0;
+  switch (appearance) {
+    case MDCTabBarItemAppearanceImages:
+      displayImage = YES;
+      defaultHeight = kImageOnlyBarHeight;
+      break;
+
+    case MDCTabBarItemAppearanceTitles:
+      displayTitle = YES;
+      defaultHeight = kTitleOnlyBarHeight;
+      break;
+
+    case MDCTabBarItemAppearanceTitledImages:
+      displayImage = YES;
+      displayTitle = YES;
+      defaultHeight = kTitledImageBarHeight;
+      break;
+
+    default:
+      NSAssert(0, @"Invalid appearance value %zd", appearance);
+      displayTitle = YES;
+      defaultHeight = kTitleOnlyBarHeight;
+      break;
+  }
+  style.shouldDisplayImage = displayImage;
+  style.shouldDisplayTitle = displayTitle;
+  style.defaultHeight = defaultHeight;
+
+  // Only show badge with images.
+  style.shouldDisplayBadge = displayImage;
+
+  return style;
+}
+
+- (void)updateItemBarStyle {
+  MDCItemBarStyle *style;
+
+  style = [[self class] defaultStyleForItemAppearance:_itemAppearance];
+
+  style.selectionIndicatorColor = self.tintColor;
+  style.inkColor = _inkColor;
+  style.selectedTitleColor = (_selectedItemTintColor ?: self.tintColor);
+  style.titleColor = _unselectedItemTintColor;
+  style.displaysUppercaseTitles = _displaysUppercaseTitles;
+
+  [_itemBar applyStyle:style];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
new file mode 100644
index 0000000..7e78559
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBarAlignment.h
@@ -0,0 +1,38 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/** Alignment styles for items in a tab bar. */
+typedef NS_ENUM(NSInteger, MDCTabBarAlignment) {
+  /** Items are aligned on the leading edge and sized to fit their content. */
+  MDCTabBarAlignmentLeading,
+
+  /**
+   Items are justified to equal size across the width of the screen. Overscrolling is disabled
+   for this alignment.
+   */
+  MDCTabBarAlignmentJustified,
+
+  /**
+   Items are sized to fit their content and center-aligned as a group. If they do not fit in view,
+   they will be leading-aligned instead.
+   */
+  MDCTabBarAlignmentCenter,
+
+  /** Tabs are center-aligned on the selected item. */
+  MDCTabBarAlignmentCenterSelected,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
new file mode 100644
index 0000000..f8e00a3
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MDCTabBarItemAppearance.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/** Appearance for content within tab bar items. */
+typedef NS_ENUM(NSInteger, MDCTabBarItemAppearance) {
+  /** Tabs are shown as titles. Badges are not supported for this appearance. */
+  MDCTabBarItemAppearanceTitles,
+
+  /** Tabs are shown as images. */
+  MDCTabBarItemAppearanceImages,
+
+  /** Tabs are shown as images with titles underneath. */
+  MDCTabBarItemAppearanceTitledImages,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ar.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ar.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b02b103
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ar.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d‏ من‏ %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "علامة تبويب";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/bg.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/bg.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/bg.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ca.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ca.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2cb6f30
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ca.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestanya";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/cs.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/cs.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..dcde450
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/cs.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d z %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "karta";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/da.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/da.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..78a052a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/da.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d af %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "fane";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/de.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/de.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..bc8b328
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/de.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d von %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Tabulatortaste";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/el.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/el.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..eeb2245
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/el.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d από %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "καρτέλα";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_AU.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_AU.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_AU.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_GB.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_GB.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_GB.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_IN.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_IN.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/en_IN.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..5ebb933
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestaña";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_419.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_419.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2cd61d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_419.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestaña";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_MX.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_MX.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2cd61d2
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/es_MX.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "pestaña";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fa.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fa.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..57be590
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fa.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d از %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "برگه";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fi.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fi.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..7f42728
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fi.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "välilehti";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2262686
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d sur %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "onglet";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr_CA.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr_CA.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..1520591
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/fr_CA.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "onglet";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/he.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/he.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b692f77
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/he.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d מתוך %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "כרטיסייה";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hi.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hi.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..6898e9d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hi.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d में से %1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "टैब";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..8d77fb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d od %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "kartica";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hu.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hu.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..97e1739
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hu.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d/%1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "lapfül";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hy.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hy.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2467de9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/hy.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d-ը՝ %2$d-ից";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "ներդիր";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/id.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/id.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..1275b47
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/id.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d dari %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/it.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/it.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..7fa1e7c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/it.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d di %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "scheda";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/iw.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/iw.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b692f77
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/iw.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d מתוך %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "כרטיסייה";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ja.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ja.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..c4393cc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ja.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "タブ";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ka.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ka.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..2140c25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ka.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d / %2$d-დან";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "ჩანართი";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/kk.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/kk.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..57bf878
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/kk.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d/%1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "қойынды";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/km.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/km.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..e4f3c95
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/km.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d នៃ %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "ថេប​";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ko.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ko.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..874831f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ko.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d개 중 %1$d번째";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lo.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lo.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..d94fbd0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lo.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d ຈາກທັງໝົດ %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lt.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lt.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..7194c55
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lt.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d iš %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "skirtukas";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lv.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lv.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..74b2d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/lv.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d of %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/mn.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/mn.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..d26886f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/mn.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%2$d-н %1$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "чихтэй хуудас";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ms.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ms.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..f82885d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ms.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d daripada %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nb.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nb.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..36e5452
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nb.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d av %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "fane";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nl.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nl.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..393b1cf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/nl.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d van %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tabblad";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/no.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/no.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..36e5452
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/no.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d av %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "fane";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pl.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pl.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..e1ebe01
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pl.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d z %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "karta";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..cd88f7f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "guia";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_BR.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_BR.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..cd88f7f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_BR.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "guia";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_PT.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_PT.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..29e3015
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/pt_PT.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d de %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "separador";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ro.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ro.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..00d64e5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ro.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d din %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "filă";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ru.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ru.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..0a8615e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/ru.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d из %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "вкладка";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sk.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sk.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..dcde450
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sk.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d z %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "karta";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sq.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sq.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..219bddd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sq.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d nga %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "skedë";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..bc3da09
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d од %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "картица";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sv.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sv.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..ea114a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/sv.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d av %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "flik";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/th.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/th.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..e70128f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/th.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d จาก %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "แท็บ";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/tr.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/tr.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..d6cc265
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/tr.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d/%2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "sekme";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/uk.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/uk.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..bef0ed7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/uk.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d з %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "Вкладка";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/vi.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/vi.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..377764c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/vi.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "%1$d trên %2$d";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "tab";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_CN.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_CN.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..b7239a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_CN.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "第 %1$d 个,共 %2$d 个";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "标签";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_HK.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_HK.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..f187f88
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_HK.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "第 %1$d 個,共 %2$d 個";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "標籤";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_TW.lproj/MaterialTabs.strings b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_TW.lproj/MaterialTabs.strings
new file mode 100644
index 0000000..cab6ccb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.bundle/Resources/zh_TW.lproj/MaterialTabs.strings
@@ -0,0 +1,5 @@
+/* Accessibility label component describing a tab's position in a list (e.g. "2 of 5"). The first format parameter is the tab's position as a number, and the second parameter is the number of tabs. */
+"MaterialTabsAccessibilityTabPositionFormat" = "第 %1$d 個,共 %2$d 個";
+
+/* Accessibility label component identifying a tab element. */
+"MaterialTabsAccessibilityTabElementLabel" = "分頁";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.h
new file mode 100644
index 0000000..d18be31
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/MaterialTabs.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCTabBar.h"
+#import "MDCTabBarAlignment.h"
+#import "MDCTabBarItemAppearance.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.h
new file mode 100644
index 0000000..9654db1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.h
@@ -0,0 +1,109 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCItemBarAlignment.h"
+
+@class MDCItemBarStyle;
+@protocol MDCItemBarDelegate;
+
+/**
+ A horizontally-scrollable list of tab-like items.
+
+ This is the private shared implementation of MDCTabBar and MDCBottomNavigationBar. It should not
+ be used directly and is not guaranteed to have a stable API.
+ */
+@interface MDCItemBar : UIView
+
+/** Return the default height for the item bar given a style. */
++ (CGFloat)defaultHeightForStyle:(nonnull MDCItemBarStyle *)style;
+
+/**
+ Items displayed in bar.
+
+ If the new items do not contain the currently selected item, the selection will be reset to the
+ first item. Changes to this property are not animated. May not be nil.
+ */
+@property(nonatomic, copy, nonnull) NSArray<UITabBarItem *> *items;
+
+/**
+ The currently selected item. May be nil if `items` is empty.
+
+ Changes to `selectedItem` are not animated.
+ */
+@property(nonatomic, strong, nullable) UITabBarItem *selectedItem;
+
+/** The item bar's delegate. */
+@property(nonatomic, weak, nullable) id<MDCItemBarDelegate> delegate;
+
+/**
+ Select an item with optional animation. Raises an NSInvalidArgumentException if selectedItem is
+ not in `items`.
+ */
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem animated:(BOOL)animated;
+
+/**
+ Horizontal alignment of items. Changes are not animated. Default alignment is
+ MDCItemBarAlignmentLeading.
+ */
+@property(nonatomic) MDCItemBarAlignment alignment;
+
+/** Updates the alignment with optional animation. */
+- (void)setAlignment:(MDCItemBarAlignment)alignment animated:(BOOL)animated;
+
+#pragma mark - Styling
+
+/** Updates the bar to use the given style properties. */
+- (void)applyStyle:(nonnull MDCItemBarStyle *)itemStyle;
+
+@end
+
+/**
+ Delegate protocol for MDCItemBar. Clients may implement this protocol to receive notifications of
+ selection changes.
+ */
+@protocol MDCItemBarDelegate <NSObject>
+
+/**
+ Called before the selected item changes by user action. This method is not called for programmatic
+ changes to the bar's selected item.
+ */
+- (void)itemBar:(nonnull MDCItemBar *)itemBar willSelectItem:(nonnull UITabBarItem *)item;
+
+/**
+ Called when the selected item changes by user action. This method is not called for programmatic
+ changes to the bar's selected item.
+ */
+- (void)itemBar:(nonnull MDCItemBar *)itemBar didSelectItem:(nonnull UITabBarItem *)item;
+
+@end
+
+#pragma mark -
+
+/** Accessibility-related methods on MDCItemBar. */
+@interface MDCItemBar (MDCItemBarAccessibility)
+
+/**
+ * Get the accessibility element representing the given item. Returns nil if item is not in `items`
+ * or if the item is not on screen.
+ *
+ * The accessibility element returned from this method may be used as the focused element after a
+ * run loop iteration.
+ */
+- (nullable id)accessibilityElementForItem:(nonnull UITabBarItem *)item;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.m
new file mode 100644
index 0000000..1e53584
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBar.m
@@ -0,0 +1,923 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCItemBar.h"
+
+#import "MDCItemBarCell.h"
+#import "MDCItemBarStyle.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialRTL.h"
+
+/// Height in points of the bar shown under selected items.
+static const CGFloat kSelectionIndicatorHeight = 2.0f;
+
+/// Cell reuse identifier for item bar cells.
+static NSString *const kItemReuseID = @"MDCItem";
+
+/// Default duration in seconds for selection change animations.
+static const NSTimeInterval kDefaultAnimationDuration = 0.3f;
+
+/// Placeholder width for cells, which get per-item sizing.
+static const CGFloat kPlaceholderCellWidth = 10.0f;
+
+/// Horizontal insets in regular size class layouts.
+static const CGFloat kRegularInset = 56.0f;
+
+/// Horizontal insets in compact size class layouts.
+static const CGFloat kCompactInset = 8.0f;
+
+/// KVO context pointer identifying changes in MDCItemBarItem properties.
+static void *kItemPropertyContext = &kItemPropertyContext;
+
+/// Custom flow layout for item content. Selectively works around bugs with RTL and flow layout:
+/// Radar 22828797: "UICollectionView with variable-sized items does not reverse item order in RTL."
+/// - On iOS 9.0 and later when a UICollectionViewFlow layout has custom-sized items via
+///   collectionView:layout:sizeForItemAtIndexPath:, it does not perform automatic right-to-left
+///   layout of items. We work around this by detecting incorrect ordering by the superclass and
+///   correcting the layout attributes.
+/// Radar 22828629, 22828529
+/// - On iOS 9 and later, the default scroll location for horizontally-scrolling collection views in
+///   RTL is correct, but resets to the left when scrolling an item to visible or manually scrolling
+///   the content. We work around this by padding collection content to always fill the scroll view.
+@interface MDCItemBarFlowLayout : UICollectionViewFlowLayout
+@end
+
+#pragma mark -
+
+@interface MDCItemBar () <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
+@end
+
+@implementation MDCItemBar {
+  // Collection view and layout for items.
+  UICollectionView *_collectionView;
+  UICollectionViewFlowLayout *_flowLayout;
+
+  /// Underline displayed under the active item.
+  UIView *_selectionIndicator;
+
+  /// Index path of the previously selected item.
+  NSIndexPath *_lastSelectedIndexPath;
+
+  /// Size of the view at last layout, for deduplicating changes.
+  CGSize _lastSize;
+
+  /// Horizontal size class at the last item metrics update. Used to calculate deltas.
+  UIUserInterfaceSizeClass _horizontalSizeClassAtLastMetricsUpdate;
+
+  /// Current style properties.
+  MDCItemBarStyle *_style;
+}
+
++ (CGFloat)defaultHeightForStyle:(nonnull MDCItemBarStyle *)style {
+  return style.defaultHeight;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    [self commonItemBarInit];
+  }
+  return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+  self = [super initWithCoder:aDecoder];
+  if (self) {
+    [self commonItemBarInit];
+  }
+  return self;
+}
+
+- (void)commonItemBarInit {
+  _alignment = MDCItemBarAlignmentLeading;
+  _style = [[MDCItemBarStyle alloc] init];
+  _items = @[];
+  _horizontalSizeClassAtLastMetricsUpdate = UIUserInterfaceSizeClassUnspecified;
+
+  // Configure the collection view.
+  _flowLayout = [self generatedFlowLayout];
+  UICollectionView *collectionView =
+      [[UICollectionView alloc] initWithFrame:self.bounds collectionViewLayout:_flowLayout];
+  collectionView.backgroundColor = [UIColor clearColor];
+  collectionView.clipsToBounds = YES;
+  collectionView.scrollsToTop = NO;
+  collectionView.showsHorizontalScrollIndicator = NO;
+  collectionView.showsVerticalScrollIndicator = NO;
+  collectionView.dataSource = self;
+  collectionView.delegate = self;
+  collectionView.autoresizingMask =
+      UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+  [collectionView registerClass:[MDCItemBarCell class] forCellWithReuseIdentifier:kItemReuseID];
+
+  _collectionView = collectionView;
+  [self addSubview:_collectionView];
+
+  // Configure the selection indicator view.
+  _selectionIndicator =
+      [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, kSelectionIndicatorHeight)];
+  _selectionIndicator.backgroundColor = [UIColor whiteColor];
+  _selectionIndicator.opaque = YES;
+  [_collectionView addSubview:_selectionIndicator];
+
+  // Set initial properties.
+  [self updateAlignmentAnimated:NO];
+  [self updateScrollProperties];
+  [self updateColors];
+  [self updateSelectionIndicatorVisibility];
+}
+
+- (void)dealloc {
+  // Clear out item observations.
+  [self stopObservingItems];
+
+  _collectionView.delegate = nil;
+}
+
+#pragma mark - Public
+
+- (void)applyStyle:(MDCItemBarStyle *)style {
+  if (style != _style && ![style isEqual:_style]) {
+    _style = [style copy];
+
+    // Update all style-dependent properties.
+    [self updateColors];
+    [self updateAlignmentAnimated:NO];
+    [self updateSelectionIndicatorVisibility];
+    [self configureVisibleCells];
+    [self invalidateIntrinsicContentSize];
+  }
+}
+
+- (void)setItems:(NSArray<UITabBarItem *> *)items {
+  NSAssert([NSThread isMainThread], @"Item array may only be set on the main thread");
+  NSParameterAssert(items != nil);
+
+  if (_items != items && ![_items isEqual:items]) {
+    // Stop observing old items.
+    [self stopObservingItems];
+
+    _items = [items copy];
+
+    [self reload];
+
+    // Reset selection to a valid item.
+    if (![_items containsObject:_selectedItem]) {
+      self.selectedItem = [_items firstObject];
+    }
+
+    // Start observing new items for changes.
+    [self startObservingItems];
+  }
+}
+
+- (void)setAlignment:(MDCItemBarAlignment)alignment {
+  [self setAlignment:alignment animated:NO];
+}
+
+- (void)setAlignment:(MDCItemBarAlignment)alignment animated:(BOOL)animated {
+  if (_alignment != alignment) {
+    _alignment = alignment;
+
+    [self updateAlignmentAnimated:animated];
+  }
+}
+
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem {
+  [self setSelectedItem:selectedItem animated:NO];
+}
+
+- (void)setSelectedItem:(nullable UITabBarItem *)selectedItem animated:(BOOL)animated {
+  if (_selectedItem != selectedItem) {
+    NSInteger itemIndex = [_items indexOfObject:selectedItem];
+    if (itemIndex == NSNotFound) {
+      [[NSException exceptionWithName:NSInvalidArgumentException
+                               reason:@"Invalid item"
+                             userInfo:nil] raise];
+    }
+
+    _selectedItem = selectedItem;
+    [self selectItemAtIndex:itemIndex animated:animated];
+  }
+}
+
+#pragma mark - Accessibility
+
+- (id)accessibilityElementForItem:(UITabBarItem *)item {
+  NSUInteger index = [_items indexOfObject:item];
+  if (index != NSNotFound) {
+    NSArray<NSIndexPath *> *visibleItems = [_collectionView indexPathsForVisibleItems];
+    NSIndexPath *indexPath = [self indexPathForItemAtIndex:index];
+    if ([visibleItems containsObject:indexPath]) {
+      MDCItemBarCell *itemCell =
+          (MDCItemBarCell *)[_collectionView cellForItemAtIndexPath:indexPath];
+      return itemCell;
+    }
+  }
+  return nil;
+}
+
+#pragma mark - NSObject
+
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
+                       context:(void *)context {
+  if (context == kItemPropertyContext) {
+    // MDCItemBarItem change, must be on the main thread.
+    NSAssert([NSThread isMainThread], @"Item bar items may only be updated on the main thread.");
+    NSAssert([object isKindOfClass:[UITabBarItem class]], @"Change in unexpected object type");
+
+    UITabBarItem *item = object;
+    NSInteger itemIndex = [_items indexOfObject:item];
+    NSAssert(itemIndex != NSNotFound, @"Inconsistency: Change in unowned item bar item.");
+
+    // Update the cell for the given item if it's visible.
+    if (itemIndex != NSNotFound) {
+      NSIndexPath *indexPath = [self indexPathForItemAtIndex:itemIndex];
+      UICollectionViewCell *cell = [_collectionView cellForItemAtIndexPath:indexPath];
+      if (cell) {
+        NSAssert([cell isKindOfClass:[MDCItemBarCell class]], @"All cells must be MDCItemBarCell");
+        MDCItemBarCell *itemCell = (MDCItemBarCell *)cell;
+        [itemCell updateWithItem:item atIndex:itemIndex count:_items.count];
+      }
+    }
+  } else {
+    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
+  }
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  const CGRect bounds = self.bounds;
+
+  _collectionView.frame = bounds;
+
+  // Update collection metrics if the size has changed.
+  if (!CGSizeEqualToSize(bounds.size, _lastSize)) {
+    [self updateFlowLayoutMetrics];
+
+    if (_lastSelectedIndexPath) {
+      // Ensure selected item is aligned properly on resize.
+      [self selectItemAtIndex:_lastSelectedIndexPath.item animated:NO];
+    }
+  }
+  _lastSize = bounds.size;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+  size.height = [[self class] defaultHeightForStyle:_style];
+  return size;
+}
+
+- (CGSize)intrinsicContentSize {
+  return CGSizeMake(UIViewNoIntrinsicMetric, [[self class] defaultHeightForStyle:_style]);
+}
+
+- (void)didMoveToWindow {
+  [super didMoveToWindow];
+
+  // New window: Update for potentially updated size class.
+  [self updateFlowLayoutMetrics];
+}
+
+- (void)traitCollectionDidChange:(nullable UITraitCollection *)previousTraitCollection {
+  [super traitCollectionDidChange:previousTraitCollection];
+
+  // Update metrics for potentially updated size class.
+  [self updateFlowLayoutMetrics];
+}
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  [self updateColors];
+}
+
+#pragma mark - UICollectionViewDelegate
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+    shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  if (_collectionView == collectionView) {
+    UITabBarItem *item = [self itemAtIndexPath:indexPath];
+
+    // Notify delegate of impending selection.
+    id<MDCItemBarDelegate> delegate = self.delegate;
+    if ([delegate respondsToSelector:@selector(itemBar:willSelectItem:)]) {
+      [delegate itemBar:self willSelectItem:item];
+    }
+  }
+  return YES;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView
+    didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+  if (_collectionView == collectionView) {
+    // Update selected item.
+    UITabBarItem *item = [self itemAtIndexPath:indexPath];
+    _selectedItem = item;
+
+    // Notify delegate of new selection.
+    id<MDCItemBarDelegate> delegate = self.delegate;
+    if ([delegate respondsToSelector:@selector(itemBar:didSelectItem:)]) {
+      [delegate itemBar:self didSelectItem:item];
+    }
+
+    // Update UI to reflect newly selected item.
+    [self didSelectItemAtIndexPath:indexPath animateTransition:YES];
+    [_collectionView scrollToItemAtIndexPath:indexPath
+                            atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
+                                    animated:YES];
+  }
+}
+
+#pragma mark - UICollectionViewDataSource
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView
+     numberOfItemsInSection:(NSInteger)section {
+  if ((_collectionView == collectionView) && section == 0) {
+    return [_items count];
+  }
+  return 0;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
+                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+  NSParameterAssert(_collectionView == collectionView);
+
+  MDCItemBarCell *itemCell =
+      [collectionView dequeueReusableCellWithReuseIdentifier:kItemReuseID forIndexPath:indexPath];
+  UITabBarItem *item = [self itemAtIndexPath:indexPath];
+
+  [self configureCell:itemCell];
+  [itemCell updateWithItem:item atIndex:indexPath.item count:_items.count];
+
+  return itemCell;
+}
+
+#pragma mark - UICollectionViewDelegateFlowLayout
+
+- (CGSize)collectionView:(UICollectionView *)collectionView
+                    layout:(UICollectionViewLayout *)collectionViewLayout
+    sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
+  NSParameterAssert(_collectionView == collectionView);
+
+  UITabBarItem *item = [self itemAtIndexPath:indexPath];
+
+  const CGFloat itemHeight = CGRectGetHeight(self.bounds);
+  CGSize size = CGSizeMake(CGFLOAT_MAX, itemHeight);
+
+  // Size cell to fit content.
+  size = [MDCItemBarCell sizeThatFits:size
+                  horizontalSizeClass:[self horizontalSizeClass]
+                                 item:item
+                                style:_style];
+
+  // Divide justified items evenly across the view.
+  if (_alignment == MDCItemBarAlignmentJustified) {
+    NSInteger count = [self collectionView:_collectionView numberOfItemsInSection:0];
+    size.width = _collectionView.bounds.size.width / MAX(count, 1);
+  }
+
+  // Constrain width if necessary.
+  if (_style.maximumItemWidth > 0) {
+    size.width = MIN(size.width, _style.maximumItemWidth);
+  }
+
+  // Force height to our height.
+  size.height = itemHeight;
+
+  return size;
+}
+
+#pragma mark - Private
+
++ (NSArray *)observableItemKeys {
+  static dispatch_once_t onceToken;
+  static NSArray *s_keys = nil;
+  dispatch_once(&onceToken, ^{
+    s_keys = @[
+      NSStringFromSelector(@selector(title)), NSStringFromSelector(@selector(image)),
+      NSStringFromSelector(@selector(badgeValue)),
+      NSStringFromSelector(@selector(accessibilityIdentifier))
+    ];
+  });
+  return s_keys;
+}
+
+- (void)startObservingItems {
+  NSAssert([NSThread isMainThread], @"Main thread required for KVO registration");
+
+  for (UITabBarItem *item in _items) {
+    for (NSString *key in [[self class] observableItemKeys]) {
+      [item addObserver:self forKeyPath:key options:0 context:kItemPropertyContext];
+    }
+  }
+}
+
+- (void)stopObservingItems {
+  NSAssert([NSThread isMainThread], @"Main thread required for KVO unregistration");
+
+  for (UITabBarItem *item in _items) {
+    for (NSString *key in [[self class] observableItemKeys]) {
+      [item removeObserver:self forKeyPath:key context:kItemPropertyContext];
+    }
+  }
+}
+
+- (UIUserInterfaceSizeClass)horizontalSizeClass {
+  // Use trait collection's horizontalSizeClass if available.
+  if ([self respondsToSelector:@selector(traitCollection)]) {
+    return self.traitCollection.horizontalSizeClass;
+  }
+
+  // Pre-iOS 8: Use fixed size class for device.
+  BOOL isPad = ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
+  return isPad ? UIUserInterfaceSizeClassRegular : UIUserInterfaceSizeClassCompact;
+}
+
+- (void)selectItemAtIndex:(NSInteger)index animated:(BOOL)animated {
+  NSParameterAssert(index >= 0 && index < (NSInteger)[_items count]);
+
+  NSIndexPath *indexPath = [self indexPathForItemAtIndex:index];
+  [_collectionView selectItemAtIndexPath:indexPath
+                                animated:animated
+                          scrollPosition:UICollectionViewScrollPositionCenteredHorizontally];
+  [self didSelectItemAtIndexPath:indexPath animateTransition:animated];
+}
+
+- (UITabBarItem *)itemAtIndexPath:(NSIndexPath *)indexPath {
+  return _items[indexPath.item];
+}
+
+- (NSIndexPath *)indexPathForItemAtIndex:(NSInteger)index {
+  return [NSIndexPath indexPathForItem:index inSection:0];
+}
+
+- (void)reload {
+  [_collectionView reloadData];
+  [self updateFlowLayoutMetrics];
+}
+
+- (UICollectionViewFlowLayout *)generatedFlowLayout {
+  UICollectionViewFlowLayout *flowLayout = [[MDCItemBarFlowLayout alloc] init];
+  CGFloat itemHeight = CGRectGetHeight(self.bounds);
+  flowLayout.itemSize = CGSizeMake(kPlaceholderCellWidth, itemHeight);
+  flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
+  flowLayout.sectionInset = UIEdgeInsetsZero;
+  flowLayout.minimumInteritemSpacing = 0.0f;
+  flowLayout.minimumLineSpacing = 0.0f;
+  return flowLayout;
+}
+
+- (void)didSelectItemAtIndexPath:(NSIndexPath *)indexPath animateTransition:(BOOL)animate {
+  void (^animationBlock)(void) = ^{
+    [self updateSelectionIndicatorToIndexPath:indexPath];
+  };
+
+  if (animate) {
+    CAMediaTimingFunction *easeInOutFunction =
+        [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionEaseInOut];
+    [UIView mdc_animateWithTimingFunction:easeInOutFunction
+                                 duration:kDefaultAnimationDuration
+                                    delay:0
+                                  options:UIViewAnimationOptionBeginFromCurrentState
+                               animations:animationBlock
+                               completion:nil];
+  } else {
+    animationBlock();
+  }
+
+  _lastSelectedIndexPath = indexPath;
+}
+
+- (void)updateAlignmentAnimated:(BOOL)animated {
+  [self updateScrollProperties];
+  [self updateFlowLayoutMetricsAnimated:animated];
+}
+
+/// Sets _selectionIndicator's bounds and center to display under the item at the given index path
+/// with no animation. May be called from an animation block to animate the transition.
+- (void)updateSelectionIndicatorToIndexPath:(NSIndexPath *)indexPath {
+  if (!indexPath) {
+    return;
+  }
+
+  // Use layout attributes as the cell may not be visible or loaded yet.
+  UICollectionViewLayoutAttributes *attributes =
+      [_flowLayout layoutAttributesForItemAtIndexPath:indexPath];
+
+  // Size selection indicator to a fixed height, equal in width to the selected item's cell.
+  CGRect selectionIndicatorBounds = attributes.bounds;
+  selectionIndicatorBounds.size.height = kSelectionIndicatorHeight;
+
+  // Center selection indicator under cell.
+  CGPoint selectionIndicatorCenter = attributes.center;
+  selectionIndicatorCenter.y =
+      CGRectGetMaxY(_collectionView.bounds) - (kSelectionIndicatorHeight / 2.0f);
+
+  _selectionIndicator.bounds = selectionIndicatorBounds;
+  _selectionIndicator.center = selectionIndicatorCenter;
+}
+
+- (void)updateFlowLayoutMetricsAnimated:(BOOL)animate {
+  void (^animationBlock)() = ^{
+    [self updateFlowLayoutMetrics];
+  };
+
+  if (animate) {
+    CAMediaTimingFunction *easeInOutFunction =
+        [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionEaseInOut];
+    [UIView mdc_animateWithTimingFunction:easeInOutFunction
+                                 duration:kDefaultAnimationDuration
+                                    delay:0.0f
+                                  options:UIViewAnimationOptionBeginFromCurrentState
+                               animations:animationBlock
+                               completion:nil];
+  } else {
+    animationBlock();
+  }
+}
+
+- (void)updateScrollProperties {
+  _collectionView.alwaysBounceHorizontal = (_alignment != MDCItemBarAlignmentJustified);
+}
+
+- (void)updateFlowLayoutMetrics {
+  // Layout metrics cannot be updated while offscreen.
+  if (!self.window) {
+    return;
+  }
+
+  UIUserInterfaceSizeClass horizontalSizeClass = [self horizontalSizeClass];
+
+  UIEdgeInsets newSectionInset = UIEdgeInsetsZero;
+  switch (_alignment) {
+    case MDCItemBarAlignmentLeading:
+      newSectionInset = [self leadingAlignedInsetsForHorizontalSizeClass:horizontalSizeClass];
+      break;
+    case MDCItemBarAlignmentJustified:
+      newSectionInset = [self justifiedInsets];
+      break;
+    case MDCItemBarAlignmentCenter:
+      newSectionInset = [self centeredInsetsForHorizontalSizeClass:horizontalSizeClass];
+      break;
+    case MDCItemBarAlignmentCenterSelected:
+      newSectionInset = [self centerSelectedInsets];
+      break;
+  }
+
+  UIEdgeInsets oldSectionInset = _flowLayout.sectionInset;
+  if (UIEdgeInsetsEqualToEdgeInsets(oldSectionInset, newSectionInset) &&
+      _alignment != MDCItemBarAlignmentJustified) {
+    // No change - can bail early, except when the item alignment is "justified". When justified,
+    // the layout metrics need updating due to change in view size or orientation.
+    return;
+  }
+
+  // Rather than just updating the sectionInset on the existing flowLayout, a new layout object
+  // is created. This gives more control over whether the change is animated or not - as there is
+  // no control when updating flow layout sectionInset (it's always animated).
+  UICollectionViewFlowLayout *flowLayout = [self generatedFlowLayout];
+  flowLayout.sectionInset = newSectionInset;
+  _flowLayout = flowLayout;
+
+  // This is not animated because -updateFlowLayoutMetrics may be called in an animation block and
+  // the change will be still get animated anyway - using NO avoids 'double' animation and allows
+  // this method to be used without animation.
+  NSAssert(_collectionView.window, @"Collection view must be in a window to update layout");
+  [_collectionView setCollectionViewLayout:_flowLayout animated:NO];
+
+  // Update selection indicator to potentially new location and size
+  // Not animated for the same reason as mentioned above.
+  [self updateSelectionIndicatorToIndexPath:_lastSelectedIndexPath];
+
+  _horizontalSizeClassAtLastMetricsUpdate = horizontalSizeClass;
+}
+
+- (UIEdgeInsets)leadingAlignedInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
+  const BOOL isRegular = (sizeClass == UIUserInterfaceSizeClassRegular);
+  const CGFloat inset = isRegular ? kRegularInset : kCompactInset;
+  return UIEdgeInsetsMake(0.0f, inset, 0.0f, inset);
+}
+
+- (UIEdgeInsets)justifiedInsets {
+  // Center items, which will be at most the width of the view.
+  CGFloat itemWidths = [self totalWidthOfAllItems];
+  CGFloat sideInsets = floorf((float)(_collectionView.bounds.size.width - itemWidths) / 2.0f);
+  return UIEdgeInsetsMake(0.0, sideInsets, 0.0, sideInsets);
+}
+
+- (UIEdgeInsets)centeredInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
+  CGFloat itemWidths = [self totalWidthOfAllItems];
+  CGFloat viewWidth = _collectionView.bounds.size.width;
+  UIEdgeInsets insets = [self leadingAlignedInsetsForHorizontalSizeClass:sizeClass];
+  if (itemWidths <= (viewWidth - insets.left - insets.right)) {
+    CGFloat sideInsets = (_collectionView.bounds.size.width - itemWidths) / 2.0f;
+    return UIEdgeInsetsMake(0.0, sideInsets, 0.0, sideInsets);
+  }
+  return insets;
+}
+
+- (UIEdgeInsets)centerSelectedInsets {
+  UIEdgeInsets sectionInset = UIEdgeInsetsZero;
+
+  NSInteger count = [self collectionView:_collectionView numberOfItemsInSection:0];
+  if (count > 0) {
+    CGRect bounds = _collectionView.bounds;
+    CGFloat halfBoundsWidth = bounds.size.width / 2.0f;
+
+    CGSize firstSize = [self collectionView:_collectionView
+                                     layout:_flowLayout
+                     sizeForItemAtIndexPath:[self indexPathForItemAtIndex:0]];
+    CGSize lastSize = [self collectionView:_collectionView
+                                    layout:_flowLayout
+                    sizeForItemAtIndexPath:[self indexPathForItemAtIndex:count - 1]];
+
+    // Left inset is equal to the space to the left of the first item when centered.
+    CGFloat halfFirstWidth = firstSize.width / 2.0f;
+    sectionInset.left = halfBoundsWidth - halfFirstWidth;
+
+    // Right inset is equal to the space to the right of the last item when centered.
+    CGFloat halfLastWidth = lastSize.width / 2.0f;
+    sectionInset.right = halfBoundsWidth - halfLastWidth;
+  }
+  return sectionInset;
+}
+
+- (CGFloat)totalWidthOfAllItems {
+  CGFloat itemWidths = 0;
+  NSInteger count = [self collectionView:_collectionView numberOfItemsInSection:0];
+  for (NSInteger itemIndex = 0; itemIndex < count; itemIndex++) {
+    CGSize itemSize = [self collectionView:_collectionView
+                                    layout:_flowLayout
+                    sizeForItemAtIndexPath:[self indexPathForItemAtIndex:itemIndex]];
+    itemWidths += itemSize.width;
+  }
+  return itemWidths;
+}
+
+- (void)configureCell:(MDCItemBarCell *)cell {
+  // Configure content style
+  [cell applyStyle:_style];
+}
+
+- (void)configureVisibleCells {
+  for (UICollectionViewCell *cell in _collectionView.visibleCells) {
+    if ([cell isKindOfClass:[MDCItemBarCell class]]) {
+      MDCItemBarCell *itemCell = (MDCItemBarCell *)cell;
+      [self configureCell:itemCell];
+    }
+  }
+}
+
+- (void)updateColors {
+  [self configureVisibleCells];
+
+  _selectionIndicator.backgroundColor = _style.selectionIndicatorColor;
+}
+
+- (void)updateSelectionIndicatorVisibility {
+  _selectionIndicator.hidden = !_style.shouldDisplaySelectionIndicator;
+}
+
+@end
+
+#pragma mark -
+
+@implementation MDCItemBarFlowLayout {
+  /// Map from item index paths to RTL-corrected layout attributes. If no RTL correction is in
+  /// effect, this will be set to nil.
+  NSDictionary *_correctedAttributesForIndexPath;
+
+  /// Controls the use of a padded collection view content size.
+  BOOL _isPaddingCollectionViewContentSize;
+
+  /// Collection view content size which will be used if padding is in effect.
+  CGSize _paddedCollectionViewContentSize;
+}
+
+- (void)prepareLayout {
+  [super prepareLayout];
+
+  // Post-process the superclass layout to determine which workarounds need to be applied.
+  BOOL shouldRelayoutAttributesForRTL = [self shouldRelayoutAttributesForRTL];
+  BOOL shouldPadContentSizeForRTL = [self shouldPadContentSizeForRTL];
+
+  // Build a new map of adjusted attributes if needed.
+  if (shouldRelayoutAttributesForRTL || shouldPadContentSizeForRTL) {
+    NSMutableDictionary *newAttributes = [NSMutableDictionary dictionary];
+    const NSInteger sectionCount = self.collectionView.numberOfSections;
+    for (NSInteger sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
+      const NSInteger itemCount = [self.collectionView numberOfItemsInSection:sectionIndex];
+      for (NSInteger itemIndex = 0; itemIndex < itemCount; itemIndex++) {
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:sectionIndex];
+
+        // Must call super here to ensure we get un-corrected attributes.
+        UICollectionViewLayoutAttributes *attributes =
+            [super layoutAttributesForItemAtIndexPath:indexPath];
+
+        // Flip attribute order for RTL. This must happen before padding because attributes are
+        // flipped using the original un-padded bounds.
+        if (shouldRelayoutAttributesForRTL) {
+          attributes = [self flippedAttributesFromAttributes:attributes];
+        }
+
+        // Apply per-item content size padding.
+        if (shouldPadContentSizeForRTL) {
+          attributes = [self paddedAttributesFromAttributes:attributes];
+        }
+
+        newAttributes[indexPath] = attributes;
+      }
+    }
+    _correctedAttributesForIndexPath = newAttributes;
+  } else {
+    // Clear out the map to indicate that no corrections are in effect.
+    _correctedAttributesForIndexPath = nil;
+  }
+
+  // Apply global content size padding.
+  if (shouldPadContentSizeForRTL) {
+    _isPaddingCollectionViewContentSize = YES;
+    _paddedCollectionViewContentSize = self.collectionView.bounds.size;
+  } else {
+    _isPaddingCollectionViewContentSize = NO;
+  }
+}
+
+- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:
+        (NSIndexPath *)indexPath {
+  if (_correctedAttributesForIndexPath) {
+    return _correctedAttributesForIndexPath[indexPath];
+  }
+
+  // No RTL correction needed.
+  return [super layoutAttributesForItemAtIndexPath:indexPath];
+}
+
+- (nullable NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
+  if (_correctedAttributesForIndexPath) {
+    NSPredicate *predicate =
+        [NSPredicate predicateWithBlock:^BOOL(UICollectionViewLayoutAttributes *layoutAttributes,
+                                              NSDictionary *__nullable bindings) {
+          return CGRectIntersectsRect(layoutAttributes.frame, rect);
+        }];
+    return [_correctedAttributesForIndexPath.allValues filteredArrayUsingPredicate:predicate];
+  }
+
+  // No RTL correction needed.
+  return [super layoutAttributesForElementsInRect:rect];
+}
+
+- (CGSize)collectionViewContentSize {
+  if (_isPaddingCollectionViewContentSize) {
+    return _paddedCollectionViewContentSize;
+  }
+  return [super collectionViewContentSize];
+}
+
+- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
+  if (!CGSizeEqualToSize(newBounds.size, self.collectionView.bounds.size)) {
+    // Padding depends on the size of the collection view, need to relayout for size changes.
+    return YES;
+  }
+  return [super shouldInvalidateLayoutForBoundsChange:newBounds];
+}
+
+#pragma mark - Private
+
+/// Computes RTL-flipped attributes given superclass-calculated attributes.
+- (UICollectionViewLayoutAttributes *)flippedAttributesFromAttributes:
+        (UICollectionViewLayoutAttributes *)attributes {
+  UICollectionViewLayoutAttributes *newAttributes = [attributes copy];
+
+  CGRect itemFrame = attributes.frame;
+
+  // Must call super here to ensure we have the original collection bounds.
+  CGRect collectionBounds = {CGPointZero, [super collectionViewContentSize]};
+  newAttributes.frame = MDCRectFlippedForRTL(itemFrame, CGRectGetWidth(collectionBounds),
+                                             UIUserInterfaceLayoutDirectionRightToLeft);
+
+  return newAttributes;
+}
+
+- (BOOL)shouldEnforceRightToLeftLayout {
+  BOOL enforceRTL = NO;
+
+  // Prior to iOS 9 RTL was not automatically applied, so we don't need to apply any fixes.
+  NSOperatingSystemVersion iOS9Version = {9, 0, 0};
+  NSProcessInfo *processInfo = [NSProcessInfo processInfo];
+  if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)] &&
+      [processInfo isOperatingSystemAtLeastVersion:iOS9Version]) {
+    if (self.collectionView.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      enforceRTL = YES;
+    }
+  }
+
+  return enforceRTL;
+}
+
+/// Indicates if the superclass' layout appears to have been layed out in a left-to-right order. If
+/// there are zero or one items total, this always returns NO.
+/// Note: This is used to detect incorrect layouts due to radar 22828797 by detecting the actual
+/// layout ordering from superclass-generated layout frames. When there's no error (item frames are
+/// already arranged RTL), this returns NO. We use this approach for two purposes:
+/// * Robustly detecting the error condition. The bug occurs under specific conditions that would be
+///   difficult to detect reliably, and given item bars are simple linear layouts it's more robust
+///   to detect the error and correct it.
+/// * Automatically disabling this workaround if the underlying bug is fixed in an unknown future OS
+///   version. At time of writing (iOS 9.2) the bug has not been fixed. Detecting the error directly
+///   and correcting it should allow this implementation to continue to produce correct results
+///   without an immediate need for changes.
+- (BOOL)shouldRelayoutAttributesForRTL {
+  // The logic contained here only applies to horizontally-scrolling flow layouts. This should
+  // always be the case for MDCItemBar, but check for safety.
+  NSParameterAssert(self.scrollDirection == UICollectionViewScrollDirectionHorizontal);
+
+  if (![self shouldEnforceRightToLeftLayout]) {
+    return NO;
+  }
+
+  CGRect previousFrame = CGRectNull;
+
+  const NSInteger sectionCount = self.collectionView.numberOfSections;
+  for (NSInteger sectionIndex = 0; sectionIndex < sectionCount; sectionIndex++) {
+    const NSInteger itemCount = [self.collectionView numberOfItemsInSection:sectionIndex];
+    for (NSInteger itemIndex = 0; itemIndex < itemCount; itemIndex++) {
+      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:itemIndex inSection:sectionIndex];
+
+      // Must call super here to ensure we get un-corrected attributes.
+      UICollectionViewLayoutAttributes *attributes =
+          [super layoutAttributesForItemAtIndexPath:indexPath];
+
+      CGRect frame = attributes.frame;
+      // If any adjacent pairs of attributes have centers that are ordered left-to-right, assume the
+      // whole layout is ordered left-to-right.
+      if (!CGRectIsNull(previousFrame) && (CGRectGetMidX(previousFrame) < CGRectGetMidX(frame))) {
+        return YES;
+      }
+
+      // Set up for next iteration.
+      previousFrame = frame;
+    }
+  }
+
+  // There are either fewer than 2 items (in which case order doesn't matter) or the whole thing is
+  // ordered RTL.
+  return NO;
+}
+
+/// Indicates if the collection's content is narrower than the collection view.
+/// Note: This is used to detect conditions under which collection view scrolling bugs happen in RTL
+/// layouts. If and when the underlying bugs are fixed in an unknown future iOS version, this method
+/// will continue to return YES and trigger harmless but unnecessary workarounds.
+- (BOOL)shouldPadContentSizeForRTL {
+  if (![self shouldEnforceRightToLeftLayout]) {
+    return NO;
+  }
+
+  // When the content is narrower than the scroll view bounds, we need to pad all attribute frames
+  // on the left to prevent the layout from "jumping" to the origin under various situations.
+  // Must call super here to ensure we have the original collection content size.
+  CGSize contentSize = [super collectionViewContentSize];
+  CGRect scrollBounds = self.collectionView.bounds;
+  return contentSize.width < CGRectGetWidth(scrollBounds);
+}
+
+- (UICollectionViewLayoutAttributes *)paddedAttributesFromAttributes:
+        (UICollectionViewLayoutAttributes *)attributes {
+  // Must call super here to ensure we have the original collection content size.
+  CGSize contentSize = [super collectionViewContentSize];
+  CGRect scrollBounds = self.collectionView.bounds;
+
+  CGFloat leftPadding = CGRectGetWidth(scrollBounds) - contentSize.width;
+
+  UICollectionViewLayoutAttributes *newAttributes = [attributes copy];
+
+  // Shift frame to the right to counteract the content size width expansion.
+  CGRect itemFrame = attributes.frame;
+  itemFrame.origin.x += leftPadding;
+
+  newAttributes.frame = itemFrame;
+
+  return newAttributes;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h
new file mode 100644
index 0000000..b3a6412
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarAlignment.h
@@ -0,0 +1,35 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/** Alignment styles for items in a tab bar. */
+typedef NS_ENUM(NSInteger, MDCItemBarAlignment) {
+  /** Items are aligned on the leading edge and sized to fit their content. */
+  MDCItemBarAlignmentLeading,
+
+  /** Items are justified to equal size across the width of the screen. */
+  MDCItemBarAlignmentJustified,
+
+  /**
+   * Items are sized to fit their content and center-aligned as a group. If they do not fit in view,
+   * they will be leading-aligned instead.
+   */
+  MDCItemBarAlignmentCenter,
+
+  /** Items are center-aligned on the selected item. */
+  MDCItemBarAlignmentCenterSelected,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h
new file mode 100644
index 0000000..c734a40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.h
@@ -0,0 +1,50 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCItemBarStyle;
+
+/** View displaying an individual item in an item bar. */
+@interface MDCItemBarCell : UICollectionViewCell
+
+/** Returns the optimal size for the item with the given size class and content view object. */
++ (CGSize)sizeThatFits:(CGSize)size
+    horizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass
+                   item:(nonnull UITabBarItem *)item
+                  style:(nonnull MDCItemBarStyle *)style;
+
+/** Returns the additional insets applied outside item content for the given size class. */
++ (UIEdgeInsets)edgeInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass;
+
+/** Title for the tab. Defaults to the empty string. */
+@property(nonatomic, copy, nonnull) NSString *title;
+
+/** Image shown on the tab. Defaults to nil. */
+@property(nonatomic, strong, nullable) UIImage *image;
+
+/** Text displayed in upper-right corner of the tab. Uses title color. */
+@property(nonatomic, copy, nullable) NSString *badgeValue;
+
+/** Updates the cell to use the given style properties. */
+- (void)applyStyle:(nonnull MDCItemBarStyle *)itemStyle;
+
+/** Updates the cell to display the given item. */
+- (void)updateWithItem:(nonnull UITabBarItem *)item
+               atIndex:(NSInteger)itemIndex
+                 count:(NSInteger)itemCount;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.m
new file mode 100644
index 0000000..049924d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarCell.m
@@ -0,0 +1,562 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCItemBarCell.h"
+
+#import "MDCItemBarStringConstants.h"
+#import "MDCItemBarStyle.h"
+#import "MaterialAnimationTiming.h"
+#import "MaterialInk.h"
+#import "MaterialRTL.h"
+#import "MaterialTypography.h"
+
+/// Padding between the bottom of the cell and its content, in points.
+static const CGFloat kBottomPadding = 20.0f;
+
+/// Size of image in points.
+static const CGSize kImageSize = {24, 24};
+
+/// Font point size for badges.
+static const CGFloat kBadgeFontSize = 12;
+
+/// Padding between top of the cell and the badge.
+static const CGFloat kBadgeTopPadding = 6;
+
+/// Maximum width of a badge. This allows for 3 characters before truncation.
+static const CGFloat kBadgeMaxWidth = 22;
+
+/// File name of the bundle (without the '.bundle' extension) containing resources.
+static NSString *const kResourceBundleName = @"MaterialTabs";
+
+/// String table name containing localized strings.
+static NSString *const kStringTableName = @"MaterialTabs";
+
+/// Scale factor applied to the title of bottom navigation items when selected.
+const CGFloat kSelectedNavigationTitleScaleFactor = (16.0f / 14.0f);
+
+/// Vertical translation applied to image components bottom navigation items when selected.
+const CGFloat kSelectedNavigationImageYOffset = -2;
+
+/// Duration of selection animations in applicable content styles.
+static const NSTimeInterval kSelectionAnimationDuration = 0.3f;
+
+@implementation MDCItemBarCell {
+  UILabel *_titleLabel;
+  UIImageView *_imageView;
+  UILabel *_badgeLabel;
+  MDCInkTouchController *_inkTouchController;
+
+  MDCItemBarStyle *_style;
+
+  NSInteger _itemIndex;
+  NSInteger _itemCount;
+}
+
+#pragma mark - Init
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    _style = [[MDCItemBarStyle alloc] init];
+    _title = @"";
+    _itemIndex = NSNotFound;
+
+    self.isAccessibilityElement = YES;
+
+    // Create initial subviews
+    [self updateSubviews];
+
+    // Set up ink controller to splash ink on taps.
+    _inkTouchController = [[MDCInkTouchController alloc] initWithView:self];
+    [_inkTouchController addInkView];
+
+    [self updateInk];
+    [self updateColors];
+    [self updateTransformsAnimated:NO];
+  }
+  return self;
+}
+
+#pragma mark - Public
+
++ (UIEdgeInsets)edgeInsetsForHorizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass {
+  // Padding from spec: https://www.google.com/design/spec/components/tabs.html
+  CGFloat outerPadding = (sizeClass == UIUserInterfaceSizeClassRegular) ? 24.0f : 12.0f;
+  return UIEdgeInsetsMake(0.0, outerPadding, 0.0, outerPadding);
+}
+
++ (CGSize)sizeThatFits:(CGSize)size
+    horizontalSizeClass:(UIUserInterfaceSizeClass)sizeClass
+                   item:(UITabBarItem *)item
+                  style:(MDCItemBarStyle *)style {
+  UIEdgeInsets insets = [self edgeInsetsForHorizontalSizeClass:sizeClass];
+  NSString *title = [self displayedTitleForTitle:item.title style:style];
+
+  CGRect textBounds = CGRectZero;
+
+  // Only compute text bounding rect if necessary (all except image-only items)
+  if (style.shouldDisplayTitle) {
+    UIFont *font = style.titleFont;
+    NSDictionary *titleAttributes = @{NSFontAttributeName : font};
+    textBounds = [title boundingRectWithSize:size
+                                     options:NSStringDrawingTruncatesLastVisibleLine
+                                  attributes:titleAttributes
+                                     context:nil];
+  }
+
+  CGRect badgeBounds = CGRectZero;
+
+  // Only compute badge bounding rect if necessary.
+  NSString *badge = item.badgeValue;
+  if (style.shouldDisplayBadge && badge.length > 0) {
+    UIFont *badgeFont = [[MDCTypography fontLoader] regularFontOfSize:kBadgeFontSize];
+    NSDictionary *badgeAttributes = @{NSFontAttributeName : badgeFont};
+    badgeBounds = [badge boundingRectWithSize:size
+                                      options:NSStringDrawingTruncatesLastVisibleLine
+                                   attributes:badgeAttributes
+                                      context:nil];
+  }
+
+  // Determine size based on content style.
+  CGRect bounds = CGRectZero;
+  if (style.shouldDisplayTitle) {
+    if (style.shouldDisplayImage) {
+      // Title and image
+      bounds.size.width = MAX(textBounds.size.width, kImageSize.width + badgeBounds.size.width * 2);
+      bounds.size.height = textBounds.size.height + style.titleImagePadding + kImageSize.height;
+    } else {
+      // Just title
+      bounds = textBounds;
+    }
+  } else {
+    if (style.shouldDisplayImage) {
+      // Image only.
+      bounds.size = kImageSize;
+      bounds.size.width += badgeBounds.size.width * 2;
+    } else {
+      // No image or title: NOP.
+    }
+  }
+
+  // Constrain to provided width.
+  bounds.size.width = MIN(bounds.size.width, size.width);
+
+  // Add insets.
+  bounds.size.width += insets.left + insets.right;
+  bounds.size.height += insets.top + insets.bottom;
+
+  // Snap to integral coordinates.
+  bounds = CGRectIntegral(bounds);
+  return bounds.size;
+}
+
+- (void)setTitle:(NSString *)title {
+  _title = [title copy];
+  [self updateDisplayedTitle];
+}
+
+- (void)setImage:(nullable UIImage *)image {
+  _image = image;
+  [self updateDisplayedImage];
+}
+
+- (void)setBadgeValue:(nullable NSString *)badgeValue {
+  _badgeValue = [badgeValue copy];
+  _badgeLabel.text = badgeValue;
+  [self setNeedsLayout];
+}
+
+- (void)applyStyle:(MDCItemBarStyle *)style {
+  if (style != _style && ![style isEqual:_style]) {
+    _style = style;
+
+    [self updateDisplayedTitle];
+    [self updateTitleTextColor];
+    [self updateInk];
+    [self updateSubviews];
+    [self updateTitleFont];
+    [self updateTransformsAnimated:NO];
+    [self setNeedsLayout];
+  }
+}
+
+- (void)updateWithItem:(UITabBarItem *)item
+               atIndex:(NSInteger)itemIndex
+                 count:(NSInteger)itemCount {
+  self.title = item.title;
+  self.image = item.image;
+  self.badgeValue = item.badgeValue;
+  self.accessibilityIdentifier = item.accessibilityIdentifier;
+
+  _itemIndex = itemIndex;
+  _itemCount = itemCount;
+}
+
+#pragma mark - UIView
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  UIEdgeInsets insets = [[self class] minimumEdgeInsets];
+  CGRect contentBounds = UIEdgeInsetsInsetRect(self.contentView.bounds, insets);
+
+  CGPoint imageCenter = CGPointZero;
+  CGPoint titleCenter = CGPointZero;
+  CGPoint badgeCenter = CGPointZero;
+  CGRect imageBounds = CGRectZero;
+  CGRect titleBounds = CGRectZero;
+  CGRect badgeBounds = CGRectZero;
+
+  // Image has a fixed size and is horizontally centered, regardless of content style.
+  imageBounds.size = kImageSize;
+  imageCenter.x = (float)round(CGRectGetMidX(contentBounds));
+
+  CGSize titleSize = [_titleLabel sizeThatFits:contentBounds.size];
+  titleSize.width = MIN(titleSize.width, CGRectGetWidth(contentBounds));
+
+  // Title is a fixed height based on content and is placed full-width, regardless of content style.
+  titleCenter.x = roundf((float)CGRectGetMidX(contentBounds));
+  titleBounds.size.width = ceilf((float)CGRectGetWidth(contentBounds));
+  titleBounds.size.height = ceilf((float)titleSize.height);
+
+  // Horizontally align the badge.
+  CGSize badgeSize = [_badgeLabel sizeThatFits:contentBounds.size];
+  badgeSize.width = MIN(kBadgeMaxWidth, badgeSize.width);
+  badgeBounds.size = badgeSize;
+
+  if (_style.shouldDisplayBadge) {
+    CGFloat badgeOffset = ((float)imageBounds.size.width / 2.0f) + ((float)badgeSize.width / 2.0f);
+    if (self.mdc_effectiveUserInterfaceLayoutDirection ==
+        UIUserInterfaceLayoutDirectionRightToLeft) {
+      badgeOffset *= -1;
+    }
+
+    badgeCenter.x = imageCenter.x + badgeOffset;
+    badgeCenter.y = kBadgeTopPadding + ((float)badgeSize.height / 2.0f);
+  }
+
+  // Place components vertically
+  if (_style.shouldDisplayTitle) {
+    if (_style.shouldDisplayImage) {
+      // Image and title, center both vertically together.
+      const CGFloat padding = _style.titleImagePadding;
+      const CGFloat totalHeight = titleSize.height + padding + kImageSize.height;
+      const CGFloat yOrigin = (float)round(CGRectGetMidY(contentBounds) - totalHeight / 2.0f);
+      imageCenter.y = yOrigin + ((float)kImageSize.height / 2.0f);
+      titleCenter.y = yOrigin + kImageSize.height + padding + ((float)titleSize.height / 2.0f);
+      titleCenter.y = roundf((float)titleCenter.y);
+
+    } else {
+      // Title only, center vertically.
+      // +1 for slight adjustment to font baseline for centered title labels.
+      const CGFloat centeredTitleYOffset = 1.0f;
+      titleCenter.y = contentBounds.size.height - kBottomPadding - titleSize.height +
+                      centeredTitleYOffset + ((float)titleSize.height / 2.0f);
+      titleCenter.y = roundf((float)titleCenter.y);
+    }
+  } else {
+    if (_style.shouldDisplayImage) {
+      // Image only, center image vertically
+      imageCenter.y = (float)round(CGRectGetMidY(contentBounds));
+    } else {
+      // Nothing: NOP
+    }
+  }
+
+  _imageView.center = imageCenter;
+  _imageView.bounds = imageBounds;
+
+  _badgeLabel.center = badgeCenter;
+  _badgeLabel.bounds = badgeBounds;
+
+  _titleLabel.center = titleCenter;
+  _titleLabel.bounds = titleBounds;
+}
+
+- (void)tintColorDidChange {
+  [super tintColorDidChange];
+
+  [self updateTitleTextColor];
+}
+
+- (void)didMoveToWindow {
+  [super didMoveToWindow];
+
+  if (self.window) {
+    [self updateTransformsAnimated:NO];
+  }
+}
+
+#pragma mark - UICollectionReusableView
+
+- (void)prepareForReuse {
+  [super prepareForReuse];
+  [self updateTitleTextColor];
+  [self updateAccessibilityTraits];
+  [_inkTouchController cancelInkTouchProcessing];
+}
+
+#pragma mark - UICollectionViewCell
+
+- (void)setSelected:(BOOL)selected {
+  // Do not animate if selected is being set before the cell is in the view hierarchy.
+  BOOL animate = (self.window != nil);
+
+  [super setSelected:selected];
+  [self updateTitleTextColor];
+  [self updateAccessibilityTraits];
+  [self updateTransformsAnimated:animate];
+}
+
+- (void)setHighlighted:(BOOL)highlighted {
+  [super setHighlighted:highlighted];
+  [self updateTitleTextColor];
+}
+
+#pragma mark - UIAccessibility
+
+- (nullable NSString *)accessibilityLabel {
+  NSMutableArray *labelComponents = [NSMutableArray array];
+
+  // Use untransformed title as accessibility label to ensure accurate reading.
+  NSString *titleComponent = _title;
+  if (titleComponent.length > 0) {
+    [labelComponents addObject:titleComponent];
+  }
+
+  if (_badgeValue.length > 0 && !_badgeLabel.hidden) {
+    [labelComponents addObject:_badgeValue];
+  }
+
+  // Describe as "tab, X of Y"
+  NSString *tabLabel =
+      [[self class] localizedStringWithKey:kMDCItemBarStringKeyAccessibilityTabElementLabel];
+  if (tabLabel) {
+    [labelComponents addObject:tabLabel];
+  }
+
+  NSString *positionFormat =
+      [[self class] localizedStringWithKey:kMDCItemBarStringKeyAccessibilityTabPositionFormat];
+  if (positionFormat) {
+    if (_itemIndex != NSNotFound && _itemCount > 0) {
+      int position = (int)(_itemIndex + 1);
+      NSString *localizedPosition =
+          [NSString localizedStringWithFormat:positionFormat, position, (int)_itemCount];
+      [labelComponents addObject:localizedPosition];
+    }
+  }
+
+  // Speak components with a pause in between.
+  return [labelComponents componentsJoinedByString:@", "];
+}
+
+#pragma mark - Private
+
++ (UIEdgeInsets)minimumEdgeInsets {
+  const CGFloat outerPadding = 2.0f;
+  return UIEdgeInsetsMake(0.0, outerPadding, 0.0, outerPadding);
+}
+
++ (NSString *)localizedStringWithKey:(NSString *)key {
+  NSBundle *containingBundle = [NSBundle bundleForClass:self];
+  NSURL *resourceBundleURL =
+      [containingBundle URLForResource:kResourceBundleName withExtension:@"bundle"];
+  NSBundle *resourceBundle = [NSBundle bundleWithURL:resourceBundleURL];
+  return [resourceBundle localizedStringForKey:key value:nil table:kStringTableName];
+}
+
++ (NSString *)displayedTitleForTitle:(NSString *)title style:(MDCItemBarStyle *)style {
+  NSString *displayedTitle = title;
+  if (style.displaysUppercaseTitles) {
+    displayedTitle = [displayedTitle uppercaseStringWithLocale:nil];
+  }
+  return displayedTitle;
+}
+
+- (UIUserInterfaceSizeClass)horizontalSizeClass {
+  // Use trait collection's horizontalSizeClass if available.
+  if ([self respondsToSelector:@selector(traitCollection)]) {
+    return self.traitCollection.horizontalSizeClass;
+  }
+
+  // Pre-iOS 8: Use fixed size class for device.
+  const BOOL isPad = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad;
+  return isPad ? UIUserInterfaceSizeClassRegular : UIUserInterfaceSizeClassCompact;
+}
+
+/// Ensures that subviews exist and have the correct visibility for the current content style.
+- (void)updateSubviews {
+  if (_style.shouldDisplayImage) {
+    // Create image view if needed.
+    if (!_imageView) {
+      _imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
+      _imageView.contentMode = UIViewContentModeCenter;
+      [self.contentView addSubview:_imageView];
+
+      // Display our image in the new image view.
+      [self updateDisplayedImage];
+    }
+
+    _imageView.hidden = NO;
+  } else {
+    _imageView.hidden = YES;
+  }
+
+  if (_style.shouldDisplayTitle) {
+    // Create title label if needed.
+    if (!_titleLabel) {
+      CGRect titleFrame = self.contentView.bounds;
+      _titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
+      _titleLabel.autoresizingMask =
+          UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
+      _titleLabel.numberOfLines = 1;
+      _titleLabel.textAlignment = NSTextAlignmentCenter;
+
+      [self.contentView addSubview:_titleLabel];
+
+      // Display title and update color for the new label.
+      [self updateDisplayedTitle];
+      [self updateTitleTextColor];
+      [self updateTitleFont];
+    }
+
+    _titleLabel.hidden = NO;
+  } else {
+    _titleLabel.hidden = YES;
+  }
+
+  if (_style.shouldDisplayBadge) {
+    if (!_badgeLabel) {
+      _badgeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+      _badgeLabel.numberOfLines = 1;
+      _badgeLabel.font = [[MDCTypography fontLoader] regularFontOfSize:kBadgeFontSize];
+      [self.contentView addSubview:_badgeLabel];
+      _badgeLabel.text = _badgeValue;
+    }
+    _badgeLabel.hidden = NO;
+  } else {
+    _badgeLabel.hidden = YES;
+  }
+}
+
+- (void)updateColors {
+  [self updateTitleTextColor];
+  [self updateInk];
+}
+
+- (void)updateTitleTextColor {
+  UIColor *textColor = _style.titleColor;
+  if (self.isHighlighted || self.isSelected) {
+    textColor = _style.selectedTitleColor;
+  }
+  _titleLabel.textColor = textColor;
+  _badgeLabel.textColor = textColor;
+  _imageView.tintColor = textColor;
+}
+
+- (void)updateTransformsAnimated:(BOOL)animated {
+  CGAffineTransform titleTransform = CGAffineTransformIdentity;
+  CGAffineTransform imageTransform = CGAffineTransformIdentity;
+
+  UIScreen *screen = self.window.screen;
+  const CGFloat screenScale = (screen ? screen.scale : 1);
+  CGFloat titleContentsScale = screenScale;
+
+  // Apply transforms to the selected item if appropriate.
+  if (_style.shouldGrowOnSelection) {
+    const CGFloat titleScaleFactor = self.selected ? kSelectedNavigationTitleScaleFactor : 1;
+    const CGFloat imageYTransform = self.selected ? kSelectedNavigationImageYOffset : 0;
+
+    /// Vertical offset in points from the bottom of the label to its baseline.
+    const CGFloat titleBaselineOffset = 3.5;
+
+    // Scale title up from the baseline.
+    titleTransform = CGAffineTransformMakeTranslation(0, titleBaselineOffset);
+    titleTransform = CGAffineTransformScale(titleTransform, titleScaleFactor, titleScaleFactor);
+    titleTransform = CGAffineTransformTranslate(titleTransform, 0, -titleBaselineOffset);
+
+    // Shift image up by a small amount.
+    imageTransform = CGAffineTransformMakeTranslation(0, imageYTransform);
+
+    // Render the title with a higher contents scale to reduce aliasing after the scale.
+    titleContentsScale = ceilf((float)(titleScaleFactor * screenScale));
+  }
+
+  void (^performAnimations)(void) = ^{
+    // Update the title scale and redraw if it'll be ending at a higher scale
+    // to minimize aliasing during animation.
+    if (titleContentsScale > _titleLabel.layer.contentsScale) {
+      _titleLabel.layer.contentsScale = titleContentsScale;
+      [_titleLabel setNeedsDisplay];
+    }
+
+    // Set the transforms.
+    _titleLabel.transform = titleTransform;
+    _badgeLabel.transform = imageTransform;
+    _imageView.transform = imageTransform;
+  };
+  void (^completeAnimations)(BOOL) = ^(BOOL finished) {
+    if (titleContentsScale != _titleLabel.layer.contentsScale) {
+      // Update the title with the final contents scale and redraw.
+      _titleLabel.layer.contentsScale = titleContentsScale;
+      [_titleLabel setNeedsDisplay];
+    }
+  };
+
+  if (animated) {
+    CAMediaTimingFunction *translateTimingFunction =
+        [CAMediaTimingFunction mdc_functionWithType:MDCAnimationTimingFunctionTranslate];
+    [UIView mdc_animateWithTimingFunction:translateTimingFunction
+                                 duration:kSelectionAnimationDuration
+                                    delay:0
+                                  options:0
+                               animations:performAnimations
+                               completion:completeAnimations];
+  } else {
+    performAnimations();
+    completeAnimations(YES);
+  }
+}
+
+- (void)updateTitleFont {
+  _titleLabel.font = _style.titleFont;
+}
+
+- (void)updateInk {
+  MDCInkView *inkView = _inkTouchController.defaultInkView;
+  inkView.inkColor = _style.inkColor;
+  inkView.inkStyle = _style.inkStyle;
+}
+
+- (void)updateAccessibilityTraits {
+  if (self.isSelected) {
+    self.accessibilityTraits |= UIAccessibilityTraitSelected;
+  } else {
+    self.accessibilityTraits &= ~UIAccessibilityTraitSelected;
+  }
+}
+
+- (void)updateDisplayedImage {
+  _imageView.image = _image;
+}
+
+- (void)updateDisplayedTitle {
+  if (!_titleLabel.hidden) {
+    _titleLabel.text = [[self class] displayedTitleForTitle:_title style:_style];
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h
new file mode 100644
index 0000000..a23785a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStringConstants.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+static NSString *const kMDCItemBarStringKeyAccessibilityTabElementLabel =
+    @"MaterialTabsAccessibilityTabElementLabel";
+
+static NSString *const kMDCItemBarStringKeyAccessibilityTabPositionFormat =
+    @"MaterialTabsAccessibilityTabPositionFormat";
+
+static NSString *const kMDCItemBarStringsTableName = @"MaterialTabs";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h
new file mode 100644
index 0000000..e892b3e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.h
@@ -0,0 +1,76 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialInk.h"
+
+/** Describes the visual style of individual items in an item bar. */
+@interface MDCItemBarStyle : NSObject <NSCopying>
+
+/** The default height of the bar. */
+@property(nonatomic) CGFloat defaultHeight;
+
+/** Determines if the selection indicator bar should be shown. */
+@property(nonatomic) BOOL shouldDisplaySelectionIndicator;
+
+/** Color used for the selection indicator bar which indicates the selected item. */
+@property(nonatomic, strong, nullable) UIColor *selectionIndicatorColor;
+
+/** The maximum width for individual items within the bar. If zero, items have no maximum width. */
+@property(nonatomic) CGFloat maximumItemWidth;
+
+#pragma mark - Item Style
+
+/** Indicates if the title should be displayed. */
+@property(nonatomic) BOOL shouldDisplayTitle;
+
+/** Indicates if the image should be displayed. */
+@property(nonatomic) BOOL shouldDisplayImage;
+
+/** Indicates if a badge may be shown. */
+@property(nonatomic) BOOL shouldDisplayBadge;
+
+/** Indicates if the cell's components should grow slightly when selected. (Bottom navigation) */
+@property(nonatomic) BOOL shouldGrowOnSelection;
+
+/** Color of title text when not selected. Default is opaque white. */
+@property(nonatomic, strong, nonnull) UIColor *titleColor;
+
+/** Color of title text when selected. Default is opaque white. */
+@property(nonatomic, strong, nonnull) UIColor *selectedTitleColor;
+
+/** Font used for item titles. */
+@property(nonatomic, nonnull) UIFont *titleFont;
+
+/** Style of ink animations on item interaction. */
+@property(nonatomic) MDCInkStyle inkStyle;
+
+/** Color of ink splashes. Default is 25% white. */
+@property(nonatomic, strong, nonnull) UIColor *inkColor;
+
+/** Padding in points between the title and image components, according to the MD spec. */
+@property(nonatomic) CGFloat titleImagePadding;
+
+/**
+ Indicates if all tab titles should be uppercased for display. If NO, item titles will be
+ displayed verbatim.
+
+ Default is YES and is recommended whenever possible.
+ */
+@property(nonatomic) BOOL displaysUppercaseTitles;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.m
new file mode 100644
index 0000000..fdd4947
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Tabs/src/private/MDCItemBarStyle.m
@@ -0,0 +1,54 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCItemBarStyle.h"
+
+@implementation MDCItemBarStyle
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _titleColor = [UIColor whiteColor];
+    _displaysUppercaseTitles = YES;
+    _shouldDisplayTitle = YES;
+    _shouldDisplaySelectionIndicator = YES;
+  }
+  return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+  MDCItemBarStyle *newStyle = [[[self class] alloc] init];
+
+  newStyle.defaultHeight = _defaultHeight;
+  newStyle.shouldDisplaySelectionIndicator = _shouldDisplaySelectionIndicator;
+  newStyle.selectionIndicatorColor = _selectionIndicatorColor;
+  newStyle.maximumItemWidth = _maximumItemWidth;
+  newStyle.shouldDisplayTitle = _shouldDisplayTitle;
+  newStyle.shouldDisplayImage = _shouldDisplayImage;
+  newStyle.shouldDisplayBadge = _shouldDisplayBadge;
+  newStyle.shouldGrowOnSelection = _shouldGrowOnSelection;
+  newStyle.titleColor = _titleColor;
+  newStyle.selectedTitleColor = _selectedTitleColor;
+  newStyle.titleFont = _titleFont;
+  newStyle.inkStyle = _inkStyle;
+  newStyle.inkColor = _inkColor;
+  newStyle.titleImagePadding = _titleImagePadding;
+  newStyle.displaysUppercaseTitles = _displaysUppercaseTitles;
+
+  return newStyle;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCFontTextStyle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCFontTextStyle.h
new file mode 100644
index 0000000..4b8c2fb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCFontTextStyle.h
@@ -0,0 +1,37 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ Material font text styles
+
+ These styles are defined in:
+ https://material.io/guidelines/style/typography.html
+ This enumeration is a set of semantic descriptions intended to describe the fonts returned by
+ + [UIFont mdc_preferredFontForMaterialTextStyle:]
+ + [UIFontDescriptor mdc_preferredFontDescriptorForMaterialTextStyle:]
+ */
+typedef NS_ENUM(NSInteger, MDCFontTextStyle) {
+  MDCFontTextStyleBody1,
+  MDCFontTextStyleBody2,
+  MDCFontTextStyleCaption,
+  MDCFontTextStyleHeadline,
+  MDCFontTextStyleSubheadline,
+  MDCFontTextStyleTitle,
+  MDCFontTextStyleDisplay1,
+  MDCFontTextStyleDisplay2,
+  MDCFontTextStyleDisplay3,
+  MDCFontTextStyleDisplay4,
+  MDCFontTextStyleButton,
+};
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCTypography.h
new file mode 100644
index 0000000..5949cc7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCTypography.h
@@ -0,0 +1,188 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ MDCTypography uses this protocol to delegate responsibility of loading the custom fonts.
+
+ The spec defines the Roboto font family and uses three fonts in the named styles. Use this
+ protocol to define your own fonts if there is a brand need.
+
+ @see https://www.google.com/design/spec/style/typography.html#typography-styles
+ */
+@protocol MDCTypographyFontLoading <NSObject>
+@required
+
+/** Asks the receiver to return a font with a light weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)lightFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return a font with a normal weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)regularFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return a font with a medium weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)mediumFontOfSize:(CGFloat)fontSize;
+
+@optional
+
+/** Asks the receiver to return a font with a bold weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)boldFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return an italic font. FontSize must be larger tha 0. */
+- (nonnull UIFont *)italicFontOfSize:(CGFloat)fontSize;
+
+/** Asks the receiver to return a font with an italic bold weight. FontSize must be larger tha 0. */
+- (nonnull UIFont *)boldItalicFontOfSize:(CGFloat)fontSize;
+
+/** Returns a bold version of the specified font. */
+- (nonnull UIFont *)boldFontFromFont:(nonnull UIFont *)font;
+
+/** Returns an italic version of the specified font. */
+- (nonnull UIFont *)italicFontFromFont:(nonnull UIFont *)font;
+/**
+ Asks the receiver to determine if a particular font would be considered "large" for the purposes of
+ calculating contrast ratios.
+
+ Large fonts are defined as greater than 18pt normal or 14pt bold. If the passed font is nil, then
+ this method returns NO.
+ For more see: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
+
+ @param font The font to examine, or nil.
+ @return YES if the font is non-nil and is considered "large".
+ */
+- (BOOL)isLargeForContrastRatios:(nonnull UIFont *)font;
+
+@end
+
+/**
+ Typographic constants and helpers.
+
+ To use these fonts, you must add MaterialTypography.bundle to your target.
+
+ @see https://www.google.com/design/spec/style/typography.html#typography-styles
+ */
+@interface MDCTypography : NSObject
+
+#pragma mark - Font loader access
+
+/** Set the font loader in order to use a non-system font. */
++ (void)setFontLoader:(nonnull id<MDCTypographyFontLoading>)fontLoader;
+
+/** Get the current font loader. */
++ (nonnull id<MDCTypographyFontLoading>)fontLoader;
+
+#pragma mark - Display fonts (extra large fonts)
+
+/** Returns the display 4 font. (largest of the display font sizes) */
++ (nonnull UIFont *)display4Font;
+
+/** Returns the recommended opacity of black text for the display fonts 4. */
++ (CGFloat)display4FontOpacity;
+
+/** Returns the display 3 font. (second largest of the display font sizes) */
++ (nonnull UIFont *)display3Font;
+
+/** Returns the recommended opacity of black text for the display fonts 3. */
++ (CGFloat)display3FontOpacity;
+
+/** Returns the display 2 font. (third largest of the display font sizes) */
++ (nonnull UIFont *)display2Font;
+
+/** Returns the recommended opacity of black text for the display fonts 2. */
++ (CGFloat)display2FontOpacity;
+
+/** Returns the display 1 font. (smallest of the display font sizes) */
++ (nonnull UIFont *)display1Font;
+
+/** Returns the recommended opacity of black text for the display fonts 1. */
++ (CGFloat)display1FontOpacity;
+
+#pragma mark - Common UI fonts
+
+/** Returns the headline font. */
++ (nonnull UIFont *)headlineFont;
+
+/** Returns the recommended opacity of black text for the headline font. */
++ (CGFloat)headlineFontOpacity;
+
+/** Returns the title font. */
++ (nonnull UIFont *)titleFont;
+
+/** Returns the recommended opacity of black text for the title font. */
++ (CGFloat)titleFontOpacity;
+
+/** Returns the subhead font. (subtitle) */
++ (nonnull UIFont *)subheadFont;
+
+/** Returns the recommended opacity of black text for the subhead font. */
++ (CGFloat)subheadFontOpacity;
+
+/** Returns the body 2 text font. (bold text) */
++ (nonnull UIFont *)body2Font;
+
+/** Returns the recommended opacity of black text for the body 2 font. */
++ (CGFloat)body2FontOpacity;
+
+/** Returns the body 1 text font. (normal text) */
++ (nonnull UIFont *)body1Font;
+
+/** Returns the recommended opacity of black text for the body 1 font. */
++ (CGFloat)body1FontOpacity;
+
+/** Returns the caption font. (a small font for image captions) */
++ (nonnull UIFont *)captionFont;
+
+/** Returns the recommended opacity of black text for the caption font. */
++ (CGFloat)captionFontOpacity;
+
+/** Returns a font for buttons. */
++ (nonnull UIFont *)buttonFont;
+
+/** Returns the recommended opacity of black text for the button font. */
++ (CGFloat)buttonFontOpacity;
+
+/** Returns a bold version of the specified font. */
++ (nonnull UIFont *)boldFontFromFont:(nonnull UIFont *)font;
+
+/** Returns an italic version of the specified font. */
++ (nonnull UIFont *)italicFontFromFont:(nonnull UIFont *)font;
+
+/**
+ Asks the receiver to determine if a particular font would be considered "large" for the purposes of
+ calculating contrast ratios.
+
+ Large fonts are defined as greater than 18pt normal or 14pt bold. If the passed font is nil, then
+ this method returns NO.
+ For more see: https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
+
+ @param font The font to examine.
+ @return YES if the font is non-nil and is considered "large".
+ */
++ (BOOL)isLargeForContrastRatios:(nonnull UIFont *)font;
+
+@end
+
+/**
+ MDCSystemFontLoader allows you to use the system font for @c MDCTypography.
+
+ #### Example
+
+ ```
+ [MDCTypography setFontLoader:[[MDCSystemFontLoader alloc] init]];
+ ```
+ */
+@interface MDCSystemFontLoader : NSObject <MDCTypographyFontLoading>
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCTypography.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCTypography.m
new file mode 100644
index 0000000..0c02d82
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MDCTypography.m
@@ -0,0 +1,259 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCTypography.h"
+#import "private/UIFont+MaterialTypographyPrivate.h"
+
+static id<MDCTypographyFontLoading> gFontLoader = nil;
+const CGFloat MDCTypographyStandardOpacity = 0.87f;
+const CGFloat MDCTypographySecondaryOpacity = 0.54f;
+
+@implementation MDCTypography
+
+#pragma mark - Font loader access
+
++ (void)setFontLoader:(id<MDCTypographyFontLoading>)fontLoader {
+  gFontLoader = fontLoader;
+  NSAssert(gFontLoader,
+           @"Font loader can't be null. The font loader will be reset to the default font loader.");
+  if (!gFontLoader) {
+    gFontLoader = [self defaultFontLoader];
+  }
+}
+
++ (id<MDCTypographyFontLoading>)fontLoader {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    if (!gFontLoader) {
+      gFontLoader = [self defaultFontLoader];
+    }
+  });
+  return gFontLoader;
+}
+
+#pragma mark - Display fonts (extra large fonts)
+
++ (UIFont *)display4Font {
+  return [[self fontLoader] lightFontOfSize:112];
+}
+
++ (CGFloat)display4FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)display3Font {
+  return [[self fontLoader] regularFontOfSize:56];
+}
+
++ (CGFloat)display3FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)display2Font {
+  return [[self fontLoader] regularFontOfSize:45];
+}
+
++ (CGFloat)display2FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)display1Font {
+  return [[self fontLoader] regularFontOfSize:34];
+}
+
++ (CGFloat)display1FontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
+#pragma mark - Common UI fonts.
+
++ (UIFont *)headlineFont {
+  return [[self fontLoader] regularFontOfSize:24];
+}
+
++ (CGFloat)headlineFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)titleFont {
+  return [[self fontLoader] mediumFontOfSize:20];
+}
+
++ (CGFloat)titleFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)subheadFont {
+  return [[self fontLoader] regularFontOfSize:16];
+}
+
++ (CGFloat)subheadFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)body2Font {
+  return [[self fontLoader] mediumFontOfSize:14];
+}
+
++ (CGFloat)body2FontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)body1Font {
+  return [[self fontLoader] regularFontOfSize:14];
+}
+
++ (CGFloat)body1FontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (UIFont *)captionFont {
+  return [[self fontLoader] regularFontOfSize:12];
+}
+
++ (CGFloat)captionFontOpacity {
+  return MDCTypographySecondaryOpacity;
+}
+
++ (UIFont *)buttonFont {
+  return [[self fontLoader] mediumFontOfSize:14];
+}
+
++ (CGFloat)buttonFontOpacity {
+  return MDCTypographyStandardOpacity;
+}
+
++ (BOOL)isLargeForContrastRatios:(nonnull UIFont *)font {
+  id<MDCTypographyFontLoading> fontLoader = [self fontLoader];
+
+  if ([fontLoader respondsToSelector:@selector(isLargeForContrastRatios:)]) {
+    return [fontLoader isLargeForContrastRatios:font];
+  }
+
+  // Copied from [MDFTextAccessibility isLargeForContrastRatios:]
+  UIFontDescriptor *fontDescriptor = font.fontDescriptor;
+  BOOL isBold =
+      (fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold;
+  return font.pointSize >= 18 || (isBold && font.pointSize >= 14);
+}
+
++ (UIFont *)italicFontFromFont:(UIFont *)font {
+  SEL selector = @selector(italicFontFromFont:);
+  if ([self.fontLoader respondsToSelector:selector]) {
+    return [self.fontLoader italicFontFromFont:font];
+  }
+  UIFontDescriptor *fontDescriptor =
+      [font.fontDescriptor fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitItalic];
+  return [UIFont fontWithDescriptor:fontDescriptor size:0] ?:
+      [UIFont italicSystemFontOfSize:font.pointSize];
+}
+
++ (UIFont *)boldFontFromFont:(UIFont *)font {
+  SEL selector = @selector(boldFontFromFont:);
+  if ([self.fontLoader respondsToSelector:selector]) {
+    return [self.fontLoader boldFontFromFont:font];
+  }
+  UIFontDescriptorSymbolicTraits traits = UIFontDescriptorTraitBold;
+  if (font.mdc_slant != 0) {
+    traits = traits | UIFontDescriptorTraitItalic;
+  }
+  UIFontDescriptor *fontDescriptor = [font.fontDescriptor fontDescriptorWithSymbolicTraits:traits];
+  return [UIFont fontWithDescriptor:fontDescriptor size:0] ?:
+      [UIFont boldSystemFontOfSize:font.pointSize];
+}
+
+#pragma mark - Private
+
++ (id<MDCTypographyFontLoading>)defaultFontLoader {
+  return [[MDCSystemFontLoader alloc] init];
+}
+
+@end
+
+@implementation MDCSystemFontLoader
+
+- (UIFont *)lightFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightLight];
+  }
+  return [UIFont fontWithName:@"HelveticaNeue-Light" size:fontSize];
+}
+
+- (UIFont *)regularFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightRegular];
+  }
+  return [UIFont systemFontOfSize:fontSize];
+}
+
+- (UIFont *)mediumFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightMedium];
+  }
+  return [UIFont fontWithName:@"HelveticaNeue-Medium" size:fontSize];
+}
+
+- (UIFont *)boldFontOfSize:(CGFloat)fontSize {
+  if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) {
+    return [UIFont systemFontOfSize:fontSize weight:UIFontWeightSemibold];
+  }
+  return [UIFont boldSystemFontOfSize:fontSize];
+}
+
+- (UIFont *)italicFontOfSize:(CGFloat)fontSize {
+  return [UIFont italicSystemFontOfSize:fontSize];
+}
+
+- (UIFont *)boldItalicFontOfSize:(CGFloat)fontSize {
+  UIFont *regular = [self regularFontOfSize:fontSize];
+  UIFontDescriptor *descriptor = [regular.fontDescriptor
+      fontDescriptorWithSymbolicTraits:UIFontDescriptorTraitBold | UIFontDescriptorTraitItalic];
+  return [UIFont fontWithDescriptor:descriptor size:fontSize];
+}
+
+- (BOOL)isLargeForContrastRatios:(UIFont *)font {
+  if (font.pointSize >= 18) {
+    return YES;
+  }
+  if (font.pointSize < 14) {
+    return NO;
+  }
+
+  UIFontDescriptor *fontDescriptor = font.fontDescriptor;
+  if ((fontDescriptor.symbolicTraits & UIFontDescriptorTraitBold) == UIFontDescriptorTraitBold) {
+    return YES;
+  }
+
+  CGFloat MDCFontWeightMedium = (CGFloat)0.23;
+// Based on Apple's SDK-Based Development: Using Weakly Linked Methods, Functions, and Symbols.
+// https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/cross_development/Using/using.html#//apple_ref/doc/uid/20002000-1114537-BABHHJBC
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
+#pragma clang diagnostic ignored "-Wunreachable-code"
+  if (&UIFontWeightMedium != NULL) {
+    MDCFontWeightMedium = UIFontWeightMedium;
+  }
+#pragma clang diagnostic pop
+
+  // We treat system font medium as large for accessibility when larger than 14.
+  if (font.mdc_weight >= MDCFontWeightMedium) {
+    return YES;
+  }
+
+  return NO;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MaterialTypography.h
new file mode 100644
index 0000000..1275c7a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/MaterialTypography.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+/**
+ The Typography component provides methods for getting sized fonts and opacities following Material
+ style guidelines.
+
+ This header is the umbrella header for the component and should be imported by consumers of the
+ Typography component. Please do not directly import other headers. This will allow the componet to
+ expand or contract the header file space without consumer modifications.
+ */
+
+#import "MDCFontTextStyle.h"
+#import "MDCTypography.h"
+#import "UIFont+MaterialTypography.h"
+#import "UIFontDescriptor+MaterialTypography.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
new file mode 100644
index 0000000..49b9468
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.h
@@ -0,0 +1,29 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCFontTextStyle.h"
+
+@interface UIFont (MaterialTypography)
+
+/**
+ Returns an instance of the font associated with the Material text style and scaled based on the
+ content size category.
+
+ @param style The Material font text style for which to return a font.
+ @return The font associated with the specified style.
+ */
++ (nonnull UIFont *)mdc_preferredFontForMaterialTextStyle:(MDCFontTextStyle)style;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.m
new file mode 100644
index 0000000..94abe31
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFont+MaterialTypography.m
@@ -0,0 +1,38 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIFont+MaterialTypography.h"
+
+#import "MDCTypography.h"
+#import "UIFontDescriptor+MaterialTypography.h"
+
+@implementation UIFont (MaterialTypography)
+
++ (UIFont *)mdc_preferredFontForMaterialTextStyle:(MDCFontTextStyle)style {
+  // Due to the way iOS handles missing glyphs in fonts, we do not support using a custom font
+  // loader with Dynamic Type.
+  id<MDCTypographyFontLoading> fontLoader = [MDCTypography fontLoader];
+  if (![fontLoader isKindOfClass:[MDCSystemFontLoader class]]) {
+    NSLog(@"MaterialTypography : Custom font loaders are not compatible with Dynamic Type.");
+  }
+
+  UIFontDescriptor *fontDescriptor =
+      [UIFontDescriptor mdc_preferredFontDescriptorForMaterialTextStyle:style];
+
+  // Size is included in the fontDescriptor, so we pass in 0.0 in the parameter.
+  UIFont *font = [UIFont fontWithDescriptor:fontDescriptor size:0.0];
+
+  return font;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
new file mode 100644
index 0000000..3a2f31f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.h
@@ -0,0 +1,30 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCFontTextStyle.h"
+
+@interface UIFontDescriptor (MaterialTypography)
+
+/**
+ Returns an instance of the font descriptor associated with the Material text style and scaled
+ based on the content size category.
+
+ @param style The Material font text style for which to return a font descriptor.
+ @return The font descriptor associated with the specified style.
+ */
++ (nonnull UIFontDescriptor *)mdc_preferredFontDescriptorForMaterialTextStyle:
+        (MDCFontTextStyle)style;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.m
new file mode 100644
index 0000000..396ff0a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/UIFontDescriptor+MaterialTypography.m
@@ -0,0 +1,47 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIFontDescriptor+MaterialTypography.h"
+
+#import "UIApplication+AppExtensions.h"
+
+#import "private/MDCFontTraits.h"
+
+@implementation UIFontDescriptor (MaterialTypography)
+
++ (nonnull UIFontDescriptor *)mdc_preferredFontDescriptorForMaterialTextStyle:
+        (MDCFontTextStyle)style {
+  // iOS' default UIContentSizeCategory is Large.
+  NSString *sizeCategory = UIContentSizeCategoryLarge;
+
+  // If we are within an application, query the preferredContentSizeCategory.
+  if ([UIApplication mdc_safeSharedApplication]) {
+    sizeCategory = [UIApplication mdc_safeSharedApplication].preferredContentSizeCategory;
+  }
+
+  // TODO(#1179): We should include our leading and tracking metrics when creating this descriptor.
+  MDCFontTraits *materialTraits =
+      [MDCFontTraits traitsForTextStyle:style sizeCategory:sizeCategory];
+
+  NSDictionary *traits = @{ UIFontWeightTrait : @(materialTraits.weight) };
+  NSDictionary *attributes = @{
+    UIFontDescriptorSizeAttribute : @(materialTraits.pointSize),
+    UIFontDescriptorTraitsAttribute : traits
+  };
+
+  UIFontDescriptor *fontDescriptor = [[UIFontDescriptor alloc] initWithFontAttributes:attributes];
+
+  return fontDescriptor;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.h
new file mode 100644
index 0000000..d623b40
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.h
@@ -0,0 +1,59 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCFontTextStyle.h"
+
+/**
+ Provides a means of storing defining font metrics based on size categories.
+
+ This class is based off Apple recommendation in WWDC 2016 - 803 - Typography and Fonts @ 17:33.
+ */
+@interface MDCFontTraits : NSObject
+
+/**
+ The size to which the font is scaled.
+
+ This value, in points, must be greater than 0.0.
+ */
+@property(nonatomic, readonly) CGFloat pointSize;
+
+/**
+ The weight of the font, specified as a font weight constant.
+
+ For a list of possible values, see "Font Weights” in UIFontDescriptor. Avoid passing an arbitrary
+ floating-point number for weight, because a font might not include a variant for every weight.
+ */
+@property(nonatomic, readonly) CGFloat weight;
+
+/**
+ The leading value represents additional space between lines of text and is measured in points.
+ */
+@property(nonatomic, readonly) CGFloat leading;
+
+/**
+ The tracking value represents additional horizontal space between glyphs and is measured in points.
+ */
+@property(nonatomic, readonly) CGFloat tracking;
+
+/**
+ @param style MDCFontStyle of font traits being requested.
+ @param sizeCategory UIContentSizeCategory of the font traits being requested.
+
+ @return Font traits that can be used to initialize a UIFont or UIFontDescriptor.
+ */
++ (nonnull MDCFontTraits *)traitsForTextStyle:(MDCFontTextStyle)style
+                                 sizeCategory:(nonnull NSString *)sizeCategory;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.m
new file mode 100644
index 0000000..27eeede
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/MDCFontTraits.m
@@ -0,0 +1,493 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCFontTraits.h"
+
+static NSDictionary<NSString *, MDCFontTraits *> *_body1Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_body2Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_buttonTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_captionTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display1Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display2Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display3Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_display4Traits;
+static NSDictionary<NSString *, MDCFontTraits *> *_headlineTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_subheadlineTraits;
+static NSDictionary<NSString *, MDCFontTraits *> *_titleTraits;
+
+static NSDictionary<NSNumber *, NSDictionary *> *_styleTable;
+
+@interface MDCFontTraits (MaterialTypographyPrivate)
+
++ (instancetype)traitsWithPointSize:(CGFloat)pointSize
+                             weight:(CGFloat)weight
+                            leading:(CGFloat)leading
+                           tracking:(CGFloat)tracking;
+
+- (instancetype)initWithPointSize:(CGFloat)pointSize
+                           weight:(CGFloat)weight
+                          leading:(CGFloat)leading
+                         tracking:(CGFloat)tracking;
+
+@end
+
+@implementation MDCFontTraits
+
++ (void)initialize {
+  _body1Traits = @{
+    UIContentSizeCategoryExtraSmall :
+        [MDCFontTraits traitsWithPointSize:11 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategorySmall :
+        [MDCFontTraits traitsWithPointSize:12 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryMedium :
+        [MDCFontTraits traitsWithPointSize:13 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryLarge :
+        [MDCFontTraits traitsWithPointSize:14 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryExtraLarge :
+        [MDCFontTraits traitsWithPointSize:16 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:18 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:20 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityMedium :
+        [MDCFontTraits traitsWithPointSize:25 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityLarge :
+        [MDCFontTraits traitsWithPointSize:30 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraLarge :
+        [MDCFontTraits traitsWithPointSize:37 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:44 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraExtraLarge :
+        [MDCFontTraits traitsWithPointSize:52 weight:UIFontWeightRegular leading:0.0 tracking:0.0],
+  };
+
+  _body2Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:12
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:13
+                                                                    weight:UIFontWeightMedium
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:16
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:18
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:20
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityMedium :
+        [[MDCFontTraits alloc] initWithPointSize:25
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityLarge :
+        [[MDCFontTraits alloc] initWithPointSize:30
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:37
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:44
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryAccessibilityExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:52
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _buttonTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:12
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:13
+                                                                    weight:UIFontWeightMedium
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:16
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:18
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:20
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _captionTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:11
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:12
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:16
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:18
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display1Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:28
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:30
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:32
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:34
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:36
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:38
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:40
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display2Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:39
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:41
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:43
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:45
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:47
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:49
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:51
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display3Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:50
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:52
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:54
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:56
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:58
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:60
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:62
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _display4Traits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:100
+                                                                        weight:UIFontWeightLight
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:104
+                                                                   weight:UIFontWeightLight
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:108
+                                                                    weight:UIFontWeightLight
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:112
+                                                                   weight:UIFontWeightLight
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:116
+                                                                        weight:UIFontWeightLight
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:120
+                                          weight:UIFontWeightLight
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:124
+                                          weight:UIFontWeightLight
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _headlineTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:21
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:22
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:23
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:24
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:26
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:28
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:30
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _subheadlineTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:13
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:14
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:15
+                                                                    weight:UIFontWeightRegular
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:16
+                                                                   weight:UIFontWeightRegular
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:18
+                                                                        weight:UIFontWeightRegular
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:20
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:22
+                                          weight:UIFontWeightRegular
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _titleTraits = @{
+    UIContentSizeCategoryExtraSmall : [[MDCFontTraits alloc] initWithPointSize:17
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategorySmall : [[MDCFontTraits alloc] initWithPointSize:18
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryMedium : [[MDCFontTraits alloc] initWithPointSize:19
+                                                                    weight:UIFontWeightMedium
+                                                                   leading:0.0
+                                                                  tracking:0.0],
+    UIContentSizeCategoryLarge : [[MDCFontTraits alloc] initWithPointSize:20
+                                                                   weight:UIFontWeightMedium
+                                                                  leading:0.0
+                                                                 tracking:0.0],
+    UIContentSizeCategoryExtraLarge : [[MDCFontTraits alloc] initWithPointSize:22
+                                                                        weight:UIFontWeightMedium
+                                                                       leading:0.0
+                                                                      tracking:0.0],
+    UIContentSizeCategoryExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:24
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+    UIContentSizeCategoryExtraExtraExtraLarge :
+        [[MDCFontTraits alloc] initWithPointSize:26
+                                          weight:UIFontWeightMedium
+                                         leading:0.0
+                                        tracking:0.0],
+  };
+
+  _styleTable = @{
+    @(MDCFontTextStyleBody1) : _body1Traits,
+    @(MDCFontTextStyleBody2) : _body2Traits,
+    @(MDCFontTextStyleButton) : _buttonTraits,
+    @(MDCFontTextStyleCaption) : _captionTraits,
+    @(MDCFontTextStyleDisplay1) : _display1Traits,
+    @(MDCFontTextStyleDisplay2) : _display2Traits,
+    @(MDCFontTextStyleDisplay3) : _display3Traits,
+    @(MDCFontTextStyleDisplay4) : _display4Traits,
+    @(MDCFontTextStyleHeadline) : _headlineTraits,
+    @(MDCFontTextStyleSubheadline) : _subheadlineTraits,
+    @(MDCFontTextStyleTitle) : _titleTraits
+  };
+}
+
++ (instancetype)traitsWithPointSize:(CGFloat)pointSize
+                             weight:(CGFloat)weight
+                            leading:(CGFloat)leading
+                           tracking:(CGFloat)tracking {
+  return [[MDCFontTraits alloc] initWithPointSize:pointSize
+                                           weight:weight
+                                          leading:leading
+                                         tracking:tracking];
+}
+
+- (instancetype)initWithPointSize:(CGFloat)pointSize
+                           weight:(CGFloat)weight
+                          leading:(CGFloat)leading
+                         tracking:(CGFloat)tracking {
+  self = [super init];
+  if (self) {
+    _pointSize = pointSize;
+    _weight = weight;
+    _leading = leading;
+    _tracking = tracking;
+  }
+
+  return self;
+}
+
++ (MDCFontTraits *)traitsForTextStyle:(MDCFontTextStyle)style
+                         sizeCategory:(NSString *)sizeCategory {
+  NSDictionary *traitsTable = _styleTable[@(style)];
+  NSCAssert(traitsTable, @"traitsTable cannot be nil. Is style valid?");
+
+  MDCFontTraits *traits;
+  if (traitsTable) {
+    if (sizeCategory) {
+      traits = traitsTable[sizeCategory];
+    }
+
+    // If you have queried the table for a sizeCategory that doesn't exist, we will return the
+    // traits for XXXL.  This handles the case where the values are requested for one of the
+    // accessibility size categories beyond XXXL such as
+    // UIContentSizeCategoryAccessibilityExtraLarge.  Accessbility size categories are only
+    // defined for the Body Font Style.
+    if (traits == nil) {
+      traits = traitsTable[UIContentSizeCategoryExtraExtraExtraLarge];
+    }
+  }
+
+  return traits;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h
new file mode 100644
index 0000000..8349357
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface UIFont (MaterialTypographyPrivate)
+
+/**
+ Returns the weight of the font.
+
+ @return A value between -1.0 (very thin) to 1.0 (very thick).
+
+ Regular weight is 0.0.
+ */
+- (CGFloat)mdc_weight;
+
+/**
+ Returns the slant of the font.
+
+ @return more than 0 when italic and 0 when not italic.
+
+ Regular slant is 0.0.
+ */
+- (CGFloat)mdc_slant;
+
+/**
+ Returns an extended description of the font including name, pointsize and weight.
+ */
+- (nonnull NSString *)mdc_extendedDescription;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m
new file mode 100644
index 0000000..c2ba020
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m
@@ -0,0 +1,98 @@
+/*
+ Copyright 2017-present the Material Components for iOS authors. All Rights Reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIFont+MaterialTypographyPrivate.h"
+
+@implementation UIFont (MaterialTypographyPrivate)
+
+/*
+ Returns a string indicating the weight of the font.  These weights were added in iOS 8.2.
+ */
++ (NSString *)mdc_fontWeightDescription:(CGFloat)weight {
+// The UIFontWeight enumeration was added in iOS 8.2
+#if defined(__IPHONE_8_2)
+  if (weight == UIFontWeightUltraLight) {
+    return @"UltraLight";
+  } else if (weight == UIFontWeightThin) {
+    return @"Thin";
+  } else if (weight == UIFontWeightLight) {
+    return @"Light";
+  } else if (weight == UIFontWeightRegular) {
+    return @"Regular";
+  } else if (weight == UIFontWeightMedium) {
+    return @"Medium";
+  } else if (weight == UIFontWeightSemibold) {
+    return @"Semibold";
+  } else if (weight == UIFontWeightBold) {
+    return @"Bold";
+  } else if (weight == UIFontWeightHeavy) {
+    return @"Heavy";
+  } else if (weight == UIFontWeightBlack) {
+    return @"Black";
+  } else {
+    NSString *description = [NSString stringWithFormat:@"(%.3f)", weight];
+    return description;
+  }
+#else
+  NSString *description = [NSString stringWithFormat:@"(%.3f)", weight];
+  return description;
+#endif
+}
+
+- (CGFloat)mdc_weight {
+  // The default font weight is UIFontWeightRegular, which is 0.0.
+  CGFloat weight = 0.0;
+
+  NSDictionary *fontTraits = [self.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
+  if (fontTraits) {
+    NSNumber *weightNumber = fontTraits[UIFontWeightTrait];
+    if (weightNumber) {
+      weight = [weightNumber floatValue];
+    }
+  }
+
+  return weight;
+}
+
+- (CGFloat)mdc_slant {
+  CGFloat slant = 0.0;
+
+  NSDictionary *fontTraits = [self.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
+  if (fontTraits) {
+    NSNumber *slantNumber = fontTraits[UIFontSlantTrait];
+    if (slantNumber) {
+      slant = [slantNumber floatValue];
+    }
+  }
+
+  return slant;
+}
+
+- (NSString *)mdc_weightString {
+  CGFloat weight = [self mdc_weight];
+  NSString *weightString = [UIFont mdc_fontWeightDescription:weight];
+
+  return weightString;
+}
+
+- (NSString *)mdc_extendedDescription {
+  NSMutableString *extendedDescription = [[NSMutableString alloc] init];
+  [extendedDescription appendFormat:@"%@ : ", self.fontName];
+  [extendedDescription appendFormat:@"%@ : ", self.familyName];
+  [extendedDescription appendFormat:@"%.1f pt : ", self.pointSize];
+  [extendedDescription appendFormat:@"%@", [self mdc_weightString]];
+
+  return extendedDescription;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/MaterialApplication.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/MaterialApplication.h
new file mode 100644
index 0000000..15c2350
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/MaterialApplication.h
@@ -0,0 +1,16 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+#import "UIApplication+AppExtensions.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
new file mode 100644
index 0000000..38a741f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.h
@@ -0,0 +1,36 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ UIApplication extension for working with sharedApplication inside of app extensions.
+ */
+@interface UIApplication (AppExtensions)
+
+/**
+ Returns sharedApplication if it is available otherwise returns nil.
+
+ This is a wrapper around sharedApplication which is safe to compile and use in app extensions.
+ */
++ (UIApplication *)mdc_safeSharedApplication;
+
+/**
+ Returns YES if called inside an application extension otherwise returns NO.
+ */
++ (BOOL)mdc_isAppExtension;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.m
new file mode 100644
index 0000000..988aebb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Application/src/UIApplication+AppExtensions.m
@@ -0,0 +1,43 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIApplication+AppExtensions.h"
+
+@implementation UIApplication (AppExtensions)
+
++ (UIApplication *)mdc_safeSharedApplication {
+  static UIApplication *application;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    if (![self mdc_isAppExtension]) {
+      // We can't call sharedApplication directly or else this won't build for app extensions.
+      application = [[UIApplication class] performSelector:@selector(sharedApplication)];
+    }
+  });
+  return application;
+}
+
++ (BOOL)mdc_isAppExtension {
+  static BOOL isAppExtension;
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    isAppExtension =
+        [[[NSBundle mainBundle] executablePath] rangeOfString:@".appex/"].location != NSNotFound;
+  });
+  return isAppExtension;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
new file mode 100644
index 0000000..8623555
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h
@@ -0,0 +1,41 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file is normally automatically generated by running ./scripts/sync_icons.sh
+// It has been temporarily modified manually to support the transition to a new style for this icon.
+
+@interface MDCIcons (ic_arrow_back)
+
+/*
+ Returns the path for the ic_arrow_back image contained in
+ MaterialIcons_ic_arrow_back.bundle.
+
+ Defaults to the old style.
+ */
++ (nonnull NSString *)pathFor_ic_arrow_back;
+
+/*
+ Change the style returned by `pathFor_ic_arrow_back`.
+
+ @param useNewStyle Use the new iOS style OR Material style for ic_arrow_back.
+ */
++ (void)ic_arrow_backUseNewStyle:(BOOL)useNewStyle;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m
new file mode 100644
index 0000000..88d51a9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m
@@ -0,0 +1,50 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file is normally automatically generated by running ./scripts/sync_icons.sh
+// It has been temporarily modified manually to support the transition to a new style for this icon.
+
+#import "MaterialIcons+ic_arrow_back.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_arrow_back";
+static NSString *const kIconName = @"ic_arrow_back";
+static NSString *const kNewIconName = @"ic_arrow_back_ios";
+
+static NSString *__icArrowBackIconName = @"ic_arrow_back_ios";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_arrow_back =
+    0;
+
+@implementation MDCIcons (ic_arrow_back)
+
++ (nonnull NSString *)pathFor_ic_arrow_back {
+  return [self pathForIconName:__icArrowBackIconName withBundleName:kBundleName];
+}
+
+// TODO(samnm): Remove this method and __icArrowBackIconName after transitioning all clients to the
+// new icon style.
++ (void)ic_arrow_backUseNewStyle:(BOOL)useNewStyle {
+  if (useNewStyle) {
+    __icArrowBackIconName = kNewIconName;
+  } else {
+    __icArrowBackIconName = kIconName;
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png
new file mode 100644
index 0000000..ad38830
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png
new file mode 100644
index 0000000..6842725
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png
new file mode 100644
index 0000000..2cebb5b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png
new file mode 100644
index 0000000..a467fe7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png
new file mode 100644
index 0000000..2189a16
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png
new file mode 100644
index 0000000..923672c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
new file mode 100644
index 0000000..1749c3e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_check)
+
+/*
+ Returns the path for the ic_check image contained in
+ MaterialIcons_ic_check.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_check;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m
new file mode 100644
index 0000000..0299dfa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_check.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_check";
+static NSString *const kIconName = @"ic_check";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_check = 0;
+
+@implementation MDCIcons (ic_check)
+
++ (nonnull NSString *)pathFor_ic_check {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png
new file mode 100644
index 0000000..1c14c9c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png
new file mode 100644
index 0000000..64a4944
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png
new file mode 100644
index 0000000..b26a2c0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
new file mode 100644
index 0000000..73e73fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_check_circle)
+
+/*
+ Returns the path for the ic_check_circle image contained in
+ MaterialIcons_ic_check_circle.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_check_circle;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m
new file mode 100644
index 0000000..a8b510b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_check_circle.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_check_circle";
+static NSString *const kIconName = @"ic_check_circle";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_check_circle =
+    0;
+
+@implementation MDCIcons (ic_check_circle)
+
++ (nonnull NSString *)pathFor_ic_check_circle {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png
new file mode 100644
index 0000000..a2caa18
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png
new file mode 100644
index 0000000..86bf38e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png
new file mode 100644
index 0000000..1c2ddcd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
new file mode 100644
index 0000000..5f67578
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_chevron_right)
+
+/*
+ Returns the path for the ic_chevron_right image contained in
+ MaterialIcons_ic_chevron_right.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_chevron_right;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m
new file mode 100644
index 0000000..31687e7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_chevron_right.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_chevron_right";
+static NSString *const kIconName = @"ic_chevron_right";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((
+    visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_chevron_right = 0;
+
+@implementation MDCIcons (ic_chevron_right)
+
++ (nonnull NSString *)pathFor_ic_chevron_right {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png
new file mode 100644
index 0000000..c11a2a5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png
new file mode 100644
index 0000000..23338b8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png
new file mode 100644
index 0000000..f97c51b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
new file mode 100644
index 0000000..1f39ab6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_info)
+
+/*
+ Returns the path for the ic_info image contained in
+ MaterialIcons_ic_info.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_info;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m
new file mode 100644
index 0000000..24ad43e
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_info.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_info";
+static NSString *const kIconName = @"ic_info";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_info = 0;
+
+@implementation MDCIcons (ic_info)
+
++ (nonnull NSString *)pathFor_ic_info {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png
new file mode 100644
index 0000000..5ef3dc0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png
new file mode 100644
index 0000000..46ed12a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png
new file mode 100644
index 0000000..a81eeb9
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
new file mode 100644
index 0000000..70a2dfb
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_radio_button_unchecked)
+
+/*
+ Returns the path for the ic_radio_button_unchecked image contained in
+ MaterialIcons_ic_radio_button_unchecked.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_radio_button_unchecked;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m
new file mode 100644
index 0000000..293c7d4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m
@@ -0,0 +1,37 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_radio_button_unchecked.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_radio_button_unchecked";
+static NSString *const kIconName = @"ic_radio_button_unchecked";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility(
+    "default"))) char MDCIconsExportToSuppressLibToolWarning_ic_radio_button_unchecked = 0;
+
+@implementation MDCIcons (ic_radio_button_unchecked)
+
++ (nonnull NSString *)pathFor_ic_radio_button_unchecked {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png
new file mode 100644
index 0000000..4c0688f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png
new file mode 100644
index 0000000..daa867f
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png
new file mode 100644
index 0000000..d8c8636
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
new file mode 100644
index 0000000..74b8f35
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MaterialIcons.h"
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+@interface MDCIcons (ic_reorder)
+
+/*
+ Returns the path for the ic_reorder image contained in
+ MaterialIcons_ic_reorder.bundle.
+ */
++ (nonnull NSString *)pathFor_ic_reorder;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m
new file mode 100644
index 0000000..e649635
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+// This file was automatically generated by running ./scripts/sync_icons.sh
+// Do not modify directly.
+
+#import "MaterialIcons+ic_reorder.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+static NSString *const kBundleName = @"MaterialIcons_ic_reorder";
+static NSString *const kIconName = @"ic_reorder";
+
+// Export a nonsense symbol to suppress a libtool warning when this is linked alone in a static lib.
+__attribute__((visibility("default"))) char MDCIconsExportToSuppressLibToolWarning_ic_reorder = 0;
+
+@implementation MDCIcons (ic_reorder)
+
++ (nonnull NSString *)pathFor_ic_reorder {
+  return [self pathForIconName:kIconName withBundleName:kBundleName];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png
new file mode 100644
index 0000000..d18997c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png
new file mode 100644
index 0000000..0b080a1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png
new file mode 100644
index 0000000..0a66529
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png
Binary files differ
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
new file mode 100644
index 0000000..37cde09
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons+BundleLoader.h
@@ -0,0 +1,31 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCIcons.h"
+
+/**
+ The MDCIcons class is designed to be extended by adding individual icon extensions to a project.
+
+ Individual icons can be accessed by importing their MaterialIcons+<icon_name>.h header and calling
+ [MDCIcons pathFor_<icon_name>] to get the icon's file system path.
+ */
+@interface MDCIcons (BundleLoader)
+
+/** Returns a disk path for an icon contained within a bundle of a given name. */
++ (nonnull NSString *)pathForIconName:(nonnull NSString *)iconName
+                       withBundleName:(nonnull NSString *)bundleName;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.h
new file mode 100644
index 0000000..b02150c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.h
@@ -0,0 +1,30 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ The MDCIcons class is designed to be extended by adding individual icon extensions to a project.
+
+ Individual icons can be accessed by importing their MaterialIcons+<icon_name>.h header and calling
+ [MDCIcons pathFor_<icon_name>] to get the icon's file system path.
+ */
+@interface MDCIcons : NSObject
+
+// This object is not intended to be instantiated.
+- (instancetype)init NS_UNAVAILABLE;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.m
new file mode 100644
index 0000000..49fa111
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MDCIcons.m
@@ -0,0 +1,32 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCIcons.h"
+
+#import "MDCIcons+BundleLoader.h"
+
+@implementation MDCIcons
+
++ (nonnull NSString *)pathForIconName:(nonnull NSString *)iconName
+                       withBundleName:(nonnull NSString *)bundleName {
+  NSBundle *baseBundle = [NSBundle bundleForClass:[self class]];
+  NSString *bundlePath = [baseBundle pathForResource:bundleName ofType:@"bundle"];
+  NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
+  NSAssert(bundle, @"Missing bundle %@ containing icon %@.", bundleName, iconName);
+  return [bundle pathForResource:iconName ofType:@"png"];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MaterialIcons.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MaterialIcons.h
new file mode 100644
index 0000000..f7cc1bf
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Icons/src/MaterialIcons.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCIcons.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
new file mode 100644
index 0000000..a24239a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h
@@ -0,0 +1,54 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+
+// These notifications mirror their UIKeyboard* counterparts. They are posted after the keyboard
+// watcher has updated its own internal state, so listeners are safe to query the keyboard watcher
+// for its values.
+OBJC_EXTERN NSString *const MDCKeyboardWatcherKeyboardWillShowNotification;
+OBJC_EXTERN NSString *const MDCKeyboardWatcherKeyboardWillHideNotification;
+OBJC_EXTERN NSString *const MDCKeyboardWatcherKeyboardWillChangeFrameNotification;
+
+/**
+ An object which will watch the state of the keyboard.
+
+ The keyboard watcher calculates an offset representing the distance from the top of the keyboard to
+ the bottom of the screen.
+ */
+@interface MDCKeyboardWatcher : NSObject
+
+/**
+ Shared singleton instance of MDCKeyboardWatcher.
+ */
++ (instancetype)sharedKeyboardWatcher;
+
+/** Extract the animation duration from the keyboard notification */
++ (NSTimeInterval)animationDurationFromKeyboardNotification:(NSNotification *)notification;
+
+/** Extract the animation curve option from the keyboard notification */
++ (UIViewAnimationOptions)animationCurveOptionFromKeyboardNotification:
+        (NSNotification *)notification;
+
+/**
+ The distance from the top of the keyboard to the bottom of the screen.
+
+ Zero if the keyboard is not currently showing or is not docked.
+ */
+@property(nonatomic, readonly) CGFloat keyboardOffset;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m
new file mode 100644
index 0000000..24a3e7a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m
@@ -0,0 +1,270 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCKeyboardWatcher.h"
+#import "UIApplication+AppExtensions.h"
+
+NSString *const MDCKeyboardWatcherKeyboardWillShowNotification =
+    @"MDCKeyboardWatcherKeyboardWillShowNotification";
+NSString *const MDCKeyboardWatcherKeyboardWillHideNotification =
+    @"MDCKeyboardWatcherKeyboardWillHideNotification";
+NSString *const MDCKeyboardWatcherKeyboardWillChangeFrameNotification =
+    @"MDCKeyboardWatcherKeyboardWillChangeFrameNotification";
+
+static MDCKeyboardWatcher *_sKeyboardWatcher;
+
+@interface MDCKeyboardWatcher ()
+
+/** The keyboard's frame, in rotation-compensated screen coordinates. */
+@property(nonatomic) CGRect keyboardFrame;
+
+@end
+
+@implementation MDCKeyboardWatcher
+
+// Because at the time of writing, there is no public API for answering the question: "Is the
+// keyboard currently showing?", we must watch the keyboard's show/hide notifications and maintain
+// that state on our own. The only time early enough to start watching the keyboard is at +load, so
+// we must create a watcher then.
++ (void)load {
+  @autoreleasepool {
+    _sKeyboardWatcher = [[MDCKeyboardWatcher alloc] init];
+  }
+}
+
++ (instancetype)sharedKeyboardWatcher {
+  return _sKeyboardWatcher;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillShow:)
+               name:UIKeyboardWillShowNotification
+             object:nil];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillHide:)
+               name:UIKeyboardWillHideNotification
+             object:nil];
+
+    [nc addObserver:self
+           selector:@selector(keyboardWillChangeFrame:)
+               name:UIKeyboardWillChangeFrameNotification
+             object:nil];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark - Keyboard Notifications
+
+- (BOOL)deviceUsesCoordinateSpaces {
+  static BOOL useCoordinateSpace = NO;
+
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    UIScreen *screen = [UIScreen mainScreen];
+    useCoordinateSpace = [screen respondsToSelector:@selector(fixedCoordinateSpace)];
+  });
+
+  return useCoordinateSpace;
+}
+
+- (void)updateKeyboardOffsetWithKeyboardUserInfo:(NSDictionary *)userInfo
+                                     forceHidden:(BOOL)forceHidden {
+  CGRect keyboardRect = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
+  UIScreen *screen = [UIScreen mainScreen];
+
+  // If we are supposed to be hidden, it doesn't matter what the keyboard rects are, the keyboard
+  // offset is 0. This applies in scenarios where a keyboard is showing on a view controller inside
+  // of a navigation controller, and that controller is popped. Instead of the normal keyboard
+  // vertical dismiss animation, the keyboard actually slides away with the view controller. In that
+  // scenario, the keyboard dictionaries do not reflect the keyboard going to the bottom of the
+  // screen. As such, we need to take into account the extra knowledge that the keyboard is being
+  // hidden, and drive the keyboard offset that way.
+  if (forceHidden) {
+    self.keyboardFrame = CGRectZero;
+    return;
+  }
+
+  // On iOS 8, the window orientation is corrected logically after transforms, so there is
+  // no need to swap the width and height like we had to on iOS 7 and below..
+  BOOL isiOS8Device = [self deviceUsesCoordinateSpaces];
+
+  // iOS 8 doesn't notify us of a new keyboard rect when a keyboard dock or undocks to/from the
+  // bottom of the screen. The more common case of no frame is a keyboard undocking and moving
+  // around, so on iOS 8 we'll take a missing frame to indicate an undocked keyboard. Unfortunately
+  // when the keyboard is re-docked, we won't know, and won't be able to re-update the offset.
+  // This also means that our "failure" mode is at the bottom of the screen, so we shouldn't get
+  // into a situation where the offset is too far up with no keyboard on screen.
+  if (CGRectIsEmpty(keyboardRect)) {
+    if (isiOS8Device) {
+      // Set the offset to zero, as if the keyboard was undocked.
+      self.keyboardFrame = CGRectZero;
+    }
+    return;
+  }
+
+  CGRect screenBounds = [screen bounds];
+  CGRect intersection = CGRectIntersection(screenBounds, keyboardRect);
+
+  UIInterfaceOrientation orientation =
+      [[UIApplication mdc_safeSharedApplication] statusBarOrientation];
+
+  BOOL isDockedKeyboard = YES;
+
+  if (!isiOS8Device) {
+    if (UIInterfaceOrientationIsLandscape(orientation)) {
+      CGFloat width = intersection.size.width;
+      CGFloat x = intersection.origin.x;
+
+      intersection.size.width = intersection.size.height;
+      intersection.size.height = width;
+
+      intersection.origin.x = intersection.origin.y;
+      intersection.origin.y = x;
+    }
+
+    // These calculations all depend on the fixed screen coordinate space, so we use the keyboard
+    // rectangle instead of @c intersection, which has already accounted for rotation.
+    switch (orientation) {
+      case UIInterfaceOrientationPortraitUpsideDown:
+        isDockedKeyboard = CGRectGetMinY(keyboardRect) == CGRectGetMinY(screenBounds);
+        break;
+      case UIInterfaceOrientationLandscapeLeft:
+        isDockedKeyboard = CGRectGetMaxX(keyboardRect) == CGRectGetMaxX(screenBounds);
+        break;
+      case UIInterfaceOrientationLandscapeRight:
+        isDockedKeyboard = CGRectGetMinX(keyboardRect) == CGRectGetMinX(screenBounds);
+        break;
+      case UIInterfaceOrientationPortrait:
+      case UIInterfaceOrientationUnknown:
+        isDockedKeyboard = CGRectGetMaxY(keyboardRect) == CGRectGetMaxY(screenBounds);
+        break;
+    }
+  } else {
+    // On an iPad an input accessory view may be shown on the screen even if there is an external
+    // keyboard attached. In that case, iOS will build a software keyboard with an accessory view
+    // attached to the top. It then sets the frame of this keyboard to be below the bounds of the
+    // screen so only the top accessory view is rendered.
+    // We handle this by considering software keyboards with a MaxY >= screen.MaxY as being docked.
+    isDockedKeyboard = CGRectGetMaxY(keyboardRect) >= CGRectGetMaxY(screenBounds);
+  }
+
+  // If the keyboard is docked and the intersection of the keyboard and the screen is
+  // non-zero update our stored keyboard frame.
+  // If the keyboard is undocked, split, or not visible set the keyboard frame to CGRectZero.
+  if (isDockedKeyboard && !CGRectIsEmpty(intersection)) {
+    self.keyboardFrame = intersection;
+  } else {
+    self.keyboardFrame = CGRectZero;
+  }
+}
+
+- (CGFloat)keyboardOffset {
+  return CGRectGetHeight(self.keyboardFrame);
+}
+
++ (NSTimeInterval)animationDurationFromKeyboardNotification:(NSNotification *)notification {
+  if (![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillShowNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillHideNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillChangeFrameNotification]) {
+    NSAssert(NO, @"Cannot extract the animation duration from a non-keyboard notification.");
+
+    return 0.0;
+  }
+
+  NSNumber *animationDurationNumber = notification.userInfo[UIKeyboardAnimationDurationUserInfoKey];
+  NSTimeInterval animationDuration = (NSTimeInterval)[animationDurationNumber doubleValue];
+
+  return animationDuration;
+}
+
+/** Convert UIViewAnimationCurve to UIViewAnimationOptions */
+static UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve animationCurve) {
+  switch (animationCurve) {
+    case UIViewAnimationCurveEaseInOut:
+      return UIViewAnimationOptionCurveEaseInOut;
+    case UIViewAnimationCurveEaseIn:
+      return UIViewAnimationOptionCurveEaseIn;
+    case UIViewAnimationCurveEaseOut:
+      return UIViewAnimationOptionCurveEaseOut;
+    case UIViewAnimationCurveLinear:
+      return UIViewAnimationOptionCurveLinear;
+  }
+
+  // UIKit unpredictably returns values that aren't declared in UIViewAnimationCurve, so we can't
+  // assert here.
+  // UIKeyboardWillChangeFrameNotification can post with a curve of 7.
+  // Based on how UIViewAnimationOptions are defined in UIView.h, (animationCurve << 16) may an
+  // be acceptable return value for unrecognized curves.
+  return UIViewAnimationOptionCurveEaseInOut;
+}
+
++ (UIViewAnimationOptions)animationCurveOptionFromKeyboardNotification:
+        (NSNotification *)notification {
+  if (![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillShowNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillHideNotification] &&
+      ![notification.name isEqualToString:MDCKeyboardWatcherKeyboardWillChangeFrameNotification]) {
+    NSAssert(NO, @"Cannot extract the animation curve option from a non-keyboard notification.");
+
+    return UIViewAnimationOptionCurveEaseInOut;
+  }
+
+  NSNumber *animationCurveNumber = notification.userInfo[UIKeyboardAnimationCurveUserInfoKey];
+  UIViewAnimationCurve animationCurve = (UIViewAnimationCurve)[animationCurveNumber integerValue];
+  UIViewAnimationOptions animationCurveOption = animationOptionsWithCurve(animationCurve);
+
+  return animationCurveOption;
+}
+
+#pragma mark - Notifications
+
+- (void)updateOffsetWithUserInfo:(NSDictionary *)userInfo
+                     forceHidden:(BOOL)forceHidden
+              notificationToPost:(NSString *)notificationToPost {
+  [self updateKeyboardOffsetWithKeyboardUserInfo:userInfo forceHidden:forceHidden];
+  [[NSNotificationCenter defaultCenter] postNotificationName:notificationToPost
+                                                      object:self
+                                                    userInfo:userInfo];
+}
+
+- (void)keyboardWillShow:(NSNotification *)notification {
+  [self updateOffsetWithUserInfo:notification.userInfo
+                     forceHidden:NO
+              notificationToPost:MDCKeyboardWatcherKeyboardWillShowNotification];
+}
+
+- (void)keyboardWillHide:(NSNotification *)notification {
+  [self updateOffsetWithUserInfo:notification.userInfo
+                     forceHidden:YES
+              notificationToPost:MDCKeyboardWatcherKeyboardWillHideNotification];
+}
+
+- (void)keyboardWillChangeFrame:(NSNotification *)notification {
+  [self updateOffsetWithUserInfo:notification.userInfo
+                     forceHidden:NO
+              notificationToPost:MDCKeyboardWatcherKeyboardWillChangeFrameNotification];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
new file mode 100644
index 0000000..15dc165
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h
@@ -0,0 +1,17 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCKeyboardWatcher.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
new file mode 100644
index 0000000..fab2f14
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayImplementor.h
@@ -0,0 +1,77 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+/**
+ These variables are intentionally static (even though this is a header file). We don't want
+ various MDC components to have to link in the overlay manager just to post overlay change
+ notifications. Any implementors who import this file will get copies of the constants which can
+ be used without linking the overlay component.
+ */
+
+/**
+ Overlay implementors should post this notification when a change in overlay frame occurs.
+
+ Use the keys below to define the features of the overlay transition.
+ */
+static NSString *const MDCOverlayDidChangeNotification = @"MDCOverlayDidChangeNotification";
+
+/**
+ The user info key indicating the identifier of the overlay.
+
+ Should be an NSString unique to the component in question. Required.
+ */
+static NSString *const MDCOverlayIdentifierKey = @"identifier";
+
+/**
+ The user info key indicating the frame of the overlay.
+
+ Should only be present if the overlay is onscreen, otherwise omit this key. The value of the key is
+ an NSValue containing a CGRect, in absolute screen coordinates (that is, in iOS 8's fixed
+ coordinate space).
+ */
+static NSString *const MDCOverlayFrameKey = @"frame";
+
+/**
+ The user info key indicating the duration of the overlay transition animation.
+
+ Should be an NSNumber containing a NSTimeInterval.
+ */
+static NSString *const MDCOverlayTransitionDurationKey = @"duration";
+
+/**
+ The user info key indicating the curve of the transition animation.
+
+ Should be an NSNumber containing an NSInteger (UIViewAnimationCurve). If the duration is non-zero,
+ either this key or the curve key should be present in the dictionary.
+ */
+static NSString *const MDCOverlayTransitionCurveKey = @"curve";
+
+/**
+ The user info key indicating the timing function of the transition animation.
+ Should be a CAMediaTimingFunction. If the duration is non-zero, either this key or the curve key
+ should be present in the dictionary.
+ */
+static NSString *const MDCOverlayTransitionTimingFunctionKey = @"timingFunction";
+
+/**
+ This key indicates that the given overlay change needs to animate immediately.
+
+ Some animations, such as the iOS keyboard animation, need to run immediately (and cannot be
+ coalesced). Should be an NSNumber containing a BOOL.
+ */
+static NSString *const MDCOverlayTransitionImmediacyKey = @"runImmediately";
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
new file mode 100644
index 0000000..7bd6539
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.h
@@ -0,0 +1,60 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Class responsible for reporting changes to overlays on a given screen.
+ */
+@interface MDCOverlayObserver : NSObject
+
+/**
+ Returns the overlay observer for the given screen.
+
+ If @c screen is nil, the main screen is used.
+ */
++ (instancetype)observerForScreen:(UIScreen *)screen;
+
+/**
+ Adds a target/action pair to listen for changes to overlays.
+
+ If an overlay is already showing when this method is called, then a call to the target/action will
+ be made immediately with an unanimated transition.
+
+ @param target The object which will be the target of @c action
+ @param action The method to invoke on @c target. This method should take a single argument, an
+               object that conforms to @c MDCOverlayTransitioning.
+ */
+- (void)addTarget:(id)target action:(SEL)action;
+
+/**
+ Prevents the given target/action pair from being notified of overlay changes.
+
+ @param target The target to stop notifying of changes. If multiple @c actions have been
+               registered, then @c target may still receive notifications via other selectors.
+ @param action The method which will no longer be called when overlay changes occur.
+ */
+- (void)removeTarget:(id)target action:(SEL)action;
+
+/**
+ Prevents the given target from being notified of any overlay changes.
+
+ @param target The target to stop notifying of changes. This will remove any and all target-action
+               pairs registered via @c addTarget:action:.
+ */
+- (void)removeTarget:(id)target;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.m
new file mode 100644
index 0000000..f6db943
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayObserver.m
@@ -0,0 +1,303 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayObserver.h"
+
+#import <CoreFoundation/CoreFoundation.h>
+#import <CoreGraphics/CoreGraphics.h>
+#import <UIKit/UIKit.h>
+
+#import "MDCOverlayImplementor.h"
+#import "MDCOverlayTransitioning.h"
+#import "private/MDCOverlayAnimationObserver.h"
+#import "private/MDCOverlayObserverOverlay.h"
+#import "private/MDCOverlayObserverTransition.h"
+
+@interface MDCOverlayObserver () <MDCOverlayAnimationObserverDelegate>
+
+/** The list of overlays currently known to this observer. */
+@property(nonatomic) NSMutableDictionary *overlays;
+
+/** The currently-pending transition. */
+@property(nonatomic) MDCOverlayObserverTransition *pendingTransition;
+
+/** The table holding the target-action mapping. */
+@property(nonatomic) NSMapTable *actionTable;
+
+/** The animation observer used to coalesce events. */
+@property(nonatomic, strong) MDCOverlayAnimationObserver *observer;
+
+@end
+
+@implementation MDCOverlayObserver
+
+static MDCOverlayObserver *_sOverlayObserver;
+
+// This class must be available before the keyboard (or any other overlay contributor) has a chance
+// to report overlay changes. The +load method is the only safe place early enough.
++ (void)load {
+  @autoreleasepool {
+    _sOverlayObserver = [[MDCOverlayObserver alloc] init];
+  }
+}
+
++ (instancetype)observerForScreen:(UIScreen *)screen {
+  NSParameterAssert(screen == nil || screen == [UIScreen mainScreen]);
+  return _sOverlayObserver;
+}
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    _overlays = [NSMutableDictionary dictionary];
+    _observer = [[MDCOverlayAnimationObserver alloc] init];
+    _observer.delegate = self;
+
+    // Set up the target/action table. The keys will be weak pointers to objects, with no calls to
+    // hashing done only on the pointer address (as opposed to calling -hash/-isEqual:).
+    // The values will be strong references to objects.
+    NSPointerFunctionsOptions keyOptions =
+        (NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPointerPersonality);
+    NSPointerFunctionsOptions valueOptions =
+        (NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality);
+    _actionTable = [NSMapTable mapTableWithKeyOptions:keyOptions valueOptions:valueOptions];
+
+    // Register to hear when an overlay changes.
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(handleOverlayChangeNotification:)
+                                                 name:MDCOverlayDidChangeNotification
+                                               object:nil];
+  }
+  return self;
+}
+
+#pragma mark - Overlays
+
+- (MDCOverlayObserverOverlay *)overlayWithIdentifier:(NSString *)identifier {
+  return self.overlays[identifier];
+}
+
+- (MDCOverlayObserverOverlay *)buildOverlayWithIdentifier:(NSString *)identifier {
+  MDCOverlayObserverOverlay *overlay = self.overlays[identifier];
+  if (overlay == nil) {
+    overlay = [[MDCOverlayObserverOverlay alloc] init];
+    overlay.identifier = identifier;
+    self.overlays[identifier] = overlay;
+  }
+
+  return overlay;
+}
+
+- (void)removeOverlayWithIdentifier:(NSString *)identifier {
+  [self.overlays removeObjectForKey:identifier];
+}
+
+- (NSArray *)sortedOverlays {
+  NSArray *sortedKeys = [[self.overlays allKeys] sortedArrayUsingSelector:@selector(compare:)];
+
+  NSMutableArray *result = [NSMutableArray array];
+  for (NSString *key in sortedKeys) {
+    [result addObject:self.overlays[key]];
+  }
+
+  return result;
+}
+
+#pragma mark - Input Sources
+
+- (BOOL)updateOverlay:(NSString *)identifier withFrame:(CGRect)frame {
+  BOOL changed = NO;
+
+  MDCOverlayObserverOverlay *existingOverlay = [self overlayWithIdentifier:identifier];
+
+  if (existingOverlay != nil) {
+    if (CGRectIsEmpty(frame)) {
+      // We're getting rid of this overlay entirely.
+      [self removeOverlayWithIdentifier:identifier];
+      changed = YES;
+    } else if (!CGRectEqualToRect(existingOverlay.frame, frame)) {
+      // We're changing to a new frame for this overlay.
+      existingOverlay.frame = frame;
+      changed = YES;
+    }
+  } else if (!CGRectIsEmpty(frame)) {
+    MDCOverlayObserverOverlay *overlay = [self buildOverlayWithIdentifier:identifier];
+    overlay.frame = frame;
+    changed = YES;
+  }
+
+  return changed;
+}
+
+- (void)handleOverlayChangeNotification:(NSNotification *)note {
+  NSDictionary *userInfo = note.userInfo;
+  NSString *identifier = userInfo[MDCOverlayIdentifierKey];
+
+  // Don't even bother if an identifier wasn't provided.
+  if (identifier.length == 0) {
+    return;
+  }
+
+  NSValue *frame = userInfo[MDCOverlayFrameKey] ?: [NSValue valueWithCGRect:CGRectNull];
+  NSNumber *duration = userInfo[MDCOverlayTransitionDurationKey];
+
+  // Update the overlay frame.
+  BOOL updated = [self updateOverlay:identifier withFrame:[frame CGRectValue]];
+
+  // If there was actually a change, set up a transition.
+  if (updated) {
+    if (self.pendingTransition == nil) {
+      self.pendingTransition = [[MDCOverlayObserverTransition alloc] init];
+      [self.observer messageDelegateOnNextRunloop];
+    }
+  }
+
+  // If we were given a duration, then update the animation parameters.
+  if (self.pendingTransition != nil && duration != nil) {
+    self.pendingTransition.duration = duration.doubleValue;
+    self.pendingTransition.customTimingFunction = userInfo[MDCOverlayTransitionTimingFunctionKey];
+    self.pendingTransition.animationCurve =
+        ((NSNumber *)userInfo[MDCOverlayTransitionCurveKey]).integerValue;
+
+    // If this update requires us to run the animation immediately, go ahead and fire it off.
+    NSNumber *runImmediately = userInfo[MDCOverlayTransitionImmediacyKey];
+    if (runImmediately.boolValue) {
+      [self fireTransition];
+    }
+  }
+}
+
+#pragma mark - Target/Action
+
+- (NSInvocation *)buildInvocationForTarget:(id)target action:(SEL)action {
+  NSMethodSignature *signature = [target methodSignatureForSelector:action];
+  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
+  [invocation setTarget:target];
+  [invocation setSelector:action];
+
+  return invocation;
+}
+
+- (void)invokeTarget:(NSInvocation *)invocation
+      withTransition:(MDCOverlayObserverTransition *)transition {
+  NSParameterAssert(invocation != nil);
+  NSParameterAssert(transition != nil);
+
+  [invocation setArgument:&transition atIndex:2];
+  [invocation invoke];
+}
+
+- (NSUInteger)indexOfInvocationForTarget:(id)target action:(SEL)action {
+  NSMutableArray *invocations = [self.actionTable objectForKey:target];
+
+  if (invocations == nil) {
+    return NSNotFound;
+  }
+
+  return [invocations
+      indexOfObjectPassingTest:^BOOL(NSInvocation *invocation, NSUInteger idx, BOOL *stop) {
+        return invocation.selector == action;
+      }];
+}
+
+- (void)addTarget:(id)target action:(SEL)action {
+  NSParameterAssert(target != nil);
+
+  NSUInteger foundIndex = [self indexOfInvocationForTarget:target action:action];
+  if (foundIndex != NSNotFound) {
+    return;
+  }
+
+  NSInvocation *invocation = [self buildInvocationForTarget:target action:action];
+  NSParameterAssert(invocation != nil);
+
+  NSMutableArray *invocations = [self.actionTable objectForKey:target];
+  if (invocations == nil) {
+    invocations = [NSMutableArray array];
+    [self.actionTable setObject:invocations forKey:target];
+  }
+
+  [invocations addObject:invocation];
+
+  if (self.overlays.count > 0) {
+    // If there's already a pending transition, let the runloop take care of it, otherwise create
+    // one and call it immediately on just the newly-added target, so that it can get its initial
+    // value.
+    if (self.pendingTransition == nil) {
+      MDCOverlayObserverTransition *transition = [[MDCOverlayObserverTransition alloc] init];
+      transition.overlays = [self sortedOverlays];
+
+      [self invokeTarget:invocation withTransition:transition];
+
+      // Run the (non-animated) transition.
+      [transition runAnimation];
+    }
+  }
+}
+
+- (void)removeTarget:(id)target {
+  NSParameterAssert(target != nil);
+
+  [self.actionTable removeObjectForKey:target];
+}
+
+- (void)removeTarget:(id)target action:(SEL)action {
+  NSParameterAssert(target != nil);
+
+  NSUInteger foundIndex = [self indexOfInvocationForTarget:target action:action];
+
+  if (foundIndex != NSNotFound) {
+    NSMutableArray *invocations = [self.actionTable objectForKey:target];
+
+    if (invocations.count == 1) {
+      // Clean up all the invocations if this was the only one.
+      [self removeTarget:target];
+    } else {
+      // Otherwise remove this single invocation.
+      [invocations removeObjectAtIndex:foundIndex];
+    }
+  }
+}
+
+#pragma mark - Runloop Observer
+
+- (void)fireTransition {
+  if (self.pendingTransition == nil) {
+    return;
+  }
+
+  // Update the transition with the latest set of overlays.
+  self.pendingTransition.overlays = [self sortedOverlays];
+
+  // Call all of our targets and let them know a transition has happened.
+  for (id target in self.actionTable) {
+    NSArray *invocations = [self.actionTable objectForKey:target];
+    for (NSInvocation *invocation in invocations) {
+      [self invokeTarget:invocation withTransition:self.pendingTransition];
+    }
+  }
+
+  // Actually run the transition animation.
+  [self.pendingTransition runAnimation];
+
+  self.pendingTransition = nil;
+}
+
+- (void)animationObserverDidEndRunloop:(MDCOverlayAnimationObserver *)observer {
+  [self fireTransition];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
new file mode 100644
index 0000000..76d6ea5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MDCOverlayTransitioning.h
@@ -0,0 +1,108 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Protocol representing a single overlay on the screen.
+ */
+@protocol MDCOverlay <NSObject>
+
+/**
+ A unique identifier for the overlay. Opaque.
+ */
+@property(nonatomic, readonly, copy) NSString *identifier;
+
+/**
+ The frame of the overlay, in screen coordinates.
+ */
+@property(nonatomic, readonly) CGRect frame;
+
+/**
+ Returns the frame of the overlay, in @c targetView's coordinate space.
+
+ The result may go outside of the bounds of @c targetView.
+ */
+- (CGRect)overlayFrameInView:(UIView *)targetView;
+
+@end
+
+/**
+ Protocol representing a change in the overlays currently on screen.
+ */
+@protocol MDCOverlayTransitioning <NSObject>
+
+/**
+ The duration of the animation used to change the overlay frames.
+
+ A duration of 0 means the transition is not animated.
+ */
+@property(nonatomic, readonly) NSTimeInterval duration;
+
+/**
+ If animated, the timing function that should be used when animating the overlay frame change.
+
+ If @c duration is 0, this value is undefined.
+ */
+@property(nonatomic, readonly) CAMediaTimingFunction *customTimingFunction;
+
+/**
+ If animated, the curve that should be used when animating the overlay frame change.
+
+ If @c duration is 0, or if @c customTimingFunction is non-nil, then this value is undefined.
+ */
+@property(nonatomic, readonly) UIViewAnimationCurve animationCurve;
+
+/**
+ The union of the frames for every overlay currently on screen, in screen coordinates.
+
+ This frame is the smallest frame which encompasses all of the overlays currently on screen.
+
+ @note This is generally the frame you want, but it can be "greedy" in that the reported frame may
+       not be the most accurate reflection of the overlays on screen. Imagine an overlay that is
+       half the screen's width above a full-width view. The resulting composite frame will be the
+       full width of the screen plus the height of the two views.
+ */
+@property(nonatomic, readonly) CGRect compositeFrame;
+
+/**
+ The value of @c compositeFrame in @c targetView's coordinate space.
+
+ The result may go outside of the bounds of @c targetView.
+ */
+- (CGRect)compositeFrameInView:(UIView *)targetView;
+
+/**
+ Enumerates through each overlay on the screen, calling @c handler for each one.
+ */
+- (void)enumerateOverlays:(void (^)(id<MDCOverlay> overlay, NSUInteger idx, BOOL *stop))handler;
+
+/**
+ Runs @c animations alongside the overlay transition animation.
+ */
+- (void)animateAlongsideTransition:(void (^)(void))animations;
+
+/**
+ Runs @c animations alongside the overlay transition animation, calling @c completion when the
+ animation is finished.
+
+ @note Any curves specified in @c options will be ignored.
+ */
+- (void)animateAlongsideTransitionWithOptions:(UIViewAnimationOptions)options
+                                   animations:(void (^)(void))animations
+                                   completion:(void (^)(BOOL finished))completion;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MaterialOverlays.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
new file mode 100644
index 0000000..7e5e8fa
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/MaterialOverlays.h
@@ -0,0 +1,22 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Availability.h>
+#import <Foundation/Foundation.h>
+
+#import "MDCOverlayImplementor.h"
+#import "MDCOverlayObserver.h"
+#import "MDCOverlayTransitioning.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h
new file mode 100644
index 0000000..9c7cb17
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h
@@ -0,0 +1,52 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <Foundation/Foundation.h>
+
+@protocol MDCOverlayAnimationObserverDelegate;
+
+/**
+ Utility class which will call its delegate at the end of the current runloop cycle.
+
+ Called before CoreAnimation has had a chance to commit any pending implicit @c CATransactions.
+ */
+@interface MDCOverlayAnimationObserver : NSObject
+
+/**
+ Called to tell the observer that it should call the @c delegate at the end of the next runloop.
+
+ Without calling this method, the observer will not call the delegate.
+ */
+- (void)messageDelegateOnNextRunloop;
+
+/**
+ The delegate to notify when the end of the runloop has occurred.
+ */
+@property(nonatomic, weak) id<MDCOverlayAnimationObserverDelegate> delegate;
+
+@end
+
+/**
+ Delegate protocol for @c MDCOverlayAnimationObserver.
+ */
+@protocol MDCOverlayAnimationObserverDelegate <NSObject>
+
+/**
+ Called at the end of the current runloop, before CoreAnimation commits any implicit transactions.
+ */
+- (void)animationObserverDidEndRunloop:(MDCOverlayAnimationObserver *)observer;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m
new file mode 100644
index 0000000..e3e0bf5
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m
@@ -0,0 +1,107 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayAnimationObserver.h"
+
+@interface MDCOverlayAnimationObserver () {
+ @public
+  /** Whether or not the observer has been primed and should report a runloop end event. */
+  BOOL _primed;  // Raw ivar to allow direct access from the runloop observer callback.
+}
+
+/**
+ The runloop observer being used on the current runloop.
+ */
+@property(nonatomic, strong) __attribute__((NSObject)) CFRunLoopObserverRef observer;
+
+/**
+ Called by the runloop observer C function.
+ */
+- (void)handleObserverFired;
+
+@end
+
+#pragma mark - Runloop Observer
+
+static void runloopObserverCallback(CFRunLoopObserverRef observer,
+                                    CFRunLoopActivity activity,
+                                    void *info) {
+  MDCOverlayAnimationObserver *animationObserver = (__bridge MDCOverlayAnimationObserver *)info;
+  if (animationObserver != NULL && animationObserver->_primed) {
+    [animationObserver handleObserverFired];
+  }
+}
+
+@implementation MDCOverlayAnimationObserver
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    [self installRunloopObserver];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [self uninstallRunloopObserver];
+}
+
+- (void)messageDelegateOnNextRunloop {
+  _primed = YES;
+}
+
+#pragma mark - Runloop Observer
+
+- (void)installRunloopObserver {
+  if (self.observer != NULL) {
+    return;
+  }
+
+  CFRunLoopRef runloop = CFRunLoopGetMain();
+  CFRunLoopObserverContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
+
+  CFRunLoopObserverRef observer =
+      CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting,
+                              YES,  // Repeats
+                              0,    // Order. Lower == earlier.
+                              &runloopObserverCallback, &context);
+
+  if (observer != NULL) {
+    // Schedule the observer and hold on to it.
+    self.observer = observer;
+    CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes);
+
+    // Clean up.
+    CFRelease(observer);
+  }
+}
+
+- (void)uninstallRunloopObserver {
+  if (self.observer == NULL) {
+    return;
+  }
+
+  CFRunLoopRef runloop = CFRunLoopGetMain();
+  CFRunLoopRemoveObserver(runloop, self.observer, kCFRunLoopCommonModes);
+  self.observer = nil;
+}
+
+- (void)handleObserverFired {
+  [self.delegate animationObserverDidEndRunloop:self];
+  _primed = NO;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h
new file mode 100644
index 0000000..970ef4c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h
@@ -0,0 +1,36 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCOverlayTransitioning.h"
+
+/**
+ Object representing a single overlay being displayed on screen.
+ */
+@interface MDCOverlayObserverOverlay : NSObject <MDCOverlay>
+
+/**
+ The unique identifier for the given overlay.
+ */
+@property(nonatomic, copy) NSString *identifier;
+
+/**
+ The frame of the overlay, in screen coordinates.
+ */
+@property(nonatomic) CGRect frame;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m
new file mode 100644
index 0000000..90dfe24
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m
@@ -0,0 +1,26 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayObserverOverlay.h"
+#import "MDCOverlayUtilities.h"
+
+@implementation MDCOverlayObserverOverlay
+
+- (CGRect)overlayFrameInView:(UIView *)targetView {
+  return MDCOverlayConvertRectToView(self.frame, targetView);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h
new file mode 100644
index 0000000..6034f22
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.h
@@ -0,0 +1,52 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+#import "MDCOverlayTransitioning.h"
+
+/**
+ Object representing the a transition between overlays on screen.
+ */
+@interface MDCOverlayObserverTransition : NSObject <MDCOverlayTransitioning>
+
+/**
+ If animated, the timing function of the transition animation.
+ */
+@property(nonatomic) CAMediaTimingFunction *customTimingFunction;
+
+/**
+ If animated, the curve of the transition animation.
+ */
+@property(nonatomic) UIViewAnimationCurve animationCurve;
+
+/**
+ If animated, the duration of the transition animation.
+ */
+@property(nonatomic) NSTimeInterval duration;
+
+/**
+ The overlays represented by this transition.
+ */
+@property(nonatomic, copy) NSArray *overlays;
+
+/**
+ Sets up an animation block (or none) and executes all of the animation blocks registered as part
+ of the MDCOverlayTransitioning protocol.
+ */
+- (void)runAnimation;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.m
new file mode 100644
index 0000000..3c6e987
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayObserverTransition.m
@@ -0,0 +1,160 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayObserverTransition.h"
+
+#import "MDCOverlayObserverOverlay.h"
+#import "MDCOverlayUtilities.h"
+
+@interface MDCOverlayObserverTransition ()
+
+/**
+ Blocks to run as part of the transition.
+ */
+@property(nonatomic) NSMutableArray *animationBlocks;
+
+/**
+ Completion blocks to run when the transition animation finishes.
+ */
+@property(nonatomic) NSMutableArray *completionBlocks;
+
+@end
+
+@implementation MDCOverlayObserverTransition
+
+- (instancetype)init {
+  self = [super init];
+  if (self != nil) {
+    _animationBlocks = [NSMutableArray array];
+    _completionBlocks = [NSMutableArray array];
+  }
+  return self;
+}
+
+/**
+ Runs the given animation block with the provided animation options, knowing that this method will
+ only run as part of @c runAnimation.
+ */
+- (void)runAnimationWithOptions:(UIViewAnimationOptions)options
+                     animations:(void (^)(void))animations {
+  if (self.duration > 0) {
+    UIViewAnimationOptions optionsToUse = options;
+
+    // Don't let the caller override the curve or the duration.
+    optionsToUse &= ~UIViewAnimationOptionOverrideInheritedDuration;
+    optionsToUse &= ~UIViewAnimationOptionOverrideInheritedOptions;
+
+    // Run a nested animation. We'll use a token animation duration, which will be ignored because
+    // this will be a nested animation.
+    [UIView animateWithDuration:1.0f
+                          delay:0.0f
+                        options:optionsToUse
+                     animations:animations
+                     completion:nil];
+  } else {
+    // Just execute the animation block if non-animated.
+    animations();
+  }
+}
+
+- (void)animateAlongsideTransitionWithOptions:(UIViewAnimationOptions)options
+                                   animations:(void (^)(void))animations
+                                   completion:(void (^)(BOOL finished))completion {
+  if (animations != nil) {
+    // Capture the options and animation block, to be executed later when @c runAnimation is called.
+    void (^animationToRun)(void) = ^{
+      [self runAnimationWithOptions:options animations:animations];
+    };
+
+    [self.animationBlocks addObject:[animationToRun copy]];
+  }
+
+  if (completion != nil) {
+    [self.completionBlocks addObject:[completion copy]];
+  }
+}
+
+- (void)animateAlongsideTransition:(void (^)(void))animations {
+  [self animateAlongsideTransitionWithOptions:0 animations:animations completion:nil];
+}
+
+- (void)runAnimation {
+  void (^animations)(void) = ^{
+    for (void (^animation)(void) in self.animationBlocks) {
+      animation();
+    }
+  };
+
+  void (^completions)(BOOL) = ^(BOOL finished) {
+    for (void (^completion)(BOOL) in self.completionBlocks) {
+      completion(finished);
+    }
+  };
+
+  if (self.duration > 0) {
+    CAMediaTimingFunction *customTiming = self.customTimingFunction;
+
+    BOOL animationsEnabled = [UIView areAnimationsEnabled];
+    [UIView setAnimationsEnabled:YES];
+
+    if (customTiming != nil) {
+      [CATransaction begin];
+      [CATransaction setAnimationTimingFunction:customTiming];
+    }
+
+    [UIView animateWithDuration:self.duration
+                          delay:0
+                        options:self.animationCurve << 16
+                     animations:animations
+                     completion:completions];
+
+    if (customTiming != nil) {
+      [CATransaction commit];
+    }
+
+    [UIView setAnimationsEnabled:animationsEnabled];
+  } else {
+    animations();
+    completions(YES);
+  }
+}
+
+- (CGRect)compositeFrame {
+  CGRect frame = CGRectNull;
+
+  for (MDCOverlayObserverOverlay *overlay in self.overlays) {
+    frame = CGRectUnion(frame, overlay.frame);
+  }
+
+  return frame;
+}
+
+- (CGRect)compositeFrameInView:(UIView *)targetView {
+  return MDCOverlayConvertRectToView(self.compositeFrame, targetView);
+}
+
+- (void)enumerateOverlays:(void (^)(id<MDCOverlay> overlay, NSUInteger idx, BOOL *stop))handler {
+  if (handler == nil) {
+    return;
+  }
+
+  [self.overlays
+      enumerateObjectsUsingBlock:^(MDCOverlayObserverOverlay *overlay, NSUInteger idx, BOOL *stop) {
+        handler(overlay, idx, stop);
+      }];
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h
new file mode 100644
index 0000000..db1a749
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.h
@@ -0,0 +1,23 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Utility function which converts a rectangle in overlay coordinates into the local coordinate
+ space of the given @c target
+ */
+OBJC_EXPORT CGRect MDCOverlayConvertRectToView(CGRect overlayFrame, UIView *targetView);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.m
new file mode 100644
index 0000000..3f1e04d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/Overlay/src/private/MDCOverlayUtilities.m
@@ -0,0 +1,34 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCOverlayUtilities.h"
+
+CGRect MDCOverlayConvertRectToView(CGRect screenRect, UIView *target) {
+  if (target != nil && !CGRectIsNull(screenRect)) {
+    // Overlay rectangles are in screen fixed coordinates in iOS 8. If available, we'll use that
+    // API to do the conversion.
+    UIScreen *screen = [UIScreen mainScreen];
+    if ([screen respondsToSelector:@selector(fixedCoordinateSpace)]) {
+      return [target convertRect:screenRect fromCoordinateSpace:screen.fixedCoordinateSpace];
+    }
+
+    // If we can't use coordinate spaces (iOS 8 only), then convert the rectangle from screen
+    // coordinates to our own view. On iOS 7 and below, the window is the same size as the screen's
+    // bounds, so we can safely convert from window coordinates here and get the same outcome.
+    return [target convertRect:screenRect fromView:nil];
+  }
+  return CGRectNull;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.h
new file mode 100644
index 0000000..2f97c25
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.h
@@ -0,0 +1,93 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Leading autoresizing mask based on layoutDirection. 'Leading' is 'Left' in
+ UIUserInterfaceLayoutDirectionLeftToRight, 'Right' otherwise.
+
+ @param layoutDirection The layout direction to consider to compute the autoresizing mask.
+ @return The leading margin part of an autoresizing mask.
+ */
+UIViewAutoresizing MDCAutoresizingFlexibleLeadingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection);
+
+/**
+ Trailing autoresizing masks based on layoutDirection. 'Trailing' is 'Right' in
+ UIUserInterfaceLayoutDirectionLeftToRight, 'Left' otherwise.
+
+ @param layoutDirection The layout direction to consider to compute the autoresizing mask.
+ @return The trailing margin part of an autoresizing mask.
+ */
+UIViewAutoresizing MDCAutoresizingFlexibleTrailingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection);
+
+/**
+ The frame to use when actually laying out a view in its superview.
+
+ A view is conceptually positioned within its superview in terms of leading/trailing. When it's time
+ to actually lay out (i.e. setting frames), leading/trailing needs to be converted to left/right,
+ based on the layout direction. Use this method to compute the international frame to use at layout
+ time.
+
+ @note Example: placing a view 50pts wide at 10pts from the leading edge of its parent 100pts wide.
+   CGRect frame = MDCRectFlippedForRTL(CGRectMake(10, originY, 50, height), 100, layoutDirection);
+
+ In LTR, frame is { { 10, originY }, { 50, height } }.
+  +----------------------------------------100----------------------------------------+
+  |                                                                                   |
+  | 10 +--------------------50--------------------+                                   |
+  |    |                                          |                                   |
+  |    +------------------------------------------+                                   |
+  |                                                                                   |
+  +----------------------------------------100----------------------------------------+
+
+ In RTL, frame is { { 40, originY }, { 50, height } }.
+  +----------------------------------------100----------------------------------------+
+  |                                                                                   |
+  |                                40 +--------------------50--------------------+    |
+  |                                   |                                          |    |
+  |                                   +------------------------------------------+    |
+  |                                                                                   |
+  +----------------------------------------100----------------------------------------+
+
+ @param leftToRightRect The frame to convert.
+ @param boundingWidth The superview's bounds's width.
+ @param layoutDirection The layout direction to consider to compute the layout origin.
+ @return The frame ready for layout, already internationalized based on the layout direction.
+ */
+CGRect MDCRectFlippedForRTL(CGRect leftToRightRect,
+                            CGFloat boundingWidth,
+                            UIUserInterfaceLayoutDirection layoutDirection);
+
+/**
+ Creates an UIEdgeInsets instance from the parameters while obeying layoutDirection.
+
+ If layoutDirection is UIUserInterfaceLayoutDirectionLeftToRight, then the left inset is leading and
+ the right inset is trailing, otherwise they are reversed.
+
+ @param top The top inset.
+ @param leading The leading inset.
+ @param bottom The bottom inset.
+ @param trailing The trailing inset.
+ @return Insets in terms of left/right, already internationalized based on the layout direction.
+ */
+UIEdgeInsets MDCInsetsMakeWithLayoutDirection(CGFloat top,
+                                              CGFloat leading,
+                                              CGFloat bottom,
+                                              CGFloat trailing,
+                                              UIUserInterfaceLayoutDirection layoutDirection);
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.m
new file mode 100644
index 0000000..2708c4d
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MDCRTL.m
@@ -0,0 +1,80 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCRTL.h"
+
+static CGFloat MDCOriginForLeadingInset(CGFloat leadingInset,
+                                        CGFloat width,
+                                        CGFloat boundingWidth,
+                                        UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return leadingInset;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return boundingWidth - leadingInset - width;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIUserInterfaceLayoutDirectionLeftToRight;
+}
+
+UIViewAutoresizing MDCAutoresizingFlexibleLeadingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return UIViewAutoresizingFlexibleLeftMargin;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return UIViewAutoresizingFlexibleRightMargin;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIViewAutoresizingFlexibleLeftMargin;
+}
+
+UIViewAutoresizing MDCAutoresizingFlexibleTrailingMargin(
+    UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return UIViewAutoresizingFlexibleRightMargin;
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return UIViewAutoresizingFlexibleLeftMargin;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIViewAutoresizingFlexibleRightMargin;
+}
+
+CGRect MDCRectFlippedForRTL(CGRect leftToRightRect,
+                            CGFloat boundingWidth,
+                            UIUserInterfaceLayoutDirection layoutDirection) {
+  leftToRightRect = CGRectStandardize(leftToRightRect);
+  leftToRightRect.origin.x =
+      MDCOriginForLeadingInset(CGRectGetMinX(leftToRightRect), CGRectGetWidth(leftToRightRect),
+                               boundingWidth, layoutDirection);
+  return leftToRightRect;
+}
+
+UIEdgeInsets MDCInsetsMakeWithLayoutDirection(CGFloat top,
+                                              CGFloat leading,
+                                              CGFloat bottom,
+                                              CGFloat trailing,
+                                              UIUserInterfaceLayoutDirection layoutDirection) {
+  switch (layoutDirection) {
+    case UIUserInterfaceLayoutDirectionLeftToRight:
+      return UIEdgeInsetsMake(top, leading, bottom, trailing);
+    case UIUserInterfaceLayoutDirectionRightToLeft:
+      return UIEdgeInsetsMake(top, trailing, bottom, leading);
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)layoutDirection);
+  return UIEdgeInsetsMake(top, leading, bottom, trailing);
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MaterialRTL.h
new file mode 100644
index 0000000..8d3de97
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/MaterialRTL.h
@@ -0,0 +1,19 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCRTL.h"
+#import "UIImage+MaterialRTL.h"
+#import "UIView+MaterialRTL.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
new file mode 100644
index 0000000..68d02af
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.h
@@ -0,0 +1,38 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Partial backporting of iOS 9's `-[UIImage imageFlippedForRightToLeftLayoutDirection]`. In Apple's
+ iOS 9 implementation, the image is not actually flipped, but prepared to be flipped when displayed
+ in a Right-to-Left environment, i.e. it's just an additional flag on the UIImage (like
+ `imageOrientation`, `scale` or `resizingMode` for example). On iOS 8, the partial backporting
+ actually flips the image, so this method should only be called when in an RTL environment already.
+ TODO: consider solutions to complete the backporting to get the same behavior.
+ https://github.com/material-components/material-components-ios/issues/599
+ */
+
+@interface UIImage (MaterialRTL)
+
+/**
+ On iOS 9 and above, returns a copy of the current image, prepared to flip horizontally if it's in a
+ right-to-left layout. Prior to iOS 9, it returns the image already flipped in place. For that
+ reason, it should be called only in RTL environments.
+ */
+- (UIImage *)mdc_imageFlippedForRightToLeftLayoutDirection;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.m
new file mode 100644
index 0000000..9f87fe7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIImage+MaterialRTL.m
@@ -0,0 +1,134 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIImage+MaterialRTL.h"
+
+/** Returns the horizontally flipped version of the given UIImageOrientation. */
+static UIImageOrientation MDCRTLMirroredOrientation(UIImageOrientation sourceOrientation) {
+  switch (sourceOrientation) {
+    case UIImageOrientationUp:
+      return UIImageOrientationUpMirrored;
+    case UIImageOrientationDown:
+      return UIImageOrientationDownMirrored;
+    case UIImageOrientationLeft:
+      return UIImageOrientationLeftMirrored;
+    case UIImageOrientationRight:
+      return UIImageOrientationRightMirrored;
+    case UIImageOrientationUpMirrored:
+      return UIImageOrientationUp;
+    case UIImageOrientationDownMirrored:
+      return UIImageOrientationDown;
+    case UIImageOrientationLeftMirrored:
+      return UIImageOrientationLeft;
+    case UIImageOrientationRightMirrored:
+      return UIImageOrientationRight;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)sourceOrientation);
+  return UIImageOrientationUpMirrored;
+}
+
+/**
+ Returns a copy of the image actually flipped. The orientation and scale are consumed, while the
+ rendering mode is ported to the new image.
+ On iOS 9 and above, use `-[UIView imageFlippedForRightToLeftLayoutDirection]` instead.
+ */
+static UIImage *MDCRTLFlippedImage(UIImage *image) {
+  NSCAssert(![image respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)],
+            @"Do not call this method on iOS 9 and above.");
+  CGSize size = [image size];
+  CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
+
+  UIGraphicsBeginImageContextWithOptions(rect.size, NO, image.scale);
+  CGContextRef context = UIGraphicsGetCurrentContext();
+  CGContextSetShouldAntialias(context, true);
+  CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
+
+  // Note: UIKit's and CoreGraphics coordinates systems are flipped vertically (UIKit's Y axis goes
+  // down, while CoreGraphics' goes up).
+  switch (image.imageOrientation) {
+    case UIImageOrientationUp:
+      CGContextScaleCTM(context, -1, -1);
+      CGContextTranslateCTM(context, -rect.size.width, -rect.size.height);
+      break;
+    case UIImageOrientationDown:
+      // Orientation down is equivalent to a 180º rotation. The difference in coordinates systems is
+      // thus sufficient and nothing needs to be down to flip the image.
+      break;
+    case UIImageOrientationLeft:
+      CGContextRotateCTM(context, -(CGFloat)M_PI / 2.f);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    case UIImageOrientationRight:
+      CGContextRotateCTM(context, (CGFloat)M_PI / 2);
+      CGContextTranslateCTM(context, 0, -rect.size.width);
+      break;
+    case UIImageOrientationUpMirrored:
+      CGContextScaleCTM(context, 1, -1);
+      CGContextTranslateCTM(context, 0, -rect.size.height);
+      break;
+    case UIImageOrientationDownMirrored:
+      CGContextScaleCTM(context, -1, 1);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    case UIImageOrientationLeftMirrored:
+      CGContextRotateCTM(context, -(CGFloat)M_PI / 2);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      CGContextScaleCTM(context, -1, 1);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    case UIImageOrientationRightMirrored:
+      CGContextRotateCTM(context, (CGFloat)M_PI / 2);
+      CGContextTranslateCTM(context, 0, -rect.size.width);
+      CGContextScaleCTM(context, -1, 1);
+      CGContextTranslateCTM(context, -rect.size.width, 0);
+      break;
+    default:
+      NSCAssert(NO, @"Invalid enumeration value %i.", (int)image.imageOrientation);
+  }
+
+  CGContextDrawImage(context, rect, image.CGImage);
+
+  UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext();
+  UIGraphicsEndImageContext();
+
+  // Port the rendering mode.
+  flippedImage = [flippedImage imageWithRenderingMode:image.renderingMode];
+  return flippedImage;
+}
+
+@implementation UIImage (MaterialRTL)
+
+- (UIImage *)mdc_imageFlippedForRightToLeftLayoutDirection {
+  // On iOS 9 and above, UIImage supports being prepared for flipping. Otherwise, do the flip
+  // manually.
+  if ([self respondsToSelector:@selector(imageFlippedForRightToLeftLayoutDirection)]) {
+    return [self imageFlippedForRightToLeftLayoutDirection];
+  } else {
+    // -[UIImage imageWithCGImage:scale:orientation:] looses the rendering mode.
+    // If the image has a default rendering mode (i.e. UIImageRenderingModeAutomatic), it is fine to
+    // use it.
+    //
+    if (self.renderingMode == UIImageRenderingModeAutomatic) {
+      return [[self class] imageWithCGImage:self.CGImage
+                                      scale:self.scale
+                                orientation:MDCRTLMirroredOrientation(self.imageOrientation)];
+    } else {  // Otherwise, flip the image manually.
+      return MDCRTLFlippedImage(self);
+    }
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
new file mode 100644
index 0000000..5f42535
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.h
@@ -0,0 +1,80 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+/**
+ Complete backporting of iOS 9's `-[UIView semanticContentAttribute]` and
+ `+[UIView userInterfaceLayoutDirectionForSemanticContentAttribute:]`, and iOS 10's
+ `-[UIView effectiveUserInterfaceLayoutDirection]` and
+ `+[UIView userInterfaceLayoutDirectionForSemanticContentAttribute:relativeToLayoutDirection:]`.
+ */
+
+@interface UIView (MaterialRTL)
+
+/**
+ A semantic description of the view's contents, used to determine whether the view should be flipped
+ when switching between left-to-right and right-to-left layouts.
+
+ @note Default:
+   - iOS 8 and below: UISemanticContentAttributeUnspecified.
+   - iOS 9 and above: same as -[UIView semanticContentAttribute]
+ */
+@property(nonatomic, setter=mdc_setSemanticContentAttribute:)
+    UISemanticContentAttribute mdc_semanticContentAttribute;
+
+/**
+ The user interface layout direction appropriate for arranging the immediate content of this view.
+
+ Always consult the mdc_effectiveUserInterfaceLayoutDirection of the view whose immediate content is
+ being arranged or drawn. Do not assume that the value propagates through the view's subtree.
+
+ @note
+   - iOS 9 and below: same as +[UIView mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:]
+   - iOS 10 and above: same as -[UIView effectiveUserInterfaceLayoutDirection]
+ */
+@property(nonatomic, readonly)
+    UIUserInterfaceLayoutDirection mdc_effectiveUserInterfaceLayoutDirection;
+
+/**
+ Returns the layout direction implied by the provided semantic content attribute relative to the
+ application-wide layout direction (as returned by
+ UIApplication.sharedApplication.userInterfaceLayoutDirection).
+
+ @param semanticContentAttribute The semantic content attribute.
+ @return The layout direction.
+ */
++ (UIUserInterfaceLayoutDirection)mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute;
+
+/**
+ Returns the layout direction implied by the provided semantic content attribute relative to the
+ provided layout direction. For example, when provided a layout direction of
+ RightToLeft and a semantic content attribute of Playback, this method returns LeftToRight. Layout
+ and drawing code can use this method to determine how to arrange elements, but might find it easier
+ to query the container view's mdc_effectiveUserInterfaceLayoutDirection property instead.
+
+ @param semanticContentAttribute The semantic content attribute.
+ @param layoutDirection The layout direction to consider.
+ @return The implied layout direction.
+ */
++ (UIUserInterfaceLayoutDirection)
+    mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute
+                                      relativeToLayoutDirection:
+                                          (UIUserInterfaceLayoutDirection)layoutDirection;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.m
new file mode 100644
index 0000000..1729e27
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/RTL/src/UIView+MaterialRTL.m
@@ -0,0 +1,151 @@
+/*
+ Copyright 2016-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "UIView+MaterialRTL.h"
+
+#import <objc/runtime.h>
+
+#define MDC_BASE_SDK_EQUAL_OR_ABOVE(x) \
+  (defined(__IPHONE_##x) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_##x))
+
+static inline UIUserInterfaceLayoutDirection
+    MDCUserInterfaceLayoutDirectionForSemanticContentAttributeRelativeToLayoutDirection(
+        UISemanticContentAttribute semanticContentAttribute,
+        UIUserInterfaceLayoutDirection userInterfaceLayoutDirection) {
+  switch (semanticContentAttribute) {
+    case UISemanticContentAttributeUnspecified:
+      return userInterfaceLayoutDirection;
+    case UISemanticContentAttributePlayback:
+    case UISemanticContentAttributeSpatial:
+    case UISemanticContentAttributeForceLeftToRight:
+      return UIUserInterfaceLayoutDirectionLeftToRight;
+    case UISemanticContentAttributeForceRightToLeft:
+      return UIUserInterfaceLayoutDirectionRightToLeft;
+  }
+  NSCAssert(NO, @"Invalid enumeration value %i.", (int)semanticContentAttribute);
+  return userInterfaceLayoutDirection;
+}
+
+@interface UIView (MaterialRTLPrivate)
+
+// On iOS 9 and above, mdc_semanticContentAttribute is backed by UIKit's semanticContentAttribute.
+// On iOS 8 and below, mdc_semanticContentAttribute is backed by an associated object.
+@property(nonatomic, setter=mdc_setAssociatedSemanticContentAttribute:)
+    UISemanticContentAttribute mdc_associatedSemanticContentAttribute;
+
+@end
+
+@implementation UIView (MaterialRTL)
+
+- (UISemanticContentAttribute)mdc_semanticContentAttribute {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  if ([self respondsToSelector:@selector(semanticContentAttribute)]) {
+    return self.semanticContentAttribute;
+  } else
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  {
+    return self.mdc_associatedSemanticContentAttribute;
+  }
+}
+
+- (void)mdc_setSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  if ([self respondsToSelector:@selector(semanticContentAttribute)]) {
+    self.semanticContentAttribute = semanticContentAttribute;
+  } else
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  {
+    self.mdc_associatedSemanticContentAttribute = semanticContentAttribute;
+  }
+
+  // Invalidate the layout.
+  [self setNeedsLayout];
+}
+
+- (UIUserInterfaceLayoutDirection)mdc_effectiveUserInterfaceLayoutDirection {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+  if ([self respondsToSelector:@selector(effectiveUserInterfaceLayoutDirection)]) {
+    return self.effectiveUserInterfaceLayoutDirection;
+  } else {
+    return [UIView mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+                       self.mdc_semanticContentAttribute];
+  }
+#else
+  return [UIView mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+                     self.mdc_semanticContentAttribute];
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+}
+
++ (UIUserInterfaceLayoutDirection)mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)attribute {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  if ([self
+          respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:)]) {
+    return [self userInterfaceLayoutDirectionForSemanticContentAttribute:attribute];
+  } else
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(9_0)
+  {
+    // Use a default of Left-to-Right, as UIKit in iOS 8 and below doesn't support native RTL
+    // layout.
+    UIUserInterfaceLayoutDirection applicationLayoutDirection =
+        UIUserInterfaceLayoutDirectionLeftToRight;
+    return [self
+        mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:attribute
+                                          relativeToLayoutDirection:applicationLayoutDirection];
+  }
+}
+
++ (UIUserInterfaceLayoutDirection)
+    mdc_userInterfaceLayoutDirectionForSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute
+                                      relativeToLayoutDirection:
+                                          (UIUserInterfaceLayoutDirection)layoutDirection {
+#if MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+  if ([self
+          respondsToSelector:@selector(userInterfaceLayoutDirectionForSemanticContentAttribute:
+                                                                     relativeToLayoutDirection:)]) {
+    return [self userInterfaceLayoutDirectionForSemanticContentAttribute:semanticContentAttribute
+                                               relativeToLayoutDirection:layoutDirection];
+  } else {
+    return MDCUserInterfaceLayoutDirectionForSemanticContentAttributeRelativeToLayoutDirection(
+        semanticContentAttribute, layoutDirection);
+  }
+#else
+  return MDCUserInterfaceLayoutDirectionForSemanticContentAttributeRelativeToLayoutDirection(
+      semanticContentAttribute, layoutDirection);
+#endif  // MDC_BASE_SDK_EQUAL_OR_ABOVE(10_0)
+}
+
+@end
+
+@implementation UIView (MaterialRTLPrivate)
+
+- (UISemanticContentAttribute)mdc_associatedSemanticContentAttribute {
+  NSNumber *semanticContentAttributeNumber =
+      objc_getAssociatedObject(self, @selector(mdc_semanticContentAttribute));
+  if (semanticContentAttributeNumber) {
+    return [semanticContentAttributeNumber integerValue];
+  }
+  return UISemanticContentAttributeUnspecified;
+}
+
+- (void)mdc_setAssociatedSemanticContentAttribute:
+        (UISemanticContentAttribute)semanticContentAttribute {
+  objc_setAssociatedObject(self, @selector(mdc_semanticContentAttribute),
+                           @(semanticContentAttribute), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
new file mode 100644
index 0000000..f453b18
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCNumericValueLabel : UIView
+
+/** The background color of the value label. */
+@property(nonatomic, retain) UIColor *backgroundColor;
+
+/** The text color of the label. */
+@property(nonatomic, retain) UIColor *textColor;
+
+/** The size of the value label. */
+@property(nonatomic) CGFloat fontSize;
+
+/** The text to be displayed in the value label. */
+@property(nonatomic, copy) NSString *text;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.m
new file mode 100644
index 0000000..0beaac4
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCNumericValueLabel.m
@@ -0,0 +1,147 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCNumericValueLabel.h"
+
+#import "MDCTypography.h"
+
+static const CGFloat kAnchorPointY = 1.15f;
+static const CGFloat kBezierSmoothingFactor = 0.0625f;
+static const CGFloat kLabelInsetSize = 6.f;
+
+@implementation MDCNumericValueLabel {
+  CAShapeLayer *_marker;
+  UILabel *_label;
+}
+
+/**
+ Inits a new numeric value label. Note that we expect the frame to be taller than it is wide, in
+ order to correctly display the "ice cream cone" shape.
+ */
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.backgroundColor = [UIColor clearColor];
+
+    _marker = [CAShapeLayer layer];
+    _marker.fillRule = kCAFillRuleNonZero;
+    [self.layer addSublayer:_marker];
+
+    _label = [[UILabel alloc] init];
+    _label.textAlignment = NSTextAlignmentCenter;
+    _label.textColor = [UIColor whiteColor];  // Default text color, override by setting textColor
+    _label.font = [MDCTypography body1Font];  // Default font size, override by setting fontSize
+    _label.adjustsFontSizeToFitWidth = YES;
+    _label.minimumScaleFactor = 0.7f;
+    [self addSubview:_label];
+
+    // So that scaling happens in relation to slightly below the thumb track. Also has the nice
+    // effect of letting us set the view's "center" to be on the track, but have the view actually
+    // appear above the thumb track.
+    self.layer.anchorPoint = CGPointMake(0.5f, kAnchorPointY);
+  }
+  return self;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  CGFloat width = self.bounds.size.width;
+  CGFloat radius = width / 2;
+  CGFloat height = self.bounds.size.height;
+  CGFloat bezierSmoothingPixels = height * kBezierSmoothingFactor;
+
+  CGMutablePathRef path = CGPathCreateMutable();
+
+  // We're drawing a shape that looks something like this:
+  //   __
+  //  (  )
+  //   \/
+
+  // Calculate what point on the circle the lines on the bottom should touch. If you're interested
+  // in the Math, we found these formulas like this:
+  // 1. x^2 + y^2 = r defines the circle
+  // 2. y = H - mx defines a family of lines from (0,H) where H is the height of the whole shape
+  // 3. Now we try to find m such that the system of equations has only one (x,y) solution that
+  //    satisfies both equations. This amounts to finding the line from (0,H) to the circle that
+  //    only touches the circle one time.
+  // 4. Substitute y = H - mx into first equation. x^2 + (H-mx)^2 = r^2
+  // 5. Simplify and set to 0. (1 + m^2)x^2 + (-2Hm)x + (H^2 - r^2) = 0
+  // 6. We now have a quadratic equation of the form ax^2 + bx + c = 0. Such equations have only
+  //    one solution if and only if the discriminant d = b^2 - 4ac = 0
+  // 7. Set discriminant to 0 and solve for m. 0 = (-2Hm)^2 - 4(1 + m^2)(H^2 - r^2)
+  // 8. m = sqrt((H^2 - r^2)/(r^2))
+  // 9. Now use quadratic formula to solve for x. x = (r * sqrt(H^2 - r^2)) / H
+  // 10. Plug into original equation to get y. y = r^2 / H
+  CGFloat x = (radius * sqrtf((float)(height * height - radius * radius))) / height;
+  CGFloat y = radius * radius / height;
+
+  // Calculate the angles at which the left and right lines touch the circle
+  CGFloat angleDelta = atanf((float)(y / x));
+  CGFloat startAngle = (float)M_PI - angleDelta;
+  CGFloat endAngle = angleDelta;
+
+  CGPathMoveToPoint(path, NULL, radius, height);
+
+  // Draws line from bottom to left side of circle, curving slightly to smooth the shape
+  CGPathAddCurveToPoint(path, NULL, radius, height, radius - x, radius + y + bezierSmoothingPixels,
+                        radius - x, radius + y);
+
+  // Draw the part of the circle that we need
+  CGPathAddArc(path, NULL, radius, radius, radius, startAngle, endAngle, NO);
+
+  // Curve back down from the right side of the circle to the bottom of the shape
+  CGPathAddCurveToPoint(path, NULL, radius + x, radius + y + bezierSmoothingPixels, radius, height,
+                        radius, height);
+  CGPathCloseSubpath(path);
+
+  _marker.path = path;
+  CGPathRelease(path);
+
+  // Place the label as well
+  _label.frame = CGRectInset(CGRectMake(0, 0, width, width), kLabelInsetSize, kLabelInsetSize);
+}
+
+- (void)setBackgroundColor:(UIColor *)backgroundColor {
+  _backgroundColor = backgroundColor;
+  _marker.fillColor = _backgroundColor.CGColor;
+}
+
+- (UIColor *)textColor {
+  return _label.textColor;
+}
+
+- (void)setTextColor:(UIColor *)textColor {
+  _label.textColor = textColor;
+}
+
+- (CGFloat)fontSize {
+  return _label.font.pointSize;
+}
+
+- (void)setFontSize:(CGFloat)fontSize {
+  _label.font = [[MDCTypography fontLoader] regularFontOfSize:fontSize];
+}
+
+- (NSString *)text {
+  return _label.text;
+}
+
+- (void)setText:(NSString *)text {
+  _label.text = text;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
new file mode 100644
index 0000000..f3ac73a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.h
@@ -0,0 +1,261 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@class MDCThumbView;
+@protocol MDCThumbTrackDelegate;
+
+@interface MDCThumbTrack : UIControl
+
+/** The delegate for the thumb track. */
+@property(nullable, nonatomic, weak) id<MDCThumbTrackDelegate> delegate;
+
+@property(nullable, nonatomic, strong) UIColor *primaryColor;
+
+/** The color of the thumb off color. */
+@property(nullable, nonatomic, strong) UIColor *thumbOffColor;
+
+/** The color of the track off color. */
+@property(nullable, nonatomic, strong) UIColor *trackOffColor;
+
+/** The color of the thumb disabled color. */
+@property(nullable, nonatomic, strong) UIColor *thumbDisabledColor;
+
+/** The color of the track disabled color. */
+@property(nullable, nonatomic, strong) UIColor *trackDisabledColor;
+
+/** Dummy property to unbreak internal clients. */
+/** TODO(#1216): Remove this property */
+@property(nonatomic, assign) BOOL interpolateOnOffColors;
+
+/**
+ The number of discrete values that the thumb can take along the track. If this property is zero,
+ then the slider operates continuously and doesn't do any snapping after the user releases the
+ thumb. If this property is greater or equal to two, then the thumb will snap to the nearest
+ discrete value on when the user lifts their finger or taps. The set of discrete values is
+ equivalent to
+ { minimumValue +  (i / (numDiscreteValues - 1.0)) * (maximumValue - minimumValue) } for
+ i = 0..numDiscreteValues-1.
+
+ The default value is zero. If numDiscreteValues is set to one, then the thumb track will act as
+ if numDiscreteValues is zero and will judge you silently.
+ */
+@property(nonatomic, assign) NSUInteger numDiscreteValues;
+
+/**
+  The value of the thumb along the track.
+
+ Setting this property causes the receiver to redraw itself using the new value. To render an
+ animated transition from the current value to the new value you should use the setValue:animated:
+ method instead. Setting the value to does not result in an action message being sent.
+
+ If you try to set a value that is below the minimum or above the maximum value, the minimum or
+ maximum value is set instead. The default value of this property is 0.0.
+ */
+@property(nonatomic, assign) CGFloat value;
+
+/**
+  The minimum value of the thumb along the track.
+
+ If you change the value of this property, and the current value of the receiver is below the new
+ minimum, the current value is adjusted to match the new minimum value automatically.
+
+ The default value of this property is 0.0.
+ */
+@property(nonatomic, assign) CGFloat minimumValue;
+
+/**
+ The maximum value of the thumb along the track.
+
+ If you change the value of this property, and the current value of the receiver is above the new
+ maximum, the current value is adjusted to match the new maximum value automatically.
+
+ The default value of this property is 1.0.
+ */
+@property(nonatomic, assign) CGFloat maximumValue;
+
+/** The current position of the center of the thumb in this view's coordinates. */
+@property(nonatomic, assign, readonly) CGPoint thumbPosition;
+
+/** The height of the track that the thumb moves along. */
+@property(nonatomic, assign) CGFloat trackHeight;
+
+/** The radius of the track thumb that moves along the track. */
+@property(nonatomic, assign) CGFloat thumbRadius;
+
+/** Whether or not the thumb should be smaller when the track is disabled. Defaults to NO. */
+@property(nonatomic, assign) BOOL thumbIsSmallerWhenDisabled;
+
+/**
+ Whether or not the thumb view should be a hollow circle when at the start position. Defaults to
+ NO.
+ */
+@property(nonatomic, assign) BOOL thumbIsHollowAtStart;
+
+/** Whether or not the thumb should grow when the user is dragging it. Default is NO. */
+@property(nonatomic, assign) BOOL thumbGrowsWhenDragging;
+
+/** The max radius of the ripple when the user touches the thumb. */
+@property(nonatomic, assign) CGFloat thumbMaxRippleRadius;
+
+/** Whether the thumb should display ink splashes on touch. */
+@property(nonatomic, assign) BOOL shouldDisplayInk;
+
+/** Whether or not to display dots indicating discrete locations. Default is NO. */
+@property(nonatomic, assign) BOOL shouldDisplayDiscreteDots;
+
+/** Whether or not to show the numeric value label when dragging a discrete slider. */
+@property(nonatomic, assign) BOOL shouldDisplayDiscreteValueLabel;
+
+/** Whether a disabled thumb track includes gaps on either side of the thumb. The default is NO. */
+@property(nonatomic, assign) BOOL disabledTrackHasThumbGaps;
+
+/** Whether the ends of the thumb track should be rounded. The default is NO. */
+@property(nonatomic, assign) BOOL trackEndsAreRounded;
+
+/** Whether the ends of the track are inset by the radius of the thumb. The default is NO. */
+@property(nonatomic, assign) BOOL trackEndsAreInset;
+
+/**
+ The value from which the filled part of the track is anchored. If set to a value between
+ minimumValue and maximumValue, then the filled/colored part of the track extends from the
+ trackAnchorValue to the thumb. Values beyond the minimum/maximum values are effectively capped.
+ The default value is -CGFLOAT_MAX, so the filled part of the track extends from the minimum value
+ to the thumb.
+ */
+@property(nonatomic, assign) CGFloat filledTrackAnchorValue;
+
+/** The thumb view that user moves along the track. */
+@property(nullable, nonatomic, strong) MDCThumbView *thumbView;
+
+/**
+ Contains a Boolean value indicating whether a user's changes in the value generate continuous
+ update events.
+
+ If YES, the slider sends update events continuously to the associated target’s action method.
+ If NO, the slider only sends an action event when the user releases the slider’s thumb control to
+ set the final value.
+
+ The default value of this property is YES.
+ */
+@property(nonatomic, assign) BOOL continuousUpdateEvents;
+
+/**
+ Whether the control should react to pan gestures all along the track, or just on the thumb.
+
+ The default value of this property is NO.
+ */
+@property(nonatomic, assign) BOOL panningAllowedOnEntireControl;
+
+/**
+ Whether the control should react to taps on the thumb itself, as opposed to the track.
+
+ The default value of this property is NO.
+ */
+@property(nonatomic, assign) BOOL tapsAllowedOnThumb;
+
+/**
+ Initialize an instance with a particular frame and color group.
+
+ Designated initializer.
+ */
+- (nonnull instancetype)initWithFrame:(CGRect)frame onTintColor:(nullable UIColor *)onTintColor;
+
+/**
+ Set the value of the thumb along the track.
+
+ If animated is YES, the thumb is animated into its new position. Setting the value does not
+ result in an action message being sent.
+
+ @param value The value to set the slider to.
+ @param animated If YES, the thumb will animate to its new position.
+ */
+- (void)setValue:(CGFloat)value animated:(BOOL)animated;
+
+/**
+ Set the value of the thumb along the track.
+
+ If animated is YES, the thumb is animated into its new position. Setting the value to does not
+ result in an action message being sent.
+
+ @param value The value to set the thumb to.
+ @param animated If YES, the change of value will be animated.
+ @param animateThumbAfterMove If YES, animate the thumb to its new state after moving it into place.
+ @param userGenerated Is this call a direct result of a user's action?
+ @param completion If not NULL, the block will be called after the value is set.
+ */
+- (void)setValue:(CGFloat)value
+                 animated:(BOOL)animated
+    animateThumbAfterMove:(BOOL)animateThumbAfterMove
+            userGenerated:(BOOL)userGenerated
+               completion:(nullable void (^)())completion;
+
+/** Set the @c icon shown on the thumb. */
+- (void)setIcon:(nullable UIImage *)icon;
+
+/** Disable setting multitouch. Has to be NO. */
+- (void)setMultipleTouchEnabled:(BOOL)multipleTouchEnabled NS_UNAVAILABLE;
+
+@end
+
+/** MDCThumbtrack delegate which allows setting custom behavior. */
+@protocol MDCThumbTrackDelegate <NSObject>
+@optional
+
+/**
+ For discrete thumb tracks, used when determining the string label to display for a given discrete
+ value.
+
+ If not implemented, or if no delegate is specified, the thumb track displays the empty string ""
+ for all values.
+
+ @param thumbTrack The thumb track sender.
+ @param value The value whose label needs to be calculated.
+ */
+- (nonnull NSString *)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack stringForValue:(CGFloat)value;
+
+/**
+ Called when the user taps on the MDCThumbTrack.
+ If not implemented, the MDCThumbTrack will always be allowed to jump to any value.
+ */
+- (BOOL)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack shouldJumpToValue:(CGFloat)value;
+
+/**
+ Called when the thumb track will jump to a specific value.
+
+ @param thumbTrack The @c MDCThumbTrack sender.
+ @param value The new value for the slider.
+ */
+- (void)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack willJumpToValue:(CGFloat)value;
+
+/**
+ Called when the thumb track will animate to a specific value.
+
+ @param thumbTrack The @c MDCThumbTrack sender.
+ @param value The new value for the slider.
+ */
+- (void)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack willAnimateToValue:(CGFloat)value;
+
+/**
+ Called just after the thumb track has animated to a specific value.
+
+ @param thumbTrack The @c MDCThumbTrack sender.
+ @param value The new value for the slider.
+ */
+- (void)thumbTrack:(nonnull MDCThumbTrack *)thumbTrack didAnimateToValue:(CGFloat)value;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.m
new file mode 100644
index 0000000..8ed4ce0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbTrack.m
@@ -0,0 +1,1146 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCThumbTrack.h"
+
+#import "MDCNumericValueLabel.h"
+#import "MDCThumbView.h"
+#import "MaterialInk.h"
+#import "MaterialRTL.h"
+
+static const CGFloat kAnimationDuration = 0.25f;
+static const CGFloat kThumbChangeAnimationDuration = 0.12f;
+static const CGFloat kDefaultThumbBorderWidth = 2.0f;
+static const CGFloat kDefaultThumbRadius = 6.0f;
+static const CGFloat kDefaultTrackHeight = 2.0f;
+static const CGFloat kDefaultFilledTrackAnchorValue = -CGFLOAT_MAX;
+static const CGFloat kTrackOnAlpha = 0.5f;
+static const CGFloat kMinTouchSize = 48.0f;
+static const CGFloat kThumbSlopFactor = 3.5f;
+static const CGFloat kValueLabelHeight = 48.f;
+static const CGFloat kValueLabelWidth = 0.81f * kValueLabelHeight;
+static const CGFloat kValueLabelFontSize = 12.f;
+
+// Credit to the Beacon Tools iOS team for the idea for this implementations
+@interface MDCDiscreteDotView : UIView
+
+@property(nonatomic, assign) NSUInteger numDiscreteDots;
+
+@end
+
+@implementation MDCDiscreteDotView
+
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    self.backgroundColor = [UIColor clearColor];
+  }
+  return self;
+}
+
+- (void)setFrame:(CGRect)frame {
+  [super setFrame:frame];
+  [self setNeedsDisplay];
+}
+
+- (void)drawRect:(CGRect)rect {
+  [super drawRect:rect];
+
+  if (_numDiscreteDots >= 2) {
+    CGContextRef contextRef = UIGraphicsGetCurrentContext();
+    CGContextSetFillColorWithColor(contextRef, [UIColor blackColor].CGColor);
+
+    CGRect circleRect = CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height);
+    CGFloat increment = (self.bounds.size.width - self.bounds.size.height) / (_numDiscreteDots - 1);
+
+    for (NSUInteger i = 0; i < _numDiscreteDots; i++) {
+      circleRect.origin.x = (i * increment);
+      CGContextFillEllipseInRect(contextRef, circleRect);
+    }
+  }
+}
+
+- (void)setNumDiscreteDots:(NSUInteger)numDiscreteDots {
+  _numDiscreteDots = numDiscreteDots;
+  [self setNeedsDisplay];
+}
+
+@end
+
+// TODO(iangordon): Properly handle broken tgmath
+static inline CGFloat Fabs(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return fabs(value);
+#else
+  return fabsf(value);
+#endif
+}
+static inline CGFloat Round(CGFloat value) {
+#if CGFLOAT_IS_DOUBLE
+  return round(value);
+#else
+  return roundf(value);
+#endif
+}
+
+static inline CGFloat Hypot(CGFloat x, CGFloat y) {
+#if CGFLOAT_IS_DOUBLE
+  return hypot(x, y);
+#else
+  return hypotf(x, y);
+#endif
+}
+
+static inline bool CGFloatEqual(CGFloat a, CGFloat b) {
+  const CGFloat constantK = 3;
+#if CGFLOAT_IS_DOUBLE
+  const CGFloat epsilon = DBL_EPSILON;
+  const CGFloat min = DBL_MIN;
+#else
+  const CGFloat epsilon = FLT_EPSILON;
+  const CGFloat min = FLT_MIN;
+#endif
+  return (Fabs(a - b) < constantK * epsilon * Fabs(a + b) || Fabs(a - b) < min);
+}
+
+/**
+ Returns the distance between two points.
+
+ @param point1 a CGPoint to measure from.
+ @param point2 a CGPoint to meature to.
+
+ @return Absolute straight line distance.
+ */
+static inline CGFloat DistanceFromPointToPoint(CGPoint point1, CGPoint point2) {
+  return Hypot(point1.x - point2.x, point1.y - point2.y);
+}
+
+#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
+@interface MDCThumbTrack () <CAAnimationDelegate>
+@end
+#endif
+
+@interface MDCThumbTrack () <MDCInkTouchControllerDelegate>
+@end
+
+@implementation MDCThumbTrack {
+  CGFloat _lastDispatchedValue;
+  UIColor *_thumbOnColor;
+  UIColor *_trackOnColor;
+  UIColor *_clearColor;
+  MDCInkTouchController *_touchController;
+  UIView *_trackView;
+  CAShapeLayer *_trackMaskLayer;
+  CALayer *_trackOnLayer;
+  MDCDiscreteDotView *_discreteDots;
+  BOOL _shouldDisplayInk;
+  MDCNumericValueLabel *_valueLabel;
+  UIPanGestureRecognizer *_dummyPanRecognizer;
+
+  // Attributes to handle interaction. To associate touches to previous touches, we keep a reference
+  // to the current touch, since the system reuses the same memory address when sending subsequent
+  // touches for the same gesture. If _currentTouch == nil, then there's no interaction going on.
+  UITouch *_currentTouch;
+  BOOL _isDraggingThumb;
+  BOOL _didChangeValueDuringPan;
+  CGFloat _panThumbGrabPosition;
+}
+
+// TODO(iangordon): ThumbView is not respecting the bounds of ThumbTrack
+- (instancetype)initWithFrame:(CGRect)frame {
+  return [self initWithFrame:frame onTintColor:nil];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame onTintColor:(UIColor *)onTintColor {
+  self = [super initWithFrame:frame];
+  if (self) {
+    self.userInteractionEnabled = YES;
+    [super setMultipleTouchEnabled:NO];  // We only want one touch event at a time
+    _continuousUpdateEvents = YES;
+    _lastDispatchedValue = _value;
+    _maximumValue = 1;
+    _trackHeight = kDefaultTrackHeight;
+    _thumbRadius = kDefaultThumbRadius;
+    _filledTrackAnchorValue = kDefaultFilledTrackAnchorValue;
+    _shouldDisplayInk = YES;
+
+    // Default thumb view.
+    CGRect thumbFrame = CGRectMake(0, 0, self.thumbRadius * 2, self.thumbRadius * 2);
+    _thumbView = [[MDCThumbView alloc] initWithFrame:thumbFrame];
+    _thumbView.borderWidth = kDefaultThumbBorderWidth;
+    _thumbView.cornerRadius = self.thumbRadius;
+    _thumbView.layer.zPosition = 1;
+    [self addSubview:_thumbView];
+
+    _trackView = [[UIView alloc] init];
+    _trackView.userInteractionEnabled = NO;
+    _trackMaskLayer = [CAShapeLayer layer];
+    _trackMaskLayer.fillRule = kCAFillRuleEvenOdd;
+    _trackView.layer.mask = _trackMaskLayer;
+
+    _trackOnLayer = [CALayer layer];
+    [_trackView.layer addSublayer:_trackOnLayer];
+
+    [self addSubview:_trackView];
+
+    // Set up ink layer.
+    _touchController = [[MDCInkTouchController alloc] initWithView:_thumbView];
+    _touchController.delegate = self;
+
+    [_touchController addInkView];
+
+    _touchController.defaultInkView.inkStyle = MDCInkStyleUnbounded;
+
+    // Set colors.
+    if (onTintColor == nil) {
+      onTintColor = [UIColor blueColor];
+    }
+    self.primaryColor = onTintColor;
+    _clearColor = [UIColor colorWithWhite:1.0f alpha:0.0f];
+
+    // We add this UIPanGestureRecognizer to our view so that any superviews of the thumb track know
+    // when we are dragging the thumb track, and can treat it accordingly. Specifically, without
+    // this if a ThumbTrack is contained within a UIScrollView, the scroll view will cancel any
+    // touch events sent to the thumb track whenever the view is scrolling, regardless of whether or
+    // not we're in the middle of dragging the thumb. Adding a dummy gesture recognizer lets the
+    // scroll view know that we are in the middle of dragging, so those touch events shouldn't be
+    // cancelled.
+    //
+    // Note that an alternative to this would be to set canCancelContentTouches = NO on the
+    // UIScrollView, but because we can't guarantee that the thumb track will always be contained in
+    // scroll views configured like that, we have to handle it within the thumb track.
+    _dummyPanRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
+    _dummyPanRecognizer.cancelsTouchesInView = NO;
+    [self updateDummyPanRecognizerTarget];
+
+    [self setValue:_minimumValue animated:NO];
+  }
+  return self;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+
+  [self updateTrackMask];
+  [self updateThumbTrackAnimated:NO animateThumbAfterMove:NO previousValue:_value completion:nil];
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  CGFloat dx = MIN(0, kDefaultThumbRadius - kMinTouchSize / 2);
+  CGFloat dy = MIN(0, (self.bounds.size.height - kMinTouchSize) / 2);
+  CGRect rect = CGRectInset(self.bounds, dx, dy);
+  return CGRectContainsPoint(rect, point);
+}
+
+#pragma mark - Properties
+
+- (void)setPrimaryColor:(UIColor *)primaryColor {
+  if (primaryColor == nil) {
+    primaryColor = [UIColor blueColor];  // YSNBH
+  }
+  _primaryColor = primaryColor;
+  _thumbOnColor = primaryColor;
+  _trackOnColor = primaryColor;
+
+  _touchController.defaultInkView.inkColor = [primaryColor colorWithAlphaComponent:kTrackOnAlpha];
+  [self setNeedsLayout];
+}
+
+- (void)setThumbOffColor:(UIColor *)thumbOffColor {
+  _thumbOffColor = thumbOffColor;
+}
+
+- (void)setThumbDisabledColor:(UIColor *)thumbDisabledColor {
+  _thumbDisabledColor = thumbDisabledColor;
+  [self setNeedsLayout];
+}
+
+- (void)setTrackOffColor:(UIColor *)trackOffColor {
+  _trackOffColor = trackOffColor;
+  [self setNeedsLayout];
+}
+
+- (void)setTrackDisabledColor:(UIColor *)trackDisabledColor {
+  _trackDisabledColor = trackDisabledColor;
+  [self setNeedsLayout];
+}
+
+- (void)setShouldDisplayDiscreteDots:(BOOL)shouldDisplayDiscreteDots {
+  if (_shouldDisplayDiscreteDots != shouldDisplayDiscreteDots) {
+    if (shouldDisplayDiscreteDots) {
+      _discreteDots = [[MDCDiscreteDotView alloc] init];
+      _discreteDots.alpha = 0.0;
+      [_trackView addSubview:_discreteDots];
+    } else {
+      [_discreteDots removeFromSuperview];
+      _discreteDots = nil;
+    }
+    _shouldDisplayDiscreteDots = shouldDisplayDiscreteDots;
+  }
+}
+
+- (void)setShouldDisplayDiscreteValueLabel:(BOOL)shouldDisplayDiscreteValueLabel {
+  if (_shouldDisplayDiscreteValueLabel == shouldDisplayDiscreteValueLabel) {
+    return;
+  }
+
+  _shouldDisplayDiscreteValueLabel = shouldDisplayDiscreteValueLabel;
+
+  if (shouldDisplayDiscreteValueLabel) {
+    _valueLabel = [[MDCNumericValueLabel alloc]
+        initWithFrame:CGRectMake(0, 0, kValueLabelWidth, kValueLabelHeight)];
+    // Effectively 0, but setting it to 0 results in animation not happening
+    _valueLabel.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
+    _valueLabel.fontSize = kValueLabelFontSize;
+    [self addSubview:_valueLabel];
+  } else {
+    [_valueLabel removeFromSuperview];
+    _valueLabel = nil;
+  }
+}
+
+- (void)setMinimumValue:(CGFloat)minimumValue {
+  _minimumValue = minimumValue;
+  CGFloat previousValue = _value;
+  if (_value < _minimumValue) {
+    _value = _minimumValue;
+  }
+  if (_maximumValue < _minimumValue) {
+    _maximumValue = _minimumValue;
+  }
+  [self updateThumbTrackAnimated:NO
+           animateThumbAfterMove:NO
+                   previousValue:previousValue
+                      completion:NULL];
+}
+
+- (void)setMaximumValue:(CGFloat)maximumValue {
+  _maximumValue = maximumValue;
+  CGFloat previousValue = _value;
+  if (_value > _maximumValue) {
+    _value = _maximumValue;
+  }
+  if (_minimumValue > _maximumValue) {
+    _minimumValue = _maximumValue;
+  }
+  [self updateThumbTrackAnimated:NO
+           animateThumbAfterMove:NO
+                   previousValue:previousValue
+                      completion:NULL];
+}
+
+- (void)setTrackEndsAreRounded:(BOOL)trackEndsAreRounded {
+  _trackEndsAreRounded = trackEndsAreRounded;
+
+  if (_trackEndsAreRounded) {
+    _trackView.layer.cornerRadius = _trackHeight / 2;
+  } else {
+    _trackView.layer.cornerRadius = 0;
+  }
+}
+
+- (void)setPanningAllowedOnEntireControl:(BOOL)panningAllowedOnEntireControl {
+  if (_panningAllowedOnEntireControl != panningAllowedOnEntireControl) {
+    _panningAllowedOnEntireControl = panningAllowedOnEntireControl;
+    [self updateDummyPanRecognizerTarget];
+  }
+}
+
+- (void)setFilledTrackAnchorValue:(CGFloat)filledTrackAnchorValue {
+  _filledTrackAnchorValue = MAX(_minimumValue, MIN(filledTrackAnchorValue, _maximumValue));
+  [self setNeedsLayout];
+}
+
+- (void)setValue:(CGFloat)value {
+  [self setValue:value animated:NO];
+}
+
+- (void)setValue:(CGFloat)value animated:(BOOL)animated {
+  [self setValue:value
+                   animated:animated
+      animateThumbAfterMove:animated
+              userGenerated:NO
+                 completion:NULL];
+}
+
+- (void)setValue:(CGFloat)value
+                 animated:(BOOL)animated
+    animateThumbAfterMove:(BOOL)animateThumbAfterMove
+            userGenerated:(BOOL)userGenerated
+               completion:(void (^)())completion {
+  CGFloat previousValue = _value;
+  CGFloat newValue = MAX(_minimumValue, MIN(value, _maximumValue));
+  newValue = [self closestValueToTargetValue:newValue];
+  if (newValue != previousValue &&
+      [_delegate respondsToSelector:@selector(thumbTrack:willJumpToValue:)]) {
+    [self.delegate thumbTrack:self willJumpToValue:newValue];
+  }
+  _value = newValue;
+
+  if (!userGenerated) {
+    _lastDispatchedValue = _value;
+  }
+
+  if (_value != previousValue) {
+    [self interruptAnimation];
+    [self updateThumbTrackAnimated:animated
+             animateThumbAfterMove:animateThumbAfterMove
+                     previousValue:previousValue
+                        completion:completion];
+  }
+}
+
+- (void)setNumDiscreteValues:(NSUInteger)numDiscreteValues {
+  _numDiscreteValues = numDiscreteValues;
+  _discreteDots.numDiscreteDots = numDiscreteValues;
+  [self setValue:_value];
+}
+
+- (void)setThumbRadius:(CGFloat)thumbRadius {
+  _thumbRadius = thumbRadius;
+  [self setDisplayThumbRadius:_thumbRadius];
+}
+
+- (void)setDisplayThumbRadius:(CGFloat)thumbRadius {
+  _thumbView.cornerRadius = thumbRadius;
+  CGPoint thumbCenter = _thumbView.center;
+  _thumbView.frame = CGRectMake(thumbCenter.x - thumbRadius, thumbCenter.y - thumbRadius,
+                                2 * thumbRadius, 2 * thumbRadius);
+}
+
+- (CGFloat)thumbMaxRippleRadius {
+  return _touchController.defaultInkView.maxRippleRadius;
+}
+
+- (void)setThumbMaxRippleRadius:(CGFloat)thumbMaxRippleRadius {
+  _touchController.defaultInkView.maxRippleRadius = thumbMaxRippleRadius;
+}
+
+- (void)setIcon:(nullable UIImage *)icon {
+  [_thumbView setIcon:icon];
+}
+
+- (void)setEnabled:(BOOL)enabled {
+  [super setEnabled:enabled];
+  if (enabled) {
+    [self setPrimaryColor:_primaryColor];
+  }
+  [self setNeedsLayout];
+}
+
+#pragma mark - MDCInkTouchControllerDelegate
+
+- (BOOL)inkTouchController:(nonnull MDCInkTouchController *)inkTouchController
+    shouldProcessInkTouchesAtTouchLocation:(CGPoint)location {
+  return _shouldDisplayInk;
+}
+
+#pragma mark - Animation helpers
+
+- (CAMediaTimingFunction *)timingFunctionFromUIViewAnimationOptions:
+        (UIViewAnimationOptions)options {
+  NSString *name;
+
+  // It's important to check these in this order, due to their actual values specified in UIView.h:
+  // UIViewAnimationOptionCurveEaseInOut            = 0 << 16, // default
+  // UIViewAnimationOptionCurveEaseIn               = 1 << 16,
+  // UIViewAnimationOptionCurveEaseOut              = 2 << 16,
+  // UIViewAnimationOptionCurveLinear               = 3 << 16,
+  if ((options & UIViewAnimationOptionCurveLinear) == UIViewAnimationOptionCurveLinear) {
+    name = kCAMediaTimingFunctionEaseIn;
+  } else if ((options & UIViewAnimationOptionCurveEaseIn) == UIViewAnimationOptionCurveEaseIn) {
+    name = kCAMediaTimingFunctionEaseIn;
+  } else if ((options & UIViewAnimationOptionCurveEaseOut) == UIViewAnimationOptionCurveEaseOut) {
+    name = kCAMediaTimingFunctionEaseOut;
+  } else {
+    name = kCAMediaTimingFunctionEaseInEaseOut;
+  }
+
+  return [CAMediaTimingFunction functionWithName:name];
+}
+
+- (void)interruptAnimation {
+  if (_thumbView.layer.presentationLayer) {
+    _thumbView.layer.position = [(CALayer *)_thumbView.layer.presentationLayer position];
+    _valueLabel.layer.position = [(CALayer *)_valueLabel.layer.presentationLayer position];
+  }
+  [_thumbView.layer removeAllAnimations];
+  [_trackView.layer removeAllAnimations];
+  [_valueLabel.layer removeAllAnimations];
+  [_trackOnLayer removeAllAnimations];
+}
+
+#pragma mark - Layout and animation
+
+/**
+ Updates the state of the thumb track. First updates the views with properties that should change
+ before the animation. Then performs the main update block, which is animated or not as specified by
+ the `animated` parameter. After this completes, the secondary animation kicks in, again
+ animated or not as specified by `animateThumbAfterMove`. After this completes, the `completion`
+ handler is run.
+ */
+- (void)updateThumbTrackAnimated:(BOOL)animated
+           animateThumbAfterMove:(BOOL)animateThumbAfterMove
+                   previousValue:(CGFloat)previousValue
+                      completion:(void (^)())completion {
+  [self updateViewsNoAnimation];
+
+  UIViewAnimationOptions baseAnimationOptions =
+      UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction;
+  // Note that UIViewAnimationOptionCurveEaseInOut == 0, so by not specifying it, these options
+  // default to animating with Ease in / Ease out
+
+  if (animated) {
+    // UIView animateWithDuration:delay:options:animations: takes a different block signature.
+    void (^animationCompletion)(BOOL) = ^void(BOOL finished) {
+      if (!finished) {
+        // If we were interrupted, we shoudldn't complete the second animation.
+        return;
+      }
+
+      // Do secondary animation and return.
+      [self updateThumbAfterMoveAnimated:animateThumbAfterMove
+                                 options:baseAnimationOptions
+                              completion:completion];
+    };
+
+    BOOL crossesAnchor =
+        (previousValue < _filledTrackAnchorValue && _filledTrackAnchorValue < _value) ||
+        (_value < _filledTrackAnchorValue && _filledTrackAnchorValue < previousValue);
+    if (crossesAnchor) {
+      CGFloat currentValue = _value;
+      CGFloat animationDurationToAnchor =
+          (Fabs(previousValue - _filledTrackAnchorValue) / Fabs(previousValue - currentValue)) *
+          kAnimationDuration;
+      void (^afterCrossingAnchorAnimation)(BOOL) = ^void(BOOL finished) {
+        UIViewAnimationOptions options = baseAnimationOptions | UIViewAnimationOptionCurveEaseOut;
+        [UIView animateWithDuration:(kAnimationDuration - animationDurationToAnchor)
+                              delay:0.0f
+                            options:options
+                         animations:^{
+                           [self updateViewsMainIsAnimated:animated
+                                              withDuration:(kAnimationDuration -
+                                                            animationDurationToAnchor)
+                                          animationOptions:options];
+                         }
+                         completion:animationCompletion];
+      };
+      UIViewAnimationOptions options = baseAnimationOptions | UIViewAnimationOptionCurveEaseIn;
+      [UIView animateWithDuration:animationDurationToAnchor
+                            delay:0.0f
+                          options:options
+                       animations:^{
+                         _value = _filledTrackAnchorValue;
+                         [self updateViewsMainIsAnimated:animated
+                                            withDuration:animationDurationToAnchor
+                                        animationOptions:options];
+                         _value = currentValue;
+                       }
+                       completion:afterCrossingAnchorAnimation];
+    } else {
+      [UIView animateWithDuration:kAnimationDuration
+                            delay:0.0f
+                          options:baseAnimationOptions
+                       animations:^{
+                         [self updateViewsMainIsAnimated:animated
+                                            withDuration:kAnimationDuration
+                                        animationOptions:baseAnimationOptions];
+                       }
+                       completion:animationCompletion];
+    }
+  } else {
+    [self updateViewsMainIsAnimated:animated
+                       withDuration:0.0f
+                   animationOptions:baseAnimationOptions];
+    [self updateThumbAfterMoveAnimated:animateThumbAfterMove
+                               options:baseAnimationOptions
+                            completion:completion];
+  }
+}
+
+- (void)updateThumbAfterMoveAnimated:(BOOL)animated
+                             options:(UIViewAnimationOptions)animationOptions
+                          completion:(void (^)())completion {
+  if (animated) {
+    [UIView animateWithDuration:kThumbChangeAnimationDuration
+        delay:0.0f
+        options:animationOptions
+        animations:^{
+          [self updateViewsForThumbAfterMoveIsAnimated:animated
+                                          withDuration:kThumbChangeAnimationDuration];
+        }
+        completion:^void(BOOL _) {
+          if (completion) {
+            completion();
+          }
+        }];
+  } else {
+    [self updateViewsForThumbAfterMoveIsAnimated:animated withDuration:0.0f];
+
+    if (completion) {
+      completion();
+    }
+  }
+}
+
+/**
+ Updates the display of the ThumbTrack with properties we want to appear instantly, before the
+ animated properties are animated.
+ */
+- (void)updateViewsNoAnimation {
+  // If not enabled, adjust thumbView accordingly
+  if (self.enabled) {
+    // Set thumb color if needed. Note that setting color to hollow start state happes in secondary
+    // animation block (-updateViewsSecondaryAnimated:withDuration:).
+    if (!_thumbIsHollowAtStart || ![self isValueAtMinimum]) {
+      [self updateTrackMask];
+
+      _thumbView.backgroundColor = _thumbOnColor;
+      _thumbView.layer.borderColor = _thumbOnColor.CGColor;
+    }
+  } else {
+    _thumbView.backgroundColor = _thumbDisabledColor;
+    _thumbView.layer.borderColor = _clearColor.CGColor;
+
+    if (_thumbIsSmallerWhenDisabled) {
+      [self setDisplayThumbRadius:_thumbRadius - _trackHeight];
+    }
+  }
+}
+
+/**
+ Updates the properties of the ThumbTrack that are animated in the main animation body. May be
+ called from within a UIView animation block.
+ */
+- (void)updateViewsMainIsAnimated:(BOOL)animated
+                     withDuration:(NSTimeInterval)duration
+                 animationOptions:(UIViewAnimationOptions)animationOptions {
+  // Move thumb position.
+  CGPoint point = [self thumbPositionForValue:_value];
+  _thumbView.center = point;
+
+  // Re-draw track position
+  if (_trackEndsAreInset) {
+    _trackView.frame = CGRectMake(_thumbRadius, CGRectGetMidY(self.bounds) - (_trackHeight / 2),
+                                  CGRectGetWidth(self.bounds) - (_thumbRadius * 2), _trackHeight);
+  } else {
+    _trackView.frame = CGRectMake(0, CGRectGetMidY(self.bounds) - (_trackHeight / 2),
+                                  CGRectGetWidth(self.bounds), _trackHeight);
+  }
+
+  // Make sure discrete dots match up
+  _discreteDots.frame = [_trackView bounds];
+
+  // Make sure Numeric Value Label matches up
+  if (_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 1) {
+    // Note that "center" here doesn't refer to the actual center, but rather the anchor point,
+    // which is re-defined to be slightly below the bottom of the label
+    _valueLabel.center = [self numericValueLabelPositionForValue:_value];
+    _valueLabel.backgroundColor = _trackOnColor;
+    _valueLabel.textColor = [UIColor whiteColor];
+    if ([_delegate respondsToSelector:@selector(thumbTrack:stringForValue:)]) {
+      _valueLabel.text = [_delegate thumbTrack:self stringForValue:_value];
+    }
+  }
+
+  // Update colors, etc.
+  if (self.enabled) {
+    _trackView.backgroundColor = _trackOffColor;
+    _trackOnLayer.backgroundColor = _trackOnColor.CGColor;
+
+    CGFloat anchorXValue = [self trackPositionForValue:_filledTrackAnchorValue].x;
+    CGFloat currentXValue = [self trackPositionForValue:_value].x;
+
+    CGFloat trackOnXValue = MIN(currentXValue, anchorXValue);
+    if (_trackEndsAreInset) {
+      // Account for the fact that the layer's coords are relative to the frame of the track.
+      trackOnXValue -= _thumbRadius;
+    }
+
+    // We have to use a CATransaction here because CALayer.frame is only animatable using this
+    // method, not the UIVIew block-based animation that the rest of this method uses. We use
+    // the timing function and duration passed in in order to match with the other animations.
+    [CATransaction begin];
+    [CATransaction
+        setAnimationTimingFunction:[self
+                                       timingFunctionFromUIViewAnimationOptions:animationOptions]];
+    [CATransaction setAnimationDuration:duration];
+    _trackOnLayer.frame =
+        CGRectMake(trackOnXValue, 0, Fabs(currentXValue - anchorXValue), _trackHeight);
+    [CATransaction commit];
+  } else {
+    // Set background colors for disabled state.
+    _trackView.backgroundColor = _trackDisabledColor;
+    _trackOnLayer.backgroundColor = _clearColor.CGColor;
+
+    // Update mask again, since thumb may have moved
+    [self updateTrackMask];
+  }
+}
+
+/**
+ Updates the properties of the ThumbTrack that animate after the thumb move has finished, i.e. after
+ the main animation block completes. May be called from within a UIView animation block.
+ */
+- (void)updateViewsForThumbAfterMoveIsAnimated:(BOOL)animated
+                                  withDuration:(NSTimeInterval)duration {
+  if (_shouldDisplayDiscreteDots) {
+    if (self.enabled && _isDraggingThumb) {
+      _discreteDots.alpha = 1.0;
+    } else {
+      _discreteDots.alpha = 0.0;
+    }
+  }
+
+  if (_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 1) {
+    if (self.enabled && _isDraggingThumb) {
+      _valueLabel.transform = CGAffineTransformIdentity;
+    } else {
+      _valueLabel.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
+    }
+  }
+
+  if (!self.enabled) {
+    // The following changes only matter if the track is enabled.
+    return;
+  }
+
+  if ([self isValueAtMinimum] && _thumbIsHollowAtStart) {
+    [self updateTrackMask];
+
+    _thumbView.backgroundColor = _clearColor;
+    _thumbView.layer.borderColor = _trackOffColor.CGColor;
+  }
+
+  CGFloat radius;
+  if (_isDraggingThumb) {
+    if (_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 1) {
+      radius = 0;
+    } else {
+      radius = _thumbRadius + _trackHeight;
+    }
+  } else {
+    radius = _thumbRadius;
+  }
+
+  if (radius == _thumbView.layer.cornerRadius || !_thumbGrowsWhenDragging) {
+    // No need to change anything
+    return;
+  }
+
+  if (animated) {
+    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"cornerRadius"];
+    anim.timingFunction =
+        [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
+    anim.fromValue = [NSNumber numberWithDouble:_thumbView.layer.cornerRadius];
+    anim.toValue = [NSNumber numberWithDouble:radius];
+    anim.duration = duration;
+    anim.delegate = self;
+    anim.removedOnCompletion = NO;  // We'll remove it ourselves as the delegate
+    [_thumbView.layer addAnimation:anim forKey:anim.keyPath];
+  }
+  [self setDisplayThumbRadius:radius];  // Updates frame and corner radius
+
+  [self updateTrackMask];
+}
+
+// Used to make sure we update the mask after animating the thumb growing or shrinking. Specifically
+// in the case where the thumb is at the start and hollow, forgetting to update could leave the mask
+// in a strange visual state.
+- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
+  if (anim == [_thumbView.layer animationForKey:@"cornerRadius"]) {
+    [_thumbView.layer removeAllAnimations];
+    [self updateTrackMask];
+  }
+}
+
+- (void)updateTrackMask {
+  // Adding 1pt to the top and bottom is necessary to account for the behavior of CAShapeLayer,
+  // which according Apple's documentation "may favor speed over accuracy" when rasterizing.
+  // https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CAShapeLayer_class
+  // This means that its rasterization sometimes doesn't line up with the UIView that it's masking,
+  // particularly when that view's edges fall on a subpixel. Adding the extra pt on the top and
+  // bottom accounts for this case here, and ensures that none of the _trackView appears where it
+  // isn't supposed to.
+  // This fixes https://github.com/material-components/material-components-ios/issues/566 for all
+  // orientations.
+  CGRect maskFrame = CGRectMake(0, -1, CGRectGetWidth(self.bounds), _trackHeight + 2);
+
+  CGMutablePathRef path = CGPathCreateMutable();
+  CGPathAddRect(path, NULL, maskFrame);
+
+  CGFloat radius = _thumbView.layer.cornerRadius;
+  if (_thumbView.layer.presentationLayer != NULL) {
+    // If we're animating (growing or shrinking) lean on the side of the smaller radius, to prevent
+    // a gap from appearing between the thumb and the track in the intermediate frames.
+    radius = MIN(((CALayer *)_thumbView.layer.presentationLayer).cornerRadius, radius);
+  }
+  radius = MAX(radius, _thumbRadius);
+
+  if ((!self.enabled && _disabledTrackHasThumbGaps) ||
+      ([self isValueAtMinimum] && _thumbIsHollowAtStart &&
+       !(_shouldDisplayDiscreteValueLabel && _numDiscreteValues > 0 && _isDraggingThumb))) {
+    // The reason we calculate this explicitly instead of just using _thumbView.frame is because
+    // the thumb view might not be have the exact radius of _thumbRadius, depending on if the track
+    // is disabled or if a user is dragging the thumb.
+    CGRect gapMaskFrame = CGRectMake(_thumbView.center.x - radius, _thumbView.center.y - radius,
+                                     radius * 2, radius * 2);
+    gapMaskFrame = [self convertRect:gapMaskFrame toView:_trackView];
+    CGPathAddRect(path, NULL, gapMaskFrame);
+  }
+
+  _trackMaskLayer.path = path;
+  CGPathRelease(path);
+}
+
+#pragma mark - Interaction Helpers
+
+- (CGPoint)thumbPosition {
+  return _thumbView.center;
+}
+
+- (CGPoint)thumbPositionForValue:(CGFloat)value {
+  CGFloat relValue = [self relativeValueForValue:value];
+  return CGPointMake(_thumbRadius + self.thumbPanRange * relValue, self.frame.size.height / 2);
+}
+
+/**
+ Gives the point on the thumb track that we should set as the "center" of the numeric value label.
+ Keep in mind that this doesn't actually correspond to the geometric center of the label, but rather
+ the anchor point which falls to the bottom of the label. So by setting this point to be on the
+ track we automatically get the property of the numeric value label hovering slightly above the
+ track.
+ */
+- (CGPoint)numericValueLabelPositionForValue:(CGFloat)value {
+  CGFloat relValue = [self relativeValueForValue:value];
+
+  // To account for the discrete dots on the left and right sides
+  CGFloat range = self.thumbPanRange - _trackHeight;
+  return CGPointMake(_thumbRadius + (_trackHeight / 2) + range * relValue,
+                     self.frame.size.height / 2);
+}
+
+- (CGFloat)valueForThumbPosition:(CGPoint)position {
+  CGFloat relValue = (position.x - _thumbRadius) / self.thumbPanRange;
+  relValue = MAX(0, MIN(relValue, 1));
+  // For RTL we invert the value
+  if (self.mdc_effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
+    relValue = 1 - relValue;
+  }
+  return (1 - relValue) * _minimumValue + relValue * _maximumValue;
+}
+
+// Describes where on the track the specified value would fall. Differs from
+// -thumbPositionForValue: because it varies by whether or not the track ends are inset. Note that
+// if the edges are inset, the two values are equivalent, but if not, this point's x value can
+// differ from the thumb's x value by at most _thumbRadius.
+- (CGPoint)trackPositionForValue:(CGFloat)value {
+  if (_trackEndsAreInset) {
+    return [self thumbPositionForValue:value];
+  }
+
+  CGFloat xValue = [self relativeValueForValue:value] * self.bounds.size.width;
+  return CGPointMake(xValue, self.frame.size.height / 2);
+}
+
+- (BOOL)isPointOnThumb:(CGPoint)point {
+  // Note that we let the thumb's draggable area extend beyond its actual view to account for
+  // the imprecise nature of hit targets on device.
+  return DistanceFromPointToPoint(point, _thumbView.center) <= (_thumbRadius * kThumbSlopFactor);
+}
+
+- (BOOL)isValueAtMinimum {
+  return _value == _minimumValue;
+}
+
+- (CGFloat)thumbPanOffset {
+  return _thumbView.frame.origin.x / self.thumbPanRange;
+}
+
+- (CGFloat)thumbPanRange {
+  return self.bounds.size.width - (self.thumbRadius * 2);
+}
+
+- (CGFloat)relativeValueForValue:(CGFloat)value {
+  value = MAX(_minimumValue, MIN(value, _maximumValue));
+  if (CGFloatEqual(_minimumValue, _maximumValue)) {
+    return _minimumValue;
+  }
+  CGFloat relValue = (value - _minimumValue) / Fabs(_minimumValue - _maximumValue);
+  // For RTL we invert the value
+  if (self.mdc_effectiveUserInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
+    relValue = 1 - relValue;
+  }
+  return relValue;
+}
+
+- (CGFloat)closestValueToTargetValue:(CGFloat)targetValue {
+  if (_numDiscreteValues < 2) {
+    return targetValue;
+  }
+  if (CGFloatEqual(_minimumValue, _maximumValue)) {
+    return _minimumValue;
+  }
+
+  CGFloat scaledTargetValue = (targetValue - _minimumValue) / (_maximumValue - _minimumValue);
+  CGFloat snappedValue =
+      Round((_numDiscreteValues - 1) * scaledTargetValue) / (_numDiscreteValues - 1.0f);
+  return (1 - snappedValue) * _minimumValue + snappedValue * _maximumValue;
+}
+
+- (void)updateDummyPanRecognizerTarget {
+  [_dummyPanRecognizer.view removeGestureRecognizer:_dummyPanRecognizer];
+  UIView *panTarget = _panningAllowedOnEntireControl ? self : _thumbView;
+  [panTarget addGestureRecognizer:_dummyPanRecognizer];
+}
+
+#pragma mark - Color Helpers
+
+- (UIColor *)colorInterpolatedFromColor:(UIColor *)fromColor
+                                toColor:(UIColor *)toColor
+                                percent:(CGFloat)percent {
+  // Clamp percent to [0.0, 1.0]
+  percent = MAX(0, percent);
+  percent = MIN(1, percent);
+
+  CGFloat r1, g1, b1, a1;
+  r1 = g1 = b1 = a1 = 1;
+  if (![fromColor getRed:&r1 green:&g1 blue:&b1 alpha:&a1]) {
+    [fromColor getWhite:&r1 alpha:&a1];
+    g1 = b1 = r1;
+  };
+
+  CGFloat r2, g2, b2, a2;
+  r2 = g2 = b2 = a2 = 1;
+  if (![toColor getRed:&r2 green:&g2 blue:&b2 alpha:&a2]) {
+    [toColor getWhite:&r2 alpha:&a2];
+    g2 = b2 = r2;
+  }
+
+  CGFloat rfinal = r1 * (1 - percent) + r2 * percent;
+  CGFloat gfinal = g1 * (1 - percent) + g2 * percent;
+  CGFloat bfinal = b1 * (1 - percent) + b2 * percent;
+  CGFloat afinal = a1 * (1 - percent) + a2 * percent;
+
+  return [UIColor colorWithRed:rfinal green:gfinal blue:bfinal alpha:afinal];
+}
+
+#pragma mark - UIResponder Events
+
+/**
+ We implement our own touch handling here instead of using gesture recognizers. This allows more
+ fine grained control over how the thumb track behaves, including more specific logic over what
+ counts as a tap vs. a drag.
+
+ Note that we must use -touchesBegan:, -touchesMoves:, etc here, rather than the UIControl methods
+ -beginDraggingWithTouch:withEvent:, -continueDraggingWithTouch:withEvent:, etc. This is because
+ with those events, we are forced to disable user interaction on our subviews else the events could
+ be swallowed up by their event handlers and not ours. We can't do this because the we have an ink
+ controller attached to the thumb view, and that needs to receive touch events in order to know when
+ to display ink.
+
+ Using -touchesBegan:, etc. solves this problem because we can handle touches ourselves as well as
+ continue to have them pass through to the contained thumb view. So we get our custom event handling
+ without disabling the ink display, hurray!
+
+ Because we set `multipleTouchEnabled = NO`, the sets of touches in these methods will always be of
+ size 1. For this reason, we can simply call `-anyObject` on the set instead of iterating through
+ every touch.
+ */
+
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  if (!self.enabled || _currentTouch != nil) {
+    return;
+  }
+
+  UITouch *touch = [touches anyObject];
+  CGPoint touchLoc = [[touches anyObject] locationInView:self];
+
+  _currentTouch = touch;
+  _didChangeValueDuringPan = NO;
+
+  _isDraggingThumb = _panningAllowedOnEntireControl || [self isPointOnThumb:touchLoc];
+
+  if (_isDraggingThumb) {
+    // Start panning
+    _panThumbGrabPosition = touchLoc.x - self.thumbPosition.x;
+
+    // Grow the thumb
+    [self updateThumbTrackAnimated:NO
+             animateThumbAfterMove:YES
+                     previousValue:_value
+                        completion:nil];
+  }
+
+  [self sendActionsForControlEvents:UIControlEventTouchDown];
+}
+
+- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  UITouch *touch = [touches anyObject];
+  if (!self.enabled || touch != _currentTouch) {
+    return;
+  }
+
+  if (!_isDraggingThumb) {
+    // The rest is dragging logic
+    return;
+  }
+
+  CGPoint touchLoc = [touch locationInView:self];
+  CGFloat thumbPosition = touchLoc.x - _panThumbGrabPosition;
+  CGFloat previousValue = _value;
+  CGFloat value = [self valueForThumbPosition:CGPointMake(thumbPosition, 0)];
+
+  BOOL shouldAnimate = _numDiscreteValues > 1;
+  [self setValue:value
+                   animated:shouldAnimate
+      animateThumbAfterMove:YES
+              userGenerated:YES
+                 completion:NULL];
+  [self sendContinuousChangeAction];
+
+  if (_value != previousValue) {
+    // We made a move, now this action can't later count as a tap
+    _didChangeValueDuringPan = YES;
+  }
+
+  if ([self pointInside:touchLoc withEvent:nil]) {
+    [self sendActionsForControlEvents:UIControlEventTouchDragInside];
+  } else {
+    [self sendActionsForControlEvents:UIControlEventTouchDragOutside];
+  }
+}
+
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  UITouch *touch = [touches anyObject];
+  if (touch == _currentTouch) {
+    BOOL wasDragging = _isDraggingThumb;
+    _isDraggingThumb = NO;
+    _currentTouch = nil;
+
+    if (wasDragging) {
+      // Shrink the thumb
+      [self updateThumbTrackAnimated:NO
+               animateThumbAfterMove:YES
+                       previousValue:_value
+                          completion:nil];
+    }
+
+    [self sendActionsForControlEvents:UIControlEventTouchCancel];
+
+    if (!_continuousUpdateEvents && wasDragging) {
+      [self sendDiscreteChangeAction];
+    }
+  }
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+  UITouch *touch = [touches anyObject];
+  if (!self.enabled || touch != _currentTouch) {
+    return;
+  }
+
+  BOOL wasDragging = _isDraggingThumb;
+  _isDraggingThumb = NO;
+  _currentTouch = nil;
+
+  if (wasDragging) {
+    // Shrink the thumb
+    [self updateThumbTrackAnimated:NO
+             animateThumbAfterMove:YES
+                     previousValue:_value
+                        completion:nil];
+  }
+
+  CGPoint touchLoc = [touch locationInView:self];
+  if ([self pointInside:touchLoc withEvent:nil]) {
+    if (!_didChangeValueDuringPan && (_tapsAllowedOnThumb || ![self isPointOnThumb:touchLoc])) {
+      // Treat it like a tap
+      if (![_delegate respondsToSelector:@selector(thumbTrack:shouldJumpToValue:)] ||
+          [self.delegate thumbTrack:self shouldJumpToValue:[self valueForThumbPosition:touchLoc]]) {
+        [self setValueFromThumbPosition:touchLoc isTap:YES];
+      }
+    }
+
+    [self sendActionsForControlEvents:UIControlEventTouchUpInside];
+  } else {
+    [self sendActionsForControlEvents:UIControlEventTouchUpOutside];
+  }
+
+  if (!_continuousUpdateEvents && wasDragging) {
+    [self sendDiscreteChangeAction];
+  }
+}
+
+- (void)setValueFromThumbPosition:(CGPoint)position isTap:(BOOL)isTap {
+  // Having two discrete values is a special case (e.g. the switch) in which any tap just flips the
+  // value between the two discrete values, irrespective of the tap location.
+  CGFloat value;
+  if (isTap && _numDiscreteValues == 2) {
+    // If we are at the maximum then make it the minimum:
+    // For switch like thumb tracks where there is only 2 values we ignore the position of the tap
+    // and toggle between the minimum and maximum values.
+    value = _value < CGFloatEqual(_value, _minimumValue) ? _maximumValue : _minimumValue;
+  } else {
+    value = [self valueForThumbPosition:position];
+  }
+  __weak MDCThumbTrack *weakSelf = self;
+  if ([_delegate respondsToSelector:@selector(thumbTrack:willAnimateToValue:)]) {
+    [_delegate thumbTrack:self willAnimateToValue:value];
+  }
+
+  if (isTap && _numDiscreteValues > 1 && _shouldDisplayDiscreteDots) {
+    _discreteDots.alpha = 1.0;
+  }
+
+  [self setValue:value
+                   animated:YES
+      animateThumbAfterMove:YES
+              userGenerated:YES
+                 completion:^{
+                   MDCThumbTrack *strongSelf = weakSelf;
+                   [strongSelf sendDiscreteChangeAction];
+                   if (strongSelf &&
+                       [strongSelf->_delegate
+                           respondsToSelector:@selector(thumbTrack:didAnimateToValue:)]) {
+                     [strongSelf->_delegate thumbTrack:weakSelf didAnimateToValue:value];
+                   }
+                 }];
+}
+
+#pragma mark - Events
+
+- (void)sendContinuousChangeAction {
+  if (_continuousUpdateEvents && _value != _lastDispatchedValue) {
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    _lastDispatchedValue = _value;
+  }
+}
+
+- (void)sendDiscreteChangeAction {
+  if (_value != _lastDispatchedValue) {
+    [self sendActionsForControlEvents:UIControlEventValueChanged];
+    _lastDispatchedValue = _value;
+  }
+}
+
+#pragma mark - UIControl methods
+
+- (BOOL)isTracking {
+  return _isDraggingThumb;
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
new file mode 100644
index 0000000..2a3840c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.h
@@ -0,0 +1,33 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import <UIKit/UIKit.h>
+
+@interface MDCThumbView : UIView
+
+/** A boolean value indicating whether the thumb view has a shadow. */
+@property(nonatomic, assign) BOOL hasShadow;
+
+/** The border width of the thumbview layer. */
+@property(nonatomic, assign) CGFloat borderWidth;
+
+/** The corner radius of the thumbview layer. */
+@property(nonatomic, assign) CGFloat cornerRadius;
+
+/** Set the @c icon shown on the thumb. */
+- (void)setIcon:(nullable UIImage *)icon;
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.m
new file mode 100644
index 0000000..1720f1c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MDCThumbView.m
@@ -0,0 +1,103 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCThumbView.h"
+
+#import "MaterialShadowElevations.h"
+#import "MaterialShadowLayer.h"
+
+@interface MDCThumbView ()
+
+@property(nonatomic, strong) UIImageView *iconView;
+
+@end
+
+@implementation MDCThumbView
+
+static const CGFloat kMinTouchSize = 48;
+
++ (Class)layerClass {
+  return [MDCShadowLayer class];
+}
+
+- (instancetype)initWithFrame:(CGRect)frame {
+  self = [super initWithFrame:frame];
+  if (self) {
+    // TODO: Remove once MDCShadowLayer is rasterized by default.
+    self.layer.shouldRasterize = YES;
+    self.layer.rasterizationScale = [UIScreen mainScreen].scale;
+  }
+  return self;
+}
+
+- (void)setBorderWidth:(CGFloat)borderWidth {
+  _borderWidth = borderWidth;
+  self.layer.borderWidth = borderWidth;
+}
+
+- (void)setCornerRadius:(CGFloat)cornerRadius {
+  _cornerRadius = cornerRadius;
+  self.layer.cornerRadius = cornerRadius;
+  [self setNeedsLayout];
+}
+
+- (void)setHasShadow:(BOOL)hasShadow {
+  _hasShadow = hasShadow;
+  [[self shadowLayer]
+      setElevation:(hasShadow) ? MDCShadowElevationCardResting : MDCShadowElevationNone];
+}
+
+- (MDCShadowLayer *)shadowLayer {
+  return (MDCShadowLayer *)self.layer;
+}
+
+- (void)layoutSubviews {
+  [super layoutSubviews];
+  self.layer.shadowPath =
+      [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:_cornerRadius].CGPath;
+}
+
+- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
+  CGFloat dx = MIN(0, _cornerRadius - kMinTouchSize / 2);
+  // Converts point to presentation layer coordinate system so gesture will land on the right visual
+  // position. Assuming superview is not animated.
+  if (self.layer.presentationLayer) {
+    point = [(CALayer *)self.layer.presentationLayer convertPoint:point
+                                                        fromLayer:self.layer.modelLayer];
+  }
+  CGRect rect = CGRectInset(self.bounds, dx, dx);
+  return CGRectContainsPoint(rect, point);
+}
+
+- (void)setIcon:(nullable UIImage *)icon {
+  if (icon == _iconView.image || [icon isEqual:_iconView.image])
+    return;
+
+  if (_iconView) {
+    [_iconView removeFromSuperview];
+    _iconView = nil;
+  }
+  if (icon) {
+    _iconView = [[UIImageView alloc] initWithImage:icon];
+    [self addSubview:_iconView];
+    // Calculate the inner square of the thumbs circle.
+    CGFloat sideLength = (CGFloat)sin(45.0 / 180.0 * M_PI) * _cornerRadius * 2;
+    CGFloat topLeft = _cornerRadius - (sideLength / 2);
+    _iconView.frame = CGRectMake(topLeft, topLeft, sideLength, sideLength);
+  }
+}
+
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
new file mode 100644
index 0000000..b09f1bd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/MaterialComponents/components/private/ThumbTrack/src/MaterialThumbTrack.h
@@ -0,0 +1,18 @@
+/*
+ Copyright 2015-present the Material Components for iOS authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+#import "MDCThumbTrack.h"
+#import "MDCThumbView.h"
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/project.pbxproj b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5e30b70
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/project.pbxproj
@@ -0,0 +1,2757 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		02B3889D3E871468F88E5DBE7E9C5E21 /* MDCButton.m in Sources */ = {isa = PBXBuildFile; fileRef = BE257A301C797B8D3C24053EFEF0DB5A /* MDCButton.m */; };
+		04EC8CBF409C803BF749B2F9E8E38E0B /* MaterialTabs.h in Headers */ = {isa = PBXBuildFile; fileRef = 0C1F25227166DC67A877DFCA5594F74B /* MaterialTabs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		051B40934BCB60C81579E65ED35CD7A0 /* ic_reorder@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 87D692B9AD07C602ED145B594F3FF7D9 /* ic_reorder@3x.png */; };
+		05E5A4ADDD5472838AAB9FFF46AF2137 /* MDCIcons.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BF39A7F429701947B09DCBEB4A07F05 /* MDCIcons.m */; };
+		05FF239C8670278A10D7BD58DD5260E1 /* UIView+MDCTimingFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 7941C852DB02A5C5D4BE708004028A52 /* UIView+MDCTimingFunction.m */; };
+		0617544187F62EC4C98A6BEE1428C5D6 /* MaterialSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = 60852389E40D9EF0F70B7BF97E7B998D /* MaterialSlider.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		07484E38806037944055D0BF76806FA4 /* MDCPageControlIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = B56398DA0E3930C91FF640F861706411 /* MDCPageControlIndicator.m */; };
+		091A8578BC600F0579CD4CB9A119DCD8 /* ic_radio_button_unchecked@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 62057440CF0144D03DEB925C378645B7 /* ic_radio_button_unchecked@3x.png */; };
+		0B0FE5E1667FA17C1026EF1F92C1A63F /* MDCFlexibleHeaderContainerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 621F64FAC8A6CDF22ADF8271D04409C6 /* MDCFlexibleHeaderContainerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		0CD124B11142B650BF877996F9F0E07A /* MDCProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C914D35C46E85C26AA1E246E17CECE5 /* MDCProgressView.m */; };
+		0D20BD182D66DBDD7E4D6CB7F77CF9F3 /* MaterialCollectionLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 444B921CA054B6ED8B57713242404400 /* MaterialCollectionLayoutAttributes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		0E3515A7AE66C29F70F654BA2B8EA7BA /* MDCPaletteExpansions.h in Headers */ = {isa = PBXBuildFile; fileRef = C4899C25A4830FCF08B2BB4F8ABC361A /* MDCPaletteExpansions.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		0E47C9B2997E679B24FA498EE2363228 /* MaterialInk.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C21154B03011C9702C295079DCF65E1 /* MaterialInk.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		0EBDEC7917FC21DD3AD7979621EA2307 /* MaterialIcons+ic_arrow_back.m in Sources */ = {isa = PBXBuildFile; fileRef = C830C5EEEAE60B4A9283F0C2F0A02094 /* MaterialIcons+ic_arrow_back.m */; };
+		10B1D8ED7E2CF740C124B7C74CDBB74E /* MDCShadowElevations.m in Sources */ = {isa = PBXBuildFile; fileRef = CC56C512FD3A98A296C04156DD8DFEC9 /* MDCShadowElevations.m */; };
+		1274CD4A2DD52C98C966921502C57446 /* MDCAppBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CA3D76D548F43BB8F241C55FB9D5656 /* MDCAppBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		140D1BAA0F86861FA7A3A788F41C2DAC /* MDCOverlayObserverOverlay.h in Headers */ = {isa = PBXBuildFile; fileRef = 16E650750C1D8383CFF76B265B232D54 /* MDCOverlayObserverOverlay.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		14612015079E6E117DED63E2337F4346 /* MaterialIcons+ic_radio_button_unchecked.m in Sources */ = {isa = PBXBuildFile; fileRef = C19F7B7784CFCB4369498613360AA4CB /* MaterialIcons+ic_radio_button_unchecked.m */; };
+		14D517DDB1CB758C5FAA1B5963590CDF /* UIViewController+MaterialDialogs.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D3E3C231B7AE692FCE91C1216645EA3 /* UIViewController+MaterialDialogs.m */; };
+		173E8E625D765B2536A2145C9F528898 /* MaterialShadowElevations.h in Headers */ = {isa = PBXBuildFile; fileRef = 03CE9EF2998E990D7C6C15AC4AEFF20D /* MaterialShadowElevations.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		195B84DD18A2352DA5EDEC2F347F0985 /* MDCPaletteExpansions.m in Sources */ = {isa = PBXBuildFile; fileRef = 67D647688DBDE7C289D22CFAADF4006C /* MDCPaletteExpansions.m */; };
+		1A0003B88CFC06F475A1A7D437E14A27 /* NSArray+MDFUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F9B634EE11CC423F51EE3D659001D14 /* NSArray+MDFUtils.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		1B25CFC33E70C55ADB21117C2E0BC425 /* MDCCollectionViewTextCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 158DFD17C32FF1158E4896DD754DDC6B /* MDCCollectionViewTextCell.m */; };
+		1C4083843A8D6038A7EAA2DD85FDC174 /* MaterialNavigationBar.h in Headers */ = {isa = PBXBuildFile; fileRef = B73577CD8AEFE5DA6EB995CC8F2C92A7 /* MaterialNavigationBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		1D8C9CF5687E222D0C1919213AA0116A /* MDCActivityIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97262CDCD801553DA99ECC7847E39E98 /* MDCActivityIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		203C4032B594FAEFC8C97B3AFB740B1D /* MaterialIcons+ic_info.m in Sources */ = {isa = PBXBuildFile; fileRef = B52A38C1D2775315C12601204EF0524E /* MaterialIcons+ic_info.m */; };
+		218A5004AD1E67EDB82023BF74D6E81D /* MDCOverlayWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = D100E5E7F62D86CE9CCC97B487779DEC /* MDCOverlayWindow.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		24900323EF8B3538F240F4824D3BC843 /* ic_info.png in Resources */ = {isa = PBXBuildFile; fileRef = ACCED250D3351A0D22EEA492436EBE80 /* ic_info.png */; };
+		24CD705DC0032088FFF4C5DF861B0099 /* MDCCollectionViewFlowLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 16C2D56E186EC25B2AD48EF7EC5DB131 /* MDCCollectionViewFlowLayout.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		25160F444E7DF39397B6D6AFC4F07141 /* MDCFlexibleHeaderView.h in Headers */ = {isa = PBXBuildFile; fileRef = 6EE3924624B8CAFC171FD153BBFC8449 /* MDCFlexibleHeaderView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		274573598F1BA1A5256CA32D7689462A /* MDCItemBarStringConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = EDD61B881B917B05AFD9539341F931FD /* MDCItemBarStringConstants.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		28D9B87B12B0ADC9D2B6D6A0DCADC59A /* MDCItemBarAlignment.h in Headers */ = {isa = PBXBuildFile; fileRef = 5677CC19D390C501CCA90EEE390AAE6D /* MDCItemBarAlignment.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		293557804A5EBF6C30C51757363B057B /* MDCSnackbarOverlayView.h in Headers */ = {isa = PBXBuildFile; fileRef = 98BE3C2752BDFA411D8AD43231FF4BCC /* MDCSnackbarOverlayView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		29508FF7916F5B95D6F4F940601AC975 /* MDCProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = 1119E38AD872AC586FC0B36077CBD452 /* MDCProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		299DD5695C130C8315A9E5FA786ECEAB /* MDCThumbTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E05EB6FB230393D92DC9A1584D7DE50 /* MDCThumbTrack.m */; };
+		2A316D54A91DA5CD37F5231CC2E36978 /* MDCRTL.m in Sources */ = {isa = PBXBuildFile; fileRef = B12139AB4284238F1123EB1E38B230E1 /* MDCRTL.m */; };
+		2AA0B61EABF1D62E39ABB6309B1E93CB /* ic_arrow_back_ios@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 33072B9B16A9B8DAAEDE9D6B449679D2 /* ic_arrow_back_ios@2x.png */; };
+		2AB6A1D688CF1EA0FA6345D547CF931D /* MDCCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 931A07F6E4357134E2E8449CFE5E056E /* MDCCollectionViewFlowLayout.m */; };
+		2DE4DA16A223502BDAE19CB16707EA25 /* ic_check_circle@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 38A6CB047FC50FA03168F50ACA26C75B /* ic_check_circle@3x.png */; };
+		2EB0AB22EC4D7AB16E9074A5013DD61C /* MDCThumbView.h in Headers */ = {isa = PBXBuildFile; fileRef = D49CC986145361BA86D40441881692D8 /* MDCThumbView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3019DD7715B81601126A4182935F7DA9 /* MaterialIcons+ic_chevron_right.h in Headers */ = {isa = PBXBuildFile; fileRef = F398E51F9526801442D77BE9612F9C62 /* MaterialIcons+ic_chevron_right.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		303E2CEF1A7B2F29A77E3275D5543798 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */; };
+		3109CBFCFA85CBFA88B4F9FA1F3A16D1 /* MDFTextAccessibility-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 506805F39B4A029793221A2B4824A062 /* MDFTextAccessibility-Bridging-Header.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		34FBD1D58C8BD1C74A876169FB1C15CA /* MDCOverlayWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F9741A397ADB188B83497B96D7D30F5 /* MDCOverlayWindow.m */; };
+		3516A50767315A26E2D625A823474101 /* MaterialProgressView.h in Headers */ = {isa = PBXBuildFile; fileRef = C67AC2707AD0B4EC907D6DC6B79DD436 /* MaterialProgressView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3584E7D333209DF162223D26DF0E795F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 409899CE1143F81E8130E2069D59605B /* CoreGraphics.framework */; };
+		35BDD24AF246B8AF9D163CF7005C3A27 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */; };
+		373D05814A0C88B4A0635C5A79FF822B /* MDCInkView.h in Headers */ = {isa = PBXBuildFile; fileRef = EF3D4AABE18C6B0D033BD47108A9156D /* MDCInkView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		3998D3B0FBE92AB251C8FE66F7214BF9 /* MDCDialogShadowedView.m in Sources */ = {isa = PBXBuildFile; fileRef = B3AB010097D6D3763F9664DCA9A711EB /* MDCDialogShadowedView.m */; };
+		3A2F4061FB79B93EA5C9B8DA9094EED5 /* MaterialPageControlStrings_table.h in Headers */ = {isa = PBXBuildFile; fileRef = 61C0E2BD02828C530EA209D50ED1B519 /* MaterialPageControlStrings_table.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		3BFFD555516224FB8FF319A087BCA29F /* MDCCollectionInfoBarView.h in Headers */ = {isa = PBXBuildFile; fileRef = 206E1270F7CD7132605A140A429FE475 /* MDCCollectionInfoBarView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		3C9EA68F25AD2F27CE9EA4F444C56FA6 /* ic_chevron_right@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 35901EA242A4B2DE85C2894CC9194C1F /* ic_chevron_right@3x.png */; };
+		3D2B20D0F1D2DF6518A6E97129778190 /* MaterialIcons+ic_chevron_right.m in Sources */ = {isa = PBXBuildFile; fileRef = 654AA469F888FFF8F1CE4AA611FD6B69 /* MaterialIcons+ic_chevron_right.m */; };
+		3D2BB082025D1252507C363E4714C625 /* MaterialDialogs.h in Headers */ = {isa = PBXBuildFile; fileRef = 84467817302E2399BA95D3A909871AFA /* MaterialDialogs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		40FECE7BF976712334BCAD110F2E2051 /* MDCSnackbarManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 25F7B26DAEC96431ECEEC467ADA2CF28 /* MDCSnackbarManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		421078E41926305DF11196F6FB28AD42 /* MDFImageCalculations.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D40D28A97062B1CC07236668DC678AD /* MDFImageCalculations.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		4211DA431C07D51F55AB2D9000F745DB /* ic_arrow_back_ios.png in Resources */ = {isa = PBXBuildFile; fileRef = 7F9E8F936B7FA4CE55F6D4A70EDF478C /* ic_arrow_back_ios.png */; };
+		45002548D32FF2E02C25B5EA30BBCA89 /* ic_info@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 029A97895F42B6AB7B7209A3BB20DCA8 /* ic_info@2x.png */; };
+		451AD57BB35CAD3C692F082E93B99BF3 /* MDCCollectionViewTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BF097DEAD72714A366668962C25EC9B /* MDCCollectionViewTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		46CB2D9B298AA3F30C5D42BC04F39E94 /* MDCDialogPresentationController.h in Headers */ = {isa = PBXBuildFile; fileRef = B4CDE57035DA000166BF394A847F6AE2 /* MDCDialogPresentationController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4717C3070FA97344C11B65BACF2DDF3C /* MDCCollectionViewEditingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = F14A5EBD4362C79FF3F8A7262FEA2D5B /* MDCCollectionViewEditingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		47C39E63B795E98E36A83BBAC82BF86F /* MaterialCollectionCells.h in Headers */ = {isa = PBXBuildFile; fileRef = A32E50911D7DB6FBC3E4CC4ECCBA1596 /* MaterialCollectionCells.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		48887AC621143DD5D40DBFE5A4E23883 /* MaterialFlexibleHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A7FE223E125A19DB7A772510BF0DEB2 /* MaterialFlexibleHeader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		49C5DD0A16846BF2E4806A9510D2998D /* MDCCollectionViewEditing.h in Headers */ = {isa = PBXBuildFile; fileRef = 752EC7F93FEFE96C89367CBBBB8CB32B /* MDCCollectionViewEditing.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4A9EFA8C13DFEB3A8EF9E7AB8802A3D1 /* MDCHeaderStackView.m in Sources */ = {isa = PBXBuildFile; fileRef = EB1C6A347A3B1B5278B6179E7E7A6C7E /* MDCHeaderStackView.m */; };
+		4AC16280803615380CABD4379AA69D65 /* MDCPaletteNames.h in Headers */ = {isa = PBXBuildFile; fileRef = C078D453FB972AF56047785185938933 /* MDCPaletteNames.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		4C2B4BA673669811FBFF71DF09D6F550 /* MaterialKeyboardWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = F5A94E964BB75BF779F888AE07B3F95C /* MaterialKeyboardWatcher.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		4C9D6933282639AAEDFCE3760D663370 /* ic_check@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8917229D3430B609F88F33A180E7063C /* ic_check@2x.png */; };
+		4CBD21241E82CCBA918B0E72FF122FF7 /* ic_arrow_back_ios@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = E95DB580D0830673D87F39AEFDA6EF67 /* ic_arrow_back_ios@3x.png */; };
+		4E8DA5386F2879E77B2E23D0E03C4A9B /* MDCButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 12BE96DCA235623AF7766C60CCFAE1C7 /* MDCButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		5180979CE3EEB34F06466107253D6BB1 /* MDCPaletteNames.m in Sources */ = {isa = PBXBuildFile; fileRef = 98F8E9B6EBCFF521C01B78E4BD1039BD /* MDCPaletteNames.m */; };
+		520EC00A1A0B6B3827DA1F4A7E655C0A /* MDCOverlayAnimationObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 81B08B2D4EB2559D2497B7BB8B215DF3 /* MDCOverlayAnimationObserver.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		52C9FD65F3A7015BF99A651500F2D24C /* MaterialFeatureHighlight.h in Headers */ = {isa = PBXBuildFile; fileRef = F5BEB5E003D1847D87CC74803474B2EF /* MaterialFeatureHighlight.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		53BB396FE274D0FB6F22F98138F0A130 /* MDCCollectionViewStyler.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F5CD9392CF68CA57F883CA8A1DA6BE /* MDCCollectionViewStyler.m */; };
+		54AC6E6DC67C3C418A85ED4983EC39D5 /* ic_chevron_right.png in Resources */ = {isa = PBXBuildFile; fileRef = 7EBAFD93350BF0CF6E8CE57A39A1FA5D /* ic_chevron_right.png */; };
+		54BB836815554D4144AC9824136B8FA9 /* MDCCollectionViewLayoutAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = 6677BBD93E7A4672F9AEA51236310EDF /* MDCCollectionViewLayoutAttributes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		5685049F462A3F846BF0EA56103E153C /* MDCButton+Subclassing.h in Headers */ = {isa = PBXBuildFile; fileRef = F82A46DDAA89ACF53DA3C47CC04971EF /* MDCButton+Subclassing.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		586B689107644E8DFF068DC9A1E927D6 /* MDCSnackbarManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F5AE307F5EF407D47769AC7313B9DCA /* MDCSnackbarManager.m */; };
+		58FB26F7D268DF6E49DE32787ECF53B3 /* MDCSnackbarMessageView.m in Sources */ = {isa = PBXBuildFile; fileRef = F1E7B70BE2622CF3F81A0AD037E21C47 /* MDCSnackbarMessageView.m */; };
+		59F2E39B0B51CF3480C2FE2A1B3B0CBA /* ic_radio_button_unchecked.png in Resources */ = {isa = PBXBuildFile; fileRef = 17AAA691CE308745D666AC354DEBD7D1 /* ic_radio_button_unchecked.png */; };
+		5A23C9982240753826D25F3648BE3915 /* MDCCollectionGridBackgroundView.m in Sources */ = {isa = PBXBuildFile; fileRef = 683A8B83E16F375FE011E9C5AA0221EE /* MDCCollectionGridBackgroundView.m */; };
+		5C146662CCCE2C78543F8A049B696E66 /* MDCKeyboardWatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 06A99FC5FF2D8E635C719D756C525052 /* MDCKeyboardWatcher.m */; };
+		5C20F66911408C3E193E604D21F47677 /* Pods-BuildingBeautifulApps-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8272252EDEB9A0A290A95F34B0A4AEBD /* Pods-BuildingBeautifulApps-dummy.m */; };
+		5CEE44CB5B97F207D902E967A7A28542 /* MDCItemBar.h in Headers */ = {isa = PBXBuildFile; fileRef = CADC6B616AB3936666BDBD42A2705DE6 /* MDCItemBar.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		5E944DEC856408844CB086300051AD03 /* MDCPageControlIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97E9347E0E620A695CA9575055B9A219 /* MDCPageControlIndicator.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		5EBEA9BE9A76AE4BA005EF74784B9739 /* MDCFlatButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4F0E678DFEF2B507BAEF2FFD1EF23228 /* MDCFlatButton.m */; };
+		601F6E1396EAC24AD0DF4FC09872F769 /* MDCCollectionInfoBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 03B1990C768D7EBE9880314C80B89B32 /* MDCCollectionInfoBarView.m */; };
+		610644D23738415ACB073C8B072244BB /* MDCIcons+BundleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = E22DE5B99BE8057D6452C77B5B4A8D39 /* MDCIcons+BundleLoader.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		624BA0196EC0BA2C9AAE7D4DE3AB068A /* MDCOverlayObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = D9E396F14C5448B3C15F7B48AFC85B6F /* MDCOverlayObserver.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		63188636F2C3E07CE98221656B929588 /* CAMediaTimingFunction+MDCAnimationTiming.m in Sources */ = {isa = PBXBuildFile; fileRef = 10B9C9D65FA83AC626EFF1C6A94BA402 /* CAMediaTimingFunction+MDCAnimationTiming.m */; };
+		63793D388D09869517A2472AE9C612B3 /* MDCSlider.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8DD7BF09A1359D0C22AD2D99DF9967 /* MDCSlider.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		641CD6C953ADD27482B6CDBCCF24CD6A /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5F7BDB2580B244756CFA046131516EF2 /* QuartzCore.framework */; };
+		64BD87D6A0EE900D83D40B3A793CB98B /* ic_check.png in Resources */ = {isa = PBXBuildFile; fileRef = 7C5778E1102FA874A7F4F6FFD400C7DE /* ic_check.png */; };
+		65E9B44BBB842E8838653E605F87B3CD /* MDCAlertController.m in Sources */ = {isa = PBXBuildFile; fileRef = C3CE561D11742D1092438C75CE67C1D4 /* MDCAlertController.m */; };
+		677A054DB9F431CF6C98E570A8223F50 /* MDCAppBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D570439942906B139B693491F7E71ED /* MDCAppBar.m */; };
+		67E00C690CF9CFB20C51270B46B6A1CB /* MDCCollectionViewStylingDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 041B9228D9CF59ABFD7ACB6A1D468715 /* MDCCollectionViewStylingDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		67ED336DA6AA8B8497F1539842808631 /* MDCFontTraits.h in Headers */ = {isa = PBXBuildFile; fileRef = 07B2F589B283B574F2B354D14386BBF8 /* MDCFontTraits.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		68E150F63885364AA7143698177876C6 /* MDCFloatingButton.m in Sources */ = {isa = PBXBuildFile; fileRef = F64F50AD20E83F81710454204053A744 /* MDCFloatingButton.m */; };
+		69CD5189E440D7767EE5B771A9FEE03D /* MDCButtonBar+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D79A92B4599903B71AD908CC7E5B0213 /* MDCButtonBar+Private.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		69EA046EE6873743400E09466C970A14 /* UIFont+MaterialTypographyPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4277E14F56DAC15ABD24D97EDC26ADEA /* UIFont+MaterialTypographyPrivate.m */; };
+		6BA617C860537C13AE7EA0AF05DF96FA /* MDCOverlayObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = E601CD11978BE11A131D16DA1717A354 /* MDCOverlayObserver.m */; };
+		6C84F71A1D807C4CB432B7B933F4FF6F /* MDFTextAccessibility.m in Sources */ = {isa = PBXBuildFile; fileRef = 4AF4F84748B988E39D513A50701185FC /* MDFTextAccessibility.m */; };
+		6CE23956E33CA9B2981055C2A5541077 /* MDCSnackbarMessageViewInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 522F0C6B92C308F6D1B7BB497022A769 /* MDCSnackbarMessageViewInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		6E5609D839CCD3390C33DFDEC3502382 /* MDCTabBar.h in Headers */ = {isa = PBXBuildFile; fileRef = BDAF0CDE00CDA3F4B1CE9E7374239490 /* MDCTabBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6FBA9C40C2CC499C9E549022E8CC48A9 /* MDCInkTouchController.h in Headers */ = {isa = PBXBuildFile; fileRef = E47ED49AEF9D2FE77E92679C5569563D /* MDCInkTouchController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6FE4364F0DE10004ECF20D68071F4739 /* MDCActivityIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 45DA800B226D1DE08F69E5BDDC45E203 /* MDCActivityIndicator.m */; };
+		701A7F5C929096A5A4AAD770AA8CC8A1 /* MDCFeatureHighlightView.m in Sources */ = {isa = PBXBuildFile; fileRef = 13923E685C01C84D742BF61E9A51D084 /* MDCFeatureHighlightView.m */; };
+		704742BFFD1D9BAE18AC34F964C43044 /* MDCOverlayObserverOverlay.m in Sources */ = {isa = PBXBuildFile; fileRef = 523EEB14DB0CEFD241559CCC496E445B /* MDCOverlayObserverOverlay.m */; };
+		71FF2344ED69DD4EC1BD52B6334C79EE /* MDCFeatureHighlightLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B3462BC5FFFCC355901DAA536C77A5A /* MDCFeatureHighlightLayer.m */; };
+		723E8EEE2D1B59FC03F6158CCF391D2C /* MDCItemBarStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = 2792F28B4CCFEB1DCDCDBB8636947EBC /* MDCItemBarStyle.m */; };
+		7321A0DEBC74D9ED66E36F9A27FF0CCD /* MaterialShadowLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 77C440E4189E05E40980CE67AF6A977D /* MaterialShadowLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7339A37AFA0F1A69B86239CE639CC15D /* MaterialRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = E88C708F20439859824CDC2F79216421 /* MaterialRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		73A9FEFF284BE8244A83EE3E68694904 /* MDCSnackbarMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D1C4015B6347137598F264D6387CCA6 /* MDCSnackbarMessage.m */; };
+		73D4A36BAE65B225B1CBC5EE9A9A802A /* ic_radio_button_unchecked@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 84D3E267E2C78F75A2831346932CF97F /* ic_radio_button_unchecked@2x.png */; };
+		74F5757E7D5A465C730D2AA937BE785C /* MDCItemBarCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 01127A0CE1E1F9D661213AD37AC639FC /* MDCItemBarCell.m */; };
+		75701D93C9E6E0E16551378FB6D15322 /* MDCCollectionStringResources.m in Sources */ = {isa = PBXBuildFile; fileRef = 96E1A962597D9C41D8E7513530EBCD7D /* MDCCollectionStringResources.m */; };
+		75CFCE1AB0C85EEC8F68A664771A0847 /* UIImage+MaterialRTL.m in Sources */ = {isa = PBXBuildFile; fileRef = 0EEA3ACEEB4A63D1DF01A8D3F89BC441 /* UIImage+MaterialRTL.m */; };
+		7673B57A3EAC6E8169C83EA5F68B70E4 /* MDCItemBar.m in Sources */ = {isa = PBXBuildFile; fileRef = BB3068591BFE9A9F8D1B79957A573691 /* MDCItemBar.m */; };
+		76FB19E59FB284927075877B825A67A6 /* UIView+MaterialRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D9BC573FF76C294C05D43278D00B4A6 /* UIView+MaterialRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		79B778A18CC8304044870CCF0AF93C92 /* MDCStatusBarShifter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2543C83779FCB7CA6F63B6E23BA22BDB /* MDCStatusBarShifter.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		7A5C50000FFBA08EB5AEB031CB02508A /* MDCThumbView.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CCFBA02AEF1EB2D0EA744C7D87ADB76 /* MDCThumbView.m */; };
+		7B1EB360F18CCF386C0AC46F154F0C9B /* MDCOverlayTransitioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D982B7FBF6D8BFF04DFD915F08E13B0 /* MDCOverlayTransitioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7BC8DF38C236F0C73D8CB5F4D9E8DBAA /* MDCPalettes.m in Sources */ = {isa = PBXBuildFile; fileRef = C9588139AB2E41A105B4F278EF0B01F3 /* MDCPalettes.m */; };
+		7BDC8151577B47E72BCB0F299F6654A8 /* MDCCollectionViewStyler.h in Headers */ = {isa = PBXBuildFile; fileRef = CAA1DC1A670B6F673EE517CD53A4EBD1 /* MDCCollectionViewStyler.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		7BF7E68DCF7F91851687A7D393812EC6 /* MaterialThumbTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = D11EB1CC12CA81275669C38699DF58A3 /* MaterialThumbTrack.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		7F7F0348C4102A49883CD88C86E122CF /* MaterialIcons+ic_check_circle.m in Sources */ = {isa = PBXBuildFile; fileRef = 443C58797FC89C1F0BDC6BDF82DD1913 /* MaterialIcons+ic_check_circle.m */; };
+		7F86C31F4F88FAD41263B8386772014A /* MDCFeatureHighlightLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0F8786C896495252AF8C693705FE27 /* MDCFeatureHighlightLayer.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		7FAA92CCF3CE42E4265CD84238775669 /* UIImage+MaterialRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = 6ECC1D1D41521DED2581889D20C4D8F9 /* UIImage+MaterialRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		81BAF4596ECCF3B2090CCEB24E981C7E /* MDCOverlayObserverTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DB14C9C7FE14E6BF99957813C38B5BA /* MDCOverlayObserverTransition.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		81F752320FBCB9A12535E3AD2602AA27 /* MDCCollectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 58B3FF2F70B1A1974204F2F8931F665B /* MDCCollectionViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8334A8C5BB14AB374900D9A579A65096 /* MDCSlider_Subclassable.h in Headers */ = {isa = PBXBuildFile; fileRef = 14793E6FDAF9C044D6ED8B67E59C7E75 /* MDCSlider_Subclassable.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		83FE983EC6EEC2C7ACAE955FCABFF518 /* MDCButtonBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 4374B11D22F0FCC5866781A5F08A4D38 /* MDCButtonBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		856224A034BF7897D5745C017D6E26BF /* MDCFeatureHighlightAnimationController.m in Sources */ = {isa = PBXBuildFile; fileRef = D2FFA02DCC45D1EDB5D30FB9CEB3B9BD /* MDCFeatureHighlightAnimationController.m */; };
+		86115CB0ADDFA0C2DA2A6C8A2834A7FD /* MaterialIcons+ic_check_circle.h in Headers */ = {isa = PBXBuildFile; fileRef = 263DB970C3B145399EBC89F15760FB2B /* MaterialIcons+ic_check_circle.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		866CA83566ACE3526AA5FABAB6E08CED /* MDCRaisedButton.h in Headers */ = {isa = PBXBuildFile; fileRef = ABED23378B104A0A25435A6674F29FF5 /* MDCRaisedButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		86ABC77AAAF3BB0E73978E7FD7B371AD /* MDCFontTraits.m in Sources */ = {isa = PBXBuildFile; fileRef = DC384A83912E8C440C7ED70B794A89D2 /* MDCFontTraits.m */; };
+		86CCCDEFFA251A9AB150EDB92E0BDCE4 /* UIFontDescriptor+MaterialTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E5285A7050BE78F06AD6EC2E4BF1A2F /* UIFontDescriptor+MaterialTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		87A2628E58EECA44CEDADB67AE99D7F7 /* MDCSnackbarOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 01C5E9A263A0FBC63B0B1E0D89013529 /* MDCSnackbarOverlayView.m */; };
+		88D4D6C491D0BB280CD6B6D01BDE39B9 /* MDCItemBarStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = C4F53B72FA10D37719F9CB9924A08CBD /* MDCItemBarStyle.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		8A714C7A8F488D84D189041AB5EA984F /* MDCTypography.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A82FF56648D80F9E61096E9A07B06F6 /* MDCTypography.m */; };
+		8B0BD0DC00C8B39EABBBA502C3CC424B /* MaterialOverlayWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = F600563B48E50DAC2BB8C3B23D131DA2 /* MaterialOverlayWindow.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		8B9D3A9491A4C5894D9BDB45F75C72EE /* MDCFlexibleHeaderContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 536F8F8CBB3D5593CFA4CBFD765F3BED /* MDCFlexibleHeaderContainerViewController.m */; };
+		91A653669E3851452FCFCA0E2A7CB837 /* MDCInkLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = EA980654C37C923AB926DF64E7E02736 /* MDCInkLayer.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		91EB3409BF51AE8448EC825B00CA7EC8 /* MDCCollectionViewEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = 24C7218ECEE1F60B1B720B21514EE621 /* MDCCollectionViewEditor.m */; };
+		93CA3734266496A1F281BDB7565FA671 /* ic_reorder.png in Resources */ = {isa = PBXBuildFile; fileRef = 403CEE2F8B8AFCD9A8ADAD83045448CB /* ic_reorder.png */; };
+		9424985CFBD9108EAB15C67DE617DDD7 /* MaterialApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F9DCB161F252F8BD0F521356180A57 /* MaterialApplication.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		945823B4D8C6E662F1C2CB08D268A088 /* MaterialIcons+ic_check.h in Headers */ = {isa = PBXBuildFile; fileRef = ACD681F6184F424EE2EAF7600B76F289 /* MaterialIcons+ic_check.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		957F0F86EAB556C7CD058DF04A23F216 /* MDCShadowLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = D8966C5049A9875A33A6802C9840E498 /* MDCShadowLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		95DA110166E184835298E627C35F5B5C /* MDCSnackbarMessageView.h in Headers */ = {isa = PBXBuildFile; fileRef = A3991A36920E062C3E82F61204091F73 /* MDCSnackbarMessageView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		96232A06DAC31122E30D7D5724150A83 /* MaterialPageControlStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 94B9A402610F5FCAEE60B7D902780413 /* MaterialPageControlStrings.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		978CE8B98451722A7BCB5F8ECF12F4D5 /* ic_chevron_right@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D5674E7D4BCC946A30114DBF9DB2F6CA /* ic_chevron_right@2x.png */; };
+		97B175A8C54E8AB93F6A1738A2E8AC32 /* MaterialCollectionsStrings_table.h in Headers */ = {isa = PBXBuildFile; fileRef = BBFB15BBA3F7C53B5BDCBDCEFD66700C /* MaterialCollectionsStrings_table.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		97EE80E12A66CFDC2291192A6D690DA1 /* UIFont+MaterialTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = A8D106719F3F199D438233D94FDF43F5 /* UIFont+MaterialTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		983CC3205216C917F8A2D94E439959F7 /* MDCButtonBar.m in Sources */ = {isa = PBXBuildFile; fileRef = FC8CB7864BDCD9DB97A3711AC446E2B0 /* MDCButtonBar.m */; };
+		9847503FD320C722569D661E21EB0B11 /* MDCAppBarContainerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F7D2E69B90D1C23D2FBD5EB175B59364 /* MDCAppBarContainerViewController.m */; };
+		984A454523FEF2464DED49EFB46F4D7D /* MDFTextAccessibility.h in Headers */ = {isa = PBXBuildFile; fileRef = 40759EC5DB49E090570D13E76C4CDA94 /* MDFTextAccessibility.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		98FFEDEEDB14192496FB90B75B9CFFB3 /* MDCDialogPresentationController.m in Sources */ = {isa = PBXBuildFile; fileRef = B9F2A6127E6482F1546297FBA86E9E19 /* MDCDialogPresentationController.m */; };
+		9C71ADED3653D657A6F952A77DA208F7 /* MaterialIcons+ic_reorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B8E69C2D115A0FE03A563709E22B4ED /* MaterialIcons+ic_reorder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9C989E66AB86785F2C11FFAC7EBC30A1 /* MaterialIcons+ic_arrow_back.h in Headers */ = {isa = PBXBuildFile; fileRef = 804D865D3D4D4C65731A550B3D8FC9A5 /* MaterialIcons+ic_arrow_back.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		9CEE28601C484B8E43252D783AFF7A05 /* MDCInkTouchController.m in Sources */ = {isa = PBXBuildFile; fileRef = FF7A269A35FCA0697B0E5BD94453D3EF /* MDCInkTouchController.m */; };
+		9D6D3B5FFB61DFD3F80B76195E605784 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */; };
+		9F337AC8E4B3FD0244949450C9FA822B /* UIView+MDCTimingFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5894DCB5AAB8B32C781B6279A0FEF8D9 /* UIView+MDCTimingFunction.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A08E58F7C109094B2B88D50771692D44 /* MaterialOverlays.h in Headers */ = {isa = PBXBuildFile; fileRef = B5929610276D0E6D8DD3158FF603C0EC /* MaterialOverlays.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A1799A83EA43D62019EFFEE6D1523F79 /* MDCSnackbarMessageInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 03B0B17771C5E17CCA5515AAC7363532 /* MDCSnackbarMessageInternal.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		A1F9E6ACAA85B87A9D8A087F80530FAF /* ic_info@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5EBBA737C7DEFC62CB07A5607401B086 /* ic_info@3x.png */; };
+		A2CEADFD01F6E59D4D792EFC35289A97 /* UIApplication+AppExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C4F931DA815928A8CA82E5513C6246A /* UIApplication+AppExtensions.m */; };
+		A2EE82AB4435B7F2278B816E9928C1AA /* MDCPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = A683F198135D9329FD62063BFB4B0F9B /* MDCPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A339971188CEF5E30398257AA87216D5 /* MaterialAppBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D0C383ECBB30F7ADEB6B1EFF274C298 /* MaterialAppBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		A53D190E021C5C1186AC498313F5366A /* MDCShadowLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = B6134FFEBB32CC196B45597FC2948611 /* MDCShadowLayer.m */; };
+		A5847C5D55280D73543922B562E3EE76 /* MDCFeatureHighlightAnimationController.h in Headers */ = {isa = PBXBuildFile; fileRef = EC8039BB5A86167E8DCDB72F46D6388B /* MDCFeatureHighlightAnimationController.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		A5CE5EE5A0CB5AC74A082871D0E4D0E2 /* NSArray+MDFUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 7231A93714A109C83065D36604C9451C /* NSArray+MDFUtils.m */; };
+		A6B49525465146B18DECD9B24AD878DE /* MDFColorCalculations.m in Sources */ = {isa = PBXBuildFile; fileRef = 516E307567E6B1C8060A69B31F20108A /* MDFColorCalculations.m */; };
+		AA10E060FCF509E24CEAEE87D2E80949 /* MDCShadowElevations.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E855EBFE6A726985077571DB7E89BD5 /* MDCShadowElevations.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		AA6B9D4E09B8642FE07CA11093EFB762 /* MDCSlider.m in Sources */ = {isa = PBXBuildFile; fileRef = 2862A3829BA4649EDB04191EB5D64C4B /* MDCSlider.m */; };
+		AB01C09668E3D82190EAE5DC10E07CAA /* UIView+MaterialRTL.m in Sources */ = {isa = PBXBuildFile; fileRef = 90B29DB14670F66061CFB82DDC68AF49 /* UIView+MaterialRTL.m */; };
+		AB8705EA210EDB911167D97874D360FB /* MDFImageCalculations.m in Sources */ = {isa = PBXBuildFile; fileRef = F68D30CBF1457E3E9AE7D3AE92AC18F0 /* MDFImageCalculations.m */; };
+		ABEC063A0D41BC10143B8DACF1B82237 /* ic_arrow_back.png in Resources */ = {isa = PBXBuildFile; fileRef = 15E9398FCB2DA33C5C08533B1716A7CE /* ic_arrow_back.png */; };
+		ADB5ECE6B1779BB7CCB7C3468BADC052 /* MDCFeatureHighlightView.h in Headers */ = {isa = PBXBuildFile; fileRef = 17B8A83C9148D87712E07EDE938E65E0 /* MDCFeatureHighlightView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		AF01D47F2E21218233A1FF787C75EBE2 /* MDCFlatButton.h in Headers */ = {isa = PBXBuildFile; fileRef = EFCF3D3D2FE3A10C4245EF66AE882178 /* MDCFlatButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B15972456A2F74F579179B9FA24B11A2 /* MaterialPageControl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D8330A4B1BF56B9147CC1FE27AFDFCA /* MaterialPageControl.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B20E8D99109D62C4F51394FBE9CB4346 /* MDCInkGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = CAC43F65D5D78A89EAC07A697ACC9837 /* MDCInkGestureRecognizer.m */; };
+		B22A6ACFF10775AFE5312ADF4FB00ECC /* UIFont+MaterialTypographyPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 6E75C79B7D5289097D15A811F188CED2 /* UIFont+MaterialTypographyPrivate.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		B31AC47ADCCE328A838CCDFB76642B4D /* UIApplication+AppExtensions.h in Headers */ = {isa = PBXBuildFile; fileRef = 95D1CF13299CEF28BCBAA62F927A3D80 /* UIApplication+AppExtensions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B6617FDF0F00EEA0091D859D88DDFD44 /* MDCHeaderStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = CE6929889D615189113913408E3D1B9E /* MDCHeaderStackView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		B818D6AEBD75B9F9CDC04357F55DF6EF /* UIFont+MaterialTypography.m in Sources */ = {isa = PBXBuildFile; fileRef = E17A7167DE53F6528C656D4979850FBC /* UIFont+MaterialTypography.m */; };
+		B8A8D97688E58A1C843EE96397D81DF9 /* MaterialPalettes.h in Headers */ = {isa = PBXBuildFile; fileRef = 0EC4BB63283347849E4A8B02A60CABC4 /* MaterialPalettes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BB463EFA3C52D5DDFFDAB937345C932F /* MDCNumericValueLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = C660FEA28DDB8CB873D9BCE3DA03F6B3 /* MDCNumericValueLabel.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BBD17582B2F80BD702EF29C8B0E5D712 /* MaterialIcons+ic_info.h in Headers */ = {isa = PBXBuildFile; fileRef = FD4ED0BAB173C96E24BFAF538C1A0353 /* MaterialIcons+ic_info.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BCFF786BA8B6010F68220F150D77BC30 /* MDCKeyboardWatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = BE4C70E576A2623B72B27F812FA19587 /* MDCKeyboardWatcher.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BD37D976E99C4BF895220E803F0CC41D /* MDCCollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D1D4C0D37627D761BB16ECB99105E4A0 /* MDCCollectionViewController.m */; };
+		BE43B4DB418BFA444DEE432B7F329C9C /* MDCStatusBarShifter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D86AB797FE0EAA5C5384DF417BF5346 /* MDCStatusBarShifter.m */; };
+		BF4527E139FB205D0EBD8F54FD8AF18D /* MDCTabBarAlignment.h in Headers */ = {isa = PBXBuildFile; fileRef = B9E2AAB8153882A4590062F569A4D595 /* MDCTabBarAlignment.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BF73F5FFED03E771C41544D7E5AF7AB8 /* MaterialCollections.h in Headers */ = {isa = PBXBuildFile; fileRef = 210894774DFDFBA293E2296F2A30C362 /* MaterialCollections.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		BF9A53B148F71E2405838165261131E7 /* MDCFlexibleHeaderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6EAC67B229E26EFB3FEF38B7164183F0 /* MDCFlexibleHeaderViewController.m */; };
+		BFCDBAD98869A1F1A6BBEAF75E86F926 /* MDCOverlayObserverTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 1509DAD755F448EBE08F87224B5BD8D3 /* MDCOverlayObserverTransition.m */; };
+		C1B17B6540AD304C1A39E0A37E19AE2C /* MDCFlexibleHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = 71BE7789CD2EC0A70DE711AC5A1FEF8D /* MDCFlexibleHeaderView.m */; };
+		C1C7F298EA4326DF2C05351A740E1D8F /* MDCInkView.m in Sources */ = {isa = PBXBuildFile; fileRef = FC7FA8E220EACEBE9FB49B6A6B3732E5 /* MDCInkView.m */; };
+		C212207098B33F8B829CE94A3706DB49 /* MDCNumericValueLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E74B45D4E01DE3821E65C8FEC806B60 /* MDCNumericValueLabel.m */; };
+		C2309CF5EBD904E226161D55F14B950A /* MaterialActivityIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7143C04351DADE6FD07918C99C3BF31E /* MaterialActivityIndicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		C3A59E6F295659D872D65BFEB6832A34 /* MDCRaisedButton.m in Sources */ = {isa = PBXBuildFile; fileRef = B77E7CD1098848AED57761E60382667D /* MDCRaisedButton.m */; };
+		C415FCA0E080D6BDAF30C011F5476604 /* MDCCollectionViewLayoutAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = 462854769E2CB8F1B329D4392C79AA61 /* MDCCollectionViewLayoutAttributes.m */; };
+		C77D1E2CEA9AC648CCAE66DD64A12E57 /* MDFTextAccessibility-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E961B158FE9954DDD2B6C09E3462883 /* MDFTextAccessibility-dummy.m */; };
+		C7AC330240BBC7E4EB43FE67062A461B /* MDCCollectionStringResources.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C42FCD2D863F783537F7B84C002801 /* MDCCollectionStringResources.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		C95B219DE3270084C28BE6FDDC86F2D5 /* MaterialTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = D1A37A0287C491DFE2089102146664E8 /* MaterialTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CA4EF6FF105C4B45D26CC12A9F8CA011 /* MaterialSnackbar.h in Headers */ = {isa = PBXBuildFile; fileRef = 9C7E38A7B56C28ED6E56D587A376C3B4 /* MaterialSnackbar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CB57A2838CE91AA87493A967057A9F50 /* ic_reorder@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 47BD4FBE1EC6F6C948B7056DFB3EAE4E /* ic_reorder@2x.png */; };
+		CB68DFA2C9FC1A3435236521B0408CEE /* UIViewController+MaterialDialogs.h in Headers */ = {isa = PBXBuildFile; fileRef = E8C4112E03A439A51F0FBD876DA804E5 /* UIViewController+MaterialDialogs.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CC4BC92CDE1AA4B8613AB884E75FB2E4 /* MDCTabBarItemAppearance.h in Headers */ = {isa = PBXBuildFile; fileRef = 2FE6A5198039451C28C172BC4168A03A /* MDCTabBarItemAppearance.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		CDAFC1E966DB3C899DE01EC81998EE9C /* MDCCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 29BB55A9B6803B9A3A7A064A6E797A79 /* MDCCollectionViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D053587851EF944EAC99AF4152E5BA75 /* MDCCollectionViewEditor.h in Headers */ = {isa = PBXBuildFile; fileRef = F4C0F26237AA99F43F82CD8B6404A8FF /* MDCCollectionViewEditor.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		D07E00458702FE480F21B32777B0F013 /* MaterialAnimationTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = C075A49AEB6D1C36BA22C458FC6A2801 /* MaterialAnimationTiming.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D143DDFD972B30645F3278852EE20F5B /* MaterialIcons+ic_reorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 3F9391682535FDA07FBB0AB83B6B96E0 /* MaterialIcons+ic_reorder.m */; };
+		D2C9BED43BB4C6FA2D23424759A4EB2F /* MDCOverlayUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DD35DF5F260987C932CF7B25AD8C22C4 /* MDCOverlayUtilities.m */; };
+		D3BC8C16993BC06EF08B9A0B91B81568 /* MDCOverlayAnimationObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = EB110721FC9D3D6E29D13627A35DFD0E /* MDCOverlayAnimationObserver.m */; };
+		D448A87D1BC2FC2702156E6FE048F9BC /* MaterialButtonBar.h in Headers */ = {isa = PBXBuildFile; fileRef = D14A347A944C556F216B967AFCF766C8 /* MaterialButtonBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D4D362E714758EDDEC809019CC26974C /* MDCNavigationBar.m in Sources */ = {isa = PBXBuildFile; fileRef = CCF1F1AE19AF21CE8869CF3A681CC787 /* MDCNavigationBar.m */; };
+		D6BE450D35006B7F2F83EB19CDC1B473 /* UIFontDescriptor+MaterialTypography.m in Sources */ = {isa = PBXBuildFile; fileRef = D7E1DE48A44A60C2AE808B6D69A73683 /* UIFontDescriptor+MaterialTypography.m */; };
+		D6CEB0B38DC1554A3B1956CB6A11D892 /* MDCAlertController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D28C66D16BE7A01B82F7FD890CA7DBC /* MDCAlertController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		D72106583CB3A2A6B758B48F27882B40 /* ic_check_circle.png in Resources */ = {isa = PBXBuildFile; fileRef = 11ED6DF86B1C41582FEF6983B868825F /* ic_check_circle.png */; };
+		D846A62610497F25E2B7A537EA12C757 /* MDCSnackbarMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = D20FE85CECC64B86387F4CA60B86C8C6 /* MDCSnackbarMessage.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DACA2B285CD4608DBB73D72910DDCC3B /* MDCOverlayUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = C03DAFCD2FB2199D18A24125D772CB7A /* MDCOverlayUtilities.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		DB772D2AC10FA285081B0AD22494A408 /* MDCAppBarContainerViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FA357A2956B620B50A4CAEFE8F1795B /* MDCAppBarContainerViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DBAAB720813BBA54AD2126495BDAA7D2 /* MaterialButtons.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B9EBBBC413F2FB5A96D131DC26FFC36 /* MaterialButtons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DBCD145300C030FCA8C9F1D8C624216B /* MDCThumbTrack.h in Headers */ = {isa = PBXBuildFile; fileRef = 86754C059E8434587187015DC770180B /* MDCThumbTrack.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DC0601BB3966D321FDC30D767B44C37F /* MaterialCollectionsStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 56417D84CA78A113438D534EE4FFC54A /* MaterialCollectionsStrings.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		DC2B567C06EA75C2EF988EE491DB370A /* ic_check@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 49A3FB5A7A3C2EEAAF7C7BD7C72CABBD /* ic_check@3x.png */; };
+		DDD7A57F4148DC9FCC8DB0DAF6866E10 /* ic_arrow_back@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = FE7AE3A31ABEA928F10508D5385C37F8 /* ic_arrow_back@3x.png */; };
+		DEEF35853A0974C2FBE1D5F0DD7AE0BC /* MDCFloatingButton.h in Headers */ = {isa = PBXBuildFile; fileRef = E66CD057FB364E80D5BC3D34A00B42FF /* MDCFloatingButton.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		DF0C93BD3E28121899DB290E32612D14 /* MDCPageControlTrackLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 8556079BFB00835D898F480913F78F13 /* MDCPageControlTrackLayer.m */; };
+		E09CE6C566DADA7AB46361EF95F0D4A2 /* MDCInkLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = E37F8FD7F722E714E0005FB0C96F9A03 /* MDCInkLayer.m */; };
+		E122D135F905A61F2F2BC12B5E752E8B /* MDCFeatureHighlightViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C27D7602B81556831B0A85A92B4E5A3 /* MDCFeatureHighlightViewController.m */; };
+		E16F8810A88826A00D8AEFEA8382FCE0 /* MaterialIcons+ic_check.m in Sources */ = {isa = PBXBuildFile; fileRef = 88AE915AB74A3A3AA3F3F10C11CD9644 /* MaterialIcons+ic_check.m */; };
+		E21FBFA76EC56E1D06EB0CD35550A7F8 /* MDCAppBarButtonBarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 193A24743DF539FCD29F2B8EF21442F2 /* MDCAppBarButtonBarBuilder.m */; };
+		E4282287703DA962B61A39D1B0D8318D /* MDCCollectionGridBackgroundView.h in Headers */ = {isa = PBXBuildFile; fileRef = 79DCB73AD07EBD187AB62F38B93A8863 /* MDCCollectionGridBackgroundView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		E4452C88A27E46E154E525C9840E1494 /* MDCPageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = BA4F460E41035D7B0B538CDC2752925D /* MDCPageControl.m */; };
+		E5CA64F5137CB5A48B42C9BB8F8EE127 /* MDCTypography.h in Headers */ = {isa = PBXBuildFile; fileRef = 12D62C2A9C95A969E4AA727F1C8C202C /* MDCTypography.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E7D877B60FFD0FF706FDDFD568088D78 /* MaterialIcons+ic_radio_button_unchecked.h in Headers */ = {isa = PBXBuildFile; fileRef = 97FBECBD5EF590F0A8005F8B94E808FF /* MaterialIcons+ic_radio_button_unchecked.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E88C4953B207850482CE8CAF646EB7F6 /* MDCInkGestureRecognizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0750459EFB95F5CE725C61781848452B /* MDCInkGestureRecognizer.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E90F58CF316377AF8434201C85BBEA50 /* MaterialIcons.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C4B4B293D1D97D44EA76F8E2DD5595E /* MaterialIcons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E98184F9E8FBA7F587905DDDD0944848 /* CAMediaTimingFunction+MDCAnimationTiming.h in Headers */ = {isa = PBXBuildFile; fileRef = 74905502A1DF96D7D84E7714A179E9E9 /* CAMediaTimingFunction+MDCAnimationTiming.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		E9FEACB48E266BE82E3F563E89A57E55 /* MDCOverlayImplementor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2506F285EFA1CEF8247B19211C38EF23 /* MDCOverlayImplementor.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		EA9BE12F0B4EC342AE180CDEAC34F8D3 /* ic_arrow_back@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 11DD5A41B2DA0290521D16D24EEC529D /* ic_arrow_back@2x.png */; };
+		EBB65F826BFB14DC485D1126FA924591 /* MDCFeatureHighlightViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 66E845FD6DDDE254DBD69B4B9FBCA3B8 /* MDCFeatureHighlightViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		ED5BBB6CB14C9E62E7C62DCDD69C727E /* MDCDialogTransitionController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0040124427B7D454BC17F95E2C95F1B9 /* MDCDialogTransitionController.m */; };
+		F2AF846BCE456A75743C8A76EFE8AC36 /* MDCPalettes.h in Headers */ = {isa = PBXBuildFile; fileRef = 675F4FE5A00141BDF25CA3589A5DEF88 /* MDCPalettes.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F428458129C3701B14F25859C60F6C4A /* MDCDialogShadowedView.h in Headers */ = {isa = PBXBuildFile; fileRef = 3F5A046B9A9E9CC97A6C6B6A65F22F53 /* MDCDialogShadowedView.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		F43265AC32261E3688370C90941A1C51 /* MDCFontTextStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = CD6BFB0EA4919F07C8AD5F586E34376D /* MDCFontTextStyle.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F5A806B7DF97350385E8C0AF48172DB2 /* MDCIcons.h in Headers */ = {isa = PBXBuildFile; fileRef = 8938D8038B0C55A96B4E161C6661FFC0 /* MDCIcons.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		F7A7869F8EB0BB5B4F817AE17001B79A /* MaterialComponents-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 13FA3054B67E07E3C004F5E26131FFC5 /* MaterialComponents-dummy.m */; };
+		F81CCFD29E38C4B4669681176C4C53C0 /* MDFColorCalculations.h in Headers */ = {isa = PBXBuildFile; fileRef = 10D3AFAF60EB1088403525BA3DF6BD18 /* MDFColorCalculations.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		F89C9B4B75A51557C4194C373983E7DD /* MDCPageControlTrackLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9D57CB474D3A2B64257FE6E21F9BD796 /* MDCPageControlTrackLayer.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		F8E7DFFB95518F5BE25C98ACA633E003 /* MDCNavigationBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 01B79C689F86C1C48EEBFE41AA191DBE /* MDCNavigationBar.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FA36A066EE5CF084A61B8E5CE4A50928 /* MDCCollectionViewStyling.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FECD187F5A83C12336BB0C55DD75C6F /* MDCCollectionViewStyling.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FAEBD8461B68C2706F8A208E3E596643 /* MDCCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BEBA1206741596666E53A5291AC6C67D /* MDCCollectionViewCell.m */; };
+		FB0210FF9893437C285475B18A6B25D6 /* MaterialHeaderStackView.h in Headers */ = {isa = PBXBuildFile; fileRef = 702CBDDD852DAA7044CE6BCB5AA2D950 /* MaterialHeaderStackView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FB207298B52DA12C580DA33D926A33CE /* ic_check_circle@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 20A374DC73FDF4CF43A4454A86E587F6 /* ic_check_circle@2x.png */; };
+		FCC2DBDF248F8D1B0759647AA9AADBC2 /* MDCFlexibleHeaderViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 24A9F1821AD8EA4BF21E13D87EC6F56D /* MDCFlexibleHeaderViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FD7FA96389A0CB49A6673EFF467DDAA3 /* MDCDialogTransitionController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0044FD236D22AB00062FFED53D72ECEF /* MDCDialogTransitionController.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FDBD2F6421CA1221915E3E4DE3B98C57 /* MDCRTL.h in Headers */ = {isa = PBXBuildFile; fileRef = 935B6D6F1FAB419F6C7B4129E6A0074F /* MDCRTL.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FF37686F3E3AFF2F94C01E95A9CE2911 /* MDCAppBarButtonBarBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FC2C7E47A0EA56BD6295D82B56F6192 /* MDCAppBarButtonBarBuilder.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		FF82D045067B9F2BE69E2C5772EEBAFE /* MDCTabBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 5D8DE150DA0161A584D8CED87D6DF987 /* MDCTabBar.m */; };
+		FFCED3ABEBE505D648ECFB89C3B5A1DE /* MDCItemBarCell.h in Headers */ = {isa = PBXBuildFile; fileRef = E70A12012C34069A15DAAEF725754A18 /* MDCItemBarCell.h */; settings = {ATTRIBUTES = (Project, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+		07B01A307DE976243C53CDA94B27C112 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = EEA5B88E1ACE47BDFFC5FD0BBAA2A28C;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_check";
+		};
+		17BCA1B89A11CC355E43FD3BFCD13C12 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2E72C96C2685FC808D51BA6B9AA64CF4;
+			remoteInfo = MDFTextAccessibility;
+		};
+		26A37A36E1641BBB8CE2EDDFC8616CCD /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 063B0E6AFAF8DCF585379E4BCB2C7131;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_chevron_right";
+		};
+		39EA7F91F3A8B4BBE7EDA6E436B1836F /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = AFFA60B0A14082D99BC69B83E990917F;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_reorder";
+		};
+		77F3D96E9E9ED94700A1F61B82743FBE /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 16E29731A9C9770DCC25F5A8A3ED71FA;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_info";
+		};
+		79BDE4F2A4F44762925D8ABCC802FDBA /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 827B847BE0C5521773C58E7A599CAD8D;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_arrow_back";
+		};
+		8B33909233E6BAB3ED98C8FEB26CD2E6 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 19634FBF87D1F1FA955FF17A6BB5585E;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+		};
+		94AE73493B374CDBE138E1C8D3A177CB /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 26C4686B7C9E9E7E4E77A332481D6196;
+			remoteInfo = MaterialComponents;
+		};
+		B92E0F607A56686D7F93C4B7757E85F5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = C2EC108B302373D03D5F0A9EB5B55787;
+			remoteInfo = "MaterialComponents-MaterialIcons_ic_check_circle";
+		};
+		F34B40D121BBEE584389E4FD1349C927 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 2E72C96C2685FC808D51BA6B9AA64CF4;
+			remoteInfo = MDFTextAccessibility;
+		};
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+		0040124427B7D454BC17F95E2C95F1B9 /* MDCDialogTransitionController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCDialogTransitionController.m; path = components/Dialogs/src/MDCDialogTransitionController.m; sourceTree = "<group>"; };
+		0044FD236D22AB00062FFED53D72ECEF /* MDCDialogTransitionController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCDialogTransitionController.h; path = components/Dialogs/src/MDCDialogTransitionController.h; sourceTree = "<group>"; };
+		01127A0CE1E1F9D661213AD37AC639FC /* MDCItemBarCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCItemBarCell.m; path = components/Tabs/src/private/MDCItemBarCell.m; sourceTree = "<group>"; };
+		01B79C689F86C1C48EEBFE41AA191DBE /* MDCNavigationBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCNavigationBar.h; path = components/NavigationBar/src/MDCNavigationBar.h; sourceTree = "<group>"; };
+		01C5E9A263A0FBC63B0B1E0D89013529 /* MDCSnackbarOverlayView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarOverlayView.m; path = components/Snackbar/src/private/MDCSnackbarOverlayView.m; sourceTree = "<group>"; };
+		029A97895F42B6AB7B7209A3BB20DCA8 /* ic_info@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_info@2x.png"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@2x.png"; sourceTree = "<group>"; };
+		02AE1C5FFC5FC596ABEC7C98AEF62DD8 /* Pods-BuildingBeautifulApps.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BuildingBeautifulApps.debug.xcconfig"; sourceTree = "<group>"; };
+		03B0B17771C5E17CCA5515AAC7363532 /* MDCSnackbarMessageInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessageInternal.h; path = components/Snackbar/src/private/MDCSnackbarMessageInternal.h; sourceTree = "<group>"; };
+		03B1990C768D7EBE9880314C80B89B32 /* MDCCollectionInfoBarView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionInfoBarView.m; path = components/Collections/src/private/MDCCollectionInfoBarView.m; sourceTree = "<group>"; };
+		03CE9EF2998E990D7C6C15AC4AEFF20D /* MaterialShadowElevations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialShadowElevations.h; path = components/ShadowElevations/src/MaterialShadowElevations.h; sourceTree = "<group>"; };
+		041B9228D9CF59ABFD7ACB6A1D468715 /* MDCCollectionViewStylingDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewStylingDelegate.h; path = components/Collections/src/MDCCollectionViewStylingDelegate.h; sourceTree = "<group>"; };
+		04BA7B9EA003598360273283129FDE9B /* MaterialCollections.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialCollections.bundle; path = components/Collections/src/MaterialCollections.bundle; sourceTree = "<group>"; };
+		06A99FC5FF2D8E635C719D756C525052 /* MDCKeyboardWatcher.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCKeyboardWatcher.m; path = components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m; sourceTree = "<group>"; };
+		0750459EFB95F5CE725C61781848452B /* MDCInkGestureRecognizer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkGestureRecognizer.h; path = components/Ink/src/MDCInkGestureRecognizer.h; sourceTree = "<group>"; };
+		07B2F589B283B574F2B354D14386BBF8 /* MDCFontTraits.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFontTraits.h; path = components/Typography/src/private/MDCFontTraits.h; sourceTree = "<group>"; };
+		09A539046C55C092B1882F2B3101A656 /* libMaterialComponents.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMaterialComponents.a; path = libMaterialComponents.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		0C1F25227166DC67A877DFCA5594F74B /* MaterialTabs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialTabs.h; path = components/Tabs/src/MaterialTabs.h; sourceTree = "<group>"; };
+		0EC4BB63283347849E4A8B02A60CABC4 /* MaterialPalettes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPalettes.h; path = components/Palettes/src/MaterialPalettes.h; sourceTree = "<group>"; };
+		0EEA3ACEEB4A63D1DF01A8D3F89BC441 /* UIImage+MaterialRTL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIImage+MaterialRTL.m"; path = "components/private/RTL/src/UIImage+MaterialRTL.m"; sourceTree = "<group>"; };
+		0F8DD7BF09A1359D0C22AD2D99DF9967 /* MDCSlider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSlider.h; path = components/Slider/src/MDCSlider.h; sourceTree = "<group>"; };
+		10B9C9D65FA83AC626EFF1C6A94BA402 /* CAMediaTimingFunction+MDCAnimationTiming.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "CAMediaTimingFunction+MDCAnimationTiming.m"; path = "components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m"; sourceTree = "<group>"; };
+		10D3AFAF60EB1088403525BA3DF6BD18 /* MDFColorCalculations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDFColorCalculations.h; path = src/private/MDFColorCalculations.h; sourceTree = "<group>"; };
+		1119E38AD872AC586FC0B36077CBD452 /* MDCProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCProgressView.h; path = components/ProgressView/src/MDCProgressView.h; sourceTree = "<group>"; };
+		11DD5A41B2DA0290521D16D24EEC529D /* ic_arrow_back@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back@2x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@2x.png"; sourceTree = "<group>"; };
+		11ED6DF86B1C41582FEF6983B868825F /* ic_check_circle.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_check_circle.png; path = components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle.png; sourceTree = "<group>"; };
+		120CFBE565880C2F4F462AAFCEBB37E5 /* Pods-BuildingBeautifulApps.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-BuildingBeautifulApps.release.xcconfig"; sourceTree = "<group>"; };
+		12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
+		12BE96DCA235623AF7766C60CCFAE1C7 /* MDCButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCButton.h; path = components/Buttons/src/MDCButton.h; sourceTree = "<group>"; };
+		12D62C2A9C95A969E4AA727F1C8C202C /* MDCTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTypography.h; path = components/Typography/src/MDCTypography.h; sourceTree = "<group>"; };
+		13923E685C01C84D742BF61E9A51D084 /* MDCFeatureHighlightView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightView.m; path = components/FeatureHighlight/src/private/MDCFeatureHighlightView.m; sourceTree = "<group>"; };
+		13DBFFD40004CC93DF060411AE7CB49F /* MDFTextAccessibility-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MDFTextAccessibility-prefix.pch"; sourceTree = "<group>"; };
+		13FA3054B67E07E3C004F5E26131FFC5 /* MaterialComponents-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MaterialComponents-dummy.m"; sourceTree = "<group>"; };
+		14793E6FDAF9C044D6ED8B67E59C7E75 /* MDCSlider_Subclassable.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSlider_Subclassable.h; path = components/Slider/src/private/MDCSlider_Subclassable.h; sourceTree = "<group>"; };
+		1509DAD755F448EBE08F87224B5BD8D3 /* MDCOverlayObserverTransition.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayObserverTransition.m; path = components/private/Overlay/src/private/MDCOverlayObserverTransition.m; sourceTree = "<group>"; };
+		158DFD17C32FF1158E4896DD754DDC6B /* MDCCollectionViewTextCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewTextCell.m; path = components/CollectionCells/src/MDCCollectionViewTextCell.m; sourceTree = "<group>"; };
+		15E9398FCB2DA33C5C08533B1716A7CE /* ic_arrow_back.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_arrow_back.png; path = components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back.png; sourceTree = "<group>"; };
+		16C2D56E186EC25B2AD48EF7EC5DB131 /* MDCCollectionViewFlowLayout.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewFlowLayout.h; path = components/Collections/src/MDCCollectionViewFlowLayout.h; sourceTree = "<group>"; };
+		16E650750C1D8383CFF76B265B232D54 /* MDCOverlayObserverOverlay.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayObserverOverlay.h; path = components/private/Overlay/src/private/MDCOverlayObserverOverlay.h; sourceTree = "<group>"; };
+		17AAA691CE308745D666AC354DEBD7D1 /* ic_radio_button_unchecked.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_radio_button_unchecked.png; path = components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked.png; sourceTree = "<group>"; };
+		17B8A83C9148D87712E07EDE938E65E0 /* MDCFeatureHighlightView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightView.h; path = components/FeatureHighlight/src/private/MDCFeatureHighlightView.h; sourceTree = "<group>"; };
+		193A24743DF539FCD29F2B8EF21442F2 /* MDCAppBarButtonBarBuilder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAppBarButtonBarBuilder.m; path = components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m; sourceTree = "<group>"; };
+		1B3462BC5FFFCC355901DAA536C77A5A /* MDCFeatureHighlightLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightLayer.m; path = components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m; sourceTree = "<group>"; };
+		1C21154B03011C9702C295079DCF65E1 /* MaterialInk.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialInk.h; path = components/Ink/src/MaterialInk.h; sourceTree = "<group>"; };
+		1D1C4015B6347137598F264D6387CCA6 /* MDCSnackbarMessage.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarMessage.m; path = components/Snackbar/src/MDCSnackbarMessage.m; sourceTree = "<group>"; };
+		1D28C66D16BE7A01B82F7FD890CA7DBC /* MDCAlertController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAlertController.h; path = components/Dialogs/src/MDCAlertController.h; sourceTree = "<group>"; };
+		1D570439942906B139B693491F7E71ED /* MDCAppBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAppBar.m; path = components/AppBar/src/MDCAppBar.m; sourceTree = "<group>"; };
+		1D9BC573FF76C294C05D43278D00B4A6 /* UIView+MaterialRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MaterialRTL.h"; path = "components/private/RTL/src/UIView+MaterialRTL.h"; sourceTree = "<group>"; };
+		1E74B45D4E01DE3821E65C8FEC806B60 /* MDCNumericValueLabel.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCNumericValueLabel.m; path = components/private/ThumbTrack/src/MDCNumericValueLabel.m; sourceTree = "<group>"; };
+		1F0F8786C896495252AF8C693705FE27 /* MDCFeatureHighlightLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightLayer.h; path = components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h; sourceTree = "<group>"; };
+		1FA357A2956B620B50A4CAEFE8F1795B /* MDCAppBarContainerViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAppBarContainerViewController.h; path = components/AppBar/src/MDCAppBarContainerViewController.h; sourceTree = "<group>"; };
+		206683C2791ADADFAC3B8A5DAA2DA22A /* MaterialComponents-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MaterialComponents-prefix.pch"; sourceTree = "<group>"; };
+		206E1270F7CD7132605A140A429FE475 /* MDCCollectionInfoBarView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionInfoBarView.h; path = components/Collections/src/private/MDCCollectionInfoBarView.h; sourceTree = "<group>"; };
+		20A374DC73FDF4CF43A4454A86E587F6 /* ic_check_circle@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check_circle@2x.png"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@2x.png"; sourceTree = "<group>"; };
+		210894774DFDFBA293E2296F2A30C362 /* MaterialCollections.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollections.h; path = components/Collections/src/MaterialCollections.h; sourceTree = "<group>"; };
+		24A9F1821AD8EA4BF21E13D87EC6F56D /* MDCFlexibleHeaderViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlexibleHeaderViewController.h; path = components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h; sourceTree = "<group>"; };
+		24C7218ECEE1F60B1B720B21514EE621 /* MDCCollectionViewEditor.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewEditor.m; path = components/Collections/src/private/MDCCollectionViewEditor.m; sourceTree = "<group>"; };
+		2506F285EFA1CEF8247B19211C38EF23 /* MDCOverlayImplementor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayImplementor.h; path = components/private/Overlay/src/MDCOverlayImplementor.h; sourceTree = "<group>"; };
+		2543C83779FCB7CA6F63B6E23BA22BDB /* MDCStatusBarShifter.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCStatusBarShifter.h; path = components/FlexibleHeader/src/private/MDCStatusBarShifter.h; sourceTree = "<group>"; };
+		25F7B26DAEC96431ECEEC467ADA2CF28 /* MDCSnackbarManager.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarManager.h; path = components/Snackbar/src/MDCSnackbarManager.h; sourceTree = "<group>"; };
+		263DB970C3B145399EBC89F15760FB2B /* MaterialIcons+ic_check_circle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_check_circle.h"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h"; sourceTree = "<group>"; };
+		2792F28B4CCFEB1DCDCDBB8636947EBC /* MDCItemBarStyle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCItemBarStyle.m; path = components/Tabs/src/private/MDCItemBarStyle.m; sourceTree = "<group>"; };
+		2862A3829BA4649EDB04191EB5D64C4B /* MDCSlider.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSlider.m; path = components/Slider/src/MDCSlider.m; sourceTree = "<group>"; };
+		29BB55A9B6803B9A3A7A064A6E797A79 /* MDCCollectionViewCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewCell.h; path = components/CollectionCells/src/MDCCollectionViewCell.h; sourceTree = "<group>"; };
+		2D0C383ECBB30F7ADEB6B1EFF274C298 /* MaterialAppBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialAppBar.h; path = components/AppBar/src/MaterialAppBar.h; sourceTree = "<group>"; };
+		2FE6A5198039451C28C172BC4168A03A /* MDCTabBarItemAppearance.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTabBarItemAppearance.h; path = components/Tabs/src/MDCTabBarItemAppearance.h; sourceTree = "<group>"; };
+		33072B9B16A9B8DAAEDE9D6B449679D2 /* ic_arrow_back_ios@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back_ios@2x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@2x.png"; sourceTree = "<group>"; };
+		35901EA242A4B2DE85C2894CC9194C1F /* ic_chevron_right@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_chevron_right@3x.png"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@3x.png"; sourceTree = "<group>"; };
+		38A6CB047FC50FA03168F50ACA26C75B /* ic_check_circle@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check_circle@3x.png"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons_ic_check_circle.bundle/ic_check_circle@3x.png"; sourceTree = "<group>"; };
+		3BF39A7F429701947B09DCBEB4A07F05 /* MDCIcons.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCIcons.m; path = components/private/Icons/src/MDCIcons.m; sourceTree = "<group>"; };
+		3C914D35C46E85C26AA1E246E17CECE5 /* MDCProgressView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCProgressView.m; path = components/ProgressView/src/MDCProgressView.m; sourceTree = "<group>"; };
+		3D8330A4B1BF56B9147CC1FE27AFDFCA /* MaterialPageControl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPageControl.h; path = components/PageControl/src/MaterialPageControl.h; sourceTree = "<group>"; };
+		3F5A046B9A9E9CC97A6C6B6A65F22F53 /* MDCDialogShadowedView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCDialogShadowedView.h; path = components/Dialogs/src/private/MDCDialogShadowedView.h; sourceTree = "<group>"; };
+		3F9391682535FDA07FBB0AB83B6B96E0 /* MaterialIcons+ic_reorder.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_reorder.m"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m"; sourceTree = "<group>"; };
+		3F9B634EE11CC423F51EE3D659001D14 /* NSArray+MDFUtils.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "NSArray+MDFUtils.h"; path = "src/private/NSArray+MDFUtils.h"; sourceTree = "<group>"; };
+		403CEE2F8B8AFCD9A8ADAD83045448CB /* ic_reorder.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_reorder.png; path = components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder.png; sourceTree = "<group>"; };
+		40759EC5DB49E090570D13E76C4CDA94 /* MDFTextAccessibility.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDFTextAccessibility.h; path = src/MDFTextAccessibility.h; sourceTree = "<group>"; };
+		409899CE1143F81E8130E2069D59605B /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+		423E686AE21269BCFA30A045BF0D5F96 /* ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist"; sourceTree = "<group>"; };
+		4277E14F56DAC15ABD24D97EDC26ADEA /* UIFont+MaterialTypographyPrivate.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIFont+MaterialTypographyPrivate.m"; path = "components/Typography/src/private/UIFont+MaterialTypographyPrivate.m"; sourceTree = "<group>"; };
+		430CFFC6D36F60111CDF22059398251D /* MaterialIcons_ic_check_circle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_check_circle.bundle; path = MaterialIcons_ic_check_circle.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		4374B11D22F0FCC5866781A5F08A4D38 /* MDCButtonBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCButtonBar.h; path = components/ButtonBar/src/MDCButtonBar.h; sourceTree = "<group>"; };
+		443C58797FC89C1F0BDC6BDF82DD1913 /* MaterialIcons+ic_check_circle.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_check_circle.m"; path = "components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m"; sourceTree = "<group>"; };
+		444B921CA054B6ED8B57713242404400 /* MaterialCollectionLayoutAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionLayoutAttributes.h; path = components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h; sourceTree = "<group>"; };
+		45DA800B226D1DE08F69E5BDDC45E203 /* MDCActivityIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCActivityIndicator.m; path = components/ActivityIndicator/src/MDCActivityIndicator.m; sourceTree = "<group>"; };
+		462854769E2CB8F1B329D4392C79AA61 /* MDCCollectionViewLayoutAttributes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewLayoutAttributes.m; path = components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m; sourceTree = "<group>"; };
+		478E465B2E211ABEB0687F1096C92E0C /* ResourceBundle-MaterialIcons_ic_reorder-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_reorder-Info.plist"; sourceTree = "<group>"; };
+		47BD4FBE1EC6F6C948B7056DFB3EAE4E /* ic_reorder@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_reorder@2x.png"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@2x.png"; sourceTree = "<group>"; };
+		49A3FB5A7A3C2EEAAF7C7BD7C72CABBD /* ic_check@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check@3x.png"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@3x.png"; sourceTree = "<group>"; };
+		4AF4F84748B988E39D513A50701185FC /* MDFTextAccessibility.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDFTextAccessibility.m; path = src/MDFTextAccessibility.m; sourceTree = "<group>"; };
+		4B9EBBBC413F2FB5A96D131DC26FFC36 /* MaterialButtons.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialButtons.h; path = components/Buttons/src/MaterialButtons.h; sourceTree = "<group>"; };
+		4D40D28A97062B1CC07236668DC678AD /* MDFImageCalculations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDFImageCalculations.h; path = src/private/MDFImageCalculations.h; sourceTree = "<group>"; };
+		4F0E678DFEF2B507BAEF2FFD1EF23228 /* MDCFlatButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlatButton.m; path = components/Buttons/src/MDCFlatButton.m; sourceTree = "<group>"; };
+		4FC2C7E47A0EA56BD6295D82B56F6192 /* MDCAppBarButtonBarBuilder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAppBarButtonBarBuilder.h; path = components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h; sourceTree = "<group>"; };
+		4FECD187F5A83C12336BB0C55DD75C6F /* MDCCollectionViewStyling.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewStyling.h; path = components/Collections/src/MDCCollectionViewStyling.h; sourceTree = "<group>"; };
+		506805F39B4A029793221A2B4824A062 /* MDFTextAccessibility-Bridging-Header.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDFTextAccessibility-Bridging-Header.h"; path = "src/MDFTextAccessibility-Bridging-Header.h"; sourceTree = "<group>"; };
+		516E307567E6B1C8060A69B31F20108A /* MDFColorCalculations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDFColorCalculations.m; path = src/private/MDFColorCalculations.m; sourceTree = "<group>"; };
+		51F9DCB161F252F8BD0F521356180A57 /* MaterialApplication.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialApplication.h; path = components/private/Application/src/MaterialApplication.h; sourceTree = "<group>"; };
+		522F0C6B92C308F6D1B7BB497022A769 /* MDCSnackbarMessageViewInternal.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessageViewInternal.h; path = components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h; sourceTree = "<group>"; };
+		523EEB14DB0CEFD241559CCC496E445B /* MDCOverlayObserverOverlay.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayObserverOverlay.m; path = components/private/Overlay/src/private/MDCOverlayObserverOverlay.m; sourceTree = "<group>"; };
+		536F8F8CBB3D5593CFA4CBFD765F3BED /* MDCFlexibleHeaderContainerViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlexibleHeaderContainerViewController.m; path = components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m; sourceTree = "<group>"; };
+		5572DC66A4C3A03942D5656C7DC33A85 /* Pods-BuildingBeautifulApps-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-BuildingBeautifulApps-acknowledgements.markdown"; sourceTree = "<group>"; };
+		56417D84CA78A113438D534EE4FFC54A /* MaterialCollectionsStrings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionsStrings.h; path = components/Collections/src/private/MaterialCollectionsStrings.h; sourceTree = "<group>"; };
+		5677CC19D390C501CCA90EEE390AAE6D /* MDCItemBarAlignment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarAlignment.h; path = components/Tabs/src/private/MDCItemBarAlignment.h; sourceTree = "<group>"; };
+		5894DCB5AAB8B32C781B6279A0FEF8D9 /* UIView+MDCTimingFunction.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIView+MDCTimingFunction.h"; path = "components/AnimationTiming/src/UIView+MDCTimingFunction.h"; sourceTree = "<group>"; };
+		58B3FF2F70B1A1974204F2F8931F665B /* MDCCollectionViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewController.h; path = components/Collections/src/MDCCollectionViewController.h; sourceTree = "<group>"; };
+		59D335F07CA6F3AF80A7760B046F9BE3 /* ResourceBundle-MaterialIcons_ic_info-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_info-Info.plist"; sourceTree = "<group>"; };
+		5B8E69C2D115A0FE03A563709E22B4ED /* MaterialIcons+ic_reorder.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_reorder.h"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h"; sourceTree = "<group>"; };
+		5C27D7602B81556831B0A85A92B4E5A3 /* MDCFeatureHighlightViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightViewController.m; path = components/FeatureHighlight/src/MDCFeatureHighlightViewController.m; sourceTree = "<group>"; };
+		5C4B4B293D1D97D44EA76F8E2DD5595E /* MaterialIcons.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialIcons.h; path = components/private/Icons/src/MaterialIcons.h; sourceTree = "<group>"; };
+		5C4F931DA815928A8CA82E5513C6246A /* UIApplication+AppExtensions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIApplication+AppExtensions.m"; path = "components/private/Application/src/UIApplication+AppExtensions.m"; sourceTree = "<group>"; };
+		5D8DE150DA0161A584D8CED87D6DF987 /* MDCTabBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCTabBar.m; path = components/Tabs/src/MDCTabBar.m; sourceTree = "<group>"; };
+		5D982B7FBF6D8BFF04DFD915F08E13B0 /* MDCOverlayTransitioning.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayTransitioning.h; path = components/private/Overlay/src/MDCOverlayTransitioning.h; sourceTree = "<group>"; };
+		5DB14C9C7FE14E6BF99957813C38B5BA /* MDCOverlayObserverTransition.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayObserverTransition.h; path = components/private/Overlay/src/private/MDCOverlayObserverTransition.h; sourceTree = "<group>"; };
+		5EBBA737C7DEFC62CB07A5607401B086 /* ic_info@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_info@3x.png"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info@3x.png"; sourceTree = "<group>"; };
+		5F7BDB2580B244756CFA046131516EF2 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; };
+		60852389E40D9EF0F70B7BF97E7B998D /* MaterialSlider.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialSlider.h; path = components/Slider/src/MaterialSlider.h; sourceTree = "<group>"; };
+		61C0E2BD02828C530EA209D50ED1B519 /* MaterialPageControlStrings_table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPageControlStrings_table.h; path = components/PageControl/src/private/MaterialPageControlStrings_table.h; sourceTree = "<group>"; };
+		62057440CF0144D03DEB925C378645B7 /* ic_radio_button_unchecked@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_radio_button_unchecked@3x.png"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@3x.png"; sourceTree = "<group>"; };
+		621F64FAC8A6CDF22ADF8271D04409C6 /* MDCFlexibleHeaderContainerViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlexibleHeaderContainerViewController.h; path = components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h; sourceTree = "<group>"; };
+		654AA469F888FFF8F1CE4AA611FD6B69 /* MaterialIcons+ic_chevron_right.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_chevron_right.m"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m"; sourceTree = "<group>"; };
+		6677BBD93E7A4672F9AEA51236310EDF /* MDCCollectionViewLayoutAttributes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewLayoutAttributes.h; path = components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h; sourceTree = "<group>"; };
+		66E845FD6DDDE254DBD69B4B9FBCA3B8 /* MDCFeatureHighlightViewController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightViewController.h; path = components/FeatureHighlight/src/MDCFeatureHighlightViewController.h; sourceTree = "<group>"; };
+		675F4FE5A00141BDF25CA3589A5DEF88 /* MDCPalettes.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPalettes.h; path = components/Palettes/src/MDCPalettes.h; sourceTree = "<group>"; };
+		67D647688DBDE7C289D22CFAADF4006C /* MDCPaletteExpansions.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPaletteExpansions.m; path = components/Palettes/src/private/MDCPaletteExpansions.m; sourceTree = "<group>"; };
+		683A8B83E16F375FE011E9C5AA0221EE /* MDCCollectionGridBackgroundView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionGridBackgroundView.m; path = components/Collections/src/private/MDCCollectionGridBackgroundView.m; sourceTree = "<group>"; };
+		6ADBE2A8BC6E0585880B9137AEDC228D /* Pods-BuildingBeautifulApps-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BuildingBeautifulApps-frameworks.sh"; sourceTree = "<group>"; };
+		6B9A7110EE95FE54D52AC78F8943FF30 /* libPods-BuildingBeautifulApps.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = "libPods-BuildingBeautifulApps.a"; path = "libPods-BuildingBeautifulApps.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		6D3E3C231B7AE692FCE91C1216645EA3 /* UIViewController+MaterialDialogs.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIViewController+MaterialDialogs.m"; path = "components/Dialogs/src/UIViewController+MaterialDialogs.m"; sourceTree = "<group>"; };
+		6E75C79B7D5289097D15A811F188CED2 /* UIFont+MaterialTypographyPrivate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIFont+MaterialTypographyPrivate.h"; path = "components/Typography/src/private/UIFont+MaterialTypographyPrivate.h"; sourceTree = "<group>"; };
+		6EAC67B229E26EFB3FEF38B7164183F0 /* MDCFlexibleHeaderViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlexibleHeaderViewController.m; path = components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m; sourceTree = "<group>"; };
+		6ECC1D1D41521DED2581889D20C4D8F9 /* UIImage+MaterialRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIImage+MaterialRTL.h"; path = "components/private/RTL/src/UIImage+MaterialRTL.h"; sourceTree = "<group>"; };
+		6EE3924624B8CAFC171FD153BBFC8449 /* MDCFlexibleHeaderView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlexibleHeaderView.h; path = components/FlexibleHeader/src/MDCFlexibleHeaderView.h; sourceTree = "<group>"; };
+		6F9741A397ADB188B83497B96D7D30F5 /* MDCOverlayWindow.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayWindow.m; path = components/OverlayWindow/src/MDCOverlayWindow.m; sourceTree = "<group>"; };
+		702CBDDD852DAA7044CE6BCB5AA2D950 /* MaterialHeaderStackView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialHeaderStackView.h; path = components/HeaderStackView/src/MaterialHeaderStackView.h; sourceTree = "<group>"; };
+		7143C04351DADE6FD07918C99C3BF31E /* MaterialActivityIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialActivityIndicator.h; path = components/ActivityIndicator/src/MaterialActivityIndicator.h; sourceTree = "<group>"; };
+		71BE7789CD2EC0A70DE711AC5A1FEF8D /* MDCFlexibleHeaderView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFlexibleHeaderView.m; path = components/FlexibleHeader/src/MDCFlexibleHeaderView.m; sourceTree = "<group>"; };
+		7231A93714A109C83065D36604C9451C /* NSArray+MDFUtils.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "NSArray+MDFUtils.m"; path = "src/private/NSArray+MDFUtils.m"; sourceTree = "<group>"; };
+		74905502A1DF96D7D84E7714A179E9E9 /* CAMediaTimingFunction+MDCAnimationTiming.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "CAMediaTimingFunction+MDCAnimationTiming.h"; path = "components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h"; sourceTree = "<group>"; };
+		752EC7F93FEFE96C89367CBBBB8CB32B /* MDCCollectionViewEditing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewEditing.h; path = components/Collections/src/MDCCollectionViewEditing.h; sourceTree = "<group>"; };
+		77C440E4189E05E40980CE67AF6A977D /* MaterialShadowLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialShadowLayer.h; path = components/ShadowLayer/src/MaterialShadowLayer.h; sourceTree = "<group>"; };
+		7941C852DB02A5C5D4BE708004028A52 /* UIView+MDCTimingFunction.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MDCTimingFunction.m"; path = "components/AnimationTiming/src/UIView+MDCTimingFunction.m"; sourceTree = "<group>"; };
+		79DCB73AD07EBD187AB62F38B93A8863 /* MDCCollectionGridBackgroundView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionGridBackgroundView.h; path = components/Collections/src/private/MDCCollectionGridBackgroundView.h; sourceTree = "<group>"; };
+		7C5778E1102FA874A7F4F6FFD400C7DE /* ic_check.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_check.png; path = components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check.png; sourceTree = "<group>"; };
+		7C6135E851D024BF64D3B71654768D9C /* ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist"; sourceTree = "<group>"; };
+		7D86AB797FE0EAA5C5384DF417BF5346 /* MDCStatusBarShifter.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCStatusBarShifter.m; path = components/FlexibleHeader/src/private/MDCStatusBarShifter.m; sourceTree = "<group>"; };
+		7E855EBFE6A726985077571DB7E89BD5 /* MDCShadowElevations.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCShadowElevations.h; path = components/ShadowElevations/src/MDCShadowElevations.h; sourceTree = "<group>"; };
+		7EBAFD93350BF0CF6E8CE57A39A1FA5D /* ic_chevron_right.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_chevron_right.png; path = components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right.png; sourceTree = "<group>"; };
+		7F9E8F936B7FA4CE55F6D4A70EDF478C /* ic_arrow_back_ios.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_arrow_back_ios.png; path = components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios.png; sourceTree = "<group>"; };
+		804D865D3D4D4C65731A550B3D8FC9A5 /* MaterialIcons+ic_arrow_back.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_arrow_back.h"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h"; sourceTree = "<group>"; };
+		81B08B2D4EB2559D2497B7BB8B215DF3 /* MDCOverlayAnimationObserver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayAnimationObserver.h; path = components/private/Overlay/src/private/MDCOverlayAnimationObserver.h; sourceTree = "<group>"; };
+		8272252EDEB9A0A290A95F34B0A4AEBD /* Pods-BuildingBeautifulApps-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-BuildingBeautifulApps-dummy.m"; sourceTree = "<group>"; };
+		84467817302E2399BA95D3A909871AFA /* MaterialDialogs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialDialogs.h; path = components/Dialogs/src/MaterialDialogs.h; sourceTree = "<group>"; };
+		84D3E267E2C78F75A2831346932CF97F /* ic_radio_button_unchecked@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_radio_button_unchecked@2x.png"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons_ic_radio_button_unchecked.bundle/ic_radio_button_unchecked@2x.png"; sourceTree = "<group>"; };
+		8556079BFB00835D898F480913F78F13 /* MDCPageControlTrackLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPageControlTrackLayer.m; path = components/PageControl/src/private/MDCPageControlTrackLayer.m; sourceTree = "<group>"; };
+		860E1A6AE14CC46812BFD2EECD3DF1B6 /* MaterialIcons_ic_check.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_check.bundle; path = MaterialIcons_ic_check.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		86754C059E8434587187015DC770180B /* MDCThumbTrack.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCThumbTrack.h; path = components/private/ThumbTrack/src/MDCThumbTrack.h; sourceTree = "<group>"; };
+		87D692B9AD07C602ED145B594F3FF7D9 /* ic_reorder@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_reorder@3x.png"; path = "components/private/Icons/icons/ic_reorder/src/MaterialIcons_ic_reorder.bundle/ic_reorder@3x.png"; sourceTree = "<group>"; };
+		88AE915AB74A3A3AA3F3F10C11CD9644 /* MaterialIcons+ic_check.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_check.m"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m"; sourceTree = "<group>"; };
+		8917229D3430B609F88F33A180E7063C /* ic_check@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_check@2x.png"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons_ic_check.bundle/ic_check@2x.png"; sourceTree = "<group>"; };
+		8938D8038B0C55A96B4E161C6661FFC0 /* MDCIcons.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCIcons.h; path = components/private/Icons/src/MDCIcons.h; sourceTree = "<group>"; };
+		8BF097DEAD72714A366668962C25EC9B /* MDCCollectionViewTextCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewTextCell.h; path = components/CollectionCells/src/MDCCollectionViewTextCell.h; sourceTree = "<group>"; };
+		8CCFBA02AEF1EB2D0EA744C7D87ADB76 /* MDCThumbView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCThumbView.m; path = components/private/ThumbTrack/src/MDCThumbView.m; sourceTree = "<group>"; };
+		8E961B158FE9954DDD2B6C09E3462883 /* MDFTextAccessibility-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MDFTextAccessibility-dummy.m"; sourceTree = "<group>"; };
+		90B29DB14670F66061CFB82DDC68AF49 /* UIView+MaterialRTL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIView+MaterialRTL.m"; path = "components/private/RTL/src/UIView+MaterialRTL.m"; sourceTree = "<group>"; };
+		915F12E15D337DE30C909A4C3749EE83 /* MaterialCollectionCells.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialCollectionCells.bundle; path = components/CollectionCells/src/MaterialCollectionCells.bundle; sourceTree = "<group>"; };
+		931A07F6E4357134E2E8449CFE5E056E /* MDCCollectionViewFlowLayout.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewFlowLayout.m; path = components/Collections/src/MDCCollectionViewFlowLayout.m; sourceTree = "<group>"; };
+		935B6D6F1FAB419F6C7B4129E6A0074F /* MDCRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCRTL.h; path = components/private/RTL/src/MDCRTL.h; sourceTree = "<group>"; };
+		93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
+		94294D2C0E41046D41ED4D332EF32E37 /* MaterialTabs.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialTabs.bundle; path = components/Tabs/src/MaterialTabs.bundle; sourceTree = "<group>"; };
+		94B9A402610F5FCAEE60B7D902780413 /* MaterialPageControlStrings.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialPageControlStrings.h; path = components/PageControl/src/private/MaterialPageControlStrings.h; sourceTree = "<group>"; };
+		95D1CF13299CEF28BCBAA62F927A3D80 /* UIApplication+AppExtensions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIApplication+AppExtensions.h"; path = "components/private/Application/src/UIApplication+AppExtensions.h"; sourceTree = "<group>"; };
+		96E1A962597D9C41D8E7513530EBCD7D /* MDCCollectionStringResources.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionStringResources.m; path = components/Collections/src/private/MDCCollectionStringResources.m; sourceTree = "<group>"; };
+		97262CDCD801553DA99ECC7847E39E98 /* MDCActivityIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCActivityIndicator.h; path = components/ActivityIndicator/src/MDCActivityIndicator.h; sourceTree = "<group>"; };
+		97E9347E0E620A695CA9575055B9A219 /* MDCPageControlIndicator.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPageControlIndicator.h; path = components/PageControl/src/private/MDCPageControlIndicator.h; sourceTree = "<group>"; };
+		97FBECBD5EF590F0A8005F8B94E808FF /* MaterialIcons+ic_radio_button_unchecked.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_radio_button_unchecked.h"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h"; sourceTree = "<group>"; };
+		98BE3C2752BDFA411D8AD43231FF4BCC /* MDCSnackbarOverlayView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarOverlayView.h; path = components/Snackbar/src/private/MDCSnackbarOverlayView.h; sourceTree = "<group>"; };
+		98F8E9B6EBCFF521C01B78E4BD1039BD /* MDCPaletteNames.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPaletteNames.m; path = components/Palettes/src/private/MDCPaletteNames.m; sourceTree = "<group>"; };
+		9A7FE223E125A19DB7A772510BF0DEB2 /* MaterialFlexibleHeader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialFlexibleHeader.h; path = components/FlexibleHeader/src/MaterialFlexibleHeader.h; sourceTree = "<group>"; };
+		9A82FF56648D80F9E61096E9A07B06F6 /* MDCTypography.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCTypography.m; path = components/Typography/src/MDCTypography.m; sourceTree = "<group>"; };
+		9B114982D3918901056DE5DF45AEAC16 /* Pods-BuildingBeautifulApps-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-BuildingBeautifulApps-resources.sh"; sourceTree = "<group>"; };
+		9C7E38A7B56C28ED6E56D587A376C3B4 /* MaterialSnackbar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialSnackbar.h; path = components/Snackbar/src/MaterialSnackbar.h; sourceTree = "<group>"; };
+		9CA3D76D548F43BB8F241C55FB9D5656 /* MDCAppBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCAppBar.h; path = components/AppBar/src/MDCAppBar.h; sourceTree = "<group>"; };
+		9D57CB474D3A2B64257FE6E21F9BD796 /* MDCPageControlTrackLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPageControlTrackLayer.h; path = components/PageControl/src/private/MDCPageControlTrackLayer.h; sourceTree = "<group>"; };
+		9E05EB6FB230393D92DC9A1584D7DE50 /* MDCThumbTrack.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCThumbTrack.m; path = components/private/ThumbTrack/src/MDCThumbTrack.m; sourceTree = "<group>"; };
+		9E5285A7050BE78F06AD6EC2E4BF1A2F /* UIFontDescriptor+MaterialTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIFontDescriptor+MaterialTypography.h"; path = "components/Typography/src/UIFontDescriptor+MaterialTypography.h"; sourceTree = "<group>"; };
+		9F5AE307F5EF407D47769AC7313B9DCA /* MDCSnackbarManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarManager.m; path = components/Snackbar/src/MDCSnackbarManager.m; sourceTree = "<group>"; };
+		9F8BE2D8847C692FB18FCFEF6F294478 /* MaterialIcons_ic_radio_button_unchecked.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_radio_button_unchecked.bundle; path = MaterialIcons_ic_radio_button_unchecked.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MDFTextAccessibility.xcconfig; sourceTree = "<group>"; };
+		A32E50911D7DB6FBC3E4CC4ECCBA1596 /* MaterialCollectionCells.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionCells.h; path = components/CollectionCells/src/MaterialCollectionCells.h; sourceTree = "<group>"; };
+		A3991A36920E062C3E82F61204091F73 /* MDCSnackbarMessageView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessageView.h; path = components/Snackbar/src/MDCSnackbarMessageView.h; sourceTree = "<group>"; };
+		A6219827B685EAAF10C4441241536DD2 /* Pods-BuildingBeautifulApps-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-BuildingBeautifulApps-acknowledgements.plist"; sourceTree = "<group>"; };
+		A683F198135D9329FD62063BFB4B0F9B /* MDCPageControl.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPageControl.h; path = components/PageControl/src/MDCPageControl.h; sourceTree = "<group>"; };
+		A8D106719F3F199D438233D94FDF43F5 /* UIFont+MaterialTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIFont+MaterialTypography.h"; path = "components/Typography/src/UIFont+MaterialTypography.h"; sourceTree = "<group>"; };
+		ABED23378B104A0A25435A6674F29FF5 /* MDCRaisedButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCRaisedButton.h; path = components/Buttons/src/MDCRaisedButton.h; sourceTree = "<group>"; };
+		ACCED250D3351A0D22EEA492436EBE80 /* ic_info.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = ic_info.png; path = components/private/Icons/icons/ic_info/src/MaterialIcons_ic_info.bundle/ic_info.png; sourceTree = "<group>"; };
+		ACD681F6184F424EE2EAF7600B76F289 /* MaterialIcons+ic_check.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_check.h"; path = "components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h"; sourceTree = "<group>"; };
+		B12139AB4284238F1123EB1E38B230E1 /* MDCRTL.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCRTL.m; path = components/private/RTL/src/MDCRTL.m; sourceTree = "<group>"; };
+		B177F408148335CFD14BF2E1C8FADB3F /* ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist"; sourceTree = "<group>"; };
+		B3AB010097D6D3763F9664DCA9A711EB /* MDCDialogShadowedView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCDialogShadowedView.m; path = components/Dialogs/src/private/MDCDialogShadowedView.m; sourceTree = "<group>"; };
+		B4CDE57035DA000166BF394A847F6AE2 /* MDCDialogPresentationController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCDialogPresentationController.h; path = components/Dialogs/src/MDCDialogPresentationController.h; sourceTree = "<group>"; };
+		B52A38C1D2775315C12601204EF0524E /* MaterialIcons+ic_info.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_info.m"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m"; sourceTree = "<group>"; };
+		B56398DA0E3930C91FF640F861706411 /* MDCPageControlIndicator.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPageControlIndicator.m; path = components/PageControl/src/private/MDCPageControlIndicator.m; sourceTree = "<group>"; };
+		B5929610276D0E6D8DD3158FF603C0EC /* MaterialOverlays.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialOverlays.h; path = components/private/Overlay/src/MaterialOverlays.h; sourceTree = "<group>"; };
+		B6134FFEBB32CC196B45597FC2948611 /* MDCShadowLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCShadowLayer.m; path = components/ShadowLayer/src/MDCShadowLayer.m; sourceTree = "<group>"; };
+		B6D338FD921EC51C550567AB2D429021 /* libMDFTextAccessibility.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; name = libMDFTextAccessibility.a; path = libMDFTextAccessibility.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		B73577CD8AEFE5DA6EB995CC8F2C92A7 /* MaterialNavigationBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialNavigationBar.h; path = components/NavigationBar/src/MaterialNavigationBar.h; sourceTree = "<group>"; };
+		B77E7CD1098848AED57761E60382667D /* MDCRaisedButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCRaisedButton.m; path = components/Buttons/src/MDCRaisedButton.m; sourceTree = "<group>"; };
+		B9E2AAB8153882A4590062F569A4D595 /* MDCTabBarAlignment.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTabBarAlignment.h; path = components/Tabs/src/MDCTabBarAlignment.h; sourceTree = "<group>"; };
+		B9F2A6127E6482F1546297FBA86E9E19 /* MDCDialogPresentationController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCDialogPresentationController.m; path = components/Dialogs/src/MDCDialogPresentationController.m; sourceTree = "<group>"; };
+		BA4F460E41035D7B0B538CDC2752925D /* MDCPageControl.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPageControl.m; path = components/PageControl/src/MDCPageControl.m; sourceTree = "<group>"; };
+		BB3068591BFE9A9F8D1B79957A573691 /* MDCItemBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCItemBar.m; path = components/Tabs/src/private/MDCItemBar.m; sourceTree = "<group>"; };
+		BBFB15BBA3F7C53B5BDCBDCEFD66700C /* MaterialCollectionsStrings_table.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialCollectionsStrings_table.h; path = components/Collections/src/private/MaterialCollectionsStrings_table.h; sourceTree = "<group>"; };
+		BDAF0CDE00CDA3F4B1CE9E7374239490 /* MDCTabBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCTabBar.h; path = components/Tabs/src/MDCTabBar.h; sourceTree = "<group>"; };
+		BE257A301C797B8D3C24053EFEF0DB5A /* MDCButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCButton.m; path = components/Buttons/src/MDCButton.m; sourceTree = "<group>"; };
+		BE4C70E576A2623B72B27F812FA19587 /* MDCKeyboardWatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCKeyboardWatcher.h; path = components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h; sourceTree = "<group>"; };
+		BEBA1206741596666E53A5291AC6C67D /* MDCCollectionViewCell.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewCell.m; path = components/CollectionCells/src/MDCCollectionViewCell.m; sourceTree = "<group>"; };
+		C03DAFCD2FB2199D18A24125D772CB7A /* MDCOverlayUtilities.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayUtilities.h; path = components/private/Overlay/src/private/MDCOverlayUtilities.h; sourceTree = "<group>"; };
+		C0499AC785EBF2667F45935055F327A1 /* ResourceBundle-MaterialIcons_ic_check_circle-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_check_circle-Info.plist"; sourceTree = "<group>"; };
+		C075A49AEB6D1C36BA22C458FC6A2801 /* MaterialAnimationTiming.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialAnimationTiming.h; path = components/AnimationTiming/src/MaterialAnimationTiming.h; sourceTree = "<group>"; };
+		C078D453FB972AF56047785185938933 /* MDCPaletteNames.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPaletteNames.h; path = components/Palettes/src/private/MDCPaletteNames.h; sourceTree = "<group>"; };
+		C092C0ED18CF0F6D5A1391571F068348 /* MaterialPageControl.bundle */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "wrapper.plug-in"; name = MaterialPageControl.bundle; path = components/PageControl/src/MaterialPageControl.bundle; sourceTree = "<group>"; };
+		C19F7B7784CFCB4369498613360AA4CB /* MaterialIcons+ic_radio_button_unchecked.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_radio_button_unchecked.m"; path = "components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m"; sourceTree = "<group>"; };
+		C3CE561D11742D1092438C75CE67C1D4 /* MDCAlertController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAlertController.m; path = components/Dialogs/src/MDCAlertController.m; sourceTree = "<group>"; };
+		C4899C25A4830FCF08B2BB4F8ABC361A /* MDCPaletteExpansions.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCPaletteExpansions.h; path = components/Palettes/src/private/MDCPaletteExpansions.h; sourceTree = "<group>"; };
+		C4F53B72FA10D37719F9CB9924A08CBD /* MDCItemBarStyle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarStyle.h; path = components/Tabs/src/private/MDCItemBarStyle.h; sourceTree = "<group>"; };
+		C660FEA28DDB8CB873D9BCE3DA03F6B3 /* MDCNumericValueLabel.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCNumericValueLabel.h; path = components/private/ThumbTrack/src/MDCNumericValueLabel.h; sourceTree = "<group>"; };
+		C67AC2707AD0B4EC907D6DC6B79DD436 /* MaterialProgressView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialProgressView.h; path = components/ProgressView/src/MaterialProgressView.h; sourceTree = "<group>"; };
+		C70F87D8C5E5F9AEBFA97552A5BCD739 /* ResourceBundle-MaterialIcons_ic_check-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MaterialIcons_ic_check-Info.plist"; sourceTree = "<group>"; };
+		C830C5EEEAE60B4A9283F0C2F0A02094 /* MaterialIcons+ic_arrow_back.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "MaterialIcons+ic_arrow_back.m"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m"; sourceTree = "<group>"; };
+		C9588139AB2E41A105B4F278EF0B01F3 /* MDCPalettes.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCPalettes.m; path = components/Palettes/src/MDCPalettes.m; sourceTree = "<group>"; };
+		CAA1DC1A670B6F673EE517CD53A4EBD1 /* MDCCollectionViewStyler.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewStyler.h; path = components/Collections/src/private/MDCCollectionViewStyler.h; sourceTree = "<group>"; };
+		CAC43F65D5D78A89EAC07A697ACC9837 /* MDCInkGestureRecognizer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkGestureRecognizer.m; path = components/Ink/src/MDCInkGestureRecognizer.m; sourceTree = "<group>"; };
+		CADC6B616AB3936666BDBD42A2705DE6 /* MDCItemBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBar.h; path = components/Tabs/src/private/MDCItemBar.h; sourceTree = "<group>"; };
+		CB370B0CFF7E9F249F9A4A4A5C9828C0 /* MaterialIcons_ic_chevron_right.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_chevron_right.bundle; path = MaterialIcons_ic_chevron_right.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		CC56C512FD3A98A296C04156DD8DFEC9 /* MDCShadowElevations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCShadowElevations.m; path = components/ShadowElevations/src/MDCShadowElevations.m; sourceTree = "<group>"; };
+		CCF1F1AE19AF21CE8869CF3A681CC787 /* MDCNavigationBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCNavigationBar.m; path = components/NavigationBar/src/MDCNavigationBar.m; sourceTree = "<group>"; };
+		CD6BFB0EA4919F07C8AD5F586E34376D /* MDCFontTextStyle.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFontTextStyle.h; path = components/Typography/src/MDCFontTextStyle.h; sourceTree = "<group>"; };
+		CE6929889D615189113913408E3D1B9E /* MDCHeaderStackView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCHeaderStackView.h; path = components/HeaderStackView/src/MDCHeaderStackView.h; sourceTree = "<group>"; };
+		D100E5E7F62D86CE9CCC97B487779DEC /* MDCOverlayWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayWindow.h; path = components/OverlayWindow/src/MDCOverlayWindow.h; sourceTree = "<group>"; };
+		D11EB1CC12CA81275669C38699DF58A3 /* MaterialThumbTrack.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialThumbTrack.h; path = components/private/ThumbTrack/src/MaterialThumbTrack.h; sourceTree = "<group>"; };
+		D14A347A944C556F216B967AFCF766C8 /* MaterialButtonBar.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialButtonBar.h; path = components/ButtonBar/src/MaterialButtonBar.h; sourceTree = "<group>"; };
+		D1A37A0287C491DFE2089102146664E8 /* MaterialTypography.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialTypography.h; path = components/Typography/src/MaterialTypography.h; sourceTree = "<group>"; };
+		D1D4C0D37627D761BB16ECB99105E4A0 /* MDCCollectionViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewController.m; path = components/Collections/src/MDCCollectionViewController.m; sourceTree = "<group>"; };
+		D20FE85CECC64B86387F4CA60B86C8C6 /* MDCSnackbarMessage.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCSnackbarMessage.h; path = components/Snackbar/src/MDCSnackbarMessage.h; sourceTree = "<group>"; };
+		D2FFA02DCC45D1EDB5D30FB9CEB3B9BD /* MDCFeatureHighlightAnimationController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFeatureHighlightAnimationController.m; path = components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m; sourceTree = "<group>"; };
+		D43D8FF7991737DB826BFF92EBF8ADFA /* MaterialIcons_ic_reorder.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_reorder.bundle; path = MaterialIcons_ic_reorder.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		D49CC986145361BA86D40441881692D8 /* MDCThumbView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCThumbView.h; path = components/private/ThumbTrack/src/MDCThumbView.h; sourceTree = "<group>"; };
+		D5674E7D4BCC946A30114DBF9DB2F6CA /* ic_chevron_right@2x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_chevron_right@2x.png"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons_ic_chevron_right.bundle/ic_chevron_right@2x.png"; sourceTree = "<group>"; };
+		D79A92B4599903B71AD908CC7E5B0213 /* MDCButtonBar+Private.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDCButtonBar+Private.h"; path = "components/ButtonBar/src/private/MDCButtonBar+Private.h"; sourceTree = "<group>"; };
+		D7E1DE48A44A60C2AE808B6D69A73683 /* UIFontDescriptor+MaterialTypography.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIFontDescriptor+MaterialTypography.m"; path = "components/Typography/src/UIFontDescriptor+MaterialTypography.m"; sourceTree = "<group>"; };
+		D8966C5049A9875A33A6802C9840E498 /* MDCShadowLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCShadowLayer.h; path = components/ShadowLayer/src/MDCShadowLayer.h; sourceTree = "<group>"; };
+		D8C42FCD2D863F783537F7B84C002801 /* MDCCollectionStringResources.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionStringResources.h; path = components/Collections/src/private/MDCCollectionStringResources.h; sourceTree = "<group>"; };
+		D9E396F14C5448B3C15F7B48AFC85B6F /* MDCOverlayObserver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCOverlayObserver.h; path = components/private/Overlay/src/MDCOverlayObserver.h; sourceTree = "<group>"; };
+		DBB2727B89FCF4B81EAB1F748F4EE6F7 /* MaterialIcons_ic_info.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_info.bundle; path = MaterialIcons_ic_info.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+		DC384A83912E8C440C7ED70B794A89D2 /* MDCFontTraits.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFontTraits.m; path = components/Typography/src/private/MDCFontTraits.m; sourceTree = "<group>"; };
+		DD35DF5F260987C932CF7B25AD8C22C4 /* MDCOverlayUtilities.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayUtilities.m; path = components/private/Overlay/src/private/MDCOverlayUtilities.m; sourceTree = "<group>"; };
+		E17A7167DE53F6528C656D4979850FBC /* UIFont+MaterialTypography.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIFont+MaterialTypography.m"; path = "components/Typography/src/UIFont+MaterialTypography.m"; sourceTree = "<group>"; };
+		E22DE5B99BE8057D6452C77B5B4A8D39 /* MDCIcons+BundleLoader.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDCIcons+BundleLoader.h"; path = "components/private/Icons/src/MDCIcons+BundleLoader.h"; sourceTree = "<group>"; };
+		E37F8FD7F722E714E0005FB0C96F9A03 /* MDCInkLayer.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkLayer.m; path = components/Ink/src/private/MDCInkLayer.m; sourceTree = "<group>"; };
+		E47ED49AEF9D2FE77E92679C5569563D /* MDCInkTouchController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkTouchController.h; path = components/Ink/src/MDCInkTouchController.h; sourceTree = "<group>"; };
+		E601CD11978BE11A131D16DA1717A354 /* MDCOverlayObserver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayObserver.m; path = components/private/Overlay/src/MDCOverlayObserver.m; sourceTree = "<group>"; };
+		E66CD057FB364E80D5BC3D34A00B42FF /* MDCFloatingButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFloatingButton.h; path = components/Buttons/src/MDCFloatingButton.h; sourceTree = "<group>"; };
+		E70A12012C34069A15DAAEF725754A18 /* MDCItemBarCell.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarCell.h; path = components/Tabs/src/private/MDCItemBarCell.h; sourceTree = "<group>"; };
+		E88C708F20439859824CDC2F79216421 /* MaterialRTL.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialRTL.h; path = components/private/RTL/src/MaterialRTL.h; sourceTree = "<group>"; };
+		E8C4112E03A439A51F0FBD876DA804E5 /* UIViewController+MaterialDialogs.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "UIViewController+MaterialDialogs.h"; path = "components/Dialogs/src/UIViewController+MaterialDialogs.h"; sourceTree = "<group>"; };
+		E95DB580D0830673D87F39AEFDA6EF67 /* ic_arrow_back_ios@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back_ios@3x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back_ios@3x.png"; sourceTree = "<group>"; };
+		EA980654C37C923AB926DF64E7E02736 /* MDCInkLayer.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkLayer.h; path = components/Ink/src/private/MDCInkLayer.h; sourceTree = "<group>"; };
+		EB110721FC9D3D6E29D13627A35DFD0E /* MDCOverlayAnimationObserver.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCOverlayAnimationObserver.m; path = components/private/Overlay/src/private/MDCOverlayAnimationObserver.m; sourceTree = "<group>"; };
+		EB1C6A347A3B1B5278B6179E7E7A6C7E /* MDCHeaderStackView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCHeaderStackView.m; path = components/HeaderStackView/src/MDCHeaderStackView.m; sourceTree = "<group>"; };
+		EC8039BB5A86167E8DCDB72F46D6388B /* MDCFeatureHighlightAnimationController.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFeatureHighlightAnimationController.h; path = components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h; sourceTree = "<group>"; };
+		EDD61B881B917B05AFD9539341F931FD /* MDCItemBarStringConstants.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCItemBarStringConstants.h; path = components/Tabs/src/private/MDCItemBarStringConstants.h; sourceTree = "<group>"; };
+		EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MaterialComponents.xcconfig; sourceTree = "<group>"; };
+		EF3D4AABE18C6B0D033BD47108A9156D /* MDCInkView.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCInkView.h; path = components/Ink/src/MDCInkView.h; sourceTree = "<group>"; };
+		EFCF3D3D2FE3A10C4245EF66AE882178 /* MDCFlatButton.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCFlatButton.h; path = components/Buttons/src/MDCFlatButton.h; sourceTree = "<group>"; };
+		F14A5EBD4362C79FF3F8A7262FEA2D5B /* MDCCollectionViewEditingDelegate.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewEditingDelegate.h; path = components/Collections/src/MDCCollectionViewEditingDelegate.h; sourceTree = "<group>"; };
+		F1E7B70BE2622CF3F81A0AD037E21C47 /* MDCSnackbarMessageView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCSnackbarMessageView.m; path = components/Snackbar/src/MDCSnackbarMessageView.m; sourceTree = "<group>"; };
+		F398E51F9526801442D77BE9612F9C62 /* MaterialIcons+ic_chevron_right.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_chevron_right.h"; path = "components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h"; sourceTree = "<group>"; };
+		F4C0F26237AA99F43F82CD8B6404A8FF /* MDCCollectionViewEditor.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MDCCollectionViewEditor.h; path = components/Collections/src/private/MDCCollectionViewEditor.h; sourceTree = "<group>"; };
+		F5A94E964BB75BF779F888AE07B3F95C /* MaterialKeyboardWatcher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialKeyboardWatcher.h; path = components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h; sourceTree = "<group>"; };
+		F5BEB5E003D1847D87CC74803474B2EF /* MaterialFeatureHighlight.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialFeatureHighlight.h; path = components/FeatureHighlight/src/MaterialFeatureHighlight.h; sourceTree = "<group>"; };
+		F5F5CD9392CF68CA57F883CA8A1DA6BE /* MDCCollectionViewStyler.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCCollectionViewStyler.m; path = components/Collections/src/private/MDCCollectionViewStyler.m; sourceTree = "<group>"; };
+		F600563B48E50DAC2BB8C3B23D131DA2 /* MaterialOverlayWindow.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = MaterialOverlayWindow.h; path = components/OverlayWindow/src/MaterialOverlayWindow.h; sourceTree = "<group>"; };
+		F64F50AD20E83F81710454204053A744 /* MDCFloatingButton.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCFloatingButton.m; path = components/Buttons/src/MDCFloatingButton.m; sourceTree = "<group>"; };
+		F68D30CBF1457E3E9AE7D3AE92AC18F0 /* MDFImageCalculations.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDFImageCalculations.m; path = src/private/MDFImageCalculations.m; sourceTree = "<group>"; };
+		F7D2E69B90D1C23D2FBD5EB175B59364 /* MDCAppBarContainerViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCAppBarContainerViewController.m; path = components/AppBar/src/MDCAppBarContainerViewController.m; sourceTree = "<group>"; };
+		F82A46DDAA89ACF53DA3C47CC04971EF /* MDCButton+Subclassing.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MDCButton+Subclassing.h"; path = "components/Buttons/src/private/MDCButton+Subclassing.h"; sourceTree = "<group>"; };
+		FC7FA8E220EACEBE9FB49B6A6B3732E5 /* MDCInkView.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkView.m; path = components/Ink/src/MDCInkView.m; sourceTree = "<group>"; };
+		FC8CB7864BDCD9DB97A3711AC446E2B0 /* MDCButtonBar.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCButtonBar.m; path = components/ButtonBar/src/MDCButtonBar.m; sourceTree = "<group>"; };
+		FD4ED0BAB173C96E24BFAF538C1A0353 /* MaterialIcons+ic_info.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = "MaterialIcons+ic_info.h"; path = "components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h"; sourceTree = "<group>"; };
+		FE7AE3A31ABEA928F10508D5385C37F8 /* ic_arrow_back@3x.png */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = image.png; name = "ic_arrow_back@3x.png"; path = "components/private/Icons/icons/ic_arrow_back/src/MaterialIcons_ic_arrow_back.bundle/ic_arrow_back@3x.png"; sourceTree = "<group>"; };
+		FF7A269A35FCA0697B0E5BD94453D3EF /* MDCInkTouchController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = MDCInkTouchController.m; path = components/Ink/src/MDCInkTouchController.m; sourceTree = "<group>"; };
+		FF9E5D282080B168147A56CBC1A20CB3 /* MaterialIcons_ic_arrow_back.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = MaterialIcons_ic_arrow_back.bundle; path = MaterialIcons_ic_arrow_back.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		0490164F31DF4DFD21CB5B6C0C9C2828 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				9D6D3B5FFB61DFD3F80B76195E605784 /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		05A8C2288619671B1A30A7EF4C739D71 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		10CE89D4B6EA0CBA4230B7FA3FE04DE3 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		120E9482EC24B536DE2A5345E8B71E40 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				303E2CEF1A7B2F29A77E3275D5543798 /* Foundation.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		142596A1D8F1283799C634488452D605 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		59F35B6B50BC5A7D99059FEC9B83AFB9 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		68E4BC6B1D0B207D3F9298FC9505A73E /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7B63882D2EA962158694D9F4255CD668 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		AA767584440C8D2E1C217BA896C2796A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				3584E7D333209DF162223D26DF0E795F /* CoreGraphics.framework in Frameworks */,
+				35BDD24AF246B8AF9D163CF7005C3A27 /* Foundation.framework in Frameworks */,
+				641CD6C953ADD27482B6CDBCCF24CD6A /* QuartzCore.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		AFFB6859E3D5DB059AA62780279F1BFA /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		00F05AF39E02FA6994432A4054A60EC2 /* Base */ = {
+			isa = PBXGroup;
+			children = (
+				5C4B4B293D1D97D44EA76F8E2DD5595E /* MaterialIcons.h */,
+				8938D8038B0C55A96B4E161C6661FFC0 /* MDCIcons.h */,
+				3BF39A7F429701947B09DCBEB4A07F05 /* MDCIcons.m */,
+				E22DE5B99BE8057D6452C77B5B4A8D39 /* MDCIcons+BundleLoader.h */,
+			);
+			name = Base;
+			sourceTree = "<group>";
+		};
+		015D80086EA2452E311127664AED6C49 /* Icons */ = {
+			isa = PBXGroup;
+			children = (
+				00F05AF39E02FA6994432A4054A60EC2 /* Base */,
+				7BBBBB41025DA2946E721C6B4CFE9582 /* ic_arrow_back */,
+				199DBEBBD73D20BC3BA7B1F7F655DC2D /* ic_check */,
+				BC22755231123F8970B82180656CBC02 /* ic_check_circle */,
+				C0478CE6F06E1DD40878AE929472991C /* ic_chevron_right */,
+				A8AC6F8EA0BF9331BC3179FC0941D312 /* ic_info */,
+				EC40E103B51AE1755CA03F26C6C066F1 /* ic_radio_button_unchecked */,
+				C8CCC6846666AAD0D3CA32B272E86A7F /* ic_reorder */,
+			);
+			name = Icons;
+			sourceTree = "<group>";
+		};
+		0A0BC298073A7DBD29E89E8AB28AFF89 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				04BA7B9EA003598360273283129FDE9B /* MaterialCollections.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		0F4F0B2885DA4E9FDA72BB907CFEEBA1 /* MDFTextAccessibility */ = {
+			isa = PBXGroup;
+			children = (
+				10D3AFAF60EB1088403525BA3DF6BD18 /* MDFColorCalculations.h */,
+				516E307567E6B1C8060A69B31F20108A /* MDFColorCalculations.m */,
+				4D40D28A97062B1CC07236668DC678AD /* MDFImageCalculations.h */,
+				F68D30CBF1457E3E9AE7D3AE92AC18F0 /* MDFImageCalculations.m */,
+				40759EC5DB49E090570D13E76C4CDA94 /* MDFTextAccessibility.h */,
+				4AF4F84748B988E39D513A50701185FC /* MDFTextAccessibility.m */,
+				506805F39B4A029793221A2B4824A062 /* MDFTextAccessibility-Bridging-Header.h */,
+				3F9B634EE11CC423F51EE3D659001D14 /* NSArray+MDFUtils.h */,
+				7231A93714A109C83065D36604C9451C /* NSArray+MDFUtils.m */,
+				8BBEF3ED9DC53D6F9F554679719F9E66 /* Support Files */,
+			);
+			name = MDFTextAccessibility;
+			path = MDFTextAccessibility;
+			sourceTree = "<group>";
+		};
+		0FFE22ED316D810F07A3CE1804C14671 /* Overlay */ = {
+			isa = PBXGroup;
+			children = (
+				B5929610276D0E6D8DD3158FF603C0EC /* MaterialOverlays.h */,
+				81B08B2D4EB2559D2497B7BB8B215DF3 /* MDCOverlayAnimationObserver.h */,
+				EB110721FC9D3D6E29D13627A35DFD0E /* MDCOverlayAnimationObserver.m */,
+				2506F285EFA1CEF8247B19211C38EF23 /* MDCOverlayImplementor.h */,
+				D9E396F14C5448B3C15F7B48AFC85B6F /* MDCOverlayObserver.h */,
+				E601CD11978BE11A131D16DA1717A354 /* MDCOverlayObserver.m */,
+				16E650750C1D8383CFF76B265B232D54 /* MDCOverlayObserverOverlay.h */,
+				523EEB14DB0CEFD241559CCC496E445B /* MDCOverlayObserverOverlay.m */,
+				5DB14C9C7FE14E6BF99957813C38B5BA /* MDCOverlayObserverTransition.h */,
+				1509DAD755F448EBE08F87224B5BD8D3 /* MDCOverlayObserverTransition.m */,
+				5D982B7FBF6D8BFF04DFD915F08E13B0 /* MDCOverlayTransitioning.h */,
+				C03DAFCD2FB2199D18A24125D772CB7A /* MDCOverlayUtilities.h */,
+				DD35DF5F260987C932CF7B25AD8C22C4 /* MDCOverlayUtilities.m */,
+			);
+			name = Overlay;
+			sourceTree = "<group>";
+		};
+		122DA2E5084A4393C29BE363C764795C /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				5A4DBD434EA75DD3EDD3494C46AE6968 /* iOS */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		14F3093C9EDA04FD806300494FD654F0 /* ProgressView */ = {
+			isa = PBXGroup;
+			children = (
+				C67AC2707AD0B4EC907D6DC6B79DD436 /* MaterialProgressView.h */,
+				1119E38AD872AC586FC0B36077CBD452 /* MDCProgressView.h */,
+				3C914D35C46E85C26AA1E246E17CECE5 /* MDCProgressView.m */,
+			);
+			name = ProgressView;
+			sourceTree = "<group>";
+		};
+		15CB945DCEE15326848DB6EE1185BC50 /* Support Files */ = {
+			isa = PBXGroup;
+			children = (
+				EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */,
+				13FA3054B67E07E3C004F5E26131FFC5 /* MaterialComponents-dummy.m */,
+				206683C2791ADADFAC3B8A5DAA2DA22A /* MaterialComponents-prefix.pch */,
+				B177F408148335CFD14BF2E1C8FADB3F /* ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist */,
+				C70F87D8C5E5F9AEBFA97552A5BCD739 /* ResourceBundle-MaterialIcons_ic_check-Info.plist */,
+				C0499AC785EBF2667F45935055F327A1 /* ResourceBundle-MaterialIcons_ic_check_circle-Info.plist */,
+				7C6135E851D024BF64D3B71654768D9C /* ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist */,
+				59D335F07CA6F3AF80A7760B046F9BE3 /* ResourceBundle-MaterialIcons_ic_info-Info.plist */,
+				423E686AE21269BCFA30A045BF0D5F96 /* ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist */,
+				478E465B2E211ABEB0687F1096C92E0C /* ResourceBundle-MaterialIcons_ic_reorder-Info.plist */,
+			);
+			name = "Support Files";
+			path = "../Target Support Files/MaterialComponents";
+			sourceTree = "<group>";
+		};
+		199DBEBBD73D20BC3BA7B1F7F655DC2D /* ic_check */ = {
+			isa = PBXGroup;
+			children = (
+				ACD681F6184F424EE2EAF7600B76F289 /* MaterialIcons+ic_check.h */,
+				88AE915AB74A3A3AA3F3F10C11CD9644 /* MaterialIcons+ic_check.m */,
+				F7107ECA24205B6455A55C23978D1621 /* Resources */,
+			);
+			name = ic_check;
+			sourceTree = "<group>";
+		};
+		1A51286FBEFC155062FB53A0ADD4D106 /* Snackbar */ = {
+			isa = PBXGroup;
+			children = (
+				9C7E38A7B56C28ED6E56D587A376C3B4 /* MaterialSnackbar.h */,
+				25F7B26DAEC96431ECEEC467ADA2CF28 /* MDCSnackbarManager.h */,
+				9F5AE307F5EF407D47769AC7313B9DCA /* MDCSnackbarManager.m */,
+				D20FE85CECC64B86387F4CA60B86C8C6 /* MDCSnackbarMessage.h */,
+				1D1C4015B6347137598F264D6387CCA6 /* MDCSnackbarMessage.m */,
+				03B0B17771C5E17CCA5515AAC7363532 /* MDCSnackbarMessageInternal.h */,
+				A3991A36920E062C3E82F61204091F73 /* MDCSnackbarMessageView.h */,
+				F1E7B70BE2622CF3F81A0AD037E21C47 /* MDCSnackbarMessageView.m */,
+				522F0C6B92C308F6D1B7BB497022A769 /* MDCSnackbarMessageViewInternal.h */,
+				98BE3C2752BDFA411D8AD43231FF4BCC /* MDCSnackbarOverlayView.h */,
+				01C5E9A263A0FBC63B0B1E0D89013529 /* MDCSnackbarOverlayView.m */,
+			);
+			name = Snackbar;
+			sourceTree = "<group>";
+		};
+		28B6E99744BA88E1C186F28B24BE34DB /* OverlayWindow */ = {
+			isa = PBXGroup;
+			children = (
+				F600563B48E50DAC2BB8C3B23D131DA2 /* MaterialOverlayWindow.h */,
+				D100E5E7F62D86CE9CCC97B487779DEC /* MDCOverlayWindow.h */,
+				6F9741A397ADB188B83497B96D7D30F5 /* MDCOverlayWindow.m */,
+			);
+			name = OverlayWindow;
+			sourceTree = "<group>";
+		};
+		2D236E262784B2E75892C151B31D5BE2 /* Dialogs */ = {
+			isa = PBXGroup;
+			children = (
+				84467817302E2399BA95D3A909871AFA /* MaterialDialogs.h */,
+				1D28C66D16BE7A01B82F7FD890CA7DBC /* MDCAlertController.h */,
+				C3CE561D11742D1092438C75CE67C1D4 /* MDCAlertController.m */,
+				B4CDE57035DA000166BF394A847F6AE2 /* MDCDialogPresentationController.h */,
+				B9F2A6127E6482F1546297FBA86E9E19 /* MDCDialogPresentationController.m */,
+				3F5A046B9A9E9CC97A6C6B6A65F22F53 /* MDCDialogShadowedView.h */,
+				B3AB010097D6D3763F9664DCA9A711EB /* MDCDialogShadowedView.m */,
+				0044FD236D22AB00062FFED53D72ECEF /* MDCDialogTransitionController.h */,
+				0040124427B7D454BC17F95E2C95F1B9 /* MDCDialogTransitionController.m */,
+				E8C4112E03A439A51F0FBD876DA804E5 /* UIViewController+MaterialDialogs.h */,
+				6D3E3C231B7AE692FCE91C1216645EA3 /* UIViewController+MaterialDialogs.m */,
+			);
+			name = Dialogs;
+			sourceTree = "<group>";
+		};
+		3BD889F6E1BD87A35685DC18128AB26A /* Pods-BuildingBeautifulApps */ = {
+			isa = PBXGroup;
+			children = (
+				5572DC66A4C3A03942D5656C7DC33A85 /* Pods-BuildingBeautifulApps-acknowledgements.markdown */,
+				A6219827B685EAAF10C4441241536DD2 /* Pods-BuildingBeautifulApps-acknowledgements.plist */,
+				8272252EDEB9A0A290A95F34B0A4AEBD /* Pods-BuildingBeautifulApps-dummy.m */,
+				6ADBE2A8BC6E0585880B9137AEDC228D /* Pods-BuildingBeautifulApps-frameworks.sh */,
+				9B114982D3918901056DE5DF45AEAC16 /* Pods-BuildingBeautifulApps-resources.sh */,
+				02AE1C5FFC5FC596ABEC7C98AEF62DD8 /* Pods-BuildingBeautifulApps.debug.xcconfig */,
+				120CFBE565880C2F4F462AAFCEBB37E5 /* Pods-BuildingBeautifulApps.release.xcconfig */,
+			);
+			name = "Pods-BuildingBeautifulApps";
+			path = "Target Support Files/Pods-BuildingBeautifulApps";
+			sourceTree = "<group>";
+		};
+		444ED16EF9B93203AFE8059068568CF6 /* PageControl */ = {
+			isa = PBXGroup;
+			children = (
+				3D8330A4B1BF56B9147CC1FE27AFDFCA /* MaterialPageControl.h */,
+				94B9A402610F5FCAEE60B7D902780413 /* MaterialPageControlStrings.h */,
+				61C0E2BD02828C530EA209D50ED1B519 /* MaterialPageControlStrings_table.h */,
+				A683F198135D9329FD62063BFB4B0F9B /* MDCPageControl.h */,
+				BA4F460E41035D7B0B538CDC2752925D /* MDCPageControl.m */,
+				97E9347E0E620A695CA9575055B9A219 /* MDCPageControlIndicator.h */,
+				B56398DA0E3930C91FF640F861706411 /* MDCPageControlIndicator.m */,
+				9D57CB474D3A2B64257FE6E21F9BD796 /* MDCPageControlTrackLayer.h */,
+				8556079BFB00835D898F480913F78F13 /* MDCPageControlTrackLayer.m */,
+				BEB9000A25F7F69AB8A2CE63887588C6 /* Resources */,
+			);
+			name = PageControl;
+			sourceTree = "<group>";
+		};
+		4B0B90B01CFF775D9C7B38D466F294D0 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				17AAA691CE308745D666AC354DEBD7D1 /* ic_radio_button_unchecked.png */,
+				84D3E267E2C78F75A2831346932CF97F /* ic_radio_button_unchecked@2x.png */,
+				62057440CF0144D03DEB925C378645B7 /* ic_radio_button_unchecked@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		4F83E7F2B19DDC28995A33F954D7B750 /* Collections */ = {
+			isa = PBXGroup;
+			children = (
+				210894774DFDFBA293E2296F2A30C362 /* MaterialCollections.h */,
+				56417D84CA78A113438D534EE4FFC54A /* MaterialCollectionsStrings.h */,
+				BBFB15BBA3F7C53B5BDCBDCEFD66700C /* MaterialCollectionsStrings_table.h */,
+				79DCB73AD07EBD187AB62F38B93A8863 /* MDCCollectionGridBackgroundView.h */,
+				683A8B83E16F375FE011E9C5AA0221EE /* MDCCollectionGridBackgroundView.m */,
+				206E1270F7CD7132605A140A429FE475 /* MDCCollectionInfoBarView.h */,
+				03B1990C768D7EBE9880314C80B89B32 /* MDCCollectionInfoBarView.m */,
+				D8C42FCD2D863F783537F7B84C002801 /* MDCCollectionStringResources.h */,
+				96E1A962597D9C41D8E7513530EBCD7D /* MDCCollectionStringResources.m */,
+				58B3FF2F70B1A1974204F2F8931F665B /* MDCCollectionViewController.h */,
+				D1D4C0D37627D761BB16ECB99105E4A0 /* MDCCollectionViewController.m */,
+				752EC7F93FEFE96C89367CBBBB8CB32B /* MDCCollectionViewEditing.h */,
+				F14A5EBD4362C79FF3F8A7262FEA2D5B /* MDCCollectionViewEditingDelegate.h */,
+				F4C0F26237AA99F43F82CD8B6404A8FF /* MDCCollectionViewEditor.h */,
+				24C7218ECEE1F60B1B720B21514EE621 /* MDCCollectionViewEditor.m */,
+				16C2D56E186EC25B2AD48EF7EC5DB131 /* MDCCollectionViewFlowLayout.h */,
+				931A07F6E4357134E2E8449CFE5E056E /* MDCCollectionViewFlowLayout.m */,
+				CAA1DC1A670B6F673EE517CD53A4EBD1 /* MDCCollectionViewStyler.h */,
+				F5F5CD9392CF68CA57F883CA8A1DA6BE /* MDCCollectionViewStyler.m */,
+				4FECD187F5A83C12336BB0C55DD75C6F /* MDCCollectionViewStyling.h */,
+				041B9228D9CF59ABFD7ACB6A1D468715 /* MDCCollectionViewStylingDelegate.h */,
+				0A0BC298073A7DBD29E89E8AB28AFF89 /* Resources */,
+			);
+			name = Collections;
+			sourceTree = "<group>";
+		};
+		53737E6E93B329D96F036A43EAF22646 /* Typography */ = {
+			isa = PBXGroup;
+			children = (
+				D1A37A0287C491DFE2089102146664E8 /* MaterialTypography.h */,
+				CD6BFB0EA4919F07C8AD5F586E34376D /* MDCFontTextStyle.h */,
+				07B2F589B283B574F2B354D14386BBF8 /* MDCFontTraits.h */,
+				DC384A83912E8C440C7ED70B794A89D2 /* MDCFontTraits.m */,
+				12D62C2A9C95A969E4AA727F1C8C202C /* MDCTypography.h */,
+				9A82FF56648D80F9E61096E9A07B06F6 /* MDCTypography.m */,
+				A8D106719F3F199D438233D94FDF43F5 /* UIFont+MaterialTypography.h */,
+				E17A7167DE53F6528C656D4979850FBC /* UIFont+MaterialTypography.m */,
+				6E75C79B7D5289097D15A811F188CED2 /* UIFont+MaterialTypographyPrivate.h */,
+				4277E14F56DAC15ABD24D97EDC26ADEA /* UIFont+MaterialTypographyPrivate.m */,
+				9E5285A7050BE78F06AD6EC2E4BF1A2F /* UIFontDescriptor+MaterialTypography.h */,
+				D7E1DE48A44A60C2AE808B6D69A73683 /* UIFontDescriptor+MaterialTypography.m */,
+			);
+			name = Typography;
+			sourceTree = "<group>";
+		};
+		57B3AC99860520DA3D05E9DCC199382E /* AnimationTiming */ = {
+			isa = PBXGroup;
+			children = (
+				74905502A1DF96D7D84E7714A179E9E9 /* CAMediaTimingFunction+MDCAnimationTiming.h */,
+				10B9C9D65FA83AC626EFF1C6A94BA402 /* CAMediaTimingFunction+MDCAnimationTiming.m */,
+				C075A49AEB6D1C36BA22C458FC6A2801 /* MaterialAnimationTiming.h */,
+				5894DCB5AAB8B32C781B6279A0FEF8D9 /* UIView+MDCTimingFunction.h */,
+				7941C852DB02A5C5D4BE708004028A52 /* UIView+MDCTimingFunction.m */,
+			);
+			name = AnimationTiming;
+			sourceTree = "<group>";
+		};
+		5A4DBD434EA75DD3EDD3494C46AE6968 /* iOS */ = {
+			isa = PBXGroup;
+			children = (
+				409899CE1143F81E8130E2069D59605B /* CoreGraphics.framework */,
+				12992E853CAE14F2102525E0D84ADAB5 /* Foundation.framework */,
+				5F7BDB2580B244756CFA046131516EF2 /* QuartzCore.framework */,
+			);
+			name = iOS;
+			sourceTree = "<group>";
+		};
+		5B9B9BF255AED07DB6926B6422A71F1B /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				6F352D5A20ECA41E1A995B662456AFC4 /* MaterialComponents */,
+				0F4F0B2885DA4E9FDA72BB907CFEEBA1 /* MDFTextAccessibility */,
+			);
+			name = Pods;
+			sourceTree = "<group>";
+		};
+		5CCDE775C68B760973ABA074B79AA9A9 /* Targets Support Files */ = {
+			isa = PBXGroup;
+			children = (
+				3BD889F6E1BD87A35685DC18128AB26A /* Pods-BuildingBeautifulApps */,
+			);
+			name = "Targets Support Files";
+			sourceTree = "<group>";
+		};
+		5EB185DA3E833BE86F7173AD153ED92B /* CollectionCells */ = {
+			isa = PBXGroup;
+			children = (
+				A32E50911D7DB6FBC3E4CC4ECCBA1596 /* MaterialCollectionCells.h */,
+				29BB55A9B6803B9A3A7A064A6E797A79 /* MDCCollectionViewCell.h */,
+				BEBA1206741596666E53A5291AC6C67D /* MDCCollectionViewCell.m */,
+				8BF097DEAD72714A366668962C25EC9B /* MDCCollectionViewTextCell.h */,
+				158DFD17C32FF1158E4896DD754DDC6B /* MDCCollectionViewTextCell.m */,
+				E92ECD77FAAF62A64A87A141AB207123 /* Resources */,
+			);
+			name = CollectionCells;
+			sourceTree = "<group>";
+		};
+		5FC45D223B2D6C4904ECBE9DDC39C4DA /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				403CEE2F8B8AFCD9A8ADAD83045448CB /* ic_reorder.png */,
+				47BD4FBE1EC6F6C948B7056DFB3EAE4E /* ic_reorder@2x.png */,
+				87D692B9AD07C602ED145B594F3FF7D9 /* ic_reorder@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		635C52F44DD7D619304875A77DEECB7A /* Tabs */ = {
+			isa = PBXGroup;
+			children = (
+				0C1F25227166DC67A877DFCA5594F74B /* MaterialTabs.h */,
+				CADC6B616AB3936666BDBD42A2705DE6 /* MDCItemBar.h */,
+				BB3068591BFE9A9F8D1B79957A573691 /* MDCItemBar.m */,
+				5677CC19D390C501CCA90EEE390AAE6D /* MDCItemBarAlignment.h */,
+				E70A12012C34069A15DAAEF725754A18 /* MDCItemBarCell.h */,
+				01127A0CE1E1F9D661213AD37AC639FC /* MDCItemBarCell.m */,
+				EDD61B881B917B05AFD9539341F931FD /* MDCItemBarStringConstants.h */,
+				C4F53B72FA10D37719F9CB9924A08CBD /* MDCItemBarStyle.h */,
+				2792F28B4CCFEB1DCDCDBB8636947EBC /* MDCItemBarStyle.m */,
+				BDAF0CDE00CDA3F4B1CE9E7374239490 /* MDCTabBar.h */,
+				5D8DE150DA0161A584D8CED87D6DF987 /* MDCTabBar.m */,
+				B9E2AAB8153882A4590062F569A4D595 /* MDCTabBarAlignment.h */,
+				2FE6A5198039451C28C172BC4168A03A /* MDCTabBarItemAppearance.h */,
+				6EF06DBA252DBC3C63E36D49176DFF34 /* Resources */,
+			);
+			name = Tabs;
+			sourceTree = "<group>";
+		};
+		67DEEE835292D3753E9C9C944975A1F1 /* ShadowLayer */ = {
+			isa = PBXGroup;
+			children = (
+				77C440E4189E05E40980CE67AF6A977D /* MaterialShadowLayer.h */,
+				D8966C5049A9875A33A6802C9840E498 /* MDCShadowLayer.h */,
+				B6134FFEBB32CC196B45597FC2948611 /* MDCShadowLayer.m */,
+			);
+			name = ShadowLayer;
+			sourceTree = "<group>";
+		};
+		6906A22C03A392F2D5612B99843C7B16 /* AppBar */ = {
+			isa = PBXGroup;
+			children = (
+				2D0C383ECBB30F7ADEB6B1EFF274C298 /* MaterialAppBar.h */,
+				9CA3D76D548F43BB8F241C55FB9D5656 /* MDCAppBar.h */,
+				1D570439942906B139B693491F7E71ED /* MDCAppBar.m */,
+				1FA357A2956B620B50A4CAEFE8F1795B /* MDCAppBarContainerViewController.h */,
+				F7D2E69B90D1C23D2FBD5EB175B59364 /* MDCAppBarContainerViewController.m */,
+			);
+			name = AppBar;
+			sourceTree = "<group>";
+		};
+		6C7910AF3C49D2EF31AEB30319482C37 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				ACCED250D3351A0D22EEA492436EBE80 /* ic_info.png */,
+				029A97895F42B6AB7B7209A3BB20DCA8 /* ic_info@2x.png */,
+				5EBBA737C7DEFC62CB07A5607401B086 /* ic_info@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		6EF06DBA252DBC3C63E36D49176DFF34 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				94294D2C0E41046D41ED4D332EF32E37 /* MaterialTabs.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		6F352D5A20ECA41E1A995B662456AFC4 /* MaterialComponents */ = {
+			isa = PBXGroup;
+			children = (
+				860FDBF1491FEF45BBDC4B10C7A6029A /* ActivityIndicator */,
+				57B3AC99860520DA3D05E9DCC199382E /* AnimationTiming */,
+				6906A22C03A392F2D5612B99843C7B16 /* AppBar */,
+				DC5320477BAF4A05AE764444E095C05E /* ButtonBar */,
+				8B423F014C2BFE2D485F66E90BE4E37A /* Buttons */,
+				5EB185DA3E833BE86F7173AD153ED92B /* CollectionCells */,
+				9E6ABE4B858C2ADEC3217A48A6B64CD1 /* CollectionLayoutAttributes */,
+				4F83E7F2B19DDC28995A33F954D7B750 /* Collections */,
+				2D236E262784B2E75892C151B31D5BE2 /* Dialogs */,
+				B26BD90E467D23E0105D42B7F1AEC069 /* FeatureHighlight */,
+				7A385EB5D98EE940F9E0187E0DB19C51 /* FlexibleHeader */,
+				7BB4357B73230E3118EC1730397E5F7E /* HeaderStackView */,
+				79A5FC65EED1F300B4FEB2C7BF3792C4 /* Ink */,
+				E1408803AF660D6CADA8F86423AF95B1 /* NavigationBar */,
+				28B6E99744BA88E1C186F28B24BE34DB /* OverlayWindow */,
+				444ED16EF9B93203AFE8059068568CF6 /* PageControl */,
+				FF842A3362760880262DF2AB9BEA82D4 /* Palettes */,
+				BE9FCA4B7CA2E2C7250B24CC35C0564C /* private */,
+				14F3093C9EDA04FD806300494FD654F0 /* ProgressView */,
+				903888289A0980729917B492E52ED941 /* ShadowElevations */,
+				67DEEE835292D3753E9C9C944975A1F1 /* ShadowLayer */,
+				8B047C13A4435E40C995F275E36DE89D /* Slider */,
+				1A51286FBEFC155062FB53A0ADD4D106 /* Snackbar */,
+				15CB945DCEE15326848DB6EE1185BC50 /* Support Files */,
+				635C52F44DD7D619304875A77DEECB7A /* Tabs */,
+				53737E6E93B329D96F036A43EAF22646 /* Typography */,
+			);
+			name = MaterialComponents;
+			path = MaterialComponents;
+			sourceTree = "<group>";
+		};
+		766E4937EA799D9EC8B3869F8CEF6B5D /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				09A539046C55C092B1882F2B3101A656 /* libMaterialComponents.a */,
+				B6D338FD921EC51C550567AB2D429021 /* libMDFTextAccessibility.a */,
+				6B9A7110EE95FE54D52AC78F8943FF30 /* libPods-BuildingBeautifulApps.a */,
+				FF9E5D282080B168147A56CBC1A20CB3 /* MaterialIcons_ic_arrow_back.bundle */,
+				860E1A6AE14CC46812BFD2EECD3DF1B6 /* MaterialIcons_ic_check.bundle */,
+				430CFFC6D36F60111CDF22059398251D /* MaterialIcons_ic_check_circle.bundle */,
+				CB370B0CFF7E9F249F9A4A4A5C9828C0 /* MaterialIcons_ic_chevron_right.bundle */,
+				DBB2727B89FCF4B81EAB1F748F4EE6F7 /* MaterialIcons_ic_info.bundle */,
+				9F8BE2D8847C692FB18FCFEF6F294478 /* MaterialIcons_ic_radio_button_unchecked.bundle */,
+				D43D8FF7991737DB826BFF92EBF8ADFA /* MaterialIcons_ic_reorder.bundle */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		79A5FC65EED1F300B4FEB2C7BF3792C4 /* Ink */ = {
+			isa = PBXGroup;
+			children = (
+				1C21154B03011C9702C295079DCF65E1 /* MaterialInk.h */,
+				0750459EFB95F5CE725C61781848452B /* MDCInkGestureRecognizer.h */,
+				CAC43F65D5D78A89EAC07A697ACC9837 /* MDCInkGestureRecognizer.m */,
+				EA980654C37C923AB926DF64E7E02736 /* MDCInkLayer.h */,
+				E37F8FD7F722E714E0005FB0C96F9A03 /* MDCInkLayer.m */,
+				E47ED49AEF9D2FE77E92679C5569563D /* MDCInkTouchController.h */,
+				FF7A269A35FCA0697B0E5BD94453D3EF /* MDCInkTouchController.m */,
+				EF3D4AABE18C6B0D033BD47108A9156D /* MDCInkView.h */,
+				FC7FA8E220EACEBE9FB49B6A6B3732E5 /* MDCInkView.m */,
+			);
+			name = Ink;
+			sourceTree = "<group>";
+		};
+		7A385EB5D98EE940F9E0187E0DB19C51 /* FlexibleHeader */ = {
+			isa = PBXGroup;
+			children = (
+				9A7FE223E125A19DB7A772510BF0DEB2 /* MaterialFlexibleHeader.h */,
+				621F64FAC8A6CDF22ADF8271D04409C6 /* MDCFlexibleHeaderContainerViewController.h */,
+				536F8F8CBB3D5593CFA4CBFD765F3BED /* MDCFlexibleHeaderContainerViewController.m */,
+				6EE3924624B8CAFC171FD153BBFC8449 /* MDCFlexibleHeaderView.h */,
+				71BE7789CD2EC0A70DE711AC5A1FEF8D /* MDCFlexibleHeaderView.m */,
+				24A9F1821AD8EA4BF21E13D87EC6F56D /* MDCFlexibleHeaderViewController.h */,
+				6EAC67B229E26EFB3FEF38B7164183F0 /* MDCFlexibleHeaderViewController.m */,
+				2543C83779FCB7CA6F63B6E23BA22BDB /* MDCStatusBarShifter.h */,
+				7D86AB797FE0EAA5C5384DF417BF5346 /* MDCStatusBarShifter.m */,
+			);
+			name = FlexibleHeader;
+			sourceTree = "<group>";
+		};
+		7BB4357B73230E3118EC1730397E5F7E /* HeaderStackView */ = {
+			isa = PBXGroup;
+			children = (
+				702CBDDD852DAA7044CE6BCB5AA2D950 /* MaterialHeaderStackView.h */,
+				CE6929889D615189113913408E3D1B9E /* MDCHeaderStackView.h */,
+				EB1C6A347A3B1B5278B6179E7E7A6C7E /* MDCHeaderStackView.m */,
+			);
+			name = HeaderStackView;
+			sourceTree = "<group>";
+		};
+		7BBBBB41025DA2946E721C6B4CFE9582 /* ic_arrow_back */ = {
+			isa = PBXGroup;
+			children = (
+				804D865D3D4D4C65731A550B3D8FC9A5 /* MaterialIcons+ic_arrow_back.h */,
+				C830C5EEEAE60B4A9283F0C2F0A02094 /* MaterialIcons+ic_arrow_back.m */,
+				9F3E1632178E5C2029635BBAE94F3A0A /* Resources */,
+			);
+			name = ic_arrow_back;
+			sourceTree = "<group>";
+		};
+		7DB346D0F39D3F0E887471402A8071AB = {
+			isa = PBXGroup;
+			children = (
+				93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */,
+				122DA2E5084A4393C29BE363C764795C /* Frameworks */,
+				5B9B9BF255AED07DB6926B6422A71F1B /* Pods */,
+				766E4937EA799D9EC8B3869F8CEF6B5D /* Products */,
+				5CCDE775C68B760973ABA074B79AA9A9 /* Targets Support Files */,
+			);
+			sourceTree = "<group>";
+		};
+		860FDBF1491FEF45BBDC4B10C7A6029A /* ActivityIndicator */ = {
+			isa = PBXGroup;
+			children = (
+				7143C04351DADE6FD07918C99C3BF31E /* MaterialActivityIndicator.h */,
+				97262CDCD801553DA99ECC7847E39E98 /* MDCActivityIndicator.h */,
+				45DA800B226D1DE08F69E5BDDC45E203 /* MDCActivityIndicator.m */,
+			);
+			name = ActivityIndicator;
+			sourceTree = "<group>";
+		};
+		87E4ABB0C4383AF0F29468B14112DF80 /* ThumbTrack */ = {
+			isa = PBXGroup;
+			children = (
+				D11EB1CC12CA81275669C38699DF58A3 /* MaterialThumbTrack.h */,
+				C660FEA28DDB8CB873D9BCE3DA03F6B3 /* MDCNumericValueLabel.h */,
+				1E74B45D4E01DE3821E65C8FEC806B60 /* MDCNumericValueLabel.m */,
+				86754C059E8434587187015DC770180B /* MDCThumbTrack.h */,
+				9E05EB6FB230393D92DC9A1584D7DE50 /* MDCThumbTrack.m */,
+				D49CC986145361BA86D40441881692D8 /* MDCThumbView.h */,
+				8CCFBA02AEF1EB2D0EA744C7D87ADB76 /* MDCThumbView.m */,
+			);
+			name = ThumbTrack;
+			sourceTree = "<group>";
+		};
+		8B047C13A4435E40C995F275E36DE89D /* Slider */ = {
+			isa = PBXGroup;
+			children = (
+				60852389E40D9EF0F70B7BF97E7B998D /* MaterialSlider.h */,
+				0F8DD7BF09A1359D0C22AD2D99DF9967 /* MDCSlider.h */,
+				2862A3829BA4649EDB04191EB5D64C4B /* MDCSlider.m */,
+				14793E6FDAF9C044D6ED8B67E59C7E75 /* MDCSlider_Subclassable.h */,
+			);
+			name = Slider;
+			sourceTree = "<group>";
+		};
+		8B423F014C2BFE2D485F66E90BE4E37A /* Buttons */ = {
+			isa = PBXGroup;
+			children = (
+				4B9EBBBC413F2FB5A96D131DC26FFC36 /* MaterialButtons.h */,
+				12BE96DCA235623AF7766C60CCFAE1C7 /* MDCButton.h */,
+				BE257A301C797B8D3C24053EFEF0DB5A /* MDCButton.m */,
+				F82A46DDAA89ACF53DA3C47CC04971EF /* MDCButton+Subclassing.h */,
+				EFCF3D3D2FE3A10C4245EF66AE882178 /* MDCFlatButton.h */,
+				4F0E678DFEF2B507BAEF2FFD1EF23228 /* MDCFlatButton.m */,
+				E66CD057FB364E80D5BC3D34A00B42FF /* MDCFloatingButton.h */,
+				F64F50AD20E83F81710454204053A744 /* MDCFloatingButton.m */,
+				ABED23378B104A0A25435A6674F29FF5 /* MDCRaisedButton.h */,
+				B77E7CD1098848AED57761E60382667D /* MDCRaisedButton.m */,
+			);
+			name = Buttons;
+			sourceTree = "<group>";
+		};
+		8BBEF3ED9DC53D6F9F554679719F9E66 /* Support Files */ = {
+			isa = PBXGroup;
+			children = (
+				A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */,
+				8E961B158FE9954DDD2B6C09E3462883 /* MDFTextAccessibility-dummy.m */,
+				13DBFFD40004CC93DF060411AE7CB49F /* MDFTextAccessibility-prefix.pch */,
+			);
+			name = "Support Files";
+			path = "../Target Support Files/MDFTextAccessibility";
+			sourceTree = "<group>";
+		};
+		903888289A0980729917B492E52ED941 /* ShadowElevations */ = {
+			isa = PBXGroup;
+			children = (
+				03CE9EF2998E990D7C6C15AC4AEFF20D /* MaterialShadowElevations.h */,
+				7E855EBFE6A726985077571DB7E89BD5 /* MDCShadowElevations.h */,
+				CC56C512FD3A98A296C04156DD8DFEC9 /* MDCShadowElevations.m */,
+			);
+			name = ShadowElevations;
+			sourceTree = "<group>";
+		};
+		9E6ABE4B858C2ADEC3217A48A6B64CD1 /* CollectionLayoutAttributes */ = {
+			isa = PBXGroup;
+			children = (
+				444B921CA054B6ED8B57713242404400 /* MaterialCollectionLayoutAttributes.h */,
+				6677BBD93E7A4672F9AEA51236310EDF /* MDCCollectionViewLayoutAttributes.h */,
+				462854769E2CB8F1B329D4392C79AA61 /* MDCCollectionViewLayoutAttributes.m */,
+			);
+			name = CollectionLayoutAttributes;
+			sourceTree = "<group>";
+		};
+		9EC1DD96659E9FFC62849C078CDEDE6E /* Application */ = {
+			isa = PBXGroup;
+			children = (
+				51F9DCB161F252F8BD0F521356180A57 /* MaterialApplication.h */,
+				95D1CF13299CEF28BCBAA62F927A3D80 /* UIApplication+AppExtensions.h */,
+				5C4F931DA815928A8CA82E5513C6246A /* UIApplication+AppExtensions.m */,
+			);
+			name = Application;
+			sourceTree = "<group>";
+		};
+		9F3E1632178E5C2029635BBAE94F3A0A /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				15E9398FCB2DA33C5C08533B1716A7CE /* ic_arrow_back.png */,
+				11DD5A41B2DA0290521D16D24EEC529D /* ic_arrow_back@2x.png */,
+				FE7AE3A31ABEA928F10508D5385C37F8 /* ic_arrow_back@3x.png */,
+				7F9E8F936B7FA4CE55F6D4A70EDF478C /* ic_arrow_back_ios.png */,
+				33072B9B16A9B8DAAEDE9D6B449679D2 /* ic_arrow_back_ios@2x.png */,
+				E95DB580D0830673D87F39AEFDA6EF67 /* ic_arrow_back_ios@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		A8AC6F8EA0BF9331BC3179FC0941D312 /* ic_info */ = {
+			isa = PBXGroup;
+			children = (
+				FD4ED0BAB173C96E24BFAF538C1A0353 /* MaterialIcons+ic_info.h */,
+				B52A38C1D2775315C12601204EF0524E /* MaterialIcons+ic_info.m */,
+				6C7910AF3C49D2EF31AEB30319482C37 /* Resources */,
+			);
+			name = ic_info;
+			sourceTree = "<group>";
+		};
+		AF25FF466DBA2941E997767B393643DA /* RTL */ = {
+			isa = PBXGroup;
+			children = (
+				E88C708F20439859824CDC2F79216421 /* MaterialRTL.h */,
+				935B6D6F1FAB419F6C7B4129E6A0074F /* MDCRTL.h */,
+				B12139AB4284238F1123EB1E38B230E1 /* MDCRTL.m */,
+				6ECC1D1D41521DED2581889D20C4D8F9 /* UIImage+MaterialRTL.h */,
+				0EEA3ACEEB4A63D1DF01A8D3F89BC441 /* UIImage+MaterialRTL.m */,
+				1D9BC573FF76C294C05D43278D00B4A6 /* UIView+MaterialRTL.h */,
+				90B29DB14670F66061CFB82DDC68AF49 /* UIView+MaterialRTL.m */,
+			);
+			name = RTL;
+			sourceTree = "<group>";
+		};
+		B26BD90E467D23E0105D42B7F1AEC069 /* FeatureHighlight */ = {
+			isa = PBXGroup;
+			children = (
+				F5BEB5E003D1847D87CC74803474B2EF /* MaterialFeatureHighlight.h */,
+				EC8039BB5A86167E8DCDB72F46D6388B /* MDCFeatureHighlightAnimationController.h */,
+				D2FFA02DCC45D1EDB5D30FB9CEB3B9BD /* MDCFeatureHighlightAnimationController.m */,
+				1F0F8786C896495252AF8C693705FE27 /* MDCFeatureHighlightLayer.h */,
+				1B3462BC5FFFCC355901DAA536C77A5A /* MDCFeatureHighlightLayer.m */,
+				17B8A83C9148D87712E07EDE938E65E0 /* MDCFeatureHighlightView.h */,
+				13923E685C01C84D742BF61E9A51D084 /* MDCFeatureHighlightView.m */,
+				66E845FD6DDDE254DBD69B4B9FBCA3B8 /* MDCFeatureHighlightViewController.h */,
+				5C27D7602B81556831B0A85A92B4E5A3 /* MDCFeatureHighlightViewController.m */,
+			);
+			name = FeatureHighlight;
+			sourceTree = "<group>";
+		};
+		BC22755231123F8970B82180656CBC02 /* ic_check_circle */ = {
+			isa = PBXGroup;
+			children = (
+				263DB970C3B145399EBC89F15760FB2B /* MaterialIcons+ic_check_circle.h */,
+				443C58797FC89C1F0BDC6BDF82DD1913 /* MaterialIcons+ic_check_circle.m */,
+				CC9F919EA99C89421B37019CDB0A409E /* Resources */,
+			);
+			name = ic_check_circle;
+			sourceTree = "<group>";
+		};
+		BE9FCA4B7CA2E2C7250B24CC35C0564C /* private */ = {
+			isa = PBXGroup;
+			children = (
+				9EC1DD96659E9FFC62849C078CDEDE6E /* Application */,
+				015D80086EA2452E311127664AED6C49 /* Icons */,
+				FBD6A87FCC2224358E3A0DFA22CEEF3A /* KeyboardWatcher */,
+				0FFE22ED316D810F07A3CE1804C14671 /* Overlay */,
+				AF25FF466DBA2941E997767B393643DA /* RTL */,
+				87E4ABB0C4383AF0F29468B14112DF80 /* ThumbTrack */,
+			);
+			name = private;
+			sourceTree = "<group>";
+		};
+		BEB9000A25F7F69AB8A2CE63887588C6 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				C092C0ED18CF0F6D5A1391571F068348 /* MaterialPageControl.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		C0478CE6F06E1DD40878AE929472991C /* ic_chevron_right */ = {
+			isa = PBXGroup;
+			children = (
+				F398E51F9526801442D77BE9612F9C62 /* MaterialIcons+ic_chevron_right.h */,
+				654AA469F888FFF8F1CE4AA611FD6B69 /* MaterialIcons+ic_chevron_right.m */,
+				D046EF7CC52EAC0CA7A571CF2A25FC45 /* Resources */,
+			);
+			name = ic_chevron_right;
+			sourceTree = "<group>";
+		};
+		C8CCC6846666AAD0D3CA32B272E86A7F /* ic_reorder */ = {
+			isa = PBXGroup;
+			children = (
+				5B8E69C2D115A0FE03A563709E22B4ED /* MaterialIcons+ic_reorder.h */,
+				3F9391682535FDA07FBB0AB83B6B96E0 /* MaterialIcons+ic_reorder.m */,
+				5FC45D223B2D6C4904ECBE9DDC39C4DA /* Resources */,
+			);
+			name = ic_reorder;
+			sourceTree = "<group>";
+		};
+		CC9F919EA99C89421B37019CDB0A409E /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				11ED6DF86B1C41582FEF6983B868825F /* ic_check_circle.png */,
+				20A374DC73FDF4CF43A4454A86E587F6 /* ic_check_circle@2x.png */,
+				38A6CB047FC50FA03168F50ACA26C75B /* ic_check_circle@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		D046EF7CC52EAC0CA7A571CF2A25FC45 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				7EBAFD93350BF0CF6E8CE57A39A1FA5D /* ic_chevron_right.png */,
+				D5674E7D4BCC946A30114DBF9DB2F6CA /* ic_chevron_right@2x.png */,
+				35901EA242A4B2DE85C2894CC9194C1F /* ic_chevron_right@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		DC5320477BAF4A05AE764444E095C05E /* ButtonBar */ = {
+			isa = PBXGroup;
+			children = (
+				D14A347A944C556F216B967AFCF766C8 /* MaterialButtonBar.h */,
+				4FC2C7E47A0EA56BD6295D82B56F6192 /* MDCAppBarButtonBarBuilder.h */,
+				193A24743DF539FCD29F2B8EF21442F2 /* MDCAppBarButtonBarBuilder.m */,
+				4374B11D22F0FCC5866781A5F08A4D38 /* MDCButtonBar.h */,
+				FC8CB7864BDCD9DB97A3711AC446E2B0 /* MDCButtonBar.m */,
+				D79A92B4599903B71AD908CC7E5B0213 /* MDCButtonBar+Private.h */,
+			);
+			name = ButtonBar;
+			sourceTree = "<group>";
+		};
+		E1408803AF660D6CADA8F86423AF95B1 /* NavigationBar */ = {
+			isa = PBXGroup;
+			children = (
+				B73577CD8AEFE5DA6EB995CC8F2C92A7 /* MaterialNavigationBar.h */,
+				01B79C689F86C1C48EEBFE41AA191DBE /* MDCNavigationBar.h */,
+				CCF1F1AE19AF21CE8869CF3A681CC787 /* MDCNavigationBar.m */,
+			);
+			name = NavigationBar;
+			sourceTree = "<group>";
+		};
+		E92ECD77FAAF62A64A87A141AB207123 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				915F12E15D337DE30C909A4C3749EE83 /* MaterialCollectionCells.bundle */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		EC40E103B51AE1755CA03F26C6C066F1 /* ic_radio_button_unchecked */ = {
+			isa = PBXGroup;
+			children = (
+				97FBECBD5EF590F0A8005F8B94E808FF /* MaterialIcons+ic_radio_button_unchecked.h */,
+				C19F7B7784CFCB4369498613360AA4CB /* MaterialIcons+ic_radio_button_unchecked.m */,
+				4B0B90B01CFF775D9C7B38D466F294D0 /* Resources */,
+			);
+			name = ic_radio_button_unchecked;
+			sourceTree = "<group>";
+		};
+		F7107ECA24205B6455A55C23978D1621 /* Resources */ = {
+			isa = PBXGroup;
+			children = (
+				7C5778E1102FA874A7F4F6FFD400C7DE /* ic_check.png */,
+				8917229D3430B609F88F33A180E7063C /* ic_check@2x.png */,
+				49A3FB5A7A3C2EEAAF7C7BD7C72CABBD /* ic_check@3x.png */,
+			);
+			name = Resources;
+			sourceTree = "<group>";
+		};
+		FBD6A87FCC2224358E3A0DFA22CEEF3A /* KeyboardWatcher */ = {
+			isa = PBXGroup;
+			children = (
+				F5A94E964BB75BF779F888AE07B3F95C /* MaterialKeyboardWatcher.h */,
+				BE4C70E576A2623B72B27F812FA19587 /* MDCKeyboardWatcher.h */,
+				06A99FC5FF2D8E635C719D756C525052 /* MDCKeyboardWatcher.m */,
+			);
+			name = KeyboardWatcher;
+			sourceTree = "<group>";
+		};
+		FF842A3362760880262DF2AB9BEA82D4 /* Palettes */ = {
+			isa = PBXGroup;
+			children = (
+				0EC4BB63283347849E4A8B02A60CABC4 /* MaterialPalettes.h */,
+				C4899C25A4830FCF08B2BB4F8ABC361A /* MDCPaletteExpansions.h */,
+				67D647688DBDE7C289D22CFAADF4006C /* MDCPaletteExpansions.m */,
+				C078D453FB972AF56047785185938933 /* MDCPaletteNames.h */,
+				98F8E9B6EBCFF521C01B78E4BD1039BD /* MDCPaletteNames.m */,
+				675F4FE5A00141BDF25CA3589A5DEF88 /* MDCPalettes.h */,
+				C9588139AB2E41A105B4F278EF0B01F3 /* MDCPalettes.m */,
+			);
+			name = Palettes;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		1BF21BF58E4EBE29C297FBEF774B04F0 /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				F81CCFD29E38C4B4669681176C4C53C0 /* MDFColorCalculations.h in Headers */,
+				421078E41926305DF11196F6FB28AD42 /* MDFImageCalculations.h in Headers */,
+				3109CBFCFA85CBFA88B4F9FA1F3A16D1 /* MDFTextAccessibility-Bridging-Header.h in Headers */,
+				984A454523FEF2464DED49EFB46F4D7D /* MDFTextAccessibility.h in Headers */,
+				1A0003B88CFC06F475A1A7D437E14A27 /* NSArray+MDFUtils.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		BD0D3F935DD310043B1C382E24090D3C /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				E98184F9E8FBA7F587905DDDD0944848 /* CAMediaTimingFunction+MDCAnimationTiming.h in Headers */,
+				C2309CF5EBD904E226161D55F14B950A /* MaterialActivityIndicator.h in Headers */,
+				D07E00458702FE480F21B32777B0F013 /* MaterialAnimationTiming.h in Headers */,
+				A339971188CEF5E30398257AA87216D5 /* MaterialAppBar.h in Headers */,
+				9424985CFBD9108EAB15C67DE617DDD7 /* MaterialApplication.h in Headers */,
+				D448A87D1BC2FC2702156E6FE048F9BC /* MaterialButtonBar.h in Headers */,
+				DBAAB720813BBA54AD2126495BDAA7D2 /* MaterialButtons.h in Headers */,
+				47C39E63B795E98E36A83BBAC82BF86F /* MaterialCollectionCells.h in Headers */,
+				0D20BD182D66DBDD7E4D6CB7F77CF9F3 /* MaterialCollectionLayoutAttributes.h in Headers */,
+				BF73F5FFED03E771C41544D7E5AF7AB8 /* MaterialCollections.h in Headers */,
+				DC0601BB3966D321FDC30D767B44C37F /* MaterialCollectionsStrings.h in Headers */,
+				97B175A8C54E8AB93F6A1738A2E8AC32 /* MaterialCollectionsStrings_table.h in Headers */,
+				3D2BB082025D1252507C363E4714C625 /* MaterialDialogs.h in Headers */,
+				52C9FD65F3A7015BF99A651500F2D24C /* MaterialFeatureHighlight.h in Headers */,
+				48887AC621143DD5D40DBFE5A4E23883 /* MaterialFlexibleHeader.h in Headers */,
+				FB0210FF9893437C285475B18A6B25D6 /* MaterialHeaderStackView.h in Headers */,
+				9C989E66AB86785F2C11FFAC7EBC30A1 /* MaterialIcons+ic_arrow_back.h in Headers */,
+				945823B4D8C6E662F1C2CB08D268A088 /* MaterialIcons+ic_check.h in Headers */,
+				86115CB0ADDFA0C2DA2A6C8A2834A7FD /* MaterialIcons+ic_check_circle.h in Headers */,
+				3019DD7715B81601126A4182935F7DA9 /* MaterialIcons+ic_chevron_right.h in Headers */,
+				BBD17582B2F80BD702EF29C8B0E5D712 /* MaterialIcons+ic_info.h in Headers */,
+				E7D877B60FFD0FF706FDDFD568088D78 /* MaterialIcons+ic_radio_button_unchecked.h in Headers */,
+				9C71ADED3653D657A6F952A77DA208F7 /* MaterialIcons+ic_reorder.h in Headers */,
+				E90F58CF316377AF8434201C85BBEA50 /* MaterialIcons.h in Headers */,
+				0E47C9B2997E679B24FA498EE2363228 /* MaterialInk.h in Headers */,
+				4C2B4BA673669811FBFF71DF09D6F550 /* MaterialKeyboardWatcher.h in Headers */,
+				1C4083843A8D6038A7EAA2DD85FDC174 /* MaterialNavigationBar.h in Headers */,
+				A08E58F7C109094B2B88D50771692D44 /* MaterialOverlays.h in Headers */,
+				8B0BD0DC00C8B39EABBBA502C3CC424B /* MaterialOverlayWindow.h in Headers */,
+				B15972456A2F74F579179B9FA24B11A2 /* MaterialPageControl.h in Headers */,
+				96232A06DAC31122E30D7D5724150A83 /* MaterialPageControlStrings.h in Headers */,
+				3A2F4061FB79B93EA5C9B8DA9094EED5 /* MaterialPageControlStrings_table.h in Headers */,
+				B8A8D97688E58A1C843EE96397D81DF9 /* MaterialPalettes.h in Headers */,
+				3516A50767315A26E2D625A823474101 /* MaterialProgressView.h in Headers */,
+				7339A37AFA0F1A69B86239CE639CC15D /* MaterialRTL.h in Headers */,
+				173E8E625D765B2536A2145C9F528898 /* MaterialShadowElevations.h in Headers */,
+				7321A0DEBC74D9ED66E36F9A27FF0CCD /* MaterialShadowLayer.h in Headers */,
+				0617544187F62EC4C98A6BEE1428C5D6 /* MaterialSlider.h in Headers */,
+				CA4EF6FF105C4B45D26CC12A9F8CA011 /* MaterialSnackbar.h in Headers */,
+				04EC8CBF409C803BF749B2F9E8E38E0B /* MaterialTabs.h in Headers */,
+				7BF7E68DCF7F91851687A7D393812EC6 /* MaterialThumbTrack.h in Headers */,
+				C95B219DE3270084C28BE6FDDC86F2D5 /* MaterialTypography.h in Headers */,
+				1D8C9CF5687E222D0C1919213AA0116A /* MDCActivityIndicator.h in Headers */,
+				D6CEB0B38DC1554A3B1956CB6A11D892 /* MDCAlertController.h in Headers */,
+				1274CD4A2DD52C98C966921502C57446 /* MDCAppBar.h in Headers */,
+				FF37686F3E3AFF2F94C01E95A9CE2911 /* MDCAppBarButtonBarBuilder.h in Headers */,
+				DB772D2AC10FA285081B0AD22494A408 /* MDCAppBarContainerViewController.h in Headers */,
+				5685049F462A3F846BF0EA56103E153C /* MDCButton+Subclassing.h in Headers */,
+				4E8DA5386F2879E77B2E23D0E03C4A9B /* MDCButton.h in Headers */,
+				69CD5189E440D7767EE5B771A9FEE03D /* MDCButtonBar+Private.h in Headers */,
+				83FE983EC6EEC2C7ACAE955FCABFF518 /* MDCButtonBar.h in Headers */,
+				E4282287703DA962B61A39D1B0D8318D /* MDCCollectionGridBackgroundView.h in Headers */,
+				3BFFD555516224FB8FF319A087BCA29F /* MDCCollectionInfoBarView.h in Headers */,
+				C7AC330240BBC7E4EB43FE67062A461B /* MDCCollectionStringResources.h in Headers */,
+				CDAFC1E966DB3C899DE01EC81998EE9C /* MDCCollectionViewCell.h in Headers */,
+				81F752320FBCB9A12535E3AD2602AA27 /* MDCCollectionViewController.h in Headers */,
+				49C5DD0A16846BF2E4806A9510D2998D /* MDCCollectionViewEditing.h in Headers */,
+				4717C3070FA97344C11B65BACF2DDF3C /* MDCCollectionViewEditingDelegate.h in Headers */,
+				D053587851EF944EAC99AF4152E5BA75 /* MDCCollectionViewEditor.h in Headers */,
+				24CD705DC0032088FFF4C5DF861B0099 /* MDCCollectionViewFlowLayout.h in Headers */,
+				54BB836815554D4144AC9824136B8FA9 /* MDCCollectionViewLayoutAttributes.h in Headers */,
+				7BDC8151577B47E72BCB0F299F6654A8 /* MDCCollectionViewStyler.h in Headers */,
+				FA36A066EE5CF084A61B8E5CE4A50928 /* MDCCollectionViewStyling.h in Headers */,
+				67E00C690CF9CFB20C51270B46B6A1CB /* MDCCollectionViewStylingDelegate.h in Headers */,
+				451AD57BB35CAD3C692F082E93B99BF3 /* MDCCollectionViewTextCell.h in Headers */,
+				46CB2D9B298AA3F30C5D42BC04F39E94 /* MDCDialogPresentationController.h in Headers */,
+				F428458129C3701B14F25859C60F6C4A /* MDCDialogShadowedView.h in Headers */,
+				FD7FA96389A0CB49A6673EFF467DDAA3 /* MDCDialogTransitionController.h in Headers */,
+				A5847C5D55280D73543922B562E3EE76 /* MDCFeatureHighlightAnimationController.h in Headers */,
+				7F86C31F4F88FAD41263B8386772014A /* MDCFeatureHighlightLayer.h in Headers */,
+				ADB5ECE6B1779BB7CCB7C3468BADC052 /* MDCFeatureHighlightView.h in Headers */,
+				EBB65F826BFB14DC485D1126FA924591 /* MDCFeatureHighlightViewController.h in Headers */,
+				AF01D47F2E21218233A1FF787C75EBE2 /* MDCFlatButton.h in Headers */,
+				0B0FE5E1667FA17C1026EF1F92C1A63F /* MDCFlexibleHeaderContainerViewController.h in Headers */,
+				25160F444E7DF39397B6D6AFC4F07141 /* MDCFlexibleHeaderView.h in Headers */,
+				FCC2DBDF248F8D1B0759647AA9AADBC2 /* MDCFlexibleHeaderViewController.h in Headers */,
+				DEEF35853A0974C2FBE1D5F0DD7AE0BC /* MDCFloatingButton.h in Headers */,
+				F43265AC32261E3688370C90941A1C51 /* MDCFontTextStyle.h in Headers */,
+				67ED336DA6AA8B8497F1539842808631 /* MDCFontTraits.h in Headers */,
+				B6617FDF0F00EEA0091D859D88DDFD44 /* MDCHeaderStackView.h in Headers */,
+				610644D23738415ACB073C8B072244BB /* MDCIcons+BundleLoader.h in Headers */,
+				F5A806B7DF97350385E8C0AF48172DB2 /* MDCIcons.h in Headers */,
+				E88C4953B207850482CE8CAF646EB7F6 /* MDCInkGestureRecognizer.h in Headers */,
+				91A653669E3851452FCFCA0E2A7CB837 /* MDCInkLayer.h in Headers */,
+				6FBA9C40C2CC499C9E549022E8CC48A9 /* MDCInkTouchController.h in Headers */,
+				373D05814A0C88B4A0635C5A79FF822B /* MDCInkView.h in Headers */,
+				5CEE44CB5B97F207D902E967A7A28542 /* MDCItemBar.h in Headers */,
+				28D9B87B12B0ADC9D2B6D6A0DCADC59A /* MDCItemBarAlignment.h in Headers */,
+				FFCED3ABEBE505D648ECFB89C3B5A1DE /* MDCItemBarCell.h in Headers */,
+				274573598F1BA1A5256CA32D7689462A /* MDCItemBarStringConstants.h in Headers */,
+				88D4D6C491D0BB280CD6B6D01BDE39B9 /* MDCItemBarStyle.h in Headers */,
+				BCFF786BA8B6010F68220F150D77BC30 /* MDCKeyboardWatcher.h in Headers */,
+				F8E7DFFB95518F5BE25C98ACA633E003 /* MDCNavigationBar.h in Headers */,
+				BB463EFA3C52D5DDFFDAB937345C932F /* MDCNumericValueLabel.h in Headers */,
+				520EC00A1A0B6B3827DA1F4A7E655C0A /* MDCOverlayAnimationObserver.h in Headers */,
+				E9FEACB48E266BE82E3F563E89A57E55 /* MDCOverlayImplementor.h in Headers */,
+				624BA0196EC0BA2C9AAE7D4DE3AB068A /* MDCOverlayObserver.h in Headers */,
+				140D1BAA0F86861FA7A3A788F41C2DAC /* MDCOverlayObserverOverlay.h in Headers */,
+				81BAF4596ECCF3B2090CCEB24E981C7E /* MDCOverlayObserverTransition.h in Headers */,
+				7B1EB360F18CCF386C0AC46F154F0C9B /* MDCOverlayTransitioning.h in Headers */,
+				DACA2B285CD4608DBB73D72910DDCC3B /* MDCOverlayUtilities.h in Headers */,
+				218A5004AD1E67EDB82023BF74D6E81D /* MDCOverlayWindow.h in Headers */,
+				A2EE82AB4435B7F2278B816E9928C1AA /* MDCPageControl.h in Headers */,
+				5E944DEC856408844CB086300051AD03 /* MDCPageControlIndicator.h in Headers */,
+				F89C9B4B75A51557C4194C373983E7DD /* MDCPageControlTrackLayer.h in Headers */,
+				0E3515A7AE66C29F70F654BA2B8EA7BA /* MDCPaletteExpansions.h in Headers */,
+				4AC16280803615380CABD4379AA69D65 /* MDCPaletteNames.h in Headers */,
+				F2AF846BCE456A75743C8A76EFE8AC36 /* MDCPalettes.h in Headers */,
+				29508FF7916F5B95D6F4F940601AC975 /* MDCProgressView.h in Headers */,
+				866CA83566ACE3526AA5FABAB6E08CED /* MDCRaisedButton.h in Headers */,
+				FDBD2F6421CA1221915E3E4DE3B98C57 /* MDCRTL.h in Headers */,
+				AA10E060FCF509E24CEAEE87D2E80949 /* MDCShadowElevations.h in Headers */,
+				957F0F86EAB556C7CD058DF04A23F216 /* MDCShadowLayer.h in Headers */,
+				63793D388D09869517A2472AE9C612B3 /* MDCSlider.h in Headers */,
+				8334A8C5BB14AB374900D9A579A65096 /* MDCSlider_Subclassable.h in Headers */,
+				40FECE7BF976712334BCAD110F2E2051 /* MDCSnackbarManager.h in Headers */,
+				D846A62610497F25E2B7A537EA12C757 /* MDCSnackbarMessage.h in Headers */,
+				A1799A83EA43D62019EFFEE6D1523F79 /* MDCSnackbarMessageInternal.h in Headers */,
+				95DA110166E184835298E627C35F5B5C /* MDCSnackbarMessageView.h in Headers */,
+				6CE23956E33CA9B2981055C2A5541077 /* MDCSnackbarMessageViewInternal.h in Headers */,
+				293557804A5EBF6C30C51757363B057B /* MDCSnackbarOverlayView.h in Headers */,
+				79B778A18CC8304044870CCF0AF93C92 /* MDCStatusBarShifter.h in Headers */,
+				6E5609D839CCD3390C33DFDEC3502382 /* MDCTabBar.h in Headers */,
+				BF4527E139FB205D0EBD8F54FD8AF18D /* MDCTabBarAlignment.h in Headers */,
+				CC4BC92CDE1AA4B8613AB884E75FB2E4 /* MDCTabBarItemAppearance.h in Headers */,
+				DBCD145300C030FCA8C9F1D8C624216B /* MDCThumbTrack.h in Headers */,
+				2EB0AB22EC4D7AB16E9074A5013DD61C /* MDCThumbView.h in Headers */,
+				E5CA64F5137CB5A48B42C9BB8F8EE127 /* MDCTypography.h in Headers */,
+				B31AC47ADCCE328A838CCDFB76642B4D /* UIApplication+AppExtensions.h in Headers */,
+				97EE80E12A66CFDC2291192A6D690DA1 /* UIFont+MaterialTypography.h in Headers */,
+				B22A6ACFF10775AFE5312ADF4FB00ECC /* UIFont+MaterialTypographyPrivate.h in Headers */,
+				86CCCDEFFA251A9AB150EDB92E0BDCE4 /* UIFontDescriptor+MaterialTypography.h in Headers */,
+				7FAA92CCF3CE42E4265CD84238775669 /* UIImage+MaterialRTL.h in Headers */,
+				76FB19E59FB284927075877B825A67A6 /* UIView+MaterialRTL.h in Headers */,
+				9F337AC8E4B3FD0244949450C9FA822B /* UIView+MDCTimingFunction.h in Headers */,
+				CB68DFA2C9FC1A3435236521B0408CEE /* UIViewController+MaterialDialogs.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+		063B0E6AFAF8DCF585379E4BCB2C7131 /* MaterialComponents-MaterialIcons_ic_chevron_right */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 3F7ABC9117313216EB86A842D3A56458 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_chevron_right" */;
+			buildPhases = (
+				D5CA2F82A40A254095FF9B7C0C6E6ED0 /* Sources */,
+				10CE89D4B6EA0CBA4230B7FA3FE04DE3 /* Frameworks */,
+				EE98E09657FE54D511C889A907255B98 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_chevron_right";
+			productName = "MaterialComponents-MaterialIcons_ic_chevron_right";
+			productReference = CB370B0CFF7E9F249F9A4A4A5C9828C0 /* MaterialIcons_ic_chevron_right.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		16E29731A9C9770DCC25F5A8A3ED71FA /* MaterialComponents-MaterialIcons_ic_info */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = A4FFB75C138E4CDA3F5386C74BF54FB1 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_info" */;
+			buildPhases = (
+				C3553527CE24E57E85CC0B99B45CBB69 /* Sources */,
+				142596A1D8F1283799C634488452D605 /* Frameworks */,
+				839CBB62A84B07725AEA9935C8274456 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_info";
+			productName = "MaterialComponents-MaterialIcons_ic_info";
+			productReference = DBB2727B89FCF4B81EAB1F748F4EE6F7 /* MaterialIcons_ic_info.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		19634FBF87D1F1FA955FF17A6BB5585E /* MaterialComponents-MaterialIcons_ic_radio_button_unchecked */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 5651E00E66CAF6F1E79453DD35C3FB00 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_radio_button_unchecked" */;
+			buildPhases = (
+				B604D0992F6963FF641E919D03F37519 /* Sources */,
+				68E4BC6B1D0B207D3F9298FC9505A73E /* Frameworks */,
+				876EC345CD610EAAF80C1868DBC537AA /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+			productName = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+			productReference = 9F8BE2D8847C692FB18FCFEF6F294478 /* MaterialIcons_ic_radio_button_unchecked.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		26C4686B7C9E9E7E4E77A332481D6196 /* MaterialComponents */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 7B14FE9889C0D696F704111E1F0E9C6F /* Build configuration list for PBXNativeTarget "MaterialComponents" */;
+			buildPhases = (
+				825931AD29BDE0F7AF200E156A2C33EA /* Sources */,
+				AA767584440C8D2E1C217BA896C2796A /* Frameworks */,
+				BD0D3F935DD310043B1C382E24090D3C /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				32F900408371178EB800134DE248AAA8 /* PBXTargetDependency */,
+				632625506E7B6EC59E5961BBEA8854DA /* PBXTargetDependency */,
+				898FE7AC319E3ED34052F71E9D0BE37D /* PBXTargetDependency */,
+				8D9AC5C7FEE2D6B171694687487F3701 /* PBXTargetDependency */,
+				3CE4BDD049C05CBBB86987FA04F5D8E7 /* PBXTargetDependency */,
+				2A0C3ADA41D941D838232940BDE2076B /* PBXTargetDependency */,
+				A2732BABC5F45114656C696C61B9E7C1 /* PBXTargetDependency */,
+				5FCFFDFE6ED996AD11CC566808C07447 /* PBXTargetDependency */,
+			);
+			name = MaterialComponents;
+			productName = MaterialComponents;
+			productReference = 09A539046C55C092B1882F2B3101A656 /* libMaterialComponents.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 524F6DEAF1626D3D3F38300C46E2E942 /* Build configuration list for PBXNativeTarget "MDFTextAccessibility" */;
+			buildPhases = (
+				7F4D7723BB12E0EC91AEBC6B23CC8CD5 /* Sources */,
+				0490164F31DF4DFD21CB5B6C0C9C2828 /* Frameworks */,
+				1BF21BF58E4EBE29C297FBEF774B04F0 /* Headers */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = MDFTextAccessibility;
+			productName = MDFTextAccessibility;
+			productReference = B6D338FD921EC51C550567AB2D429021 /* libMDFTextAccessibility.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		827B847BE0C5521773C58E7A599CAD8D /* MaterialComponents-MaterialIcons_ic_arrow_back */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CC7BE8C55AE7F464F23B6EBDA2A73DA8 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_arrow_back" */;
+			buildPhases = (
+				EA618F0B994D2DD0B72131F1055443A0 /* Sources */,
+				7B63882D2EA962158694D9F4255CD668 /* Frameworks */,
+				7EDA433322A6D744439989E189CC6023 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_arrow_back";
+			productName = "MaterialComponents-MaterialIcons_ic_arrow_back";
+			productReference = FF9E5D282080B168147A56CBC1A20CB3 /* MaterialIcons_ic_arrow_back.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		AFFA60B0A14082D99BC69B83E990917F /* MaterialComponents-MaterialIcons_ic_reorder */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 892D4ECEBD307A77824E601B91911F7E /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_reorder" */;
+			buildPhases = (
+				33704B71CC0F5E694015731B788D1ED9 /* Sources */,
+				AFFB6859E3D5DB059AA62780279F1BFA /* Frameworks */,
+				F00F50DDE4719D170DB52573A8F0C4F1 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_reorder";
+			productName = "MaterialComponents-MaterialIcons_ic_reorder";
+			productReference = D43D8FF7991737DB826BFF92EBF8ADFA /* MaterialIcons_ic_reorder.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		C2EC108B302373D03D5F0A9EB5B55787 /* MaterialComponents-MaterialIcons_ic_check_circle */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = EAC712836DA82097060BEA2911374AE6 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check_circle" */;
+			buildPhases = (
+				E7B5F4908CD3AA75538A82DF89CF8899 /* Sources */,
+				05A8C2288619671B1A30A7EF4C739D71 /* Frameworks */,
+				1F0BEAADFE445C4F493876E5175E917F /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_check_circle";
+			productName = "MaterialComponents-MaterialIcons_ic_check_circle";
+			productReference = 430CFFC6D36F60111CDF22059398251D /* MaterialIcons_ic_check_circle.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+		CC81BAB345F2D13D67703EDBFE5DFEFE /* Pods-BuildingBeautifulApps */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = C644C7353E6F78383A06A7910789EF03 /* Build configuration list for PBXNativeTarget "Pods-BuildingBeautifulApps" */;
+			buildPhases = (
+				A71B5F92A81592C0CDCFA1B721CDD4BD /* Sources */,
+				120E9482EC24B536DE2A5345E8B71E40 /* Frameworks */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				314C50DFC3461E84B3EA7B21D6AF6986 /* PBXTargetDependency */,
+				B18A9A072ED45E647C7FD129E60E231F /* PBXTargetDependency */,
+			);
+			name = "Pods-BuildingBeautifulApps";
+			productName = "Pods-BuildingBeautifulApps";
+			productReference = 6B9A7110EE95FE54D52AC78F8943FF30 /* libPods-BuildingBeautifulApps.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+		EEA5B88E1ACE47BDFFC5FD0BBAA2A28C /* MaterialComponents-MaterialIcons_ic_check */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = EC5DC1C972130F562B5702C94306D164 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check" */;
+			buildPhases = (
+				0FF20C6B6E2BE811475F118AE5F72055 /* Sources */,
+				59F35B6B50BC5A7D99059FEC9B83AFB9 /* Frameworks */,
+				02106D26B2898B8D12579C4037186994 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = "MaterialComponents-MaterialIcons_ic_check";
+			productName = "MaterialComponents-MaterialIcons_ic_check";
+			productReference = 860E1A6AE14CC46812BFD2EECD3DF1B6 /* MaterialIcons_ic_check.bundle */;
+			productType = "com.apple.product-type.bundle";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		D41D8CD98F00B204E9800998ECF8427E /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastSwiftUpdateCheck = 0830;
+				LastUpgradeCheck = 0700;
+			};
+			buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 7DB346D0F39D3F0E887471402A8071AB;
+			productRefGroup = 766E4937EA799D9EC8B3869F8CEF6B5D /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				26C4686B7C9E9E7E4E77A332481D6196 /* MaterialComponents */,
+				827B847BE0C5521773C58E7A599CAD8D /* MaterialComponents-MaterialIcons_ic_arrow_back */,
+				EEA5B88E1ACE47BDFFC5FD0BBAA2A28C /* MaterialComponents-MaterialIcons_ic_check */,
+				C2EC108B302373D03D5F0A9EB5B55787 /* MaterialComponents-MaterialIcons_ic_check_circle */,
+				063B0E6AFAF8DCF585379E4BCB2C7131 /* MaterialComponents-MaterialIcons_ic_chevron_right */,
+				16E29731A9C9770DCC25F5A8A3ED71FA /* MaterialComponents-MaterialIcons_ic_info */,
+				19634FBF87D1F1FA955FF17A6BB5585E /* MaterialComponents-MaterialIcons_ic_radio_button_unchecked */,
+				AFFA60B0A14082D99BC69B83E990917F /* MaterialComponents-MaterialIcons_ic_reorder */,
+				2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */,
+				CC81BAB345F2D13D67703EDBFE5DFEFE /* Pods-BuildingBeautifulApps */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		02106D26B2898B8D12579C4037186994 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				64BD87D6A0EE900D83D40B3A793CB98B /* ic_check.png in Resources */,
+				4C9D6933282639AAEDFCE3760D663370 /* ic_check@2x.png in Resources */,
+				DC2B567C06EA75C2EF988EE491DB370A /* ic_check@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		1F0BEAADFE445C4F493876E5175E917F /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D72106583CB3A2A6B758B48F27882B40 /* ic_check_circle.png in Resources */,
+				FB207298B52DA12C580DA33D926A33CE /* ic_check_circle@2x.png in Resources */,
+				2DE4DA16A223502BDAE19CB16707EA25 /* ic_check_circle@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7EDA433322A6D744439989E189CC6023 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				ABEC063A0D41BC10143B8DACF1B82237 /* ic_arrow_back.png in Resources */,
+				EA9BE12F0B4EC342AE180CDEAC34F8D3 /* ic_arrow_back@2x.png in Resources */,
+				DDD7A57F4148DC9FCC8DB0DAF6866E10 /* ic_arrow_back@3x.png in Resources */,
+				4211DA431C07D51F55AB2D9000F745DB /* ic_arrow_back_ios.png in Resources */,
+				2AA0B61EABF1D62E39ABB6309B1E93CB /* ic_arrow_back_ios@2x.png in Resources */,
+				4CBD21241E82CCBA918B0E72FF122FF7 /* ic_arrow_back_ios@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		839CBB62A84B07725AEA9935C8274456 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				24900323EF8B3538F240F4824D3BC843 /* ic_info.png in Resources */,
+				45002548D32FF2E02C25B5EA30BBCA89 /* ic_info@2x.png in Resources */,
+				A1F9E6ACAA85B87A9D8A087F80530FAF /* ic_info@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		876EC345CD610EAAF80C1868DBC537AA /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				59F2E39B0B51CF3480C2FE2A1B3B0CBA /* ic_radio_button_unchecked.png in Resources */,
+				73D4A36BAE65B225B1CBC5EE9A9A802A /* ic_radio_button_unchecked@2x.png in Resources */,
+				091A8578BC600F0579CD4CB9A119DCD8 /* ic_radio_button_unchecked@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EE98E09657FE54D511C889A907255B98 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				54AC6E6DC67C3C418A85ED4983EC39D5 /* ic_chevron_right.png in Resources */,
+				978CE8B98451722A7BCB5F8ECF12F4D5 /* ic_chevron_right@2x.png in Resources */,
+				3C9EA68F25AD2F27CE9EA4F444C56FA6 /* ic_chevron_right@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		F00F50DDE4719D170DB52573A8F0C4F1 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				93CA3734266496A1F281BDB7565FA671 /* ic_reorder.png in Resources */,
+				CB57A2838CE91AA87493A967057A9F50 /* ic_reorder@2x.png in Resources */,
+				051B40934BCB60C81579E65ED35CD7A0 /* ic_reorder@3x.png in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		0FF20C6B6E2BE811475F118AE5F72055 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		33704B71CC0F5E694015731B788D1ED9 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		7F4D7723BB12E0EC91AEBC6B23CC8CD5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				A6B49525465146B18DECD9B24AD878DE /* MDFColorCalculations.m in Sources */,
+				AB8705EA210EDB911167D97874D360FB /* MDFImageCalculations.m in Sources */,
+				C77D1E2CEA9AC648CCAE66DD64A12E57 /* MDFTextAccessibility-dummy.m in Sources */,
+				6C84F71A1D807C4CB432B7B933F4FF6F /* MDFTextAccessibility.m in Sources */,
+				A5CE5EE5A0CB5AC74A082871D0E4D0E2 /* NSArray+MDFUtils.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		825931AD29BDE0F7AF200E156A2C33EA /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				63188636F2C3E07CE98221656B929588 /* CAMediaTimingFunction+MDCAnimationTiming.m in Sources */,
+				F7A7869F8EB0BB5B4F817AE17001B79A /* MaterialComponents-dummy.m in Sources */,
+				0EBDEC7917FC21DD3AD7979621EA2307 /* MaterialIcons+ic_arrow_back.m in Sources */,
+				E16F8810A88826A00D8AEFEA8382FCE0 /* MaterialIcons+ic_check.m in Sources */,
+				7F7F0348C4102A49883CD88C86E122CF /* MaterialIcons+ic_check_circle.m in Sources */,
+				3D2B20D0F1D2DF6518A6E97129778190 /* MaterialIcons+ic_chevron_right.m in Sources */,
+				203C4032B594FAEFC8C97B3AFB740B1D /* MaterialIcons+ic_info.m in Sources */,
+				14612015079E6E117DED63E2337F4346 /* MaterialIcons+ic_radio_button_unchecked.m in Sources */,
+				D143DDFD972B30645F3278852EE20F5B /* MaterialIcons+ic_reorder.m in Sources */,
+				6FE4364F0DE10004ECF20D68071F4739 /* MDCActivityIndicator.m in Sources */,
+				65E9B44BBB842E8838653E605F87B3CD /* MDCAlertController.m in Sources */,
+				677A054DB9F431CF6C98E570A8223F50 /* MDCAppBar.m in Sources */,
+				E21FBFA76EC56E1D06EB0CD35550A7F8 /* MDCAppBarButtonBarBuilder.m in Sources */,
+				9847503FD320C722569D661E21EB0B11 /* MDCAppBarContainerViewController.m in Sources */,
+				02B3889D3E871468F88E5DBE7E9C5E21 /* MDCButton.m in Sources */,
+				983CC3205216C917F8A2D94E439959F7 /* MDCButtonBar.m in Sources */,
+				5A23C9982240753826D25F3648BE3915 /* MDCCollectionGridBackgroundView.m in Sources */,
+				601F6E1396EAC24AD0DF4FC09872F769 /* MDCCollectionInfoBarView.m in Sources */,
+				75701D93C9E6E0E16551378FB6D15322 /* MDCCollectionStringResources.m in Sources */,
+				FAEBD8461B68C2706F8A208E3E596643 /* MDCCollectionViewCell.m in Sources */,
+				BD37D976E99C4BF895220E803F0CC41D /* MDCCollectionViewController.m in Sources */,
+				91EB3409BF51AE8448EC825B00CA7EC8 /* MDCCollectionViewEditor.m in Sources */,
+				2AB6A1D688CF1EA0FA6345D547CF931D /* MDCCollectionViewFlowLayout.m in Sources */,
+				C415FCA0E080D6BDAF30C011F5476604 /* MDCCollectionViewLayoutAttributes.m in Sources */,
+				53BB396FE274D0FB6F22F98138F0A130 /* MDCCollectionViewStyler.m in Sources */,
+				1B25CFC33E70C55ADB21117C2E0BC425 /* MDCCollectionViewTextCell.m in Sources */,
+				98FFEDEEDB14192496FB90B75B9CFFB3 /* MDCDialogPresentationController.m in Sources */,
+				3998D3B0FBE92AB251C8FE66F7214BF9 /* MDCDialogShadowedView.m in Sources */,
+				ED5BBB6CB14C9E62E7C62DCDD69C727E /* MDCDialogTransitionController.m in Sources */,
+				856224A034BF7897D5745C017D6E26BF /* MDCFeatureHighlightAnimationController.m in Sources */,
+				71FF2344ED69DD4EC1BD52B6334C79EE /* MDCFeatureHighlightLayer.m in Sources */,
+				701A7F5C929096A5A4AAD770AA8CC8A1 /* MDCFeatureHighlightView.m in Sources */,
+				E122D135F905A61F2F2BC12B5E752E8B /* MDCFeatureHighlightViewController.m in Sources */,
+				5EBEA9BE9A76AE4BA005EF74784B9739 /* MDCFlatButton.m in Sources */,
+				8B9D3A9491A4C5894D9BDB45F75C72EE /* MDCFlexibleHeaderContainerViewController.m in Sources */,
+				C1B17B6540AD304C1A39E0A37E19AE2C /* MDCFlexibleHeaderView.m in Sources */,
+				BF9A53B148F71E2405838165261131E7 /* MDCFlexibleHeaderViewController.m in Sources */,
+				68E150F63885364AA7143698177876C6 /* MDCFloatingButton.m in Sources */,
+				86ABC77AAAF3BB0E73978E7FD7B371AD /* MDCFontTraits.m in Sources */,
+				4A9EFA8C13DFEB3A8EF9E7AB8802A3D1 /* MDCHeaderStackView.m in Sources */,
+				05E5A4ADDD5472838AAB9FFF46AF2137 /* MDCIcons.m in Sources */,
+				B20E8D99109D62C4F51394FBE9CB4346 /* MDCInkGestureRecognizer.m in Sources */,
+				E09CE6C566DADA7AB46361EF95F0D4A2 /* MDCInkLayer.m in Sources */,
+				9CEE28601C484B8E43252D783AFF7A05 /* MDCInkTouchController.m in Sources */,
+				C1C7F298EA4326DF2C05351A740E1D8F /* MDCInkView.m in Sources */,
+				7673B57A3EAC6E8169C83EA5F68B70E4 /* MDCItemBar.m in Sources */,
+				74F5757E7D5A465C730D2AA937BE785C /* MDCItemBarCell.m in Sources */,
+				723E8EEE2D1B59FC03F6158CCF391D2C /* MDCItemBarStyle.m in Sources */,
+				5C146662CCCE2C78543F8A049B696E66 /* MDCKeyboardWatcher.m in Sources */,
+				D4D362E714758EDDEC809019CC26974C /* MDCNavigationBar.m in Sources */,
+				C212207098B33F8B829CE94A3706DB49 /* MDCNumericValueLabel.m in Sources */,
+				D3BC8C16993BC06EF08B9A0B91B81568 /* MDCOverlayAnimationObserver.m in Sources */,
+				6BA617C860537C13AE7EA0AF05DF96FA /* MDCOverlayObserver.m in Sources */,
+				704742BFFD1D9BAE18AC34F964C43044 /* MDCOverlayObserverOverlay.m in Sources */,
+				BFCDBAD98869A1F1A6BBEAF75E86F926 /* MDCOverlayObserverTransition.m in Sources */,
+				D2C9BED43BB4C6FA2D23424759A4EB2F /* MDCOverlayUtilities.m in Sources */,
+				34FBD1D58C8BD1C74A876169FB1C15CA /* MDCOverlayWindow.m in Sources */,
+				E4452C88A27E46E154E525C9840E1494 /* MDCPageControl.m in Sources */,
+				07484E38806037944055D0BF76806FA4 /* MDCPageControlIndicator.m in Sources */,
+				DF0C93BD3E28121899DB290E32612D14 /* MDCPageControlTrackLayer.m in Sources */,
+				195B84DD18A2352DA5EDEC2F347F0985 /* MDCPaletteExpansions.m in Sources */,
+				5180979CE3EEB34F06466107253D6BB1 /* MDCPaletteNames.m in Sources */,
+				7BC8DF38C236F0C73D8CB5F4D9E8DBAA /* MDCPalettes.m in Sources */,
+				0CD124B11142B650BF877996F9F0E07A /* MDCProgressView.m in Sources */,
+				C3A59E6F295659D872D65BFEB6832A34 /* MDCRaisedButton.m in Sources */,
+				2A316D54A91DA5CD37F5231CC2E36978 /* MDCRTL.m in Sources */,
+				10B1D8ED7E2CF740C124B7C74CDBB74E /* MDCShadowElevations.m in Sources */,
+				A53D190E021C5C1186AC498313F5366A /* MDCShadowLayer.m in Sources */,
+				AA6B9D4E09B8642FE07CA11093EFB762 /* MDCSlider.m in Sources */,
+				586B689107644E8DFF068DC9A1E927D6 /* MDCSnackbarManager.m in Sources */,
+				73A9FEFF284BE8244A83EE3E68694904 /* MDCSnackbarMessage.m in Sources */,
+				58FB26F7D268DF6E49DE32787ECF53B3 /* MDCSnackbarMessageView.m in Sources */,
+				87A2628E58EECA44CEDADB67AE99D7F7 /* MDCSnackbarOverlayView.m in Sources */,
+				BE43B4DB418BFA444DEE432B7F329C9C /* MDCStatusBarShifter.m in Sources */,
+				FF82D045067B9F2BE69E2C5772EEBAFE /* MDCTabBar.m in Sources */,
+				299DD5695C130C8315A9E5FA786ECEAB /* MDCThumbTrack.m in Sources */,
+				7A5C50000FFBA08EB5AEB031CB02508A /* MDCThumbView.m in Sources */,
+				8A714C7A8F488D84D189041AB5EA984F /* MDCTypography.m in Sources */,
+				A2CEADFD01F6E59D4D792EFC35289A97 /* UIApplication+AppExtensions.m in Sources */,
+				B818D6AEBD75B9F9CDC04357F55DF6EF /* UIFont+MaterialTypography.m in Sources */,
+				69EA046EE6873743400E09466C970A14 /* UIFont+MaterialTypographyPrivate.m in Sources */,
+				D6BE450D35006B7F2F83EB19CDC1B473 /* UIFontDescriptor+MaterialTypography.m in Sources */,
+				75CFCE1AB0C85EEC8F68A664771A0847 /* UIImage+MaterialRTL.m in Sources */,
+				AB01C09668E3D82190EAE5DC10E07CAA /* UIView+MaterialRTL.m in Sources */,
+				05FF239C8670278A10D7BD58DD5260E1 /* UIView+MDCTimingFunction.m in Sources */,
+				14D517DDB1CB758C5FAA1B5963590CDF /* UIViewController+MaterialDialogs.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		A71B5F92A81592C0CDCFA1B721CDD4BD /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				5C20F66911408C3E193E604D21F47677 /* Pods-BuildingBeautifulApps-dummy.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		B604D0992F6963FF641E919D03F37519 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		C3553527CE24E57E85CC0B99B45CBB69 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		D5CA2F82A40A254095FF9B7C0C6E6ED0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		E7B5F4908CD3AA75538A82DF89CF8899 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		EA618F0B994D2DD0B72131F1055443A0 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+		2A0C3ADA41D941D838232940BDE2076B /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_info";
+			target = 16E29731A9C9770DCC25F5A8A3ED71FA /* MaterialComponents-MaterialIcons_ic_info */;
+			targetProxy = 77F3D96E9E9ED94700A1F61B82743FBE /* PBXContainerItemProxy */;
+		};
+		314C50DFC3461E84B3EA7B21D6AF6986 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MDFTextAccessibility;
+			target = 2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */;
+			targetProxy = 17BCA1B89A11CC355E43FD3BFCD13C12 /* PBXContainerItemProxy */;
+		};
+		32F900408371178EB800134DE248AAA8 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MDFTextAccessibility;
+			target = 2E72C96C2685FC808D51BA6B9AA64CF4 /* MDFTextAccessibility */;
+			targetProxy = F34B40D121BBEE584389E4FD1349C927 /* PBXContainerItemProxy */;
+		};
+		3CE4BDD049C05CBBB86987FA04F5D8E7 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_chevron_right";
+			target = 063B0E6AFAF8DCF585379E4BCB2C7131 /* MaterialComponents-MaterialIcons_ic_chevron_right */;
+			targetProxy = 26A37A36E1641BBB8CE2EDDFC8616CCD /* PBXContainerItemProxy */;
+		};
+		5FCFFDFE6ED996AD11CC566808C07447 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_reorder";
+			target = AFFA60B0A14082D99BC69B83E990917F /* MaterialComponents-MaterialIcons_ic_reorder */;
+			targetProxy = 39EA7F91F3A8B4BBE7EDA6E436B1836F /* PBXContainerItemProxy */;
+		};
+		632625506E7B6EC59E5961BBEA8854DA /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_arrow_back";
+			target = 827B847BE0C5521773C58E7A599CAD8D /* MaterialComponents-MaterialIcons_ic_arrow_back */;
+			targetProxy = 79BDE4F2A4F44762925D8ABCC802FDBA /* PBXContainerItemProxy */;
+		};
+		898FE7AC319E3ED34052F71E9D0BE37D /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_check";
+			target = EEA5B88E1ACE47BDFFC5FD0BBAA2A28C /* MaterialComponents-MaterialIcons_ic_check */;
+			targetProxy = 07B01A307DE976243C53CDA94B27C112 /* PBXContainerItemProxy */;
+		};
+		8D9AC5C7FEE2D6B171694687487F3701 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_check_circle";
+			target = C2EC108B302373D03D5F0A9EB5B55787 /* MaterialComponents-MaterialIcons_ic_check_circle */;
+			targetProxy = B92E0F607A56686D7F93C4B7757E85F5 /* PBXContainerItemProxy */;
+		};
+		A2732BABC5F45114656C696C61B9E7C1 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = "MaterialComponents-MaterialIcons_ic_radio_button_unchecked";
+			target = 19634FBF87D1F1FA955FF17A6BB5585E /* MaterialComponents-MaterialIcons_ic_radio_button_unchecked */;
+			targetProxy = 8B33909233E6BAB3ED98C8FEB26CD2E6 /* PBXContainerItemProxy */;
+		};
+		B18A9A072ED45E647C7FD129E60E231F /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			name = MaterialComponents;
+			target = 26C4686B7C9E9E7E4E77A332481D6196 /* MaterialComponents */;
+			targetProxy = 94AE73493B374CDBE138E1C8D3A177CB /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+		26A41178C802A87FA1AD4A3956B6AE95 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 120CFBE565880C2F4F462AAFCEBB37E5 /* Pods-BuildingBeautifulApps.release.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				MACH_O_TYPE = staticlib;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PODS_ROOT = "$(SRCROOT)";
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		287CBD65CDB3E73D2A9EA687E99A5751 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		2A7F72C933E47CDA496240F2DB012CCC /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_arrow_back;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		2E3057527561F89CCF7C36156EA42661 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_info;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		31EACB913B5F8E3A5C01AFA41C7D6289 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		42F4DA7BA113F8850E6E6467FECD7C52 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_radio_button_unchecked;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		4E292B5527D60C961400A6DAD7DC288B /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_arrow_back;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		4E487F173E6C9664F4E9E26B9635D23C /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				COPY_PHASE_STRIP = NO;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"POD_CONFIGURATION_DEBUG=1",
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				ONLY_ACTIVE_ARCH = YES;
+				PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
+				STRIP_INSTALLED_PRODUCT = NO;
+				SYMROOT = "${SRCROOT}/../build";
+			};
+			name = Debug;
+		};
+		5DC26BFB28032F299B56B7044BC93363 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_reorder;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		65F909AC31A48502DA9CDC7270A6D92F /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_info;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		6C32666A141D43FD834C6383A3836F88 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MaterialComponents/MaterialComponents-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
+		6F0457C9499D58F5CAA67923DCDB19F1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_reorder;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		78467EE81EF50258F8C619B09A659B4F /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check_circle;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		82B23D2232C7A01F1938A674A4665348 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_chevron_right;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		9BBC2037B7A2FA8F55E4C50B43624CC9 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = A1BC19DD22FF7E7E9C57669DF5BB9ACA /* MDFTextAccessibility.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		9C5B0D020E4C763E746EE2589F8D88DD /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 02AE1C5FFC5FC596ABEC7C98AEF62DD8 /* Pods-BuildingBeautifulApps.debug.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				MACH_O_TYPE = staticlib;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PODS_ROOT = "$(SRCROOT)";
+				PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		AE5C6E7CD6F75A92598D888038A66873 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check_circle;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		BDD0139D6EB93FA375F887ABD62DAB2E /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				CODE_SIGNING_REQUIRED = NO;
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"POD_CONFIGURATION_RELEASE=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
+				STRIP_INSTALLED_PRODUCT = NO;
+				SYMROOT = "${SRCROOT}/../build";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		E490E9C2F965850E4BA4D30EC78FB5F8 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_chevron_right;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+		EE8AED0DB82801B10AD5298ABA16D730 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
+				"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_PREFIX_HEADER = "Target Support Files/MaterialComponents/MaterialComponents-prefix.pch";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				MTL_ENABLE_DEBUG_INFO = YES;
+				OTHER_LDFLAGS = "";
+				OTHER_LIBTOOLFLAGS = "";
+				PRIVATE_HEADERS_FOLDER_PATH = "";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PUBLIC_HEADERS_FOLDER_PATH = "";
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		F6EF1039304C9649537A65ED79C81CC1 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_radio_button_unchecked;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Debug;
+		};
+		F82ACD5AEAD83427020470C7DA4A22E1 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = EEBAE91FD6B267E7B75551CAF125F273 /* MaterialComponents.xcconfig */;
+			buildSettings = {
+				CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MaterialComponents";
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_NO_COMMON_BLOCKS = YES;
+				INFOPLIST_FILE = "Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_NAME = MaterialIcons_ic_check;
+				SDKROOT = iphoneos;
+				SKIP_INSTALL = YES;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = bundle;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				4E487F173E6C9664F4E9E26B9635D23C /* Debug */,
+				BDD0139D6EB93FA375F887ABD62DAB2E /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		3F7ABC9117313216EB86A842D3A56458 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_chevron_right" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				82B23D2232C7A01F1938A674A4665348 /* Debug */,
+				E490E9C2F965850E4BA4D30EC78FB5F8 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		524F6DEAF1626D3D3F38300C46E2E942 /* Build configuration list for PBXNativeTarget "MDFTextAccessibility" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9BBC2037B7A2FA8F55E4C50B43624CC9 /* Debug */,
+				287CBD65CDB3E73D2A9EA687E99A5751 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		5651E00E66CAF6F1E79453DD35C3FB00 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_radio_button_unchecked" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				F6EF1039304C9649537A65ED79C81CC1 /* Debug */,
+				42F4DA7BA113F8850E6E6467FECD7C52 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7B14FE9889C0D696F704111E1F0E9C6F /* Build configuration list for PBXNativeTarget "MaterialComponents" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				EE8AED0DB82801B10AD5298ABA16D730 /* Debug */,
+				6C32666A141D43FD834C6383A3836F88 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		892D4ECEBD307A77824E601B91911F7E /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_reorder" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				5DC26BFB28032F299B56B7044BC93363 /* Debug */,
+				6F0457C9499D58F5CAA67923DCDB19F1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		A4FFB75C138E4CDA3F5386C74BF54FB1 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_info" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				65F909AC31A48502DA9CDC7270A6D92F /* Debug */,
+				2E3057527561F89CCF7C36156EA42661 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		C644C7353E6F78383A06A7910789EF03 /* Build configuration list for PBXNativeTarget "Pods-BuildingBeautifulApps" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				9C5B0D020E4C763E746EE2589F8D88DD /* Debug */,
+				26A41178C802A87FA1AD4A3956B6AE95 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		CC7BE8C55AE7F464F23B6EBDA2A73DA8 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_arrow_back" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2A7F72C933E47CDA496240F2DB012CCC /* Debug */,
+				4E292B5527D60C961400A6DAD7DC288B /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		EAC712836DA82097060BEA2911374AE6 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check_circle" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				AE5C6E7CD6F75A92598D888038A66873 /* Debug */,
+				78467EE81EF50258F8C619B09A659B4F /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		EC5DC1C972130F562B5702C94306D164 /* Build configuration list for PBXNativeTarget "MaterialComponents-MaterialIcons_ic_check" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				31EACB913B5F8E3A5C01AFA41C7D6289 /* Debug */,
+				F82ACD5AEAD83427020470C7DA4A22E1 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */;
+}
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MDFTextAccessibility.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MDFTextAccessibility.xcscheme
new file mode 100644
index 0000000..18c0c00
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MDFTextAccessibility.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '2E72C96C2685FC808D51BA6B9AA64CF4'
+               BlueprintName = 'MDFTextAccessibility'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'libMDFTextAccessibility.a'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme
new file mode 100644
index 0000000..01458fc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '827B847BE0C5521773C58E7A599CAD8D'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_arrow_back'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_arrow_back.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check.xcscheme
new file mode 100644
index 0000000..fd44e2a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'EEA5B88E1ACE47BDFFC5FD0BBAA2A28C'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_check'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_check.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check_circle.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check_circle.xcscheme
new file mode 100644
index 0000000..99be795
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_check_circle.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'C2EC108B302373D03D5F0A9EB5B55787'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_check_circle'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_check_circle.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme
new file mode 100644
index 0000000..dcc3b83
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '063B0E6AFAF8DCF585379E4BCB2C7131'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_chevron_right'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_chevron_right.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_info.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_info.xcscheme
new file mode 100644
index 0000000..0ad6725
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_info.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '16E29731A9C9770DCC25F5A8A3ED71FA'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_info'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_info.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme
new file mode 100644
index 0000000..95e4dcc
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '19634FBF87D1F1FA955FF17A6BB5585E'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_radio_button_unchecked'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_radio_button_unchecked.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_reorder.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_reorder.xcscheme
new file mode 100644
index 0000000..dda74d1
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents-MaterialIcons_ic_reorder.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'AFFA60B0A14082D99BC69B83E990917F'
+               BlueprintName = 'MaterialComponents-MaterialIcons_ic_reorder'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'MaterialIcons_ic_reorder.bundle'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents.xcscheme
new file mode 100644
index 0000000..fedc528
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/MaterialComponents.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = '26C4686B7C9E9E7E4E77A332481D6196'
+               BlueprintName = 'MaterialComponents'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'libMaterialComponents.a'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/Pods-BuildingBeautifulApps.xcscheme b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/Pods-BuildingBeautifulApps.xcscheme
new file mode 100644
index 0000000..eceb195
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/Pods-BuildingBeautifulApps.xcscheme
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0700"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForAnalyzing = "YES"
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES">
+            <BuildableReference
+               BuildableIdentifier = 'primary'
+               BlueprintIdentifier = 'CC81BAB345F2D13D67703EDBFE5DFEFE'
+               BlueprintName = 'Pods-BuildingBeautifulApps'
+               ReferencedContainer = 'container:Pods.xcodeproj'
+               BuildableName = 'libPods-BuildingBeautifulApps.a'>
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      buildConfiguration = "Debug">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      buildConfiguration = "Debug"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES"
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/xcschememanagement.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..99cc136
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Pods.xcodeproj/xcuserdata/larche.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>SchemeUserState</key>
+	<dict>
+		<key>MDFTextAccessibility.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>8</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_arrow_back.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>1</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_check.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>2</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_check_circle.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>3</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_chevron_right.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>4</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_info.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>5</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_radio_button_unchecked.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>6</integer>
+		</dict>
+		<key>MaterialComponents-MaterialIcons_ic_reorder.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>7</integer>
+		</dict>
+		<key>MaterialComponents.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>0</integer>
+		</dict>
+		<key>Pods-BuildingBeautifulApps.xcscheme</key>
+		<dict>
+			<key>isShown</key>
+			<false/>
+			<key>orderHint</key>
+			<integer>9</integer>
+		</dict>
+	</dict>
+	<key>SuppressBuildableAutocreation</key>
+	<dict>
+		<key>063B0E6AFAF8DCF585379E4BCB2C7131</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>16E29731A9C9770DCC25F5A8A3ED71FA</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>19634FBF87D1F1FA955FF17A6BB5585E</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>26C4686B7C9E9E7E4E77A332481D6196</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>2E72C96C2685FC808D51BA6B9AA64CF4</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>827B847BE0C5521773C58E7A599CAD8D</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>AFFA60B0A14082D99BC69B83E990917F</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>C2EC108B302373D03D5F0A9EB5B55787</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>CC81BAB345F2D13D67703EDBFE5DFEFE</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+		<key>EEA5B88E1ACE47BDFFC5FD0BBAA2A28C</key>
+		<dict>
+			<key>primary</key>
+			<true/>
+		</dict>
+	</dict>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-dummy.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-dummy.m
new file mode 100644
index 0000000..1c4041a
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_MDFTextAccessibility : NSObject
+@end
+@implementation PodsDummy_MDFTextAccessibility
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch
new file mode 100644
index 0000000..beb2a24
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility-prefix.pch
@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility.xcconfig
new file mode 100644
index 0000000..40ebbb7
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MDFTextAccessibility/MDFTextAccessibility.xcconfig
@@ -0,0 +1,9 @@
+CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/MDFTextAccessibility
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents-dummy.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents-dummy.m
new file mode 100644
index 0000000..6ba91fd
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_MaterialComponents : NSObject
+@end
+@implementation PodsDummy_MaterialComponents
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents-prefix.pch b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents-prefix.pch
new file mode 100644
index 0000000..beb2a24
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents-prefix.pch
@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents.xcconfig
new file mode 100644
index 0000000..cf0750c
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/MaterialComponents.xcconfig
@@ -0,0 +1,11 @@
+CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/MaterialComponents
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/MaterialComponents" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility"
+OTHER_LDFLAGS = -framework "CoreGraphics" -framework "QuartzCore"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/MaterialComponents
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_arrow_back-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_check_circle-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_chevron_right-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_info-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_radio_button_unchecked-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist
new file mode 100644
index 0000000..ed97b3b
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/MaterialComponents/ResourceBundle-MaterialIcons_ic_reorder-Info.plist
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>en</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>BNDL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>23.0.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>1</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.markdown b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.markdown
new file mode 100644
index 0000000..488d4d6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.markdown
@@ -0,0 +1,415 @@
+# Acknowledgements
+This application makes use of the following third party libraries:
+
+## MDFTextAccessibility
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+## MaterialComponents
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+Generated by CocoaPods - https://cocoapods.org
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.plist b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.plist
new file mode 100644
index 0000000..3707be8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-acknowledgements.plist
@@ -0,0 +1,453 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>PreferenceSpecifiers</key>
+	<array>
+		<dict>
+			<key>FooterText</key>
+			<string>This application makes use of the following third party libraries:</string>
+			<key>Title</key>
+			<string>Acknowledgements</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+</string>
+			<key>License</key>
+			<string>Apache License, Version 2.0</string>
+			<key>Title</key>
+			<string>MDFTextAccessibility</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+</string>
+			<key>License</key>
+			<string>Apache 2.0</string>
+			<key>Title</key>
+			<string>MaterialComponents</string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+		<dict>
+			<key>FooterText</key>
+			<string>Generated by CocoaPods - https://cocoapods.org</string>
+			<key>Title</key>
+			<string></string>
+			<key>Type</key>
+			<string>PSGroupSpecifier</string>
+		</dict>
+	</array>
+	<key>StringsTable</key>
+	<string>Acknowledgements</string>
+	<key>Title</key>
+	<string>Acknowledgements</string>
+</dict>
+</plist>
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-dummy.m b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-dummy.m
new file mode 100644
index 0000000..7efe4e0
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-dummy.m
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_Pods_BuildingBeautifulApps : NSObject
+@end
+@implementation PodsDummy_Pods_BuildingBeautifulApps
+@end
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh
new file mode 100755
index 0000000..0f29f13
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-frameworks.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+set -e
+
+echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+
+SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
+
+install_framework()
+{
+  if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
+    local source="${BUILT_PRODUCTS_DIR}/$1"
+  elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
+    local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
+  elif [ -r "$1" ]; then
+    local source="$1"
+  fi
+
+  local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+
+  if [ -L "${source}" ]; then
+      echo "Symlinked..."
+      source="$(readlink "${source}")"
+  fi
+
+  # use filter instead of exclude so missing patterns dont' throw errors
+  echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\""
+  rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
+
+  local basename
+  basename="$(basename -s .framework "$1")"
+  binary="${destination}/${basename}.framework/${basename}"
+  if ! [ -r "$binary" ]; then
+    binary="${destination}/${basename}"
+  fi
+
+  # Strip invalid architectures so "fat" simulator / device frameworks work on device
+  if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
+    strip_invalid_archs "$binary"
+  fi
+
+  # Resign the code if required by the build settings to avoid unstable apps
+  code_sign_if_enabled "${destination}/$(basename "$1")"
+
+  # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7.
+  if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then
+    local swift_runtime_libs
+    swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u  && exit ${PIPESTATUS[0]})
+    for lib in $swift_runtime_libs; do
+      echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\""
+      rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
+      code_sign_if_enabled "${destination}/${lib}"
+    done
+  fi
+}
+
+# Signs a framework with the provided identity
+code_sign_if_enabled() {
+  if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then
+    # Use the current code_sign_identitiy
+    echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
+    local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements '$1'"
+
+    if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
+      code_sign_cmd="$code_sign_cmd &"
+    fi
+    echo "$code_sign_cmd"
+    eval "$code_sign_cmd"
+  fi
+}
+
+# Strip invalid architectures
+strip_invalid_archs() {
+  binary="$1"
+  # Get architectures for current file
+  archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
+  stripped=""
+  for arch in $archs; do
+    if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
+      # Strip non-valid architectures in-place
+      lipo -remove "$arch" -output "$binary" "$binary" || exit 1
+      stripped="$stripped $arch"
+    fi
+  done
+  if [[ "$stripped" ]]; then
+    echo "Stripped $binary of architectures:$stripped"
+  fi
+}
+
+if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
+  wait
+fi
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh
new file mode 100755
index 0000000..41487d8
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps-resources.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+set -e
+
+mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+
+RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt
+> "$RESOURCES_TO_COPY"
+
+XCASSET_FILES=()
+
+case "${TARGETED_DEVICE_FAMILY}" in
+  1,2)
+    TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone"
+    ;;
+  1)
+    TARGET_DEVICE_ARGS="--target-device iphone"
+    ;;
+  2)
+    TARGET_DEVICE_ARGS="--target-device ipad"
+    ;;
+  3)
+    TARGET_DEVICE_ARGS="--target-device tv"
+    ;;
+  4)
+    TARGET_DEVICE_ARGS="--target-device watch"
+    ;;
+  *)
+    TARGET_DEVICE_ARGS="--target-device mac"
+    ;;
+esac
+
+install_resource()
+{
+  if [[ "$1" = /* ]] ; then
+    RESOURCE_PATH="$1"
+  else
+    RESOURCE_PATH="${PODS_ROOT}/$1"
+  fi
+  if [[ ! -e "$RESOURCE_PATH" ]] ; then
+    cat << EOM
+error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script.
+EOM
+    exit 1
+  fi
+  case $RESOURCE_PATH in
+    *.storyboard)
+      echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
+      ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
+      ;;
+    *.xib)
+      echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}"
+      ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS}
+      ;;
+    *.framework)
+      echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
+      ;;
+    *.xcdatamodel)
+      echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\""
+      xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom"
+      ;;
+    *.xcdatamodeld)
+      echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\""
+      xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd"
+      ;;
+    *.xcmappingmodel)
+      echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\""
+      xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
+      ;;
+    *.xcassets)
+      ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
+      XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
+      ;;
+    *)
+      echo "$RESOURCE_PATH"
+      echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY"
+      ;;
+  esac
+}
+if [[ "$CONFIGURATION" == "Debug" ]]; then
+  install_resource "MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle"
+  install_resource "MaterialComponents/components/Collections/src/MaterialCollections.bundle"
+  install_resource "MaterialComponents/components/PageControl/src/MaterialPageControl.bundle"
+  install_resource "MaterialComponents/components/Tabs/src/MaterialTabs.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_arrow_back.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check_circle.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_chevron_right.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_info.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_radio_button_unchecked.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_reorder.bundle"
+fi
+if [[ "$CONFIGURATION" == "Release" ]]; then
+  install_resource "MaterialComponents/components/CollectionCells/src/MaterialCollectionCells.bundle"
+  install_resource "MaterialComponents/components/Collections/src/MaterialCollections.bundle"
+  install_resource "MaterialComponents/components/PageControl/src/MaterialPageControl.bundle"
+  install_resource "MaterialComponents/components/Tabs/src/MaterialTabs.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_arrow_back.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_check_circle.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_chevron_right.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_info.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_radio_button_unchecked.bundle"
+  install_resource "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents/MaterialIcons_ic_reorder.bundle"
+fi
+
+mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then
+  mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+  rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
+rm -f "$RESOURCES_TO_COPY"
+
+if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ]
+then
+  # Find all other xcassets (this unfortunately includes those of path pods and other targets).
+  OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
+  while read line; do
+    if [[ $line != "${PODS_ROOT}*" ]]; then
+      XCASSET_FILES+=("$line")
+    fi
+  done <<<"$OTHER_XCASSETS"
+
+  printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+fi
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig
new file mode 100644
index 0000000..9efe4c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.debug.xcconfig
@@ -0,0 +1,9 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility" "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" -isystem "${PODS_ROOT}/Headers/Public/MaterialComponents"
+OTHER_LDFLAGS = $(inherited) -ObjC -l"MDFTextAccessibility" -l"MaterialComponents" -framework "CoreGraphics" -framework "QuartzCore"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
+PODS_ROOT = ${SRCROOT}/Pods
diff --git a/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig
new file mode 100644
index 0000000..9efe4c6
--- /dev/null
+++ b/demos/Codelabs/BuildingBeautifulApps/ObjectiveC/Starter/Pods/Target Support Files/Pods-BuildingBeautifulApps/Pods-BuildingBeautifulApps.release.xcconfig
@@ -0,0 +1,9 @@
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" "${PODS_ROOT}/Headers/Public/MaterialComponents"
+LIBRARY_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/MDFTextAccessibility" "$PODS_CONFIGURATION_BUILD_DIR/MaterialComponents"
+OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/MDFTextAccessibility" -isystem "${PODS_ROOT}/Headers/Public/MaterialComponents"
+OTHER_LDFLAGS = $(inherited) -ObjC -l"MDFTextAccessibility" -l"MaterialComponents" -framework "CoreGraphics" -framework "QuartzCore"
+PODS_BUILD_DIR = $BUILD_DIR
+PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
+PODS_ROOT = ${SRCROOT}/Pods
diff --git a/demos/Pesto/Pesto/Assets.xcassets/PestoLogoSmall.imageset/Contents.json b/demos/Pesto/Pesto/Assets.xcassets/PestoLogoSmall.imageset/Contents.json
deleted file mode 100644
index 709238c..0000000
--- a/demos/Pesto/Pesto/Assets.xcassets/PestoLogoSmall.imageset/Contents.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "images" : [
-    {
-      "idiom" : "universal",
-      "filename" : "pesto_text.pdf"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
\ No newline at end of file
diff --git a/demos/Pesto/Podfile.lock b/demos/Pesto/Podfile.lock
index a1b0f5e..84added 100644
--- a/demos/Pesto/Podfile.lock
+++ b/demos/Pesto/Podfile.lock
@@ -1,6 +1,6 @@
 PODS:
-  - MaterialComponents/AnimationTiming (23.0.2)
-  - MaterialComponents/AppBar (23.0.2):
+  - MaterialComponents/AnimationTiming (23.1.0)
+  - MaterialComponents/AppBar (23.1.0):
     - MaterialComponents/FlexibleHeader
     - MaterialComponents/HeaderStackView
     - MaterialComponents/NavigationBar
@@ -9,17 +9,17 @@
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
-  - MaterialComponents/ButtonBar (23.0.2):
+  - MaterialComponents/ButtonBar (23.1.0):
     - MaterialComponents/Buttons
     - MaterialComponents/private/RTL
-  - MaterialComponents/Buttons (23.0.2):
+  - MaterialComponents/Buttons (23.1.0):
     - MaterialComponents/Ink
     - MaterialComponents/private/Math
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/CollectionCells (23.0.2):
+  - MaterialComponents/CollectionCells (23.1.0):
     - MaterialComponents/CollectionLayoutAttributes
     - MaterialComponents/Ink
     - MaterialComponents/private/Icons/ic_check
@@ -31,46 +31,46 @@
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
     - MaterialComponents/Typography
-  - MaterialComponents/CollectionLayoutAttributes (23.0.2)
-  - MaterialComponents/Collections (23.0.2):
+  - MaterialComponents/CollectionLayoutAttributes (23.1.0)
+  - MaterialComponents/Collections (23.1.0):
     - MaterialComponents/CollectionCells
     - MaterialComponents/CollectionLayoutAttributes
     - MaterialComponents/Ink
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
-  - MaterialComponents/FlexibleHeader (23.0.2):
+  - MaterialComponents/FlexibleHeader (23.1.0):
     - MaterialComponents/private/Application
     - MDFTextAccessibility
-  - MaterialComponents/HeaderStackView (23.0.2)
-  - MaterialComponents/Ink (23.0.2)
-  - MaterialComponents/NavigationBar (23.0.2):
+  - MaterialComponents/HeaderStackView (23.1.0)
+  - MaterialComponents/Ink (23.1.0)
+  - MaterialComponents/NavigationBar (23.1.0):
     - MaterialComponents/ButtonBar
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/private/Application (23.0.2)
-  - MaterialComponents/private/Icons/Base (23.0.2)
-  - MaterialComponents/private/Icons/ic_arrow_back (23.0.2):
+  - MaterialComponents/private/Application (23.1.0)
+  - MaterialComponents/private/Icons/Base (23.1.0)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_check (23.0.2):
+  - MaterialComponents/private/Icons/ic_check (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_check_circle (23.0.2):
+  - MaterialComponents/private/Icons/ic_check_circle (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_chevron_right (23.0.2):
+  - MaterialComponents/private/Icons/ic_chevron_right (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_info (23.0.2):
+  - MaterialComponents/private/Icons/ic_info (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.0.2):
+  - MaterialComponents/private/Icons/ic_radio_button_unchecked (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Icons/ic_reorder (23.0.2):
+  - MaterialComponents/private/Icons/ic_reorder (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Math (23.0.2)
-  - MaterialComponents/private/RTL (23.0.2)
-  - MaterialComponents/ShadowElevations (23.0.2)
-  - MaterialComponents/ShadowLayer (23.0.2)
-  - MaterialComponents/Typography (23.0.2):
+  - MaterialComponents/private/Math (23.1.0)
+  - MaterialComponents/private/RTL (23.1.0)
+  - MaterialComponents/ShadowElevations (23.1.0)
+  - MaterialComponents/ShadowLayer (23.1.0)
+  - MaterialComponents/Typography (23.1.0):
     - MaterialComponents/private/Application
   - MDFTextAccessibility (1.2.0)
 
@@ -89,7 +89,7 @@
     :path: "../../"
 
 SPEC CHECKSUMS:
-  MaterialComponents: fc0b6f9725db1f434aa3f8d7feb7832ac99a3692
+  MaterialComponents: 7979134f28cca6654f9d3786e96a8d1bff26dfc6
   MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
 
 PODFILE CHECKSUM: 0bae51237ebf30ce3f4ecbcefedc8cf3d7af40cf
diff --git a/demos/README.md b/demos/README.md
index 562494b..95bcb4c 100644
--- a/demos/README.md
+++ b/demos/README.md
@@ -8,7 +8,7 @@
 
 ## Trying out Material Components
 
-Our [catalog](../catalog/) showcases Material Components. 
+Our [catalog](../catalog/) showcases Material Components.
 You can use the `pod try` command from anywhere on your machine to try the components, even if you haven't checked out the repo yet:
 
 ``` bash
@@ -16,7 +16,7 @@
 ```
 
 In case you have already checked out the repo, run the following command:
-  
+
 ``` bash
 pod install --project-directory=catalog/
 ```
@@ -30,5 +30,5 @@
 - [Contributing](../contributing/)
 - [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
 - [Material.io](https://www.material.io) (external site)
-- [Material Design Guidelines](https://material.google.com) (external site)
-  
+- [Material Design Guidelines](https://material.io/guidelines) (external site)
+
diff --git a/demos/Shrine/Podfile.lock b/demos/Shrine/Podfile.lock
index c559f78..742a860 100644
--- a/demos/Shrine/Podfile.lock
+++ b/demos/Shrine/Podfile.lock
@@ -1,5 +1,5 @@
 PODS:
-  - MaterialComponents/AppBar (23.0.2):
+  - MaterialComponents/AppBar (23.1.0):
     - MaterialComponents/FlexibleHeader
     - MaterialComponents/HeaderStackView
     - MaterialComponents/NavigationBar
@@ -8,40 +8,40 @@
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
-  - MaterialComponents/ButtonBar (23.0.2):
+  - MaterialComponents/ButtonBar (23.1.0):
     - MaterialComponents/Buttons
     - MaterialComponents/private/RTL
-  - MaterialComponents/Buttons (23.0.2):
+  - MaterialComponents/Buttons (23.1.0):
     - MaterialComponents/Ink
     - MaterialComponents/private/Math
     - MaterialComponents/ShadowElevations
     - MaterialComponents/ShadowLayer
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/FlexibleHeader (23.0.2):
+  - MaterialComponents/FlexibleHeader (23.1.0):
     - MaterialComponents/private/Application
     - MDFTextAccessibility
-  - MaterialComponents/HeaderStackView (23.0.2)
-  - MaterialComponents/Ink (23.0.2)
-  - MaterialComponents/NavigationBar (23.0.2):
+  - MaterialComponents/HeaderStackView (23.1.0)
+  - MaterialComponents/Ink (23.1.0)
+  - MaterialComponents/NavigationBar (23.1.0):
     - MaterialComponents/ButtonBar
     - MaterialComponents/private/Math
     - MaterialComponents/private/RTL
     - MaterialComponents/Typography
     - MDFTextAccessibility
-  - MaterialComponents/PageControl (23.0.2)
-  - MaterialComponents/private/Application (23.0.2)
-  - MaterialComponents/private/Icons/Base (23.0.2)
-  - MaterialComponents/private/Icons/ic_arrow_back (23.0.2):
+  - MaterialComponents/PageControl (23.1.0)
+  - MaterialComponents/private/Application (23.1.0)
+  - MaterialComponents/private/Icons/Base (23.1.0)
+  - MaterialComponents/private/Icons/ic_arrow_back (23.1.0):
     - MaterialComponents/private/Icons/Base
-  - MaterialComponents/private/Math (23.0.2)
-  - MaterialComponents/private/RTL (23.0.2)
-  - MaterialComponents/ShadowElevations (23.0.2)
-  - MaterialComponents/ShadowLayer (23.0.2)
-  - MaterialComponents/Typography (23.0.2):
+  - MaterialComponents/private/Math (23.1.0)
+  - MaterialComponents/private/RTL (23.1.0)
+  - MaterialComponents/ShadowElevations (23.1.0)
+  - MaterialComponents/ShadowLayer (23.1.0)
+  - MaterialComponents/Typography (23.1.0):
     - MaterialComponents/private/Application
   - MDFTextAccessibility (1.2.0)
-  - RemoteImageServiceForMDCDemos (23.0.2)
+  - RemoteImageServiceForMDCDemos (23.1.0)
 
 DEPENDENCIES:
   - MaterialComponents/AppBar (from `../../`)
@@ -55,9 +55,9 @@
     :path: "../supplemental"
 
 SPEC CHECKSUMS:
-  MaterialComponents: fc0b6f9725db1f434aa3f8d7feb7832ac99a3692
+  MaterialComponents: 7979134f28cca6654f9d3786e96a8d1bff26dfc6
   MDFTextAccessibility: 94098925e0853551c5a311ce7c1ecefbe297cdb6
-  RemoteImageServiceForMDCDemos: 062e4570b6c42a1b9022aef51d1b178898985071
+  RemoteImageServiceForMDCDemos: 4bad57e92050da4c100ff679d5b8fbf042e0c34c
 
 PODFILE CHECKSUM: 5eb94d7fb8deeb6709b7300f5d0e0e1a75902cca
 
diff --git a/demos/ZShadow/Podfile.lock b/demos/ZShadow/Podfile.lock
index 90927ca..80a0cd2 100644
--- a/demos/ZShadow/Podfile.lock
+++ b/demos/ZShadow/Podfile.lock
@@ -1,6 +1,6 @@
 PODS:
-  - MaterialComponents/ShadowElevations (23.0.2)
-  - MaterialComponents/ShadowLayer (23.0.2)
+  - MaterialComponents/ShadowElevations (23.1.0)
+  - MaterialComponents/ShadowLayer (23.1.0)
 
 DEPENDENCIES:
   - MaterialComponents/ShadowElevations (from `../../`)
@@ -11,7 +11,7 @@
     :path: "../../"
 
 SPEC CHECKSUMS:
-  MaterialComponents: fc0b6f9725db1f434aa3f8d7feb7832ac99a3692
+  MaterialComponents: 7979134f28cca6654f9d3786e96a8d1bff26dfc6
 
 PODFILE CHECKSUM: 238ed9ba58d5e4a3638e6cea92b00109641989f8
 
diff --git a/demos/supplemental/RemoteImageServiceForMDCDemos.podspec b/demos/supplemental/RemoteImageServiceForMDCDemos.podspec
index 1e5ccef..b7afd9b 100644
--- a/demos/supplemental/RemoteImageServiceForMDCDemos.podspec
+++ b/demos/supplemental/RemoteImageServiceForMDCDemos.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name         = "RemoteImageServiceForMDCDemos"
-  s.version      = "23.0.2"
+  s.version      = "23.1.0"
   s.summary      = "A helper image class for the MDC demos."
   s.description  = "This spec is made for use in the MDC demos. It gets images via url."
   s.homepage     = "https://github.com/material-components/material-components-ios"
diff --git a/docs/docsite-components.md b/docs/docsite-components.md
new file mode 100644
index 0000000..9d21b31
--- /dev/null
+++ b/docs/docsite-components.md
@@ -0,0 +1,8 @@
+<!--docs:
+title: "Components"
+layout: landing-no-drawer
+section: components
+path: /catalog/
+-->
+
+<!--{% include components-list.html %}-->
diff --git a/docs/docsite-index.md b/docs/docsite-index.md
new file mode 100644
index 0000000..77aa7a7
--- /dev/null
+++ b/docs/docsite-index.md
@@ -0,0 +1,155 @@
+---
+title: "Material Components for iOS"
+layout: "homepage"
+path: /
+---
+
+{% contentfor benefits %}
+<ul class="benefits-list">
+  <li class="benefits-list-item">
+    <h3>Pixel-perfect &amp; up to date</h3>
+    <p>Implement <a href="https://material.io/guidelines">Material Design</a> with pixel-perfect components, maintained by Google engineers and designers</p>
+  </li>
+  <li class="benefits-list-item">
+    <h3>Flexible development</h3>
+    <p>Develop apps using components that support iOS technologies like Swift, Objective-C, and storyboards</p>
+  </li>
+  <li class="benefits-list-item">
+    <h3>Industry standards</h3>
+    <p>Take advantage of the same components used in Google’s iOS apps, which meet industry standards for internationalization and accessibility</p>
+  </li>
+</ul>
+{% endcontentfor %}
+
+# Getting Started
+
+An easy way to create beautiful apps with modular and customizable UI&nbsp;components.
+
+1.  {: .step-list-item } ### Install CocoaPods
+
+    [CocoaPods](https://cocoapods.org/) is the easiest way to get started.
+    If you're new to CocoaPods, check out their
+    [getting started documentation](https://guides.cocoapods.org/using/getting-started.html).
+
+    To install CocoaPods, run the following commands:
+
+    ``` bash
+    sudo gem install cocoapods
+    ```
+
+
+2.  {: .step-list-item } ### Create Podfile
+
+    Once you've created an iOS application in Xcode you can start using
+    Material Components for iOS.
+
+    To initialize CocoaPods in your project, run the following commands:
+
+    ``` bash
+    cd your-project-directory
+    pod init
+    ```
+
+3.  {: .step-list-item } ### Edit Podfile
+
+    Once you've initialized CocoaPods, add the
+    [Material Components for iOS Pod](https://cocoapods.org/pods/MaterialComponentsIOS)
+    to your target in your Podfile:
+
+
+    ``` ruby
+    target "MyApp" do
+      ...
+      pod 'MaterialComponents'
+    end
+    ```
+
+    If you are using Swift, don’t forget to uncomment the `use_frameworks!` line
+    at the top of your Podfile.
+
+    Then run the command:
+
+    ``` bash
+    pod install
+    open your-project.xcworkspace
+    ```
+
+    Now you're ready to get started in Xcode.
+
+4.  {: .step-list-item } ### Usage
+
+    Now you’re ready to add a component (e.g. Buttons) to your app!
+    Include the Material Components header for the component you're interested
+    in to your app (detailed below) to get all of the required classes.
+
+    Choose from Objective-C or Swift:
+
+    <!--<div class="material-code-render" markdown="1">-->
+    #### Objective-C
+
+    ``` objc
+    #import "MaterialButtons.h"
+
+    @implementation ViewController
+
+    - (void)viewDidLoad {
+      [super viewDidLoad];
+
+      MDCRaisedButton *raisedButton = [MDCRaisedButton new];
+      [raisedButton setTitle:@"Raised Button" forState:UIControlStateNormal];
+      [raisedButton sizeToFit];
+      [raisedButton addTarget:self
+                       action:@selector(tapped:)
+             forControlEvents:UIControlEventTouchUpInside];
+
+      [self.view addSubview:raisedButton];
+    }
+
+    - (void)tapped:(id)sender {
+      NSLog(@"Button was tapped!");
+    }
+
+    @end
+    ```
+
+    #### Swift
+
+    ``` swift
+    import MaterialComponents.MaterialButtons
+
+    class MDCBuildTestViewController: UIViewController {
+
+        override func viewDidLoad() {
+            super.viewDidLoad()
+            let raiseButton = MDCRaisedButton.init();
+            raiseButton.setTitle("Raised Button", forState: .Normal);
+            raiseButton.sizeToFit();
+            raiseButton.addTarget(self, action: "tapped:", forControlEvents: .TouchUpInside);
+            self.view.addSubview(raiseButton);
+        }
+
+        func tapped(sender: UIButton!){
+            NSLog("Button was tapped!");
+        }
+
+    }
+    ```
+    <!--</div>-->
+
+5.  {: .step-list-item } ### What's next?
+
+    <ul class="icon-list">
+      <li class="icon-list-item icon-list-item--guide">
+        <a href="../howto">Read the Development Guide</a>
+      </li>
+      <li class="icon-list-item icon-list-item--components">
+        <a href="../components">View the Component Documentation</a>
+      </li>
+      <li class="icon-list-item icon-list-item--sample">
+        <a href="../howto/tutorial/#sample-code">Explore our Code Samples</a>
+      </li>
+      <li class="icon-list-item icon-list-item--github">
+        <a href="https://github.com/material-components/material-components-ios/">View the project on GitHub</a>
+      </li>
+    </ul>
+{: .step-list }
diff --git a/howto/README.md b/howto/README.md
index 6e20f69..7ffd21a 100644
--- a/howto/README.md
+++ b/howto/README.md
@@ -1,7 +1,8 @@
 <!--docs:
 title: "How to use Material Components"
 layout: landing
-section: howto
+section: docs
+path: /docs/
 -->
 
 # How to use Material Components
@@ -21,8 +22,7 @@
 
 - [All Components](../components/)
 - [Demo Apps](../demos/)
-- [Contributing](../contributing/)
+- [Contributing](contributing/)
 - [MDC-iOS on Stack Overflow](https://www.stackoverflow.com/questions/tagged/material-components+ios) (external site)
 - [Material.io](https://www.material.io) (external site)
-- [Material Design Guidelines](https://material.google.com) (external site)
-
+- [Material Design Guidelines](https://material.io/guidelines) (external site)
diff --git a/howto/build-env/README.md b/howto/build-env/README.md
index 6969a08..86c1c6c 100644
--- a/howto/build-env/README.md
+++ b/howto/build-env/README.md
@@ -1,7 +1,8 @@
 <!--docs:
 title: "Build environment"
 layout: landing
-section: howto
+section: docs
+path: /docs/build-env/
 -->
 
 # Build environment
diff --git a/howto/faq/README.md b/howto/faq/README.md
index 862c3b5..a4c0e3d 100644
--- a/howto/faq/README.md
+++ b/howto/faq/README.md
@@ -1,10 +1,11 @@
 <!--docs:
 title: "Frequently Asked Questions"
 layout: landing
-section: howto
+section: docs
+path: /docs/faq/
 -->
 
-## Frequently Asked Questions
+# Frequently Asked Questions
 
 ### How do we stay true to our brand while using Material Design?
 
diff --git a/howto/tutorial/README.md b/howto/tutorial/README.md
index 452a9b7..f15c56a 100644
--- a/howto/tutorial/README.md
+++ b/howto/tutorial/README.md
@@ -1,10 +1,11 @@
 <!--docs:
-title: "Material Components Development Guide"
+title: "Tutorial"
 layout: landing
-section: howto
+section: docs
+path: /docs/tutorial/
 -->
 
-## Tutorial
+# Tutorial
 
 Whether new or legacy, storyboard or code, Swift or Objective C, it's easy to use Material Components in your app.
 
@@ -514,7 +515,7 @@
 ```
 <!--</div>-->
 
-**NOTE:** We used margins of 16 points to match the guidelines found in the [Material Design spec](https://material.google.com/components/buttons-floating-action-button.html#buttons-floating-action-button-floating-action-button). Lots of suggestions for padding, sizing and alignment choices can be found [there](https://material.google.com/layout/metrics-keylines.html#metrics-keylines-baseline-grids).
+**NOTE:** We used margins of 16 points to match the guidelines found in the [Material Design spec](https://material.io/guidelines/components/buttons-floating-action-button.html#buttons-floating-action-button-floating-action-button). Lots of suggestions for padding, sizing and alignment choices can be found [there](https://material.io/guidelines/layout/metrics-keylines.html#metrics-keylines-baseline-grids).
 
 Build and run your app. The fab shows up but it doesn't do anything yet.
 
diff --git a/scripts/build_site.sh b/scripts/build_site.sh
index bf5f673..64f5e88 100755
--- a/scripts/build_site.sh
+++ b/scripts/build_site.sh
@@ -21,7 +21,7 @@
 # Getting the link for github repository
 GITHUB_REMOTE="git@github.com:material-components/material-components-site-generator.git"
 SITE_SOURCE_BRANCH='master'
-SITE_SOURCE_FOLDER='docsite'
+SITE_SOURCE_FOLDER='docsite-generator'
 
 # Switching to the root folder of mdc
 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
@@ -38,7 +38,7 @@
 else
   echo "Set up site folder...";
   git clone $GITHUB_REMOTE $SITE_SOURCE_FOLDER || { echo "Failed to clone."; exit 1; }
-  echo "Please follow the instructions in docsite/README.md, then run build_site.sh to complete the build.";
+  echo "Please follow the instructions in $SITE_SOURCE_FOLDER/README.md, then run build_site.sh to complete the build.";
   exit 0
 fi
 
diff --git a/site-index.md b/site-index.md
deleted file mode 100644
index cac0a74..0000000
--- a/site-index.md
+++ /dev/null
@@ -1,147 +0,0 @@
----
-title: "Material Components for iOS"
-layout: "homepage"
----
-
-# Material Components for&nbsp;iOS
-<!--{: .title }-->
-
-An easy way to create beautiful apps with modular and customizable UI&nbsp;components.
-<!--{: .subhead }-->
-
-[Get Started](#quickstart)
-[View on GitHub](https://github.com/material-components/material-components-ios)
-<!--{: .button-getstarted }-->
-
-<a name="quickstart"></a>
-<!--{: .jumplink }-->
-
-1.  ## Install CocoaPods
-
-    [CocoaPods](https://cocoapods.org/) is the easiest way to get started.
-    If you're new to CocoaPods, check out their
-    [getting started documentation](https://guides.cocoapods.org/using/getting-started.html).
-
-    To install CocoaPods, run the following commands:
-
-    ``` bash
-    sudo gem install cocoapods
-    ```
-
-
-2.  ## Create Podfile
-
-    Once you've created an iOS application in Xcode you can start using
-    Material Components for iOS.
-
-    To initialize CocoaPods in your project, run the following commands:
-
-    ``` bash
-    cd your-project-directory
-    pod init
-    ```
-
-3.  ## Edit Podfile
-
-    Once you've initialized CocoaPods, add the
-    [Material Components for iOS Pod](https://cocoapods.org/pods/MaterialComponentsIOS)
-    to your target in your Podfile:
-
-
-    ``` ruby
-    target "MyApp" do
-      ...
-      pod 'MaterialComponents'
-    end
-    ```
-
-    If you are using Swift, don’t forget to uncomment the `use_frameworks!` line
-    at the top of your Podfile.
-
-    Then run the command:
-
-    ``` bash
-    pod install
-    open your-project.xcworkspace
-    ```
-
-    Now you're ready to get started in Xcode.
-
-4.  ## Usage
-
-    Now you’re ready to add a component (e.g. Buttons) to your app!
-    Include the Material Components header for the component you're interested
-    in to your app (detailed below) to get all of the required classes.
-
-    Choose from Objective-C or Swift:
-
-    <!--<div class="material-code-render" markdown="1">-->
-    #### Objective-C
-
-    ``` objc
-    #import "MaterialButtons.h"
-
-    @implementation ViewController
-
-    - (void)viewDidLoad {
-      [super viewDidLoad];
-
-      MDCRaisedButton *raisedButton = [MDCRaisedButton new];
-      [raisedButton setTitle:@"Raised Button" forState:UIControlStateNormal];
-      [raisedButton sizeToFit];
-      [raisedButton addTarget:self
-                       action:@selector(tapped:)
-             forControlEvents:UIControlEventTouchUpInside];
-
-      [self.view addSubview:raisedButton];
-    }
-
-    - (void)tapped:(id)sender {
-      NSLog(@"Button was tapped!");
-    }
-
-    @end
-    ```
-
-    #### Swift
-
-    ``` swift
-    import MaterialComponents.MaterialButtons
-
-    class MDCBuildTestViewController: UIViewController {
-
-        override func viewDidLoad() {
-            super.viewDidLoad()
-            let raiseButton = MDCRaisedButton.init();
-            raiseButton.setTitle("Raised Button", forState: .Normal);
-            raiseButton.sizeToFit();
-            raiseButton.addTarget(self, action: "tapped:", forControlEvents: .TouchUpInside);
-            self.view.addSubview(raiseButton);
-        }
-
-        func tapped(sender: UIButton!){
-            NSLog("Button was tapped!");
-        }
-
-    }
-    ```
-    <!--</div>-->
-
-5.  ## What's next?
-
-    <ul class="icon-list">
-      <li class="icon-list-item icon-list-item--guide">
-        <a href="{{ site.folder }}/howto">Read the Development Guide</a>
-      </li>
-      <li class="icon-list-item icon-list-item--components">
-        <a href="{{ site.folder }}/components">View the Component Documentation</a>
-      </li>
-      <li class="icon-list-item icon-list-item--sample">
-        <a href="{{ site.folder }}/howto/tutorial/#sample-code">Explore our Code Samples</a>
-      </li>
-      <li class="icon-list-item icon-list-item--github">
-        <a href="https://github.com/material-components/material-components-ios/">View the project on GitHub</a>
-      </li>
-    </ul>
-
-<!--{: .step-sequence }-->