├── .gitignore ├── example ├── index_page.png ├── product_page.png └── database_scheme.png ├── app ├── static │ ├── images │ │ ├── 13_kale.jpg │ │ ├── 15_kale.jpg │ │ ├── 13_celery.jpg │ │ ├── 13_ginger.jpg │ │ ├── 13_parsley.jpg │ │ ├── 15_celery.jpg │ │ ├── 15_ginger.jpg │ │ ├── 15_parsley.jpg │ │ ├── 13_blueberry.jpg │ │ └── 15_blueberry.jpg │ ├── styles_index.css │ └── styles_product.css ├── notebooks │ ├── __init__.py │ └── routes.py ├── templates │ ├── layout.html │ ├── notebooks.html │ └── product.html ├── __init__.py └── models.py ├── run.py ├── config └── development.py ├── requirements.txt └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | *.db -------------------------------------------------------------------------------- /example/index_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/example/index_page.png -------------------------------------------------------------------------------- /example/product_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/example/product_page.png -------------------------------------------------------------------------------- /example/database_scheme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/example/database_scheme.png -------------------------------------------------------------------------------- /app/static/images/13_kale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/13_kale.jpg -------------------------------------------------------------------------------- /app/static/images/15_kale.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/15_kale.jpg -------------------------------------------------------------------------------- /app/static/images/13_celery.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/13_celery.jpg -------------------------------------------------------------------------------- /app/static/images/13_ginger.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/13_ginger.jpg -------------------------------------------------------------------------------- /app/static/images/13_parsley.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/13_parsley.jpg -------------------------------------------------------------------------------- /app/static/images/15_celery.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/15_celery.jpg -------------------------------------------------------------------------------- /app/static/images/15_ginger.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/15_ginger.jpg -------------------------------------------------------------------------------- /app/static/images/15_parsley.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/15_parsley.jpg -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | from app import create_app 2 | 3 | if __name__ == '__main__': 4 | app = create_app('development') 5 | app.run() -------------------------------------------------------------------------------- /app/static/images/13_blueberry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/13_blueberry.jpg -------------------------------------------------------------------------------- /app/static/images/15_blueberry.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fitoprincipe/Flask-Market/master/app/static/images/15_blueberry.jpg -------------------------------------------------------------------------------- /app/notebooks/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | notebooks = Blueprint('notebooks', __name__) 4 | 5 | from . import routes -------------------------------------------------------------------------------- /config/development.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | DEBUG = True 5 | SECRET_KEY = os.environ.get('SECRET_KEY') 6 | SQLALCHEMY_DATABASE_URI = 'sqlite:///notebooks.db' -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click==6.7 2 | Flask==0.12.2 3 | Flask-Admin==1.5.0 4 | Flask-SQLAlchemy==2.3.2 5 | itsdangerous==0.24 6 | Jinja2==2.10 7 | MarkupSafe==1.0 8 | SQLAlchemy==1.2.2 9 | Werkzeug==0.14.1 10 | WTForms==2.1 11 | -------------------------------------------------------------------------------- /app/notebooks/routes.py: -------------------------------------------------------------------------------- 1 | from flask import render_template 2 | from ..models import Product 3 | from . import notebooks 4 | from .. import db 5 | 6 | 7 | @notebooks.route('/') 8 | def index(): 9 | products = Product.query.all() 10 | return render_template('notebooks.html', products=products, quantity=len(products)) 11 | 12 | 13 | @notebooks.route('/') 14 | def personal(id): 15 | product = Product.query.get(id) 16 | return render_template('product.html', product=product) 17 | 18 | -------------------------------------------------------------------------------- /app/templates/layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% block title %}{% endblock %} 9 | {% block links %}{% endblock %} 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |

Nordream Market

18 |

MODERN PYTHON SOLUTIONS

19 |
20 |
21 | 22 | {% block main %}{% endblock %} 23 | 24 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /app/templates/notebooks.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} Notebooks {% endblock %} 4 | 5 | 6 | {% block links %} 7 | 8 | 9 | 10 | {% endblock %} 11 | 12 | 13 | {% block main %} 14 | 15 |
16 | 17 |
18 |
19 |

Notebooks | {{ quantity }} models

20 |
21 |
22 | 23 | 32 | 33 |
34 | 35 | {% endblock %} 36 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from flask_sqlalchemy import SQLAlchemy 3 | from flask import Flask 4 | from flask_admin import Admin 5 | from flask_admin.contrib.sqla import ModelView 6 | 7 | db = SQLAlchemy() 8 | admin = Admin() 9 | 10 | def create_app(config_name): 11 | 12 | app = Flask(__name__) 13 | 14 | # import configuration 15 | cfg = os.path.join(os.getcwd(), 'config', config_name + '.py') 16 | app.config.from_pyfile(cfg) 17 | 18 | # initialize extensions 19 | db.init_app(app) 20 | admin.init_app(app) 21 | 22 | with app.app_context(): 23 | from .models import Product, Year, Brand, Specification ,Screen, Processor, Memory, Storage, Image 24 | admin.add_view(ModelView(Product, db.session())) 25 | admin.add_view(ModelView(Year, db.session())) 26 | admin.add_view(ModelView(Brand, db.session())) 27 | admin.add_view(ModelView(Specification, db.session())) 28 | admin.add_view(ModelView(Screen, db.session())) 29 | admin.add_view(ModelView(Processor, db.session())) 30 | admin.add_view(ModelView(Memory, db.session())) 31 | admin.add_view(ModelView(Storage, db.session())) 32 | admin.add_view(ModelView(Image, db.session())) 33 | 34 | # import blueprints 35 | from .notebooks import notebooks as notebooks_blueprint 36 | app.register_blueprint(notebooks_blueprint, url_prefix='/notebooks') 37 | 38 | return app -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laptop-Market 2 | 3 | About 4 | ---------- 5 | Laptop-Market is a simple 2-page web application to store and show information about laptops. 6 | Application is built with Flask, SQLAlchemy and SQLite database. 7 | 8 | How it looks 9 | ---------------- 10 | Index page example: 11 | ![Index page example](/example/index_page.png) 12 | 13 | 14 | Product page example: 15 | ![Product page example](/example/product_page.png) 16 | 17 | Database scheme 18 | -------------------- 19 | ![Database scheme](/example/database_scheme.png) 20 | 21 | Installation 22 | ----------- 23 | ``` 24 | $ git clone https://github.com/N0rdream/Laptop-Market.git 25 | $ cd Laptop-Market 26 | ``` 27 | 28 | Dependencies & requirments 29 | ---------- 30 | Check requirments.txt file for dependencies. 31 | Make sure to install the last version of Flask-admin: 32 | ```pip install --upgrade git+https://github.com/flask-admin/flask-admin``` 33 | Laptop-Market runs with Python 3.6+. 34 | 35 | How to run 36 | ------------- 37 | Set SECRET_KEY enviroment variable. For example: 38 | ``` 39 | $ export SECRET_KEY="top_secret" 40 | ``` 41 | Then run application: 42 | ``` 43 | python3 run.py 44 | ``` 45 | Type in browser: http://localhost:5000/notebooks 46 | 47 | Database 48 | --------------------- 49 | You can use Flask-Admin panel to add new laptop models to database: 50 | http://localhost:5000/admin 51 | 52 | Notes 53 | ----------- 54 | Laptop-Market is written for educational purpose. 55 | -------------------------------------------------------------------------------- /app/templates/product.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %} Cherry notebook {% endblock %} 4 | 5 | 6 | {% block links %} 7 | 8 | 9 | 10 | {% endblock %} 11 | 12 | 13 | {% block main %} 14 | 15 |
16 |
17 |
18 |

{{ product.brand}} notebook | Model: {{ product.spec.screen}}-{{ product.spec.processor}}-{{ product.spec.memory}}-{{ product.spec.storage}}

19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 |
27 |
28 |

Specification

29 |
    30 |
  • Screen size: {{ product.spec.screen }}
  • 31 |
  • Processor: {{ product.spec.processor }}
  • 32 |
  • Memory size: {{ product.spec.memory }}
  • 33 |
  • Hard drive size: {{ product.spec.storage }}
  • 34 |
  • Year: {{ product.year }}
  • 35 |
36 |
37 |
38 |

{{ product.price }}

39 | Buy me 40 |
41 | 42 |
43 | 44 |
45 |
46 | 47 |
48 | 49 | {% endblock %} -------------------------------------------------------------------------------- /app/static/styles_index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Arial, Helvetica, sans-serif; 4 | background: #fff; 5 | color: #363734; 6 | font-size: 16px; 7 | line-height: 1.7; 8 | text-align: center; 9 | } 10 | 11 | img { 12 | display: block; 13 | width: 100%; 14 | height: auto; 15 | } 16 | 17 | h1, h2, h3 { 18 | margin: 0.8em 0; 19 | padding: 0; 20 | } 21 | 22 | h1 { 23 | font-size: 2.8em; 24 | } 25 | 26 | h2 { 27 | font-size: 1.7em; 28 | margin-bottom: 0; 29 | } 30 | 31 | .fading-grey { 32 | opacity: 0.7; 33 | } 34 | 35 | 36 | p { 37 | margin-bottom: 1em; 38 | padding: 0; 39 | font-size: 1em; 40 | } 41 | 42 | .btn { 43 | background: #ebae3d; 44 | color: #fff; 45 | text-decoration: none; 46 | padding: 0.5em 2em; 47 | /*border: 1px solid #363734;*/ 48 | display: inline-block; 49 | margin: 1em 0; 50 | /*opacity: 0.9;*/ 51 | } 52 | 53 | .btn:hover { 54 | background: rgba(54, 55, 52, 0.8); 55 | color: #fff; 56 | } 57 | 58 | .orange { 59 | color: #ebae3d; 60 | } 61 | 62 | /* Header showcase*/ 63 | 64 | #showcase { 65 | min-height: 200px; 66 | color: #fff; 67 | text-align: center; 68 | } 69 | 70 | #showcase .bg-image { 71 | position: absolute; 72 | background: #363734; 73 | background-position: center; 74 | background-repeat: no-repeat; 75 | background-size: 400px; 76 | width: 100%; 77 | height: 200px; 78 | z-index: -1; 79 | /*opacity: 0.4;*/ 80 | 81 | } 82 | 83 | 84 | #showcase h1 { 85 | padding-top: 0.3em; 86 | padding-bottom: 0; 87 | margin-top: 0; 88 | margin-bottom: 0.3em; 89 | } 90 | 91 | #showcase .content-wrap { 92 | padding: 0; 93 | } 94 | 95 | #theme { 96 | padding-bottom: 0; 97 | /*text-align: left;*/ 98 | } 99 | 100 | #footer { 101 | background: #363734; 102 | color: #fff; 103 | } 104 | 105 | .content-wrap, 106 | .theme-wrap, 107 | .gallery-wrap, 108 | .footer-wrap { 109 | margin: 0; 110 | /*padding: 1em;*/ 111 | /*border: 1px solid red;*/ 112 | } 113 | 114 | 115 | .footer-wrap { 116 | padding: 0.8em; 117 | } 118 | 119 | .image-wrap { 120 | padding: 0.5em; 121 | } 122 | 123 | 124 | @media(min-width: 1200px) { 125 | 126 | body { 127 | font-size: 20px; 128 | } 129 | 130 | .grid { 131 | display: grid; 132 | grid-template-columns: 1fr 1fr 1fr 1fr 1fr; 133 | grid-auto-rows: minmax(auto, 10px); 134 | /*border: 1px solid green;*/ 135 | /*grid-gap: 1em;*/ 136 | 137 | } 138 | 139 | .content-wrap, 140 | .theme-wrap, 141 | .footer-wrap { 142 | grid-column: 2/5; 143 | 144 | } 145 | } 146 | 147 | @media screen and (max-width: 1200px) and (min-width: 700px) { 148 | 149 | body { 150 | font-size: 18px; 151 | } 152 | 153 | .grid { 154 | display: grid; 155 | grid-template-columns: 1fr 1fr 1fr; 156 | grid-auto-rows: minmax(auto, 100px); 157 | /*border: 1px solid green;*/ 158 | /*grid-gap: 1em;*/ 159 | } 160 | 161 | .content-wrap, 162 | .theme-wrap, 163 | .footer-wrap { 164 | grid-column: 1/4; 165 | 166 | } 167 | } 168 | 169 | .image-wrap { 170 | border-bottom: 1px solid #363734; 171 | margin: 0.5em; 172 | /*background: rgba(54, 55, 52, 0.1);*/ 173 | } 174 | 175 | /*.gallery { 176 | display: grid; 177 | grid-template-columns: 1fr 1fr; 178 | }*/ -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | from . import db 2 | 3 | 4 | class Image(db.Model): 5 | __tablename__ = 'images' 6 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 7 | file = db.Column(db.String) 8 | products = db.relationship('Product', backref='image', lazy='dynamic') 9 | 10 | def __repr__(self): 11 | return f'{self.file}' 12 | 13 | 14 | class Year(db.Model): 15 | __tablename__ = 'years' 16 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 17 | year = db.Column(db.String) 18 | products = db.relationship('Product', backref='year', lazy='dynamic') 19 | 20 | def __repr__(self): 21 | return f'{self.year}' 22 | 23 | 24 | class Brand(db.Model): 25 | __tablename__ = 'brands' 26 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 27 | brand = db.Column(db.String) 28 | products = db.relationship('Product', backref='brand', lazy='dynamic') 29 | 30 | def __repr__(self): 31 | return f'{self.brand}' 32 | 33 | 34 | class Screen(db.Model): 35 | __tablename__ = 'screens' 36 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 37 | screen = db.Column(db.String) 38 | specifications = db.relationship('Specification', backref='screen', lazy='dynamic') 39 | 40 | def __repr__(self): 41 | return f'{self.screen}' 42 | 43 | 44 | class Processor(db.Model): 45 | __tablename__ = 'processors' 46 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 47 | processor = db.Column(db.String) 48 | specifications = db.relationship('Specification', backref='processor', lazy='dynamic') 49 | 50 | def __repr__(self): 51 | return f'{self.processor}' 52 | 53 | 54 | class Memory(db.Model): 55 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 56 | memory = db.Column(db.String) 57 | specifications = db.relationship('Specification', backref='memory', lazy='dynamic') 58 | 59 | def __repr__(self): 60 | return f'{self.memory}' 61 | 62 | 63 | class Storage(db.Model): 64 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 65 | storage = db.Column(db.String) 66 | specifications = db.relationship('Specification', backref='storage', lazy='dynamic') 67 | 68 | def __repr__(self): 69 | return f'{self.storage}' 70 | 71 | 72 | class Specification(db.Model): 73 | __tablename__ = 'specifications' 74 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 75 | processor_id = db.Column(db.Integer, db.ForeignKey(Processor.id)) 76 | screen_id = db.Column(db.Integer, db.ForeignKey(Screen.id)) 77 | memory_id = db.Column(db.Integer, db.ForeignKey(Memory.id)) 78 | storage_id = db.Column(db.Integer, db.ForeignKey(Storage.id)) 79 | products = db.relationship('Product', backref='spec', lazy='dynamic') 80 | 81 | 82 | def __repr__(self): 83 | return f'{self.screen}, {self.processor}, {self.memory}, {self.storage}' 84 | 85 | 86 | class Product(db.Model): 87 | __tablename__ = 'products' 88 | id = db.Column(db.Integer, primary_key=True, autoincrement=True) 89 | price = db.Column(db.String) 90 | year_id = db.Column(db.Integer, db.ForeignKey(Year.id)) 91 | spec_id = db.Column(db.Integer, db.ForeignKey(Specification.id)) 92 | brand_id = db.Column(db.Integer, db.ForeignKey(Brand.id)) 93 | image_id = db.Column(db.Integer, db.ForeignKey(Image.id)) -------------------------------------------------------------------------------- /app/static/styles_product.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Arial, Helvetica, sans-serif; 4 | background: #fff; 5 | color: #363734; 6 | font-size: 16px; 7 | line-height: 1.7; 8 | text-align: center; 9 | } 10 | 11 | img { 12 | display: block; 13 | width: 100%; 14 | height: auto; 15 | } 16 | 17 | h1, h2, h3 { 18 | margin: 0.8em 0; 19 | padding: 0; 20 | } 21 | 22 | h1 { 23 | font-size: 2.8em; 24 | } 25 | 26 | h2 { 27 | font-size: 2em; 28 | } 29 | 30 | .fading-grey { 31 | opacity: 0.7; 32 | } 33 | 34 | 35 | p { 36 | margin-bottom: 1em; 37 | padding: 0; 38 | font-size: 1em; 39 | } 40 | 41 | .btn { 42 | background: #ebae3d; 43 | color: #fff; 44 | text-decoration: none; 45 | padding: 0.5em 2em; 46 | /*border: 1px solid #363734;*/ 47 | display: inline-block; 48 | margin: 1em 0; 49 | /*opacity: 0.9;*/ 50 | } 51 | 52 | .btn:hover { 53 | background: rgba(54, 55, 52, 0.8); 54 | color: #fff; 55 | } 56 | 57 | .orange { 58 | color: #ebae3d; 59 | } 60 | 61 | /* Header showcase*/ 62 | 63 | #showcase { 64 | min-height: 200px; 65 | color: #fff; 66 | text-align: center; 67 | } 68 | 69 | #showcase .bg-image { 70 | position: absolute; 71 | background: #363734; 72 | background-position: center; 73 | background-repeat: no-repeat; 74 | background-size: 400px; 75 | width: 100%; 76 | height: 200px; 77 | z-index: -1; 78 | /*opacity: 0.4;*/ 79 | 80 | } 81 | 82 | #price h2 { 83 | margin-top: 0.1em; 84 | margin-bottom: 0.2em; 85 | } 86 | 87 | #showcase h1 { 88 | padding-top: 0.3em; 89 | padding-bottom: 0; 90 | margin-top: 0; 91 | margin-bottom: 0.3em; 92 | } 93 | 94 | #showcase .content-wrap { 95 | padding: 0; 96 | } 97 | 98 | #theme { 99 | padding-bottom: 0; 100 | /*text-align: left;*/ 101 | } 102 | 103 | #footer { 104 | background: #363734; 105 | color: #fff; 106 | } 107 | 108 | .content-wrap, 109 | .theme-wrap, 110 | .image-wrap, 111 | .specification-wrap, 112 | .price-wrap, 113 | .description-wrap, 114 | .footer-wrap { 115 | margin: 0; 116 | /*padding: 1em;*/ 117 | /*border: 1px solid red;*/ 118 | } 119 | 120 | .price-wrap { 121 | border-top: 4px solid rgba(54, 55, 52, 0.5); 122 | border-bottom: 4px solid rgba(54, 55, 52, 0.5); 123 | } 124 | 125 | .footer-wrap { 126 | padding: 0.8em; 127 | } 128 | 129 | 130 | 131 | @media(min-width: 1200px) { 132 | 133 | body { 134 | font-size: 20px; 135 | } 136 | 137 | .grid { 138 | display: grid; 139 | grid-template-columns: 1fr 2fr 2fr 1fr; 140 | /*grid-auto-rows: minmax(auto, 10px);*/ 141 | /*border: 1px solid green;*/ 142 | grid-gap: 1em; 143 | 144 | } 145 | 146 | .content-wrap, 147 | .theme-wrap, 148 | .footer-wrap { 149 | grid-column: 2/4; 150 | 151 | } 152 | 153 | .image-wrap { 154 | grid-column: 2/3; 155 | grid-row: 1/3; 156 | align-self: center; 157 | /*align-items: center;*/ 158 | 159 | } 160 | 161 | .specification-wrap { 162 | grid-column: 3/4; 163 | grid-row: 1/2; 164 | } 165 | 166 | .price-wrap { 167 | grid-column: 3/4; 168 | align-self: end; 169 | grid-row: 2/3; 170 | } 171 | 172 | .description-wrap { 173 | grid-column: 2/4; 174 | align-self: end; 175 | } 176 | 177 | 178 | 179 | 180 | .specification-wrap h2, 181 | .price-wrap h2 { 182 | margin: 0; 183 | 184 | } 185 | 186 | } 187 | 188 | @media screen and (max-width: 1200px) and (min-width: 700px) { 189 | 190 | body { 191 | font-size: 18px; 192 | } 193 | 194 | .grid { 195 | display: grid; 196 | grid-template-columns: 1fr 1fr; 197 | /*grid-auto-rows: minmax(auto, 100px);*/ 198 | /*border: 1px solid green;*/ 199 | grid-gap: 1em; 200 | 201 | } 202 | 203 | .content-wrap, 204 | .theme-wrap, 205 | .footer-wrap { 206 | grid-column: 1/3; 207 | 208 | } 209 | 210 | .image-wrap { 211 | grid-column: 1/2; 212 | grid-row: 1/3; 213 | align-self: center; 214 | /*align-items: center;*/ 215 | } 216 | 217 | .specification-wrap { 218 | grid-column: 2/3; 219 | grid-row: 1/2; 220 | } 221 | 222 | .price-wrap { 223 | grid-column: 2/3; 224 | align-self: end; 225 | grid-row: 2/3; 226 | } 227 | 228 | .description-wrap { 229 | grid-column: 1/3; 230 | align-self: end; 231 | } 232 | 233 | 234 | 235 | 236 | .specification-wrap h2, 237 | .price-wrap h2 { 238 | margin: 0; 239 | 240 | } 241 | 242 | } --------------------------------------------------------------------------------