diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..70f5ed3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = tab +indent_size = 4 +tab_width = 4 + +[*.{json,txt,js}] +indent_style = space +indent_size = 2 + +[*.txt] +end_of_line = crlf diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e3578aa --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "standard" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c7867e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,172 @@ +# Created by https://www.gitignore.io/api/node,sublimetext,windows,macos,sass + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# next.js build output +.next + +# nuxt.js build output +.nuxt + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless + +### Sass ### +.sass-cache/ +*.css.map +*.sass.map +*.scss.map + +### SublimeText ### +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +# End of https://www.gitignore.io/api/node,sublimetext,windows,macos,sass + +dist/ diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..3dce7a2 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,8 @@ +"rules": { + "block-no-empty": true, + "color-hex-case": "lower", + "color-hex-length": "short", + "color-no-invalid-hex": true, + "declaration-colon-space-after": "always", + "max-empty-lines": 2 +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d71db49 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,75 @@ +# CHANGELOG.md + +## 1.1.3 (Dec 16, 2018) + +##### Update PDF file +* /Evelyn.pdf + +## 1.1.2 (Nov 19, 2018) + +##### Update PDF file +* /Evelyn.pdf + +## 1.1.1 (Nov 8, 2018) + +##### Fix typo +* /index.html + +## 1.1.0 (Oct 5, 2018) + +##### Update license and PDF +* /Evelyn.pdf +* /package-sample.json +* /LICENSE + +## 1.0.9 (Sep 25, 2018) + +##### Fix minor typographic issue and small buttons fix +* /src/scss/base/_typography.scss +* /src/scss/components/_buttons.scss + +## 1.0.8 (Sep 18, 2018) + +##### Fix forms and buttons height issue on Safari +* /src/scss/components/_buttons.scss + +## 1.0.7 (Sep 15, 2018) + +##### Minor CSS fix +* /src/scss/layout/_features.scss + +## 1.0.6 (Sep 13, 2018) + +##### Minor CSS fix +* /src/scss/base/_base.scss +* /src/scss/layout/_features-extended.scss + +## 1.0.5 (Sep 11, 2018) + +##### Update license +* /package-sample.json +* /LICENSE.rtf + +## 1.0.4 (Sep 11, 2018) + +##### Keep animating elements visible when animations are disabled +* /src/scss/base/_helpers.scss + +## 1.0.3 (Sep 10, 2018) + +##### Fix issue with not clickable button +* /src/scss/layout/_pricing.scss + +## 1.0.2 (Sep 10, 2018) + +##### Fix buttons aspect conflict +* /src/scss/layout/_buttons.scss + +## 1.0.1 (Sep 10, 2018) + +##### Fixed typo +* /src/scss/layout/_footer.scss + +## 1.0.0 (Aug 27, 2018) + +First release diff --git a/Evelyn.pdf b/Evelyn.pdf new file mode 100644 index 0000000..db5b24a Binary files /dev/null and b/Evelyn.pdf differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5f37774 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + {one line to give the program's name and a brief idea of what it does.} + Copyright (C) {year} {name of author} + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + {project} Copyright (C) {year} {fullname} + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/index.html b/index.html new file mode 100644 index 0000000..d5580d8 --- /dev/null +++ b/index.html @@ -0,0 +1,421 @@ + + + + + + + Evelyn Template + + + + + +
+ + +
+
+
+
+

Landing template for startups

+

Our landing page template works on all devices, so you only have to set it up once, and get beautiful results forever.

+

Get started now

+
+
+
+
+
+ +
+
+
+
+
    +
  • + Instagram + + + +
  • +
  • + Dell + + + +
  • +
  • + Unilever + + + + + +
  • +
  • + Uber + + + +
  • +
+
+
+
+
+ +
+
+
+

Product features

+
+
+
+
+ + + + + + +
+

Lorem Ipsum

+

often arouses curiosity due to its resemblance to classical latin

+
+
+
+
+
+ + + + + + + +
+

Lorem Ipsum

+

often arouses curiosity due to its resemblance to classical latin

+
+
+
+
+
+ + + + + + +
+

Lorem Ipsum

+

often arouses curiosity due to its resemblance to classical latin

+
+
+
+
+
+ + + + + + + +
+

Lorem Ipsum

+

often arouses curiosity due to its resemblance to classical latin

+
+
+
+
+
+
+ +
+
+
+
+
+

Meet Evelyn

+

Lorem ipsum is common placeholder text used to demonstrate the graphic elements of a document or visual presentation

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+

Discover

+

Where text is visible, people tend to focus on the textual content rather than upon overall presentation

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+

Discover

+

Where text is visible, people tend to focus on the textual content rather than upon overall presentation

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + +
+
+

Discover

+

Where text is visible, people tend to focus on the textual content rather than upon overall presentation

+
+
+
+
+
+ +
+
+
+

Pricing

+
+
+
+
+
+
Lorem ipsum
+
$29
+
+
    +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
+
+ +
+
+
+
+
+
+
Lorem ipsum
+
$129
+
+
    +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
  • + + + + + + Sed do eiusmod tempor cesa. +
  • +
+
+ +
+
+
+
+
+
+
+ + +
+ + + diff --git a/package-sample.json b/package-sample.json new file mode 100644 index 0000000..c47afaf --- /dev/null +++ b/package-sample.json @@ -0,0 +1,54 @@ +{ + "name": "evelyn", + "version": "1.0.0", + "description": "Evelyn Template", + "author": "Pasquale Vitiello ", + "license": "GPLv3", + "repository": { + "type": "git", + "url": "https://bitbucket.org/pasqualevitiello/evelyn.git" + }, + "bugs": { + "url": "https://bitbucket.org/pasqualevitiello/evelyn/issues" + }, + "scripts": { + "clean": "rimraf dist/{css/*,js/*,images/*}", + "autoprefixer": "postcss -u autoprefixer -r dist/css/*", + "scss": "node-sass --output-style compressed -o dist/css src/scss", + "lint": "eslint src/js || true", + "lint-scss": "stylelint src/scss/*.scss --syntax scss || true", + "uglify": "mkdirp dist/js -p && uglifyjs src/js/*.js -m -c -o dist/js/main.min.js", + "imagemin": "imagemin src/images/* -o dist/images", + "serve": "browser-sync start --server --files \"dist/css/*.css, dist/js/*.js, **/*.html, !node_modules/**/*.html\"", + "build:css": "run-s lint-scss scss autoprefixer", + "build:js": "run-s lint uglify", + "build:images": "run-s imagemin", + "build": "run-s build:*", + "watch:css": "onchange \"src/scss\" -- run-s build:css", + "watch:js": "onchange \"src/js\" -- run-s build:js", + "watch:images": "onchange \"src/images\" -- run-s build:images", + "watch": "run-p serve watch:*", + "postinstall": "run-s build watch" + }, + "devDependencies": { + "autoprefixer": "^9.0.1", + "browser-sync": "^2.12.8", + "eslint": "^5.2.0", + "eslint-config-standard": "^12.0.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-node": "^7.0.1", + "eslint-plugin-promise": "^3.8.0", + "eslint-plugin-standard": "^3.1.0", + "imagemin-cli": "^3.0.0", + "mkdirp": "^0.5.1", + "node-sass": "^4.9.2", + "npm-run-all": "^4.1.3", + "onchange": "^4.1.0", + "postcss-cli": "^6.0.0", + "rimraf": "^2.5.4", + "stylelint": "^9.4.0", + "uglify-es": "^3.3.10" + }, + "homepage": "https://bitbucket.org/pasqualevitiello/evelyn#readme", + "main": ".eslintrc.js" +} diff --git a/src/js/main.js b/src/js/main.js new file mode 100644 index 0000000..309614d --- /dev/null +++ b/src/js/main.js @@ -0,0 +1,36 @@ +(function () { + const doc = document.documentElement + + doc.classList.remove('no-js') + doc.classList.add('js') + + // Reveal animations + if (document.body.classList.contains('has-animations')) { + /* global ScrollReveal */ + const sr = window.sr = ScrollReveal() + + sr.reveal('.hero-title, .hero-paragraph, .hero-cta', { + duration: 1000, + distance: '40px', + easing: 'cubic-bezier(0.5, -0.01, 0, 1.005)', + origin: 'bottom', + interval: 150 + }) + + sr.reveal('.feature, .pricing-table', { + duration: 600, + distance: '40px', + easing: 'cubic-bezier(0.5, -0.01, 0, 1.005)', + interval: 100, + origin: 'bottom', + viewFactor: 0.5 + }) + + sr.reveal('.feature-extended-image', { + duration: 600, + scale: 0.9, + easing: 'cubic-bezier(0.5, -0.01, 0, 1.005)', + viewFactor: 0.5 + }) + } +}()) diff --git a/src/scss/_normalize.scss b/src/scss/_normalize.scss new file mode 100644 index 0000000..8025dce --- /dev/null +++ b/src/scss/_normalize.scss @@ -0,0 +1,231 @@ +html { + line-height: 1.15; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +article, +aside, +footer, +header, +nav, +section { + display: block; +} + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +figcaption, +figure, +main { + display: block; +} + +figure { + margin: 1em 40px; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +pre { + font-family: monospace, monospace; + font-size: 1em; +} + +a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +abbr[title] { + border-bottom: none; + text-decoration: underline; + text-decoration: underline dotted; +} + +b, +strong { + font-weight: inherit; +} + +b, +strong { + font-weight: bolder; +} + +code, +kbd, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +dfn { + font-style: italic; +} + +mark { + background-color: #ff0; + color: #000; +} + +small { + font-size: 80%; +} + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +audio, +video { + display: inline-block; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +img { + border-style: none; +} + +svg:not(:root) { + overflow: hidden; +} + +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; + font-size: 100%; + line-height: 1.15; + margin: 0; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +legend { + box-sizing: border-box; + color: inherit; + display: table; + max-width: 100%; + padding: 0; + white-space: normal; +} + +progress { + display: inline-block; + vertical-align: baseline; +} + +textarea { + overflow: auto; +} + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; + padding: 0; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + -webkit-appearance: textfield; + outline-offset: -2px; +} + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} + +details, +menu { + display: block; +} + +summary { + display: list-item; +} + +canvas { + display: inline-block; +} + +template { + display: none; +} + +[hidden] { + display: none; +} \ No newline at end of file diff --git a/src/scss/abstracts/_functions.scss b/src/scss/abstracts/_functions.scss new file mode 100644 index 0000000..6aa6a1c --- /dev/null +++ b/src/scss/abstracts/_functions.scss @@ -0,0 +1,55 @@ +// -------------------------------------------------------------------- +// Retrieve Font Size ------------------------------------------------- +// Used in _mixins.scss [@mixin font-size] ---------------------------- +// -------------------------------------------------------------------- +@function get-font-size($size, $elem) { + @return nth(map-get(map-get($font__scale, $elem), $size), 1); +} + +// -------------------------------------------------------------------- +// Retrieve Line Height ----------------------------------------------- +// Used in _mixins.scss [@mixin font-size] ---------------------------- +// -------------------------------------------------------------------- +@function get-line-height($size, $elem) { + @return nth(map-get(map-get($font__scale, $elem), $size), 2); +} + +// -------------------------------------------------------------------- +// Retrieve Kerning --------------------------------------------------- +// Used in _mixins.scss [@mixin font-size] ---------------------------- +// -------------------------------------------------------------------- +@function get-kerning($size, $elem) { + @return nth(map-get(map-get($font__scale, $elem), $size), 3); +} + +// -------------------------------------------------------------------- +// Retrieve Font Family ----------------------------------------------- +// Used in _mixins.scss [@mixin font-family] -------------------------- +// -------------------------------------------------------------------- +@function get-font-family($elem) { + @return map-get($font__family, $elem); +} + +// -------------------------------------------------------------------- +// Retrieve Font Weight ----------------------------------------------- +// Used in _mixins.scss [@mixin font-weight] -------------------------- +// -------------------------------------------------------------------- +@function get-font-weight($elem) { + @return map-get($font__weight, $elem); +} + +// -------------------------------------------------------------------- +// Retrieve Padding of Content Area Elements -------------------------- +// Used in _mixins.scss [@mixin font-size] ---------------------------- +// -------------------------------------------------------------------- +@function get-content-padding($elem) { + @return map-get($content__padding, $elem); +} + +// -------------------------------------------------------------------- +// Retrieve Colors ---------------------------------------------------- +// Usage: color(typography, 1) ---------------------------------------------- +// -------------------------------------------------------------------- +@function color($elem, $variant) { + @return map-get(map-get($color, $elem), $variant); +} diff --git a/src/scss/abstracts/_include-media.scss b/src/scss/abstracts/_include-media.scss new file mode 100644 index 0000000..bb5ccd5 --- /dev/null +++ b/src/scss/abstracts/_include-media.scss @@ -0,0 +1,567 @@ +@charset "UTF-8"; + +// _ _ _ _ _ +// (_) | | | | | (_) +// _ _ __ ___| |_ _ __| | ___ _ __ ___ ___ __| |_ __ _ +// | | '_ \ / __| | | | |/ _` |/ _ \ | '_ ` _ \ / _ \/ _` | |/ _` | +// | | | | | (__| | |_| | (_| | __/ | | | | | | __/ (_| | | (_| | +// |_|_| |_|\___|_|\__,_|\__,_|\___| |_| |_| |_|\___|\__,_|_|\__,_| +// +// Simple, elegant and maintainable media queries in Sass +// v1.4.9 +// +// http://include-media.com +// +// Authors: Eduardo Boucas (@eduardoboucas) +// Hugo Giraudel (@hugogiraudel) +// +// This project is licensed under the terms of the MIT license + + +//// +/// include-media library public configuration +/// @author Eduardo Boucas +/// @access public +//// + + +/// +/// Creates a list of global breakpoints +/// +/// @example scss - Creates a single breakpoint with the label `phone` +/// $breakpoints: ('phone': 320px); +/// +$breakpoints: ( + 'small': 480px, + 'medium': 640px, + 'large': 1024px, +) !default; + + +/// +/// Creates a list of static expressions or media types +/// +/// @example scss - Creates a single media type (screen) +/// $media-expressions: ('screen': 'screen'); +/// +/// @example scss - Creates a static expression with logical disjunction (OR operator) +/// $media-expressions: ( +/// 'retina2x': '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)' +/// ); +/// +$media-expressions: ( + 'screen': 'screen', + 'print': 'print', + 'handheld': 'handheld', + 'landscape': '(orientation: landscape)', + 'portrait': '(orientation: portrait)', + 'retina2x': '(-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi), (min-resolution: 2dppx)', + 'retina3x': '(-webkit-min-device-pixel-ratio: 3), (min-resolution: 350dpi), (min-resolution: 3dppx)' +) !default; + + +/// +/// Defines a number to be added or subtracted from each unit when declaring breakpoints with exclusive intervals +/// +/// @example scss - Interval for pixels is defined as `1` by default +/// @include media('>128px') {} +/// +/// /* Generates: */ +/// @media (min-width: 129px) {} +/// +/// @example scss - Interval for ems is defined as `0.01` by default +/// @include media('>20em') {} +/// +/// /* Generates: */ +/// @media (min-width: 20.01em) {} +/// +/// @example scss - Interval for rems is defined as `0.1` by default, to be used with `font-size: 62.5%;` +/// @include media('>2.0rem') {} +/// +/// /* Generates: */ +/// @media (min-width: 2.1rem) {} +/// +$unit-intervals: ( + 'px': 1, + 'em': 0.01, + 'rem': 0.1, + '': 0 +) !default; + +/// +/// Defines whether support for media queries is available, useful for creating separate stylesheets +/// for browsers that don't support media queries. +/// +/// @example scss - Disables support for media queries +/// $im-media-support: false; +/// @include media('>=tablet') { +/// .foo { +/// color: tomato; +/// } +/// } +/// +/// /* Generates: */ +/// .foo { +/// color: tomato; +/// } +/// +$im-media-support: true !default; + +/// +/// Selects which breakpoint to emulate when support for media queries is disabled. Media queries that start at or +/// intercept the breakpoint will be displayed, any others will be ignored. +/// +/// @example scss - This media query will show because it intercepts the static breakpoint +/// $im-media-support: false; +/// $im-no-media-breakpoint: 'desktop'; +/// @include media('>=tablet') { +/// .foo { +/// color: tomato; +/// } +/// } +/// +/// /* Generates: */ +/// .foo { +/// color: tomato; +/// } +/// +/// @example scss - This media query will NOT show because it does not intercept the desktop breakpoint +/// $im-media-support: false; +/// $im-no-media-breakpoint: 'tablet'; +/// @include media('>=desktop') { +/// .foo { +/// color: tomato; +/// } +/// } +/// +/// /* No output */ +/// +$im-no-media-breakpoint: 'desktop' !default; + +/// +/// Selects which media expressions are allowed in an expression for it to be used when media queries +/// are not supported. +/// +/// @example scss - This media query will show because it intercepts the static breakpoint and contains only accepted media expressions +/// $im-media-support: false; +/// $im-no-media-breakpoint: 'desktop'; +/// $im-no-media-expressions: ('screen'); +/// @include media('>=tablet', 'screen') { +/// .foo { +/// color: tomato; +/// } +/// } +/// +/// /* Generates: */ +/// .foo { +/// color: tomato; +/// } +/// +/// @example scss - This media query will NOT show because it intercepts the static breakpoint but contains a media expression that is not accepted +/// $im-media-support: false; +/// $im-no-media-breakpoint: 'desktop'; +/// $im-no-media-expressions: ('screen'); +/// @include media('>=tablet', 'retina2x') { +/// .foo { +/// color: tomato; +/// } +/// } +/// +/// /* No output */ +/// +$im-no-media-expressions: ('screen', 'portrait', 'landscape') !default; + +//// +/// Cross-engine logging engine +/// @author Hugo Giraudel +/// @access private +//// + + +/// +/// Log a message either with `@error` if supported +/// else with `@warn`, using `feature-exists('at-error')` +/// to detect support. +/// +/// @param {String} $message - Message to log +/// +@function im-log($message) { + @if feature-exists('at-error') { + @error $message; + } @else { + @warn $message; + $_: noop(); + } + + @return $message; +} + + +/// +/// Wrapper mixin for the log function so it can be used with a more friendly +/// API than `@if im-log('..') {}` or `$_: im-log('..')`. Basically, use the function +/// within functions because it is not possible to include a mixin in a function +/// and use the mixin everywhere else because it's much more elegant. +/// +/// @param {String} $message - Message to log +/// +@mixin log($message) { + @if im-log($message) {} +} + + +/// +/// Function with no `@return` called next to `@warn` in Sass 3.3 +/// to trigger a compiling error and stop the process. +/// +@function noop() {} + +/// +/// Determines whether a list of conditions is intercepted by the static breakpoint. +/// +/// @param {Arglist} $conditions - Media query conditions +/// +/// @return {Boolean} - Returns true if the conditions are intercepted by the static breakpoint +/// +@function im-intercepts-static-breakpoint($conditions...) { + $no-media-breakpoint-value: map-get($breakpoints, $im-no-media-breakpoint); + + @if not $no-media-breakpoint-value { + @if im-log('`#{$im-no-media-breakpoint}` is not a valid breakpoint.') {} + } + + @each $condition in $conditions { + @if not map-has-key($media-expressions, $condition) { + $operator: get-expression-operator($condition); + $prefix: get-expression-prefix($operator); + $value: get-expression-value($condition, $operator); + + @if ($prefix == 'max' and $value <= $no-media-breakpoint-value) or + ($prefix == 'min' and $value > $no-media-breakpoint-value) { + @return false; + } + } @else if not index($im-no-media-expressions, $condition) { + @return false; + } + } + + @return true; +} + +//// +/// Parsing engine +/// @author Hugo Giraudel +/// @access private +//// + + +/// +/// Get operator of an expression +/// +/// @param {String} $expression - Expression to extract operator from +/// +/// @return {String} - Any of `>=`, `>`, `<=`, `<`, `≥`, `≤` +/// +@function get-expression-operator($expression) { + @each $operator in ('>=', '>', '<=', '<', '≥', '≤') { + @if str-index($expression, $operator) { + @return $operator; + } + } + + // It is not possible to include a mixin inside a function, so we have to + // rely on the `im-log(..)` function rather than the `log(..)` mixin. Because + // functions cannot be called anywhere in Sass, we need to hack the call in + // a dummy variable, such as `$_`. If anybody ever raise a scoping issue with + // Sass 3.3, change this line in `@if im-log(..) {}` instead. + $_: im-log('No operator found in `#{$expression}`.'); +} + + +/// +/// Get dimension of an expression, based on a found operator +/// +/// @param {String} $expression - Expression to extract dimension from +/// @param {String} $operator - Operator from `$expression` +/// +/// @return {String} - `width` or `height` (or potentially anything else) +/// +@function get-expression-dimension($expression, $operator) { + $operator-index: str-index($expression, $operator); + $parsed-dimension: str-slice($expression, 0, $operator-index - 1); + $dimension: 'width'; + + @if str-length($parsed-dimension) > 0 { + $dimension: $parsed-dimension; + } + + @return $dimension; +} + + +/// +/// Get dimension prefix based on an operator +/// +/// @param {String} $operator - Operator +/// +/// @return {String} - `min` or `max` +/// +@function get-expression-prefix($operator) { + @return if(index(('<', '<=', '≤'), $operator), 'max', 'min'); +} + + +/// +/// Get value of an expression, based on a found operator +/// +/// @param {String} $expression - Expression to extract value from +/// @param {String} $operator - Operator from `$expression` +/// +/// @return {Number} - A numeric value +/// +@function get-expression-value($expression, $operator) { + $operator-index: str-index($expression, $operator); + $value: str-slice($expression, $operator-index + str-length($operator)); + + @if map-has-key($breakpoints, $value) { + $value: map-get($breakpoints, $value); + } @else { + $value: to-number($value); + } + + $interval: map-get($unit-intervals, unit($value)); + + @if not $interval { + // It is not possible to include a mixin inside a function, so we have to + // rely on the `im-log(..)` function rather than the `log(..)` mixin. Because + // functions cannot be called anywhere in Sass, we need to hack the call in + // a dummy variable, such as `$_`. If anybody ever raise a scoping issue with + // Sass 3.3, change this line in `@if im-log(..) {}` instead. + $_: im-log('Unknown unit `#{unit($value)}`.'); + } + + @if $operator == '>' { + $value: $value + $interval; + } @else if $operator == '<' { + $value: $value - $interval; + } + + @return $value; +} + + +/// +/// Parse an expression to return a valid media-query expression +/// +/// @param {String} $expression - Expression to parse +/// +/// @return {String} - Valid media query +/// +@function parse-expression($expression) { + // If it is part of $media-expressions, it has no operator + // then there is no need to go any further, just return the value + @if map-has-key($media-expressions, $expression) { + @return map-get($media-expressions, $expression); + } + + $operator: get-expression-operator($expression); + $dimension: get-expression-dimension($expression, $operator); + $prefix: get-expression-prefix($operator); + $value: get-expression-value($expression, $operator); + + @return '(#{$prefix}-#{$dimension}: #{$value})'; +} + +/// +/// Slice `$list` between `$start` and `$end` indexes +/// +/// @access private +/// +/// @param {List} $list - List to slice +/// @param {Number} $start [1] - Start index +/// @param {Number} $end [length($list)] - End index +/// +/// @return {List} Sliced list +/// +@function slice($list, $start: 1, $end: length($list)) { + @if length($list) < 1 or $start > $end { + @return (); + } + + $result: (); + + @for $i from $start through $end { + $result: append($result, nth($list, $i)); + } + + @return $result; +} + +//// +/// String to number converter +/// @author Hugo Giraudel +/// @access private +//// + + +/// +/// Casts a string into a number +/// +/// @param {String | Number} $value - Value to be parsed +/// +/// @return {Number} +/// +@function to-number($value) { + @if type-of($value) == 'number' { + @return $value; + } @else if type-of($value) != 'string' { + $_: im-log('Value for `to-number` should be a number or a string.'); + } + + $first-character: str-slice($value, 1, 1); + $result: 0; + $digits: 0; + $minus: ($first-character == '-'); + $numbers: ('0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9); + + // Remove +/- sign if present at first character + @if ($first-character == '+' or $first-character == '-') { + $value: str-slice($value, 2); + } + + @for $i from 1 through str-length($value) { + $character: str-slice($value, $i, $i); + + @if not (index(map-keys($numbers), $character) or $character == '.') { + @return to-length(if($minus, -$result, $result), str-slice($value, $i)) + } + + @if $character == '.' { + $digits: 1; + } @else if $digits == 0 { + $result: $result * 10 + map-get($numbers, $character); + } @else { + $digits: $digits * 10; + $result: $result + map-get($numbers, $character) / $digits; + } + } + + @return if($minus, -$result, $result); +} + + +/// +/// Add `$unit` to `$value` +/// +/// @param {Number} $value - Value to add unit to +/// @param {String} $unit - String representation of the unit +/// +/// @return {Number} - `$value` expressed in `$unit` +/// +@function to-length($value, $unit) { + $units: ('px': 1px, 'cm': 1cm, 'mm': 1mm, '%': 1%, 'ch': 1ch, 'pc': 1pc, 'in': 1in, 'em': 1em, 'rem': 1rem, 'pt': 1pt, 'ex': 1ex, 'vw': 1vw, 'vh': 1vh, 'vmin': 1vmin, 'vmax': 1vmax); + + @if not index(map-keys($units), $unit) { + $_: im-log('Invalid unit `#{$unit}`.'); + } + + @return $value * map-get($units, $unit); +} + +/// +/// This mixin aims at redefining the configuration just for the scope of +/// the call. It is helpful when having a component needing an extended +/// configuration such as custom breakpoints (referred to as tweakpoints) +/// for instance. +/// +/// @author Hugo Giraudel +/// +/// @param {Map} $tweakpoints [()] - Map of tweakpoints to be merged with `$breakpoints` +/// @param {Map} $tweak-media-expressions [()] - Map of tweaked media expressions to be merged with `$media-expression` +/// +/// @example scss - Extend the global breakpoints with a tweakpoint +/// @include media-context(('custom': 678px)) { +/// .foo { +/// @include media('>phone', '<=custom') { +/// // ... +/// } +/// } +/// } +/// +/// @example scss - Extend the global media expressions with a custom one +/// @include media-context($tweak-media-expressions: ('all': 'all')) { +/// .foo { +/// @include media('all', '>phone') { +/// // ... +/// } +/// } +/// } +/// +/// @example scss - Extend both configuration maps +/// @include media-context(('custom': 678px), ('all': 'all')) { +/// .foo { +/// @include media('all', '>phone', '<=custom') { +/// // ... +/// } +/// } +/// } +/// +@mixin media-context($tweakpoints: (), $tweak-media-expressions: ()) { + // Save global configuration + $global-breakpoints: $breakpoints; + $global-media-expressions: $media-expressions; + + // Update global configuration + $breakpoints: map-merge($breakpoints, $tweakpoints) !global; + $media-expressions: map-merge($media-expressions, $tweak-media-expressions) !global; + + @content; + + // Restore global configuration + $breakpoints: $global-breakpoints !global; + $media-expressions: $global-media-expressions !global; +} + +//// +/// include-media public exposed API +/// @author Eduardo Boucas +/// @access public +//// + + +/// +/// Generates a media query based on a list of conditions +/// +/// @param {Arglist} $conditions - Media query conditions +/// +/// @example scss - With a single set breakpoint +/// @include media('>phone') { } +/// +/// @example scss - With two set breakpoints +/// @include media('>phone', '<=tablet') { } +/// +/// @example scss - With custom values +/// @include media('>=358px', '<850px') { } +/// +/// @example scss - With set breakpoints with custom values +/// @include media('>desktop', '<=1350px') { } +/// +/// @example scss - With a static expression +/// @include media('retina2x') { } +/// +/// @example scss - Mixing everything +/// @include media('>=350px', ' 0) { + @media #{unquote(parse-expression(nth($conditions, 1)))} { + // Recursive call + @include media(slice($conditions, 2)...) { + @content; + } + } + } +} diff --git a/src/scss/abstracts/_mixins.scss b/src/scss/abstracts/_mixins.scss new file mode 100644 index 0000000..0a3e1ee --- /dev/null +++ b/src/scss/abstracts/_mixins.scss @@ -0,0 +1,103 @@ +// Font-size + Line-height + Kerning +// Usage: @include font-size(1, mobile) +// Add more true/false args to control what to output: font-size, line-height, kerning +@mixin font-size($size, $elem, $font-size: true, $line-height: false, $kerning: false, $adjust-font-size: 0) { + @if not map-has-key(map-get($font__scale, $elem), $size) { + @warn "'#{$size}' key does not exist in array!"; + } + @if ( $font-size != false ) { + font-size: get-font-size($size, $elem) + $adjust-font-size; + } + @if ( $line-height == true ) { + line-height: get-line-height($size, $elem); + } + @if ( $kerning == true ) { + letter-spacing: get-kerning($size, $elem); + } +} + +// Font Family +@mixin font-family($elem) { + font-family: unquote(get-font-family($elem)); +} + +// Font Weight +@mixin font-weight($elem) { + font-weight: get-font-weight($elem); +} + +// Anchor aspect +@mixin anchor-aspect($type: 'main') { + @if ($type == 'main') { // Base + color: inherit; + text-decoration: underline; + + &:hover, + &:active { + outline: 0; + text-decoration: none; + } + } @else if ($type == 'header') { + color: color(typography, 2i); + text-transform: uppercase; + text-decoration: none; + + &:hover, + &:active { + color: color(typography, 1i); + } + } @else if ($type == 'footer') { + color: color(typography, 3); + text-decoration: none; + + &:hover, + &:active { + color: color(typography, 2); + text-decoration: underline; + } + } +} + +@mixin shadow { + box-shadow: 0 16px 48px color(bg, 3); + + /* Edge fallback */ + @supports(-ms-ime-align:auto) { + box-shadow: 0 16px 48px rgba(color(typography, 1), .12); + } +} + +@mixin divider-mix { + display: block; + height: 1px; + background: color(bg, 3); + background: linear-gradient(to right, rgba(color(bg, 3), .1) 0, rgba(color(bg, 3), .6) 50%, rgba(color(bg, 3), .1) 100%); +} + +@mixin divider($type: false) { + @if ( $type == 'before' ) { + position: relative; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + @include divider-mix; + } + } @else if ($type == 'after') { + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + @include divider-mix; + } + } @else { + @include divider-mix; + } +} diff --git a/src/scss/abstracts/_variables.scss b/src/scss/abstracts/_variables.scss new file mode 100644 index 0000000..cf4265f --- /dev/null +++ b/src/scss/abstracts/_variables.scss @@ -0,0 +1,95 @@ +// -------------------------------------------- +// Colors ------------------------------------- +// Usage example: color(primary, main) +// -------------------------------------------- +$color: ( + typography: ( + 1: #202B36, + 2: #5B6F82, + 3: #92A2B1, + 1i: #FFF, + 2i: rgba( #FFF, .8 ) + ), + bg: ( + 1: #FFFFFF, + 2: #F6F8FA, + 3: #E3E7EB + ), + primary: ( + 1: #00A2B8, + 2: #00CFEB, + 3: #007585, + ), + secondary: ( + 1: #00C6A7, + 2: #00F9D2, + 3: #00937C + ), + additional: ( + 1: #00C6A7, + 2: #1E4D92 + ) +); + +// -------------------------------------------- +// Typography --------------------------------- +// -------------------------------------------- +$font__family: ( + base: '"Lato", sans-serif', // font-family(base) + heading: '"PT Serif", serif', // font-family(heading) + code: 'Monaco, Consolas, "Andale Mono", "DejaVu Sans Mono", monospace', // font-family(code) + pre: '"Courier 10 Pitch", Courier, monospace' // font-family(pre) +); + +$font__sizes: ( + alpha: ( 42px, 52px, -0.1px ), // font-size, line-height, kerning (use '0' if don't want to output any kerning) + beta: ( 36px, 46px, -0.2px ), + gamma: ( 30px, 40px, -0.1px ), + delta: ( 20px, 30px, -0.1px ), + epsilon: ( 18px, 27px, -0.1px ), + zeta: ( 16px, 24px, -0.1px ), + eta: ( 14px, 20px, 0px ), + theta: ( 13px, 18px, 0px ) +); + +$font__scale: ( + desktop: ( // i.e. $breakpoint__m + $breakpoint__l (600 - 1024) + 1: map-get($font__sizes, alpha), // H1 + 2: map-get($font__sizes, beta), // H2 + 3: map-get($font__sizes, gamma), // H3 + 4: map-get($font__sizes, delta), // H4, H5, H6 + 5: map-get($font__sizes, delta), // Body + 6: map-get($font__sizes, epsilon), // Text small (e.g. features description) + 7: map-get($font__sizes, zeta), // Text smaller (e.g. pricing table's lists) + 8: map-get($font__sizes, eta), // Footer area + 9: map-get($font__sizes, theta) // Header links, buttons + ), + mobile: ( // i.e. $breakpoint__xs + $breakpoint__s (up to 600) + 1: map-get($font__sizes, beta), // H1 + 2: map-get($font__sizes, gamma), // H2 + 3: map-get($font__sizes, delta), // H3 + 4: map-get($font__sizes, epsilon), // H4, H5, H6 + 5: map-get($font__sizes, epsilon), // Body + 6: map-get($font__sizes, epsilon), // Text small (e.g. features description) + 7: map-get($font__sizes, zeta), // Text smaller (e.g. pricing table's lists) + 8: map-get($font__sizes, eta), // Footer area + 9: map-get($font__sizes, theta) // Header links, buttons + ) +); + +$font__weight: ( + regular: 400, // font__weight(regular) + medium: 500, // font__weight(medium) + semibold: 600, // font__weight(semi-bold) + bold: 700 // font__weight(bold) +); + +// -------------------------------------------- +// Structure ---------------------------------- +// -------------------------------------------- +$content__padding: ( + mobile: 16px, + desktop: 24px +); +$container__width: 1080px; +$container__width-sm: 800px; diff --git a/src/scss/base/_base.scss b/src/scss/base/_base.scss new file mode 100644 index 0000000..77113e3 --- /dev/null +++ b/src/scss/base/_base.scss @@ -0,0 +1,102 @@ +html { + box-sizing: border-box; +} + +*, +*:before, +*:after { /* Inherit box-sizing to make it easier to change the property for components that leverage other behavior; see http://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/ */ + box-sizing: inherit; +} + +body { + background: color(bg, 1); /* Fallback for when there is no custom background color defined. */ + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; +} + +hr { + border: 0; + @include divider(); + margin-top: 24px; + margin-bottom: 24px; +} + +ul, ol { + margin-top: 0; + margin-bottom: 24px; + padding-left: 24px; +} + +ul { + list-style: disc; +} + +ol { + list-style: decimal; +} + +li > ul, +li > ol { + margin-bottom: 0; +} + +dl { + margin-top: 0; + margin-bottom: 24px; +} + +dt { + @include font-weight(bold); +} + +dd { + margin-left: 24px; + margin-bottom: 24px; +} + +img { + height: auto; /* Make sure images are scaled correctly. */ + max-width: 100%; /* Adhere to container width. */ + vertical-align: middle; +} + +figure { + margin: 24px 0; /* Extra wide images within figure tags don't overflow the content area. */ +} + +figcaption { + @include font-size(7, mobile, true, true); + padding: 8px 0; +} + +img, +svg { + display: block; +} + +table { + border-collapse: collapse; + margin-bottom: 24px; + width: 100%; +} + +tr { + border-bottom: 1px solid color(bg, 3); +} + +th { + text-align: left; +} + +th, +td { + padding: 10px 16px; + + &:first-child { + padding-left: 0; + } + + &:last-child { + padding-right: 0; + } +} diff --git a/src/scss/base/_helpers.scss b/src/scss/base/_helpers.scss new file mode 100644 index 0000000..f1c1346 --- /dev/null +++ b/src/scss/base/_helpers.scss @@ -0,0 +1,469 @@ +.container, +.container-sm { + width: 100%; + margin: 0 auto; + padding-left: get-content-padding(mobile); + padding-right: get-content-padding(mobile); + + @include media( '>small' ) { + padding-left: get-content-padding(desktop); + padding-right: get-content-padding(desktop); + } +} + +.container { + max-width: $container__width + ( get-content-padding(desktop) * 2 ); +} + +.container-sm { + max-width: $container__width-sm + ( get-content-padding(desktop) * 2 ); +} + +.container { + + .container-sm { + max-width: $container__width-sm; + padding-left: 0; + padding-right: 0; + } +} + +/* Text meant only for screen readers. */ +.screen-reader-text { + clip: rect(1px, 1px, 1px, 1px); + position: absolute !important; + height: 1px; + width: 1px; + overflow: hidden; + word-wrap: normal !important; /* Many screen reader and browser combinations announce broken words as they would appear visually. */ + + &:focus { + border-radius: 2px; + box-shadow: 0 0 2px 2px rgba(0, 0, 0, 0.6); + clip: auto !important; + display: block; + @include font-size(9, mobile, true, false, true); + @if ( get-font-size(9, desktop) != get-font-size(9, mobile) ) { + @include media( '>medium' ) { + @include font-size(9, desktop, true, false, true); + } + } + @include font-weight(bold); + line-height: 16px; + text-transform: uppercase; + text-decoration: none; + background-color: color(bg, 1); + color: color(primary, 1) !important; + border: none; + height: auto; + left: 8px; + padding: 16px 32px; + top: 8px; + width: auto; + z-index: 100000; + } +} + +.list-reset { + list-style: none; + padding: 0; +} + +.text-left { + text-align: left; +} + +.text-center { + text-align: center; +} + +.text-right { + text-align: right; +} + +.text-primary { + color: color(primary, 1); +} + +.text-secondary { + color: color(secondary, 1); +} + +.has-top-divider { + @include divider(before); +} + +.has-bottom-divider { + @include divider(after); +} + +.m-0 { + margin: 0; +} + +.mt-0 { + margin-top: 0; +} + +.mr-0 { + margin-right: 0; +} + +.mb-0 { + margin-bottom: 0; +} + +.ml-0 { + margin-left: 0; +} + +.m-8 { + margin: 8px; +} + +.mt-8 { + margin-top: 8px; +} + +.mr-8 { + margin-right: 8px; +} + +.mb-8 { + margin-bottom: 8px; +} + +.ml-8 { + margin-left: 8px; +} + +.m-16 { + margin: 16px; +} + +.mt-16 { + margin-top: 16px; +} + +.mr-16 { + margin-right: 16px; +} + +.mb-16 { + margin-bottom: 16px; +} + +.ml-16 { + margin-left: 16px; +} + +.m-24 { + margin: 24px; +} + +.mt-24 { + margin-top: 24px; +} + +.mr-24 { + margin-right: 24px; +} + +.mb-24 { + margin-bottom: 24px; +} + +.ml-24 { + margin-left: 24px; +} + +.m-32 { + margin: 32px; +} + +.mt-32 { + margin-top: 32px; +} + +.mr-32 { + margin-right: 32px; +} + +.mb-32 { + margin-bottom: 32px; +} + +.ml-32 { + margin-left: 32px; +} + +.m-40 { + margin: 40px; +} + +.mt-40 { + margin-top: 40px; +} + +.mr-40 { + margin-right: 40px; +} + +.mb-40 { + margin-bottom: 40px; +} + +.ml-40 { + margin-left: 40px; +} + +.m-48 { + margin: 48px; +} + +.mt-48 { + margin-top: 48px; +} + +.mr-48 { + margin-right: 48px; +} + +.mb-48 { + margin-bottom: 48px; +} + +.ml-48 { + margin-left: 48px; +} + +.m-56 { + margin: 56px; +} + +.mt-56 { + margin-top: 56px; +} + +.mr-56 { + margin-right: 56px; +} + +.mb-56 { + margin-bottom: 56px; +} + +.ml-56 { + margin-left: 56px; +} + +.m-64 { + margin: 64px; +} + +.mt-64 { + margin-top: 64px; +} + +.mr-64 { + margin-right: 64px; +} + +.mb-64 { + margin-bottom: 64px; +} + +.ml-64 { + margin-left: 64px; +} + +.p-0 { + padding: 0; +} + +.pt-0 { + padding-top: 0; +} + +.pr-0 { + padding-right: 0; +} + +.pb-0 { + padding-bottom: 0; +} + +.pl-0 { + padding-left: 0; +} + +.p-8 { + padding: 8px; +} + +.pt-8 { + padding-top: 8px; +} + +.pr-8 { + padding-right: 8px; +} + +.pb-8 { + padding-bottom: 8px; +} + +.pl-8 { + padding-left: 8px; +} + +.p-16 { + padding: 16px; +} + +.pt-16 { + padding-top: 16px; +} + +.pr-16 { + padding-right: 16px; +} + +.pb-16 { + padding-bottom: 16px; +} + +.pl-16 { + padding-left: 16px; +} + +.p-24 { + padding: 24px; +} + +.pt-24 { + padding-top: 24px; +} + +.pr-24 { + padding-right: 24px; +} + +.pb-24 { + padding-bottom: 24px; +} + +.pl-24 { + padding-left: 24px; +} + +.p-32 { + padding: 32px; +} + +.pt-32 { + padding-top: 32px; +} + +.pr-32 { + padding-right: 32px; +} + +.pb-32 { + padding-bottom: 32px; +} + +.pl-32 { + padding-left: 32px; +} + +.p-40 { + padding: 40px; +} + +.pt-40 { + padding-top: 40px; +} + +.pr-40 { + padding-right: 40px; +} + +.pb-40 { + padding-bottom: 40px; +} + +.pl-40 { + padding-left: 40px; +} + +.p-48 { + padding: 48px; +} + +.pt-48 { + padding-top: 48px; +} + +.pr-48 { + padding-right: 48px; +} + +.pb-48 { + padding-bottom: 48px; +} + +.pl-48 { + padding-left: 48px; +} + +.p-56 { + padding: 56px; +} + +.pt-56 { + padding-top: 56px; +} + +.pr-56 { + padding-right: 56px; +} + +.pb-56 { + padding-bottom: 56px; +} + +.pl-56 { + padding-left: 56px; +} + +.p-64 { + padding: 64px; +} + +.pt-64 { + padding-top: 64px; +} + +.pr-64 { + padding-right: 64px; +} + +.pb-64 { + padding-bottom: 64px; +} + +.pl-64 { + padding-left: 64px; +} + +/* Reveal animations */ +.sr { + + .has-animations { + + .is-revealing { + visibility: hidden; + } + } +} diff --git a/src/scss/base/_typography.scss b/src/scss/base/_typography.scss new file mode 100644 index 0000000..fb6551c --- /dev/null +++ b/src/scss/base/_typography.scss @@ -0,0 +1,252 @@ +html { + @include font-size(5, mobile, true, true); + @if ( get-font-size(5, desktop) != get-font-size(5, mobile) ) { + @include media( '>medium' ) { + @include font-size(5, desktop, true, true, true); + } + } +} + +body { + color: color(typography, 2); + font-size: 1rem; +} + +body, +button, +input, +select, +textarea { + @include font-family(base); +} + +a { + @include anchor-aspect(main); +} + +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + clear: both; + color: color(typography, 1); + @if ( get-font-family(heading) != get-font-family(base) ) { + @include font-family(heading); + } + @include font-weight(bold); +} + +h1, +.h1 { + @include font-size(1, mobile, true, true, true); + @if ( get-font-size(1, desktop) != get-font-size(1, mobile) ) { + @include media( '>medium' ) { + @include font-size(1, desktop, true, true, true); + } + } +} + +h2, +.h2 { + @include font-size(2, mobile, true, true, true); + @if ( get-font-size(2, desktop) != get-font-size(2, mobile) ) { + @include media( '>medium' ) { + @include font-size(2, desktop, true, true, true); + } + } +} + +h3, +.h3, +blockquote { + @include font-size(3, mobile, true, true, true); + @if ( get-font-size(3, desktop) != get-font-size(3, mobile) ) { + @include media( '>medium' ) { + @include font-size(3, desktop, true, true, true); + } + } +} + +h4, +h5, +h6, +.h4, +.h5, +.h6 { + @include font-size(4, mobile, true, true, true); + @if ( get-font-size(4, desktop) != get-font-size(4, mobile) ) { + @include media( '>medium' ) { + @include font-size(4, desktop, true, true, true); + } + } +} + +@include media( '<=medium' ) { + + .h1-mobile { + @include font-size(1, mobile, true, true, true); + } + + .h2-mobile { + @include font-size(2, mobile, true, true, true); + } + + .h3-mobile { + @include font-size(3, mobile, true, true, true); + } + + .h4-mobile, + .h5-mobile, + .h6-mobile { + @include font-size(4, mobile, true, true, true); + } +} + +.text-light { + color: color(typography, 2i); + + a { + color: color(typography, 2i); + } +} + +.text-light { + + h1, h2, h3, h4, h5, h6, + .h1, .h2, .h3, .h4, .h5, .h6 { + color: color(typography, 1i) !important; + } +} + +.text-sm { + @include font-size(6, mobile, true, true, true); + @if ( get-font-size(6, desktop) != get-font-size(6, mobile) ) { + @include media( '>medium' ) { + @include font-size(6, desktop, true, true, true); + } + } +} + +.text-xs { + @include font-size(7, mobile, true, true, true); + @if ( get-font-size(7, desktop) != get-font-size(7, mobile) ) { + @include media( '>medium' ) { + @include font-size(7, desktop, true, true, true); + } + } +} + +h1, h2, +.h1, .h2 { + margin-top: 48px; + margin-bottom: 16px; +} + +h3, +.h3 { + margin-top: 36px; + margin-bottom: 12px; +} + +h4, h5, h6, +.h4, .h5, .h6 { + margin-top: 24px; + margin-bottom: 4px; +} + +p { + margin-top: 0; + margin-bottom: 24px; +} + +dfn, cite, em, i { + font-style: italic; +} + +blockquote { + color: color(typography, 3); + font-style: italic; + margin-top: 24px; + margin-bottom: 24px; + margin-left: 24px; + + &::before { + content: "\201C"; + } + + &::after { + content: "\201D"; + } + + p { + display: inline; + } +} + +address { + color: color(typography, 2); + border-width: 1px 0; + border-style: solid; + border-color: color(bg, 3); + padding: 24px 0; + margin: 0 0 24px; +} + +pre, +pre h1, +pre h2, +pre h3, +pre h4, +pre h5, +pre h6, +pre .h1, +pre .h2, +pre .h3, +pre .h4, +pre .h5, +pre .h6 { + @include font-family(pre); +} + +pre, code, kbd, tt, var { + background: color(bg, 2); +} + +pre { + @include font-size(7, mobile, true, true); + margin-bottom: 1.6em; + max-width: 100%; + overflow: auto; + padding: 24px; + margin-top: 24px; + margin-bottom: 24px; +} + +code, kbd, tt, var { + @include font-family(code); + @include font-size(7, mobile, true); + padding: 2px 4px; +} + +abbr, acronym { + cursor: help; +} + +mark, ins { + text-decoration: none; +} + +small { + @include font-size(6, mobile, true, true, true); +} + +b, +strong { + @include font-weight(bold); +} + +button, +input, +select, +textarea, +label { + @include font-size(5, mobile, true, true); +} diff --git a/src/scss/components/_buttons.scss b/src/scss/components/_buttons.scss new file mode 100644 index 0000000..5f77cde --- /dev/null +++ b/src/scss/components/_buttons.scss @@ -0,0 +1,103 @@ +.button { + display: inline-flex; + @include font-size(9, mobile, true, false, true); + @if ( get-font-size(9, desktop) != get-font-size(9, mobile) ) { + @include media( '>medium' ) { + @include font-size(9, desktop, true, false, true); + } + } + @include font-weight(bold); + line-height: 16px; + text-transform: uppercase; + text-decoration: none !important; + background-color: color(bg, 1); + color: color(primary, 1) !important; + border: none; + border-radius: 2px; + cursor: pointer; + justify-content: center; + padding: 16px 32px; + height: 48px; + text-align: center; + white-space: nowrap; + + &:active { + outline: 0; + } + + &::before { + border-radius: 2px; + } +} + +.button-shadow { + position: relative; + + &::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + box-shadow: 0 8px 24px rgba(color(typography, 1), .12); + mix-blend-mode: multiply; + transition: box-shadow .15s ease; + } + + &:hover { + + &::before { + box-shadow: 0 8px 24px rgba(color(typography, 1), .25); + } + } +} + +.button-sm { + padding: 8px 24px; + height: 32px; + + &.button-shadow { + + &::before { + box-shadow: 0 4px 16px rgba(color(typography, 1), .12); + } + + &:hover { + + &::before { + box-shadow: 0 4px 16px rgba(color(typography, 1), .25); + } + } + } +} + +.button-primary, +.button-secondary { + color: color(typography, 1i) !important; + transition: background .15s ease; +} + +.button-primary { + background: mix(color(primary, 1), color(primary, 2)); + background: linear-gradient(65deg, color(primary, 1) -25%, color(primary, 2) 100%); + + &:hover { + background: lighten(mix(color(primary, 1), color(primary, 2)), .5%); + background: linear-gradient(65deg, lighten(color(primary, 1), .5%) -25%, lighten(color(primary, 2), .5%) 100%); + } +} + +.button-secondary { + background: mix(color(primary, 1), color(secondary, 2)); + background: linear-gradient(65deg, color(primary, 1) -25%, color(secondary, 2) 100%); + + &:hover { + background: lighten(mix(color(primary, 1), color(secondary, 2)), .5%); + background: linear-gradient(65deg, lighten(color(primary, 1), .5%) -25%, lighten(color(secondary, 2), .5%) 100%); + } +} + +.button-block { + display: flex; +} diff --git a/src/scss/layout/_clients.scss b/src/scss/layout/_clients.scss new file mode 100644 index 0000000..d7424e5 --- /dev/null +++ b/src/scss/layout/_clients.scss @@ -0,0 +1,38 @@ +.clients { + + .section-inner { + padding-top: 30px; + padding-bottom: 30px; + } + + ul { + display: flex; + flex-wrap: wrap; + } + + li { + display: flex; + justify-content: center; + width: 100%; + padding: 10px 0; + } +} + +@include media( '>medium' ) { + + .clients { + + .section-inner { + padding-top: 26px; + padding-bottom: 26px; + } + + ul { + justify-content: space-around; + } + + li { + width: auto; + } + } +} diff --git a/src/scss/layout/_features-extended.scss b/src/scss/layout/_features-extended.scss new file mode 100644 index 0000000..55d2ab4 --- /dev/null +++ b/src/scss/layout/_features-extended.scss @@ -0,0 +1,91 @@ +.feature-extended { + padding-top: 48px; +} + +.feature-extended-image, +.feature-extended-body { + width: 100%; +} + +.feature-extended-image { + margin-bottom: 24px; + + img, + svg { + width: 100%; + max-width: 320px; + height: auto; + margin: 0 auto; + overflow: visible; + } +} + +.feature-extended-body { + text-align: center; +} + +@include media( '>medium' ) { + + .features-extended { + + .section-paragraph { + padding-left: 72px; + padding-right: 72px; + margin-bottom: 0; + } + } + + .feature-extended { + display: flex; + align-items: center; + padding-top: 72px; + + &:nth-child(even) { + + .feature-extended-image { + order: 1; + } + } + } + + .feature-extended-image, + .feature-extended-body { + width: auto; + padding: 0 24px; + } + + .feature-extended-image { + margin-bottom: 0; + + img, + svg { + max-width: none; + width: 320px; + } + } + + .feature-extended-body { + text-align: left; + } +} + +@include media( '>large' ) { + + .feature-extended { + padding-left: 40px; + padding-right: 40px; + } + + .feature-extended-image, + .feature-extended-body { + padding: 0 40px; + } + + .feature-extended-image { + + img, + svg { + width: 480px; + } + } +} diff --git a/src/scss/layout/_features.scss b/src/scss/layout/_features.scss new file mode 100644 index 0000000..a95289e --- /dev/null +++ b/src/scss/layout/_features.scss @@ -0,0 +1,67 @@ +.features { + + .section-title { + margin-bottom: 48px; + } +} + +.features-wrap { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-right: -12px; + margin-left: -12px; + + &:first-child { + margin-top: -12px; + } + + &:last-child { + margin-bottom: -12px; + } +} + +.feature { + padding: 12px; + width: 276px; + max-width: 276px; + flex-grow: 1; +} + +.feature-inner { + position: relative; + height: 100%; + background: color(bg, 1); + padding: 40px 24px; + + &::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + @include shadow; + mix-blend-mode: multiply; + } +} + +.feature-icon { + display: flex; + justify-content: center; +} + +@include media( '>medium' ) { + + .features { + + .section-title { + margin-bottom: 56px; + } + + .section-inner { + padding-top: 56px; + padding-bottom: 64px; + } + } +} diff --git a/src/scss/layout/_footer.scss b/src/scss/layout/_footer.scss new file mode 100644 index 0000000..190afb6 --- /dev/null +++ b/src/scss/layout/_footer.scss @@ -0,0 +1,89 @@ +.site-footer { + @include font-size(8, mobile, true, true, true); + @if ( get-font-size(8, desktop) != get-font-size(8, mobile) ) { + @include media( '>medium' ) { + @include font-size(8, desktop, true, true, true); + } + } + color: color(typography, 3); + border-top: 1px solid color(bg, 3); + + a { + @include anchor-aspect(footer); + } +} + +.site-footer-inner { + position: relative; /* To display all elements above the background color */ + display: flex; + flex-wrap: wrap; + padding-top: 40px; + padding-bottom: 40px; +} + +.footer-brand, +.footer-links, +.footer-social-links, +.footer-copyright { + flex: none; + width: 100%; + display: inline-flex; + justify-content: center; +} + +.footer-brand, +.footer-links, +.footer-social-links { + margin-bottom: 24px; +} + +.footer-links, +.footer-social-links { + + li { + + + li { + margin-left: 16px; + } + } +} + +.footer-social-links { + + li { + display: inline-flex; + + a { + padding: 8px; + } + } +} + +@include media( '>medium' ) { + + .site-footer-inner { + justify-content: space-between; + } + + .footer-brand, + .footer-links, + .footer-social-links, + .footer-copyright { + flex: 50%; + } + + .footer-brand, + .footer-copyright { + justify-content: flex-start; + } + + .footer-links, + .footer-social-links { + justify-content: flex-end; + } + + .footer-links { + order: 1; + margin-bottom: 0; + } +} diff --git a/src/scss/layout/_header.scss b/src/scss/layout/_header.scss new file mode 100644 index 0000000..165ee69 --- /dev/null +++ b/src/scss/layout/_header.scss @@ -0,0 +1,55 @@ +.site-header { + position: relative; + padding: 24px 0; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 500px; + background: mix(color(secondary, 1), color(additional, 2)); + background: linear-gradient(57deg, color(secondary, 1) 0%, color(additional, 2) 100%); + transform-origin: 0; + transform: skewY(-12deg); + } +} + +.site-header-inner { + position: relative; /* To display all elements above the background color */ + display: flex; + justify-content: space-between; + align-items: center; +} + +.header-links { + display: inline-flex; + + li { + display: inline-flex; + } + + a:not(.button) { + @include font-size(9, mobile, true, true, true); + @if ( get-font-size(9, desktop) != get-font-size(9, mobile) ) { + @include media( '>medium' ) { + @include font-size(9, desktop, true, true, true); + } + } + @include font-weight(bold); + @include anchor-aspect(header); + line-height: 16px; + padding: 8px 24px; + } +} + +@include media( '>medium' ) { + + .site-header { + + &::before { + height: 640px; + } + } +} diff --git a/src/scss/layout/_hero.scss b/src/scss/layout/_hero.scss new file mode 100644 index 0000000..1fc49a8 --- /dev/null +++ b/src/scss/layout/_hero.scss @@ -0,0 +1,46 @@ +.hero { + position: relative; + padding-top: 40px; + overflow: hidden; +} + +.hero-paragraph { + margin-bottom: 32px; +} + +.hero-media { + position: relative; + height: 200px; + margin-top: 40px; + background: color(bg, 1); + border-radius: 4px 4px 0 0; + + &::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + @include shadow; + mix-blend-mode: multiply; + } +} + +@include media( '>medium' ) { + + .hero { + padding-top: 80px; + } + + .hero-paragraph { + margin-bottom: 40px; + padding-left: 72px; + padding-right: 72px; + } + + .hero-media { + margin-top: 64px; + height: 400px; + } +} diff --git a/src/scss/layout/_main.scss b/src/scss/layout/_main.scss new file mode 100644 index 0000000..16a3b5e --- /dev/null +++ b/src/scss/layout/_main.scss @@ -0,0 +1,36 @@ +.is-boxed { + background: color(bg, 2); +} + +.body-wrap { + background: color(bg, 1); + overflow: hidden; + /* Sticky footer */ + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.boxed-container { + max-width: 1440px; + margin: 0 auto; + @include shadow; +} + +main { + flex: 1 0 auto; +} + +.section-inner { + position: relative; /* To always display inner elements above pseudo decorative stuff */ + padding-top: 48px; + padding-bottom: 48px; +} + +@include media( '>medium' ) { + + .section-inner { + padding-top: 80px; + padding-bottom: 80px; + } +} diff --git a/src/scss/layout/_pricing.scss b/src/scss/layout/_pricing.scss new file mode 100644 index 0000000..020f535 --- /dev/null +++ b/src/scss/layout/_pricing.scss @@ -0,0 +1,108 @@ +.pricing { + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + top: 100%; + left: 0; + width: 100%; + height: 640px; + background: color(bg, 2); + transform-origin: 0; + transform: skewY(-40deg); + overflow: hidden; + } + + .section-title { + margin-bottom: 48px; + } +} + +.pricing-tables-wrap { + display: flex; + flex-wrap: wrap; + justify-content: center; + margin-right: -12px; + margin-left: -12px; + + &:first-child { + margin-top: -12px; + } + + &:last-child { + margin-bottom: -12px; + } +} + +.pricing-table { + padding: 12px; + width: 344px; + max-width: 344px; + flex-grow: 1; +} + +.pricing-table-inner { + position: relative; + display: flex; + flex-wrap: wrap; + background: color(bg, 1); + padding: 24px; + height: 100%; + + > * { + position: relative; /* To display all elements above the box with shadow */ + width: 100%; + } + + &::before { + content: ''; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + @include shadow; + mix-blend-mode: multiply; + } +} + +.pricing-table-header { + @include divider(after); +} + +.pricing-table-features { + color: color(typography, 3); + + li { + display: flex; + align-items: center; + margin-bottom: 14px; + + .list-icon { + display: inline-flex; + width: 16px; + height: 12px; + margin-right: 12px; + } + } +} + +.pricing-table-cta { + align-self: flex-end; +} + +@include media( '>medium' ) { + + .pricing { + + &::before { + transform: skewY(-12deg); + } + + .section-title { + margin-bottom: 64px; + } + } +} diff --git a/src/scss/style.scss b/src/scss/style.scss new file mode 100644 index 0000000..3b0bca3 --- /dev/null +++ b/src/scss/style.scss @@ -0,0 +1,74 @@ +/*-------------------------------------------------------------- +# Variables, functions and mixins +--------------------------------------------------------------*/ +@import "abstracts/variables", + "abstracts/functions", + "abstracts/mixins", + 'abstracts/include-media'; + +/*-------------------------------------------------------------- +1.0 Normalize + * normalize.css v7.0.0 | MIT License + * github.com/necolas/normalize.css +--------------------------------------------------------------*/ +@import "normalize"; + +/*-------------------------------------------------------------- +# Base +--------------------------------------------------------------*/ +@import "base/base"; + +/*-------------------------------------------------------------- +# Typography +--------------------------------------------------------------*/ +@import "base/typography"; + +/*-------------------------------------------------------------- +# Helpers +--------------------------------------------------------------*/ +@import "base/helpers"; + +/*-------------------------------------------------------------- +# Buttons +--------------------------------------------------------------*/ +@import "components/buttons"; + +/*-------------------------------------------------------------- +# Header +--------------------------------------------------------------*/ +@import "layout/header"; + +/*-------------------------------------------------------------- +# Hero +--------------------------------------------------------------*/ +@import "layout/hero"; + +/*-------------------------------------------------------------- +# Clients +--------------------------------------------------------------*/ +@import "layout/clients"; + +/*-------------------------------------------------------------- +# Features +--------------------------------------------------------------*/ +@import "layout/features"; + +/*-------------------------------------------------------------- +# Features extended +--------------------------------------------------------------*/ +@import "layout/features-extended"; + +/*-------------------------------------------------------------- +# Pricing +--------------------------------------------------------------*/ +@import "layout/pricing"; + +/*-------------------------------------------------------------- +# Site content +--------------------------------------------------------------*/ +@import "layout/main"; + +/*-------------------------------------------------------------- +# Footer +--------------------------------------------------------------*/ +@import "layout/footer";