diff --git a/app/src/main/java/it/reyboz/bustorino/ActivityIntro.kt b/app/src/main/java/it/reyboz/bustorino/ActivityIntro.kt
--- a/app/src/main/java/it/reyboz/bustorino/ActivityIntro.kt
+++ b/app/src/main/java/it/reyboz/bustorino/ActivityIntro.kt
@@ -3,9 +3,11 @@
 import android.content.Intent
 import android.os.Bundle
 import android.util.Log
+import android.util.TypedValue
 import android.view.View
 import android.widget.ImageButton
 import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.res.ResourcesCompat
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentActivity
 import androidx.viewpager2.adapter.FragmentStateAdapter
@@ -21,10 +23,12 @@
     private lateinit var viewPager : ViewPager2
     private lateinit var btnForward: ImageButton
     private lateinit var btnBackward: ImageButton
+    private lateinit var closeBottomButton: ImageButton
 
     private var restartMain = true
 
 
+
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_intro)
@@ -32,6 +36,7 @@
         viewPager = findViewById(R.id.viewPager)
         btnBackward = findViewById(R.id.btnPrevious)
         btnForward = findViewById(R.id.btnNext)
+        closeBottomButton = findViewById(R.id.btnCompactClose)
 
         val extras = intent.extras
         if(extras!=null){
@@ -56,6 +61,11 @@
         btnBackward.setOnClickListener {
             viewPager.setCurrentItem(viewPager.currentItem-1, true)
         }
+        /*closeBottomButton.setOnClickListener {
+            closeIntroduction()
+        }
+
+         */
 
         viewPager.registerOnPageChangeCallback(object : OnPageChangeCallback() {
 
@@ -67,12 +77,30 @@
                 }
                 if(position == NUM_ITEMS-1){
                     btnForward.visibility = View.INVISIBLE
-                } else{
-                    btnForward.visibility = View.VISIBLE
+                    closeBottomButton.visibility = View.VISIBLE
+                }else if(position == NUM_ITEMS-2){
+                    if(closeBottomButton.visibility == View.VISIBLE) {
+                        closeBottomButton.visibility = View.INVISIBLE
+                        btnForward.visibility = View.VISIBLE
+                    }
+                    //btnForward.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.arrow_forward_white, null))
+                    //btnForward.setBackgroundColor(ResourcesCompat.getColor(resources,R.attr.colorAccent, theme))
+                    /*val
+                    GET THE COLOR VALUE OF THE THEMER
+                    colo = TypedValue()
+                    theme.resolveAttribute(R.attr.colorAccent,colo, true)
+                    btnForward.backgroundTintList  //(colo.data)
+
+                     */
                 }
             }
 
+
         })
+
+        closeBottomButton.setOnClickListener {
+            closeIntroduction()
+        }
     }
 
 
diff --git a/app/src/main/java/it/reyboz/bustorino/adapters/RouteAdapter.kt b/app/src/main/java/it/reyboz/bustorino/adapters/RouteAdapter.kt
--- a/app/src/main/java/it/reyboz/bustorino/adapters/RouteAdapter.kt
+++ b/app/src/main/java/it/reyboz/bustorino/adapters/RouteAdapter.kt
@@ -11,11 +11,11 @@
 import java.lang.ref.WeakReference
 
 class RouteAdapter(val routes: List<GtfsRoute>,
-                    click: onItemClick,
-                    private val layoutId: Int = R.layout.line_title_header) :
+                   click: ItemClicker,
+                   private val layoutId: Int = R.layout.line_title_header) :
     RecyclerView.Adapter<RouteAdapter.ViewHolder>()
 {
-        val clickreference: WeakReference<onItemClick>
+        val clickreference: WeakReference<ItemClicker>
         init {
             clickreference = WeakReference(click)
         }
@@ -53,7 +53,7 @@
         }
     }
 
-    fun interface onItemClick{
+    fun interface ItemClicker{
         fun onRouteItemClicked(gtfsRoute: GtfsRoute)
     }
 }
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/adapters/RouteOnlyLineAdapter.kt b/app/src/main/java/it/reyboz/bustorino/adapters/RouteOnlyLineAdapter.kt
--- a/app/src/main/java/it/reyboz/bustorino/adapters/RouteOnlyLineAdapter.kt
+++ b/app/src/main/java/it/reyboz/bustorino/adapters/RouteOnlyLineAdapter.kt
@@ -7,10 +7,18 @@
 import androidx.recyclerview.widget.RecyclerView
 import it.reyboz.bustorino.R
 import it.reyboz.bustorino.backend.Palina
+import java.lang.ref.WeakReference
 
-class RouteOnlyLineAdapter (val routeNames: List<String>) :
+class RouteOnlyLineAdapter (val routeNames: List<String>,
+                            onItemClick: OnClick?) :
     RecyclerView.Adapter<RouteOnlyLineAdapter.ViewHolder>() {
 
+
+    private val clickreference: WeakReference<OnClick>?
+    init {
+        clickreference = if(onItemClick!=null) WeakReference(onItemClick) else null
+    }
+
     /**
      * Provide a reference to the type of views that you are using
      * (custom ViewHolder)
@@ -23,7 +31,7 @@
             textView = view.findViewById(R.id.routeBallID)
         }
     }
-    constructor(palina: Palina, showOnlyEmpty: Boolean): this(palina.routesNamesWithNoPassages)
+    constructor(palina: Palina, showOnlyEmpty: Boolean): this(palina.routesNamesWithNoPassages, null)
 
     // Create new views (invoked by the layout manager)
     override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
@@ -40,9 +48,15 @@
         // Get element from your dataset at this position and replace the
         // contents of the view with that element
         viewHolder.textView.text = routeNames[position]
+        viewHolder.itemView.setOnClickListener{
+            clickreference?.get()?.onItemClick(position, routeNames[position])
+        }
     }
 
     // Return the size of your dataset (invoked by the layout manager)
     override fun getItemCount() = routeNames.size
 
+    fun interface OnClick{
+        fun onItemClick(index: Int, name: String)
+    }
 }
diff --git a/app/src/main/java/it/reyboz/bustorino/data/GtfsRepository.kt b/app/src/main/java/it/reyboz/bustorino/data/GtfsRepository.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/GtfsRepository.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/GtfsRepository.kt
@@ -35,4 +35,8 @@
     fun getAllRoutes(): LiveData<List<GtfsRoute>>{
         return  gtfsDao.getAllRoutes()
     }
+
+    fun getRouteFromGtfsId(gtfsId: String): LiveData<GtfsRoute>{
+        return gtfsDao.getRouteByGtfsID(gtfsId)
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java b/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java
--- a/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java
+++ b/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java
@@ -19,12 +19,16 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
+import android.util.Log;
 import it.reyboz.bustorino.R;
 
 import static android.content.Context.MODE_PRIVATE;
 
 import androidx.preference.PreferenceManager;
 
+import java.util.HashSet;
+import java.util.Set;
+
 /**
  * Static class for commonly used SharedPreference operations
  */
@@ -33,6 +37,8 @@
     public static final String PREF_GTFS_DB_VERSION = "gtfs_db_version";
     public static final String PREF_INTRO_ACTIVITY_RUN ="pref_intro_activity_run";
 
+    public static final String PREF_FAVORITE_LINES = "pref_favorite_lines";
+
     public static SharedPreferences getMainSharedPreferences(Context context){
         return context.getSharedPreferences(context.getString(R.string.mainSharedPreferences), MODE_PRIVATE);
     }
@@ -59,4 +65,27 @@
         final SharedPreferences pref = getMainSharedPreferences(con);
         return pref.getBoolean(PREF_INTRO_ACTIVITY_RUN, false);
     }
+
+    public static boolean addOrRemoveLineToFavorites(Context con, String gtfsLineId, boolean addToFavorites){
+        final SharedPreferences pref = getMainSharedPreferences(con);
+        final HashSet<String> favorites = new HashSet<>(pref.getStringSet(PREF_FAVORITE_LINES, new HashSet<>()));
+        boolean modified = true;
+        if(addToFavorites)
+            favorites.add(gtfsLineId);
+        else if(favorites.contains(gtfsLineId))
+            favorites.remove(gtfsLineId);
+        else
+            modified = false; // we are not changing anything
+        if(modified) {
+            final SharedPreferences.Editor editor = pref.edit();
+            editor.putStringSet(PREF_FAVORITE_LINES, favorites);
+            editor.apply();
+        }
+        return modified;
+    }
+
+    public static HashSet<String> getFavoritesLinesGtfsIDs(Context con){
+        final SharedPreferences pref = getMainSharedPreferences(con);
+        return new HashSet<>(pref.getStringSet(PREF_FAVORITE_LINES, new HashSet<>()));
+    }
 }
diff --git a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt
@@ -26,8 +26,8 @@
     @Query("SELECT * FROM "+GtfsRoute.DB_TABLE)
     fun getAllRoutes() : LiveData<List<GtfsRoute>>
 
-    @Query("SELECT * FROM ${GtfsRoute.DB_TABLE} WHERE ${GtfsRoute.COL_ROUTE_ID} IN (:routeGtfsIds)")
-    fun getRoutesByIDs(routeGtfsIds: List<String>): LiveData<List<GtfsRoute>>
+    @Query("SELECT * FROM ${GtfsRoute.DB_TABLE} WHERE ${GtfsRoute.COL_ROUTE_ID} LIKE :gtfsId")
+    fun getRouteByGtfsID(gtfsId: String) : LiveData<GtfsRoute>
 
 
     @Query("SELECT "+GtfsTrip.COL_TRIP_ID+" FROM "+GtfsTrip.DB_TABLE)
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.java b/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.java
--- a/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.java
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.java
@@ -409,7 +409,7 @@
 
             final ArrayList<String> routesWithNoPassages = lastUpdatedPalina.getRoutesNamesWithNoPassages();
             Collections.sort(routesWithNoPassages, new LinesNameSorter());
-            noArrivalsAdapter = new RouteOnlyLineAdapter(routesWithNoPassages);
+            noArrivalsAdapter = new RouteOnlyLineAdapter(routesWithNoPassages, null);
             if(noArrivalsRecyclerView!=null){
                 noArrivalsRecyclerView.setAdapter(noArrivalsAdapter);
                 //hide the views if there are no empty routes
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/IntroFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/IntroFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/IntroFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/IntroFragment.kt
@@ -9,6 +9,7 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.Button
+import android.widget.ImageButton
 import android.widget.ImageView
 import android.widget.TextView
 import androidx.fragment.app.Fragment
@@ -33,6 +34,7 @@
     private lateinit var textView: TextView
 
 
+
     private lateinit var listener: IntroListener
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
@@ -88,6 +90,7 @@
             6-> {
                 setImageBitmap(imageHolder,R.drawable.tuto_menu)
                 setTextHtmlDescription(R.string.tutorial_menu)
+                //this is the cheapest trick ever lol
                 val closeButton = root.findViewById<Button>(R.id.closeAllButton)
                 closeButton.visibility = View.VISIBLE
                 closeButton.setOnClickListener {
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
@@ -20,6 +20,7 @@
 import android.animation.ObjectAnimator
 import android.annotation.SuppressLint
 import android.content.Context
+import android.content.SharedPreferences
 import android.graphics.Paint
 import android.os.Bundle
 import android.util.Log
@@ -45,6 +46,7 @@
 import it.reyboz.bustorino.backend.gtfs.PolylineParser
 import it.reyboz.bustorino.backend.utils
 import it.reyboz.bustorino.data.MatoTripsDownloadWorker
+import it.reyboz.bustorino.data.PreferencesHolder
 import it.reyboz.bustorino.data.gtfs.MatoPattern
 import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops
 import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops
@@ -67,7 +69,7 @@
 
 class LinesDetailFragment() : ScreenBaseFragment() {
 
-    private lateinit var lineID: String
+    private var lineID = ""
     private lateinit var patternsSpinner: Spinner
     private var patternsAdapter: ArrayAdapter<String>? = null
 
@@ -83,7 +85,31 @@
     private var firstInit = true
     private var pausedFragment = false
     private lateinit var switchButton: ImageButton
+
+    private var favoritesButton: ImageButton? = null
+    private var isLineInFavorite = false
+    private val lineSharedPrefMonitor = SharedPreferences.OnSharedPreferenceChangeListener { pref, keychanged ->
+        if(keychanged!=PreferencesHolder.PREF_FAVORITE_LINES || lineID.isEmpty()) return@OnSharedPreferenceChangeListener
+        val newFavorites = pref.getStringSet(PreferencesHolder.PREF_FAVORITE_LINES, HashSet())
+        newFavorites?.let {
+            isLineInFavorite = it.contains(lineID)
+            //if the button has been intialized, change the icon accordingly
+            favoritesButton?.let { button->
+                if(isLineInFavorite) {
+                    button.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_star_filled, null))
+                    Toast.makeText(context,R.string.favorites_line_add,Toast.LENGTH_SHORT).show()
+                } else {
+                    button.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_star_outline, null))
+                    Toast.makeText(context,R.string.favorites_line_remove,Toast.LENGTH_SHORT).show()
+                }
+
+
+            }
+        }
+    }
+
     private lateinit var stopsRecyclerView: RecyclerView
+    private lateinit var descripTextView: TextView
     //adapter for recyclerView
     private val stopAdapterListener= object : StopAdapterListener {
         override fun onTappedStop(stop: Stop?) {
@@ -93,7 +119,7 @@
                 viewModel.shouldShowMessage=false
             }
             stop?.let {
-                fragmentListener?.requestArrivalsForStopID(it.ID)
+                fragmentListener.requestArrivalsForStopID(it.ID)
             }
             if(stop == null){
                 Log.e(DEBUG_TAG,"Passed wrong stop")
@@ -142,12 +168,27 @@
         val rootView = inflater.inflate(R.layout.fragment_lines_detail, container, false)
         lineID = requireArguments().getString(LINEID_KEY, "")
         switchButton = rootView.findViewById(R.id.switchImageButton)
+        favoritesButton = rootView.findViewById(R.id.favoritesButton)
         stopsRecyclerView = rootView.findViewById(R.id.patternStopsRecyclerView)
+        descripTextView = rootView.findViewById(R.id.lineDescripTextView)
+        descripTextView.visibility = View.INVISIBLE
 
         val titleTextView = rootView.findViewById<TextView>(R.id.titleTextView)
-
         titleTextView.text = getString(R.string.line)+" "+GtfsUtils.getLineNameFromGtfsID(lineID)
 
+        favoritesButton?.isClickable = true
+        favoritesButton?.setOnClickListener {
+            if(lineID.isNotEmpty())
+                PreferencesHolder.addOrRemoveLineToFavorites(requireContext(),lineID,!isLineInFavorite)
+        }
+        val preferences = PreferencesHolder.getMainSharedPreferences(requireContext())
+        val favorites = preferences.getStringSet(PreferencesHolder.PREF_FAVORITE_LINES, HashSet())
+        if(favorites!=null && favorites.contains(lineID)){
+            favoritesButton?.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.ic_star_filled, null))
+            isLineInFavorite = true
+        }
+        preferences.registerOnSharedPreferenceChangeListener(lineSharedPrefMonitor)
+
         patternsSpinner = rootView.findViewById(R.id.patternsSpinner)
         patternsAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, ArrayList<String>())
         patternsSpinner.adapter = patternsAdapter
@@ -195,6 +236,10 @@
                     showStopsAsList(stops)
             }
         }
+        viewModel.gtfsRoute.observe(viewLifecycleOwner){route->
+             descripTextView.text = route.longName
+            descripTextView.visibility = View.VISIBLE
+        }
         if(pausedFragment && viewModel.selectedPatternLiveData.value!=null){
             val patt = viewModel.selectedPatternLiveData.value!!
             Log.d(DEBUG_TAG, "Recreating views on resume, setting pattern: ${patt.pattern.code}")
@@ -310,7 +355,7 @@
 
             // add ability to zoom with 2 fingers
             it.setMultiTouchControls(true)
-            it.minZoomLevel = 11.0
+            it.minZoomLevel = 12.0
 
             //map controller setup
             val mapController = it.controller
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/LinesGridShowingFragment.kt
@@ -15,7 +15,9 @@
 import androidx.recyclerview.widget.RecyclerView
 import it.reyboz.bustorino.R
 import it.reyboz.bustorino.adapters.RouteAdapter
+import it.reyboz.bustorino.adapters.RouteOnlyLineAdapter
 import it.reyboz.bustorino.backend.utils
+import it.reyboz.bustorino.data.PreferencesHolder
 import it.reyboz.bustorino.data.gtfs.GtfsRoute
 import it.reyboz.bustorino.middleware.AutoFitGridLayoutManager
 import it.reyboz.bustorino.util.LinesNameSorter
@@ -29,11 +31,12 @@
 
     private val viewModel: LinesGridShowingViewModel by viewModels()
     //private lateinit var gridLayoutManager: AutoFitGridLayoutManager
-
+    private lateinit var favoritesRecyclerView: RecyclerView
     private lateinit var urbanRecyclerView: RecyclerView
     private lateinit var extraurbanRecyclerView: RecyclerView
     private lateinit var touristRecyclerView: RecyclerView
 
+    private lateinit var favoritesTitle: TextView
     private lateinit var urbanLinesTitle: TextView
     private lateinit var extrurbanLinesTitle: TextView
     private lateinit var touristLinesTitle: TextView
@@ -53,7 +56,7 @@
         return@Comparator linesNameSorter.compare(a.shortName, b.shortName)
     }
 
-    private val routeClickListener = RouteAdapter.onItemClick {
+    private val routeClickListener = RouteAdapter.ItemClicker {
         fragmentListener.showLineOnMap(it.gtfsId)
     }
     private val arrows = HashMap<String, ImageView>()
@@ -66,10 +69,12 @@
     ): View? {
         val rootView =  inflater.inflate(R.layout.fragment_lines_grid, container, false)
 
+        favoritesRecyclerView = rootView.findViewById(R.id.favoritesRecyclerView)
         urbanRecyclerView = rootView.findViewById(R.id.urbanLinesRecyclerView)
         extraurbanRecyclerView = rootView.findViewById(R.id.extraurbanLinesRecyclerView)
         touristRecyclerView = rootView.findViewById(R.id.touristLinesRecyclerView)
 
+        favoritesTitle = rootView.findViewById(R.id.favoritesTitleView)
         urbanLinesTitle = rootView.findViewById(R.id.urbanLinesTitleView)
         extrurbanLinesTitle = rootView.findViewById(R.id.extraurbanLinesTitleView)
         touristLinesTitle = rootView.findViewById(R.id.touristLinesTitleView)
@@ -77,6 +82,7 @@
         arrows[AG_URBAN] = rootView.findViewById(R.id.arrowUrb)
         arrows[AG_TOUR] = rootView.findViewById(R.id.arrowTourist)
         arrows[AG_EXTRAURB] = rootView.findViewById(R.id.arrowExtraurban)
+        arrows[AG_FAV] = rootView.findViewById(R.id.arrowFavorites)
         //show urban expanded by default
 
         val recViews = listOf(urbanRecyclerView, extraurbanRecyclerView,  touristRecyclerView)
@@ -87,6 +93,13 @@
             )
             recyView.layoutManager = gridLayoutManager
         }
+        //init favorites recyclerview
+        val gridLayoutManager = AutoFitGridLayoutManager(
+            requireContext().applicationContext,
+            (utils.convertDipToPixels(context, 70f)).toInt()
+        )
+        favoritesRecyclerView.layoutManager = gridLayoutManager
+
 
         viewModel.routesLiveData.observe(viewLifecycleOwner){
             //routesList = ArrayList(it)
@@ -116,6 +129,15 @@
             }
 
         }
+        viewModel.favoritesLines.observe(viewLifecycleOwner){ routes->
+            val routesNames = routes.map { it.shortName }
+            //create new item click listener every time
+            val adapter = RouteOnlyLineAdapter(routesNames){  pos, _ ->
+                val r = routes[pos]
+                fragmentListener.showLineOnMap(r.gtfsId)
+            }
+            favoritesRecyclerView.adapter = adapter
+        }
 
         //onClicks
         urbanLinesTitle.setOnClickListener {
@@ -127,14 +149,33 @@
         touristLinesTitle.setOnClickListener {
             openLinesAndCloseOthersIfNeeded(AG_TOUR)
         }
+        favoritesTitle.setOnClickListener {
+            closeOpenFavorites()
+        }
+        arrows[AG_FAV]?.setOnClickListener {
+            closeOpenFavorites()
+        }
         //arrows onClicks
-        for(k in arrows.keys){
+        for(k in Companion.AGENCIES){
             //k is either AG_TOUR, AG_EXTRAURBAN, AG_URBAN
             arrows[k]?.setOnClickListener { openLinesAndCloseOthersIfNeeded(k) }
         }
 
+
         return rootView
     }
+    private fun closeOpenFavorites(){
+        if(favoritesRecyclerView.visibility == View.VISIBLE){
+            //close it
+            favoritesRecyclerView.visibility = View.GONE
+            setOpen(arrows[AG_FAV]!!, false)
+            viewModel.favoritesExpanded.value = false
+        } else{
+            favoritesRecyclerView.visibility = View.VISIBLE
+            setOpen(arrows[AG_FAV]!!, true)
+            viewModel.favoritesExpanded.value = true
+        }
+    }
 
     private fun openLinesAndCloseOthersIfNeeded(agency: String){
         if(openRecyclerView!="" && openRecyclerView!= agency) {
@@ -205,6 +246,20 @@
 
     override fun onResume() {
         super.onResume()
+        val pref = PreferencesHolder.getMainSharedPreferences(requireContext())
+        val res = pref.getStringSet(PreferencesHolder.PREF_FAVORITE_LINES, HashSet())
+        res?.let { viewModel.setFavoritesLinesIDs(HashSet(it))}
+        //restore state
+        viewModel.favoritesExpanded.value?.let {
+            if(!it){
+                //close it
+                favoritesRecyclerView.visibility = View.GONE
+                setOpen(arrows[AG_FAV]!!, false)
+            } else{
+                favoritesRecyclerView.visibility = View.VISIBLE
+                setOpen(arrows[AG_FAV]!!, true)
+            }
+        }
         viewModel.isUrbanExpanded.value?.let {
             if(it) {
                 urbanRecyclerView.visibility = View.VISIBLE
@@ -246,6 +301,7 @@
 
     companion object {
         private const val COLUMN_WIDTH_DP=200
+        private const val AG_FAV = "fav"
         private const val AG_URBAN = "gtt:U"
         private const val AG_EXTRAURB ="gtt:E"
         private const val AG_TOUR ="gtt:T"
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesGridShowingViewModel.kt
@@ -4,10 +4,11 @@
 import androidx.lifecycle.AndroidViewModel
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.ViewModel
+import androidx.lifecycle.map
 import it.reyboz.bustorino.data.GtfsRepository
-import it.reyboz.bustorino.data.NextGenDB
-import it.reyboz.bustorino.data.OldDataRepository
 import it.reyboz.bustorino.data.gtfs.GtfsDatabase
+import it.reyboz.bustorino.data.gtfs.GtfsRoute
+import it.reyboz.bustorino.util.LinesNameSorter
 
 class LinesGridShowingViewModel(application: Application) : AndroidViewModel(application) {
 
@@ -24,4 +25,27 @@
     val isUrbanExpanded = MutableLiveData(true)
     val isExtraUrbanExpanded = MutableLiveData(false)
     val isTouristExpanded = MutableLiveData(false)
+    val favoritesExpanded = MutableLiveData(true)
+
+    val favoritesLinesIDs = MutableLiveData<HashSet<String>>()
+
+    private val linesNameSorter = LinesNameSorter()
+    private val linesComparator = Comparator<GtfsRoute> { a,b ->
+        return@Comparator linesNameSorter.compare(a.shortName, b.shortName)
+    }
+
+    fun setFavoritesLinesIDs(linesIds: HashSet<String>){
+        favoritesLinesIDs.value = linesIds
+    }
+
+    val favoritesLines = favoritesLinesIDs.map {lineIds ->
+        val linesList = ArrayList<GtfsRoute>()
+        if (lineIds.size == 0 || routesLiveData.value==null) return@map linesList
+        for(line in routesLiveData.value!!){
+            if(lineIds.contains(line.gtfsId))
+                linesList.add(line)
+        }
+        linesList.sortWith(linesComparator)
+        return@map linesList
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/LinesViewModel.kt
@@ -52,6 +52,9 @@
         gtfsRepo.getPatternsWithStopsForRouteID(it)
 
     }
+    val gtfsRoute = routeIDToSearch.switchMap {
+        gtfsRepo.getRouteFromGtfsId(it)
+    }
 
 
     fun setRouteIDQuery(routeID: String){
diff --git a/app/src/main/res/drawable-it-xhdpi/tuto_menu.webp b/app/src/main/res/drawable-it-xhdpi/tuto_menu.webp
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/app/src/main/res/drawable-xhdpi/tuto_menu.webp b/app/src/main/res/drawable-xhdpi/tuto_menu.webp
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001

literal 0
Hc$@<O00001

diff --git a/app/src/main/res/drawable/close_white_large.xml b/app/src/main/res/drawable/close_white_large.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/close_white_large.xml
@@ -0,0 +1,5 @@
+<vector android:height="32dp"
+    android:viewportHeight="24" android:viewportWidth="24"
+    android:width="32dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_star_filled.xml b/app/src/main/res/drawable/ic_star_filled.xml
--- a/app/src/main/res/drawable/ic_star_filled.xml
+++ b/app/src/main/res/drawable/ic_star_filled.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="28dp"
+    android:height="28dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
   <path
diff --git a/app/src/main/res/drawable/ic_star_outline.xml b/app/src/main/res/drawable/ic_star_outline.xml
--- a/app/src/main/res/drawable/ic_star_outline.xml
+++ b/app/src/main/res/drawable/ic_star_outline.xml
@@ -1,6 +1,6 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
+    android:width="28dp"
+    android:height="28dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
   <path
diff --git a/app/src/main/res/layout/activity_intro.xml b/app/src/main/res/layout/activity_intro.xml
--- a/app/src/main/res/layout/activity_intro.xml
+++ b/app/src/main/res/layout/activity_intro.xml
@@ -26,6 +26,17 @@
             android:contentDescription="@string/next"
 
             app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"/>
+
+    <ImageButton
+            android:src="@drawable/close_white_large"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" android:id="@+id/btnCompactClose"
+            android:backgroundTint="?colorAccent"
+            android:textColor="@color/white"
+            app:circularflow_radiusInDP="5dp"
+            android:contentDescription="@string/next"
+            android:visibility="gone"
+            app:layout_constraintEnd_toEndOf="parent" app:layout_constraintBottom_toBottomOf="parent"/>
     <androidx.viewpager2.widget.ViewPager2
             android:layout_width="0dp"
             android:layout_height="0dp"
diff --git a/app/src/main/res/layout/fragment_intro.xml b/app/src/main/res/layout/fragment_intro.xml
--- a/app/src/main/res/layout/fragment_intro.xml
+++ b/app/src/main/res/layout/fragment_intro.xml
@@ -20,7 +20,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" android:id="@+id/tutorialTextView"
             app:layout_constraintTop_toBottomOf="@+id/image_tutorial"
-            android:layout_marginTop="60dp"
+            android:layout_marginTop="30dp"
             android:maxWidth="280dp"
             android:textSize="18sp"
             android:textAlignment="center"
@@ -37,7 +37,9 @@
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintStart_toStartOf="@id/tutorialTextView"
             android:backgroundTint="?colorPrimaryDark"
+            android:fontFamily="@font/pitagon_semibold"
             android:textColor="@color/white"
-            app:layout_constraintEnd_toEndOf="@id/tutorialTextView" android:layout_marginTop="12dp"/>
+            app:layout_constraintEnd_toEndOf="@id/tutorialTextView"
+            android:layout_marginTop="18dp"/>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_lines_detail.xml b/app/src/main/res/layout/fragment_lines_detail.xml
--- a/app/src/main/res/layout/fragment_lines_detail.xml
+++ b/app/src/main/res/layout/fragment_lines_detail.xml
@@ -20,18 +20,58 @@
                   android:layout_marginTop="8dp" android:gravity="center_horizontal|center_vertical"
                   app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"
                   android:layout_marginStart="8dp" android:layout_marginEnd="8dp"/>
+        <ImageButton
+                android:src="@drawable/ic_list_30"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" android:id="@+id/switchImageButton"
+                app:layout_constraintTop_toTopOf="parent"
+                app:layout_constraintRight_toRightOf="parent"
+                android:layout_margin="6dp"
+                android:backgroundTint="@color/blue_620"
+        />
+        <androidx.cardview.widget.CardView
+                android:layout_width="wrap_content" android:layout_height="30dp"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="@id/switchImageButton"
+                app:layout_constraintBottom_toBottomOf="@id/switchImageButton"
+                android:id="@+id/starCardView"
+                android:layout_marginStart="10dp"
+                android:minHeight="20sp"
+                android:elevation="10dp"
+                android:padding="5dp">
+            <ImageButton
+                    android:id="@+id/favoritesButton"
+                    android:layout_width="45dp"
+                    android:layout_height="match_parent"
+                    android:layout_gravity="end"
+                    android:background="@android:color/transparent"
+                    android:foreground="?attr/selectableItemBackground"
+                    app:srcCompat="@drawable/ic_star_outline"
+                    tools:ignore="OnClick"/>
+        </androidx.cardview.widget.CardView>
+        <TextView
+                android:text="DCCII"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" android:id="@+id/lineDescripTextView"
+                app:layout_constraintTop_toBottomOf="@id/titleTextView"
+                app:layout_constraintLeft_toLeftOf="@id/titleTextView"
+                app:layout_constraintRight_toRightOf="@id/titleTextView"
+                android:textColor="@color/grey_700"
+                android:textSize="16sp"
+                android:maxWidth="300sp"
+                android:layout_marginTop="8dp"/>
         <Spinner
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:id="@+id/patternsSpinner"
-                app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/routeDescrTextView"
-                android:layout_marginTop="8dp" app:layout_constraintTop_toBottomOf="@+id/titleTextView"
+                app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/headingToTextView"
+                android:layout_marginTop="4dp" app:layout_constraintTop_toBottomOf="@+id/lineDescripTextView"
                 android:layout_marginStart="4dp"/>
         <TextView
                 android:text="@string/direction_duep"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:id="@+id/routeDescrTextView"
+                android:id="@+id/headingToTextView"
                 app:layout_constraintStart_toStartOf="parent"
                 android:textAppearance="@style/TextAppearance.AppCompat.Body1"
                 android:textColor="?android:attr/textColorPrimary"
@@ -79,16 +119,7 @@
             android:layout_marginRight="10dp"
             android:layout_marginEnd="10dp"
     />-->
-        <ImageButton
-                android:src="@drawable/ic_list_30"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" android:id="@+id/switchImageButton"
-                app:layout_constraintTop_toTopOf="parent"
-                app:layout_constraintRight_toRightOf="parent"
-                app:layout_constraintBottom_toTopOf="@id/patternsSpinner"
-                android:layout_margin="6dp"
-                android:backgroundTint="@color/blue_500"
-        />
+
 
         <View
                 android:id="@+id/divider"
diff --git a/app/src/main/res/layout/fragment_lines_grid.xml b/app/src/main/res/layout/fragment_lines_grid.xml
--- a/app/src/main/res/layout/fragment_lines_grid.xml
+++ b/app/src/main/res/layout/fragment_lines_grid.xml
@@ -15,6 +15,44 @@
                 android:layout_width="match_parent" android:layout_height="match_parent"
                 android:animateLayoutChanges="true"
         >
+            <ImageView
+                    android:src="@drawable/baseline_chevron_right_24"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" android:id="@+id/arrowFavorites"
+                    app:layout_constraintLeft_toLeftOf="parent"
+                    app:layout_constraintBottom_toBottomOf="@id/favoritesTitleView"
+                    android:layout_margin="4dp"
+                    android:layout_marginStart="16dp"
+                    android:rotation="90"
+            />
+            <TextView android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:text="@string/favorites_lines"
+                      android:textAppearance="@style/TextAppearance.AppCompat.Body2"
+                      android:textSize="@dimen/subtitle_size"
+                      android:layout_margin="4dp"
+                      android:textColor="@color/black_900"
+                      android:gravity="center"
+                      android:id="@+id/favoritesTitleView"
+                      app:layout_constraintTop_toTopOf="parent"
+                      app:layout_constraintLeft_toRightOf="@id/arrowFavorites"
+                      app:layout_constraintBottom_toTopOf="@id/favoritesRecyclerView"
+                      android:layout_marginLeft="6dp"
+                      app:layout_constraintVertical_bias="0.0"
+                      app:layout_constraintVertical_chainStyle="packed"/>
+            <androidx.recyclerview.widget.RecyclerView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:id="@+id/favoritesRecyclerView"
+                    android:layout_marginLeft="20dp"
+                    android:layout_marginRight="20dp"
+                    android:visibility="visible"
+                    app:layout_constraintTop_toBottomOf="@id/favoritesTitleView"
+                    app:layout_constraintBottom_toTopOf="@id/urbanLinesTitleView"
+                    app:layout_constraintLeft_toLeftOf="parent"
+                    app:layout_constraintVertical_bias="0.0"
+
+            />
             <ImageView
                     android:src="@drawable/baseline_chevron_right_24"
                     android:layout_width="wrap_content"
@@ -34,12 +72,12 @@
                       android:textColor="@color/black_900"
                       android:gravity="center"
                       android:id="@+id/urbanLinesTitleView"
-                      app:layout_constraintTop_toTopOf="parent"
+                      app:layout_constraintTop_toBottomOf="@id/favoritesRecyclerView"
                       app:layout_constraintLeft_toRightOf="@id/arrowUrb"
                       app:layout_constraintBottom_toTopOf="@id/urbanLinesRecyclerView"
                       android:layout_marginLeft="6dp"
                       app:layout_constraintVertical_bias="0.0"
-                      app:layout_constraintVertical_chainStyle="packed"/>
+            />
             <androidx.recyclerview.widget.RecyclerView
                     android:layout_width="match_parent"
                     android:layout_height="0dp"
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -211,12 +211,15 @@
     <string name="pref_shown_startup_def_desc">Tocca per cambiare</string>
 
     <string name="positions_source_pref_title">Fonte posizioni in tempo reale di bus e tram</string>
-
     <array name="positions_source_sel">
         <item>MaTO (aggiornate più spesso, può non funzionare)</item>
         <item>GTFS RT (più stabile)</item>
     </array>
 
+    <string name="favorites_line_add">Linea aggiunta ai preferiti</string>
+    <string name="favorites_line_remove">Linea rimossa dai preferiti</string>
+    <string name="favorites_lines">Preferite</string>
+
     <!-- lines -->
     <string name="long_press_stop_4_options">Tocca a lungo la fermata per le opzioni</string>
     <string name="remove_all_trips">Rimuovi tutti i trip GTFS</string>
@@ -246,7 +249,7 @@
         <![CDATA[Tutte queste funzioni si trovano nel menu laterale.<br>
 Guarda nelle <b>Impostazioni</b> per personalizzare l\'app come preferisci, e su <b>Informazioni</b> per sapere di più sull\'app e il team di sviluppo.]]>
     </string>
-    <string name="close_tutorial">Chiudi</string>
+    <string name="close_tutorial">Capito, chiudi il tutorial</string>
 
 
 </resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -39,7 +39,7 @@
     <string name="extraurban_lines">Extra urban lines</string>
     <string name="turist_lines">Tourist lines</string>
 
-    <string name="direction_duep">Heading to:</string>
+    <string name="direction_duep">Destination:</string>
     <string name="lines_fill">Lines: %1$s</string>
     <string name="line_fill">Line: %1$s</string>
     <string name="no_passages">No timetable found</string>
@@ -55,6 +55,9 @@
     <string name="action_author">Meet the author</string>
     <string name="added_in_favorites">Bus stop is now in your favorites</string>
     <string name="removed_from_favorites">Bus stop removed from your favorites</string>
+    <string name="favorites_line_add">Added line to favorites</string>
+    <string name="favorites_line_remove">Remove line from favorites</string>
+    <string name="favorites_lines">Favorites</string>
     <string name="action_favorites">Favorites</string>
     <string name="title_activity_favorites">Favorites</string>
     <string name="title_activity_map">Map</string>
@@ -281,6 +284,6 @@
         <![CDATA[You can find all of this from the lateral menu.
 Look in the <b>Settings</b> to customize the app behaviour, and in the <b>About the app</b> section if you want to know more about the app and the developers.]]>
     </string>
-    <string name="close_tutorial">Close</string>
+    <string name="close_tutorial">OK, close the tutorial</string>
 
 </resources>