Repository: codeAdrian/modern-fluid-typography-editor
Branch: develop
Commit: 6e1eefa0f0b1
Files: 79
Total size: 170.5 KB
Directory structure:
gitextract_d9euyxbe/
├── .eslintrc.cjs
├── .gitignore
├── .prettierrc
├── LICENSE.md
├── README.md
├── package.json
├── postcss.config.cjs
├── src/
│ ├── app.html
│ ├── components/
│ │ ├── Footer.svelte
│ │ ├── Header.svelte
│ │ ├── InputWithRange.svelte
│ │ ├── Legend.svelte
│ │ ├── LineChart.svelte
│ │ ├── Message.svelte
│ │ ├── ShareButton.svelte
│ │ ├── Snippet.svelte
│ │ └── Stats.svelte
│ ├── global.d.ts
│ ├── modules/
│ │ ├── code/
│ │ │ └── Section.svelte
│ │ ├── form/
│ │ │ ├── Form.svelte
│ │ │ └── store.ts
│ │ ├── graph/
│ │ │ ├── Graph.svelte
│ │ │ ├── consts.ts
│ │ │ ├── customTooltip.ts
│ │ │ ├── derived.ts
│ │ │ ├── store.ts
│ │ │ └── utils.ts
│ │ ├── tabs/
│ │ │ └── Tabs.svelte
│ │ └── tracker/
│ │ ├── AddValue.svelte
│ │ ├── Sort.svelte
│ │ ├── TableDataRow.svelte
│ │ ├── Tracker.svelte
│ │ ├── derived.ts
│ │ ├── store.ts
│ │ └── utils.ts
│ ├── routes/
│ │ ├── __error.svelte
│ │ ├── __layout.svelte
│ │ ├── about.svelte
│ │ └── index.svelte
│ ├── stores/
│ │ └── currentSubtitle.ts
│ ├── styles/
│ │ ├── globals.pcss
│ │ ├── icons.pcss
│ │ ├── media.pcss
│ │ ├── normalize.pcss
│ │ ├── page.pcss
│ │ ├── range.pcss
│ │ ├── reset-custom.pcss
│ │ ├── scrollbar.pcss
│ │ ├── typography.pcss
│ │ └── variables.pcss
│ └── utils/
│ ├── clampRange.ts
│ ├── clickOutside.ts
│ ├── getClampValue.ts
│ ├── getShareUrl.ts
│ ├── parseQueryString.ts
│ ├── setToPrecision.ts
│ ├── toPx.ts
│ └── toRem.ts
├── static/
│ ├── browserconfig.xml
│ ├── g/
│ │ └── images/
│ │ ├── editor.5a8f99a.2bb048a65192a85028ae21e277cf3ba1.avif
│ │ ├── editor.668f068.2bb048a65192a85028ae21e277cf3ba1.avif
│ │ ├── editor.a1d08c9.2bb048a65192a85028ae21e277cf3ba1.avif
│ │ ├── editor.d9015d2.2bb048a65192a85028ae21e277cf3ba1.avif
│ │ ├── graph-increase.5a8f99a.3e7989db31c3fb99059f7341810d53eb.avif
│ │ ├── graph-increase.5eb441f.3e7989db31c3fb99059f7341810d53eb.avif
│ │ ├── graph-increase.a1d08c9.3e7989db31c3fb99059f7341810d53eb.avif
│ │ ├── graph-increase.d9015d2.3e7989db31c3fb99059f7341810d53eb.avif
│ │ ├── snippet.8509b1a.63b149124717d1f23fc75f409f86c762.avif
│ │ ├── snippet.a1d08c9.63b149124717d1f23fc75f409f86c762.avif
│ │ ├── table.48e1f11.c30557c7f994bcd0da96c3395c69ff71.avif
│ │ ├── table.5a8f99a.c30557c7f994bcd0da96c3395c69ff71.avif
│ │ ├── table.a1d08c9.c30557c7f994bcd0da96c3395c69ff71.avif
│ │ └── table.d9015d2.c30557c7f994bcd0da96c3395c69ff71.avif
│ ├── google6e1010a8fae63903.html
│ ├── robots.txt
│ ├── site.webmanifest
│ └── sitemap.xml
├── svelte.config.js
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintrc.cjs
================================================
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['svelte3', '@typescript-eslint'],
ignorePatterns: ['*.cjs'],
overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
settings: {
'svelte3/typescript': () => require('typescript')
},
parserOptions: {
sourceType: 'module',
ecmaVersion: 2019
},
env: {
browser: true,
es2017: true,
node: true
}
};
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
================================================
FILE: .prettierrc
================================================
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100
}
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2021 Adrian Bece
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Modern Fluid Typography Editor
<p align="center">
<img src="./static/socials-default.jpg" alt="drawing" width="480"/>
</p>
- Easily create and fine-tune fluid typography values
- Modern CSS with CSS `clamp`
- Code snippet generation
- Supports user-defined font preferences
- Build with Svelte
## Setup
```
npm install
```
## Run project
```
npm run dev
```
## Bugs and issues?
Feel free to open the issue in project's repository and contribute code!
## Support
[Buy me a coffee!](https://www.buymeacoffee.com/ubnZ8GgDJ)
================================================
FILE: package.json
================================================
{
"name": "modern-fluid-typography-editor",
"version": "0.0.1",
"scripts": {
"dev": "svelte-kit dev",
"build": "svelte-kit build",
"package": "svelte-kit package",
"preview": "svelte-kit preview",
"check": "svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"@typescript-eslint/eslint-plugin": "^4.31.1",
"@typescript-eslint/parser": "^4.31.1",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-svelte3": "^3.2.1",
"postcss": "^8.4.4",
"postcss-custom-media": "^8.0.0",
"postcss-load-config": "^3.1.0",
"postcss-preset-env": "^7.0.1",
"prettier": "^2.4.1",
"prettier-plugin-svelte": "^2.4.0",
"svelte": "^3.44.0",
"svelte-check": "^2.2.6",
"svelte-clipboard": "^1.0.0",
"svelte-preprocess": "^4.9.4",
"svimg": "^1.1.0",
"tslib": "^2.3.1",
"typescript": "^4.4.3",
"@sveltejs/adapter-vercel": "next",
"cssnano": "^5.0.12"
},
"type": "module",
"dependencies": {
"@floating-ui/dom": "^0.1.4",
"chart.js": "^3.4.0",
"chartjs-plugin-crosshair": "^1.2.0"
}
}
================================================
FILE: postcss.config.cjs
================================================
module.exports = {
plugins: [
require('postcss-preset-env')({
stage: 3,
features: {
'nesting-rules': true,
'custom-media-queries': {
importFrom: './src/styles/media.pcss',
},
},
}),
require('cssnano'),
],
};
================================================
FILE: src/app.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="robots" content="index, follow" />
<title>Modern fluid typography editor</title>
<meta name="title" content="Modern fluid typography editor" />
<meta
name="description"
content="Generate fluid typography code snippets using modern CSS clamp function and fine-tune fluid typography behavior using this robust and sleek editor."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://modern-fluid-typography.vercel.app" />
<meta property="og:title" content="Modern fluid typography editor" />
<meta
property="og:description"
content="Generate fluid typography code snippets using modern CSS clamp function and fine-tune fluid typography behavior using this robust and sleek editor."
/>
<meta
property="og:image"
content="https://modern-fluid-typography.vercel.app/socials-default.jpg"
/>
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content="https://modern-fluid-typography.vercel.app" />
<meta property="twitter:title" content="Modern fluid typography editor" />
<meta
property="twitter:description"
content="Generate fluid typography code snippets using modern CSS clamp function and fine-tune fluid typography behavior using this robust and sleek editor."
/>
<meta
property="twitter:image"
content="https://modern-fluid-typography.vercel.app/socials-default.jpg"
/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700&family=Ubuntu:wght@700&family=Ubuntu+Mono:wght@700&display=swap"
rel="stylesheet"
/>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#37314b" />
<meta name="msapplication-TileColor" content="#37314b" />
<meta name="theme-color" content="#37314b" />
<script async src="https://www.googletagmanager.com/gtag/js?id=G-YJ8SQ0016B"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-YJ8SQ0016B');
</script>
%svelte.head%
</head>
<body id="svelte">
%svelte.body%
</body>
</html>
================================================
FILE: src/components/Footer.svelte
================================================
<footer class="footer">
<p class="footer__section">
Inspired by
<a
class="footer__link footer__link--primary"
href="https://www.joshwcomeau.com/"
target="_blank"
rel="noopener noreferrer"
>
Josh Comeau's
</a>
"Fluid Calculator" from
<a
class="footer__link footer__link--primary"
href="https://css-for-js.dev/"
target="_blank"
rel="noopener noreferrer"
>
CSS for JS devs
</a> course.
</p>
<p class="footer__section">
Created with <i class="fa-solid fa-heart footer__icon" /> and
<i class="fa-solid fa-fire footer__icon" />
by
<a
class="footer__link footer__link--secondary"
href="http://codeadrian.github.io"
target="_blank"
rel="noopener noreferrer"
>
Adrian Bece
</a>
</p>
<ul class="footer__links">
<li class="footer__item">
<a
href="https://twitter.com/AdrianBeceDev"
target="_blank"
class="footer__link footer__link--social"
rel="noopener noreferrer"
>
<i class="fa-brands fa-twitter" />
</a>
</li>
<li class="footer__item">
<a
href="https://www.linkedin.com/in/adrianbece/"
target="_blank"
class="footer__link footer__link--social"
rel="noopener noreferrer"
>
<i class="fa-brands fa-linkedin-in" />
</a>
</li>
<li class="footer__item">
<a
href="https://github.com/codeAdrian/modern-fluid-typography-editor"
target="_blank"
class="footer__link footer__link--social"
rel="noopener noreferrer"
>
<i class="fa-brands fa-github-alt" />
</a>
</li>
<li class="footer__item">
<a
href="https://www.buymeacoffee.com/ubnZ8GgDJ"
target="_blank"
class="footer__link footer__link--social"
rel="noopener noreferrer"
>
<i class="fa-solid fa-mug-saucer" />
</a>
</li>
</ul>
</footer>
<style>
.footer {
text-align: center;
padding: var(--spacing-2) var(--spacing-n1);
background-color: var(--color-gray-medium-faded);
border-top: 2px solid var(--color-gray-medium);
font-weight: var(--font-weight-bold);
@media (--mq-tablet-min) {
padding: var(--spacing-2);
}
}
.footer__link {
text-decoration: none;
font-family: var(--font-family-primary);
}
.footer__link:hover,
.footer__link:active {
text-decoration: underline;
}
.footer__link--primary {
color: var(--color-primary);
}
.footer__link--secondary {
color: var(--color-secondary);
}
.footer__section + .footer__section {
margin-top: var(--spacing-1);
}
.footer__link--social {
display: flex;
align-items: center;
text-align: center;
justify-content: center;
color: var(--color-gray-light);
background-color: var(--color-gray-medium-faded);
border: 2px solid currentColor;
width: calc(var(--spacing-1) + var(--spacing-n1));
aspect-ratio: 1;
font-family: var(--font-family-primary);
border-radius: var(--spacing-n2);
}
.footer__link--social:hover,
.footer__link--social:active,
.footer__link--social:focus {
box-shadow: 0 0 2px 1px var(--color-gray-light);
text-decoration: none;
}
.footer__links {
list-style: none;
padding: 0;
display: flex;
justify-content: center;
margin-top: var(--spacing-1);
}
.footer__item + .footer__item {
margin-left: var(--spacing-n1);
}
</style>
================================================
FILE: src/components/Header.svelte
================================================
<script>
import { currentSubtitle } from 'src/stores/currentSubtitle';
import { onMount } from 'svelte';
const subtitles = [
'Created by',
'Willed into existence by',
'Pixels pushed by',
'Cybernatically enchanced by',
'Found bugs in the app? Blame ',
'Joy sparked by',
'Bugs and other stuff by',
'Made on Arrakis by',
'Space-time folded by',
'Spice harvested by',
'Created on the dark side of the moon by',
'Transmogrified into existence by',
'Created according to the Great Convention by',
'TODO: Some witty subtitle to be added later by',
'As decreed by Leto II, this was created by',
'Created according to the Shadow Proclamation by',
'Created according to the Codex Astartes by',
'Blessed by Shai Hulud and made by',
'An Oscar-winning performance by'
];
let hasChanged = false;
onMount(() => {
if ($currentSubtitle) {
return;
}
hasChanged = true;
currentSubtitle.set(subtitles[Math.floor(Math.random() * subtitles.length)]);
});
</script>
<header class="header">
<div class="header__wrapper">
<div>
<h1 class="header__title">
<a class="header__link header__link--title" href="/"> Modern fluid typography editor </a>
</h1>
<h2 class:header__subtitle--ready={$currentSubtitle && hasChanged} class="header__subtitle">
{#if $currentSubtitle}
{$currentSubtitle}
<a
class="header__link header__link--subtitle"
href="http://codeadrian.github.io"
target="_blank"
rel="noopener noreferrer"
>
Adrian Bece
</a>
{:else}
<a href="/"> </a>
{/if}
</h2>
</div>
<nav>
<ul class="header__list">
<li><a class="header__link header__link--page" href="/about">About</a></li>
<li>
<a
href="https://twitter.com/AdrianBeceDev"
target="_blank"
class="header__link header__link--social"
rel="noopener noreferrer"
>
<i class="fa-brands fa-twitter" />
</a>
</li>
<li>
<a
href="https://github.com/codeAdrian/modern-fluid-typography-editor"
target="_blank"
class="header__link header__link--social"
rel="noopener noreferrer"
>
<i class="fa-brands fa-github-alt" />
</a>
</li>
<li>
<a
href="https://www.buymeacoffee.com/ubnZ8GgDJ"
target="_blank"
class="header__link header__link--social"
rel="noopener noreferrer"
>
<i class="fa-solid fa-mug-saucer" />
</a>
</li>
</ul>
</nav>
</div>
</header>
<style>
.header {
margin-bottom: var(--spacing-1);
background-color: var(--color-gray-medium-faded);
border-bottom: 2px solid var(--color-gray-medium);
text-align: center;
@media (--mq-tablet-min) {
margin-bottom: var(--spacing-2);
text-align: left;
}
}
.header__wrapper {
justify-content: space-between;
align-items: center;
padding: var(--spacing-1) var(--spacing-n1);
max-width: var(--container-max);
margin: 0 auto;
@media (--mq-tablet-min) {
padding: var(--spacing-1) var(--spacing-2);
display: flex;
}
}
.header__title {
font-size: var(--font-size-medium);
}
.header__subtitle {
font-size: var(--font-size-small);
color: var(--color-gray-light);
padding: var(--spacing-n1) 0;
@media (--mq-tablet-min) {
padding: var(--spacing-n4) 0 0 0;
}
}
.header__link {
display: block;
text-decoration: none;
color: var(--color-gray-light);
margin: 0;
}
.header__link--title {
color: var(--color-primary);
}
.header__link--title:hover {
color: var(--color-primary-tint);
}
.header__list {
display: flex;
list-style: none;
padding: 0;
justify-content: center;
@media (--mq-tablet-min) {
justify-content: flex-end;
}
}
.header__list > li + li {
margin-left: var(--spacing-n1);
}
.header__link--subtitle {
display: inline-block;
text-decoration: underline;
}
.header__link--subtitle:hover {
color: var(--color-secondary-tint);
}
.header__link--page {
color: var(--color-secondary);
background-color: var(--color-secondary-faded);
border: 2px solid currentColor;
padding: var(--spacing-n2) var(--spacing-1);
font-family: var(--font-family-primary);
border-radius: var(--spacing-n2);
}
.header__link--page:hover,
.header__link--page:active,
.header__link--page:focus {
box-shadow: 0 0 2px 1px var(--color-secondary);
}
.header__link--social {
background-color: var(--color-gray-medium-faded);
border: 2px solid currentColor;
padding: var(--spacing-n2) var(--spacing-n1);
font-family: var(--font-family-primary);
border-radius: var(--spacing-n2);
}
.header__link--social:hover,
.header__link--social:active,
.header__link--social:focus {
box-shadow: 0 0 2px 1px var(--color-gray-light);
}
.header__subtitle--ready {
animation: fadeIn 0.5s ease forwards 1;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
================================================
FILE: src/components/InputWithRange.svelte
================================================
<script lang="ts">
export let label;
export let id;
export let unit = '';
export let value;
</script>
<label class="input__label" for={id}>{label}</label>
<slot />
<div class="input__wrapper">
<input class="input__element" type="number" bind:value={$value} {id} {...$$restProps} />
<span class="input__unit">{unit}</span>
</div>
<input
aria-labelledby={id}
class="input__range"
type="range"
list={`${id}-tickmarks`}
bind:value={$value}
{...$$restProps}
/>
<style>
.input__label {
font-family: var(--font-family-primary);
display: inline-block;
margin-bottom: var(--spacing-n2);
}
.input__wrapper {
display: flex;
border: 2px solid var(--color-secondary);
background-color: var(--color-secondary-faded);
border-radius: var(--spacing-n4);
margin-bottom: var(--spacing-n1);
}
.input__wrapper:focus-within {
border-color: var(--color-secondary);
box-shadow: 0 0 3px 1px var(--color-secondary);
}
.input__element {
font-weight: var(--font-weight-bold);
padding: var(--spacing-n3);
background-color: transparent;
border-width: 0;
color: var(--color-gray-light);
width: 100%;
padding: var(--spacing-n2) var(--spacing-n1);
outline: 0;
}
.input__unit {
padding: var(--spacing-n3) var(--spacing-n2);
font-family: var(--font-family-primary);
border-left: inherit;
min-width: calc(4ch + 2 * var(--spacing-n2));
text-align: center;
color: var(--color-secondary);
}
.input__range {
display: block;
width: 100%;
}
</style>
================================================
FILE: src/components/Legend.svelte
================================================
<aside class="legend-wrapper">
<strong>Legend</strong>
<ul class="legend">
<li class="legend__box legend__box--min">Min value</li>
<li class="legend__box legend__box--fluid">Within min and max range</li>
<li class="legend__box legend__box--max">Max value</li>
</ul>
</aside>
<style>
.legend-wrapper {
font-weight: var(--font-weight-bold);
border: 2px solid var(--color-gray-medium);
border-radius: var(--spacing-n4);
background-color: var(--color-gray-medium-faded);
margin-top: var(--spacing-1);
padding: var(--spacing-1);
@media (--mq-desktop-min) {
display: inline-block;
width: auto;
margin-top: 0;
}
}
.legend {
list-style: none;
padding: 0;
margin-top: var(--spacing-1);
}
.legend__box {
display: flex;
align-items: center;
}
.legend__box + .legend__box {
margin-top: var(--spacing-1);
}
.legend__box::before {
content: '';
display: inline-block;
width: var(--spacing-1);
height: var(--spacing-1);
margin-right: var(--spacing-n2);
}
.legend__box--fluid::before {
border: 2px solid var(--color-gray-light);
background-color: var(--color-gray-medium-faded);
}
.legend__box--min::before {
border: 2px solid var(--color-secondary);
background-color: var(--color-secondary-faded);
}
.legend__box--max::before {
border: 2px solid var(--color-primary);
background-color: var(--color-primary-faded);
}
</style>
================================================
FILE: src/components/LineChart.svelte
================================================
<script>
import { Chart, registerables, Interaction } from 'chart.js';
import { onMount } from 'svelte';
import { CrosshairPlugin, Interpolate } from 'chartjs-plugin-crosshair';
export let chartOptions;
export let data;
let canvas;
let chart;
const initChart = () => {
Interaction.modes.interpolate = Interpolate;
Chart.register(CrosshairPlugin, ...registerables);
chart = new Chart(canvas?.getContext('2d'), chartOptions);
var gradientFill = chart.ctx.createLinearGradient(0, 0, 0, chart.chartArea.height);
gradientFill.addColorStop(0, 'hsla(182, 29%, 51%, 0.17)');
gradientFill.addColorStop(1, 'hsla(182, 29%, 51%, 0)');
chart.options.backgroundColor = gradientFill;
chart.data.datasets[0].data = data;
chart?.update();
};
$: {
if (chart) {
chart.data.datasets[0].data = data;
chart?.update();
}
}
onMount(initChart);
</script>
<figure>
<canvas bind:this={canvas} />
</figure>
<style>
figure {
width: 100%;
}
canvas {
margin-top: calc(var(--spacing-1) + var(--spacing-n2));
cursor: crosshair;
width: 100%;
max-width: 100%;
@media (--mq-desktop-min) {
margin-left: calc(-1 * var(--spacing-2));
max-width: calc(100% + var(--spacing-2));
}
}
</style>
================================================
FILE: src/components/Message.svelte
================================================
<script>
import { computePosition } from '@floating-ui/dom';
import { clickOutside } from 'src/utils/clickOutside';
import { onMount } from 'svelte';
export let type;
export let id;
// First, select the elements on the document
let button;
let tooltip;
let showTooltip = false;
onMount(() => {
computePosition(button, tooltip, { placement: 'right' }).then(({ x, y }) => {
Object.assign(tooltip.style, {
left: `${x}px`,
top: `${y}px`
});
});
});
const handleClickOutside = () => (showTooltip = false);
</script>
<div class="tooltip" use:clickOutside on:click_outside={handleClickOutside}>
<button
on:mouseenter={() => {
showTooltip = true;
}}
on:mouseleave={() => {
showTooltip = false;
}}
on:click={() => (showTooltip = true)}
class="tooltip-button"
bind:this={button}
>
<i class={`fa-solid fa-triangle-exclamation tooltip__icon tooltip__icon--${type}`} />
</button>
<div class="tooltip__message" bind:this={tooltip} class:tooltip__message--visible={showTooltip}>
<div class="tooltip__message-inner">
<slot />
</div>
</div>
</div>
<style>
.tooltip {
display: inline-block;
}
.tooltip-button {
background-color: transparent;
border-width: 0;
cursor: help;
padding: 0;
margin-left: var(--spacing-n5);
}
.tooltip__icon {
color: var(--color-tertiary);
}
.tooltip__message {
position: absolute;
display: none;
z-index: var(--level-4);
max-width: 250px;
background-color: var(--color-gray-dark);
border: 2px solid var(--color-tertiary);
border-radius: var(--spacing-n2);
margin-top: calc(-1 * var(--spacing-1));
margin-left: var(--spacing-n1);
}
.tooltip__message::before {
content: '\f0d9';
font-family: 'Font Awesome 6 Free';
font-weight: 900;
position: absolute;
color: var(--color-tertiary);
font-size: var(--font-size-medium);
left: 2px;
top: 0;
width: var(--spacing-n1);
height: var(--spacing-n1);
transform: translate3d(-100%, 50%, 0);
z-index: var(--level-2);
}
.tooltip__message-inner {
padding: var(--spacing-n1);
background-color: var(--color-tertiary-faded);
font-weight: var(--font-weight-bold);
}
.tooltip__message--visible {
display: initial;
}
</style>
================================================
FILE: src/components/ShareButton.svelte
================================================
<script>
import { shareUrl } from 'src/modules/form/store';
import Clipboard from 'svelte-clipboard';
let hasCopied = false;
const handleCopyAnimation = () => {
hasCopied = true;
setTimeout(() => {
hasCopied = false;
}, 1000);
};
</script>
<Clipboard on:copy={handleCopyAnimation} text={$shareUrl} let:copy>
<button on:click={copy} href={$shareUrl} title="Share this value">
{#if hasCopied}
<i class="fa-solid fa-check" />
Link copied
{:else}
<i class="fa-solid fa-share-from-square" />
Copy link
{/if}
</button>
</Clipboard>
<style>
button {
cursor: pointer;
display: inline-flex;
justify-content: center;
align-items: center;
color: var(--color-secondary);
background-color: var(--color-secondary-faded);
border: 2px solid currentColor;
padding: var(--spacing-n1) var(--spacing-1);
font-family: var(--font-family-primary);
border-radius: var(--spacing-n2);
text-decoration: none;
min-width: 180px;
}
button i {
padding-right: var(--spacing-n4);
}
button:hover,
button:active,
button:focus {
box-shadow: 0 0 2px 1px var(--color-secondary);
}
</style>
================================================
FILE: src/components/Snippet.svelte
================================================
<script>
import Clipboard from 'svelte-clipboard';
export let text;
let isAnimated = false;
const handleCopyAnimation = () => {
isAnimated = true;
setTimeout(() => {
isAnimated = false;
}, 300);
};
</script>
<div class="snippet">
<Clipboard on:copy={handleCopyAnimation} {text} let:copy>
<button class="snippet__button" on:click={copy}>
<i class="fa-solid fa-copy" />
<i class:snippet__icon--animated={isAnimated} class="fa-solid fa-copy snippet__icon" />
</button>
</Clipboard>
<pre
class="snippet__wrapper">
<code class="snippet__code">
{text}
</code>
</pre>
</div>
<style>
.snippet {
display: inline-flex;
align-items: center;
border: 2px solid var(--color-gray-light);
background-color: var(--color-gray-medium-faded);
border-radius: 8px;
color: var(--color-gray-light);
max-width: 100%;
ovverflow: auto;
@media (--mq-desktop-min) {
display: flex;
}
}
.snippet__wrapper {
padding: var(--spacing-n2) var(--spacing-n1);
max-width: calc(3 * var(--spacing-5));
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.snippet__code {
font-family: var(--font-family-mono);
user-select: all;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
white-space: break-spaces;
}
.snippet__button {
background: transparent;
border-width: 0;
border-right: 2px solid var(--color-gray-light);
padding: var(--spacing-n2) var(--spacing-n1);
color: var(--color-gray-light);
font-size: var(--font-size-medium);
cursor: pointer;
position: relative;
}
.snippet__button:hover {
background: var(--color-gray-medium-faded);
}
.snippet__icon {
position: absolute;
left: 50%;
right: 0;
top: 50%;
transform: translate3d(-50%, -50%, 0);
}
.snippet__icon--animated {
animation: moveAndFade 0.3s ease-out;
}
@keyframes moveAndFade {
from {
opacity: 1;
transform: translate3d(-50%, -50%, 0) scale(1);
}
to {
opacity: 0;
transform: translate3d(-50%, -50%, 0) scale(2);
}
}
</style>
================================================
FILE: src/components/Stats.svelte
================================================
<script>
import { fluidSize } from 'src/modules/form/store';
export let start = 0;
export let minValue = 0;
export let end = 0;
export let maxValue = 0;
</script>
<aside class="stats">
{#if $fluidSize >= 0}
Min value <strong class="stats__value--min">({minValue}px)</strong> ends at
<strong class="stats__value--min"> {start} px</strong>. Max value
<strong class="stats__value--max">({maxValue}px)</strong>
starts at
<strong class="stats__value--max"> {end} px</strong>.
{:else}
Max value <strong class="stats__value--min">({maxValue}px)</strong> ends at
<strong class="stats__value--min"> {end} px</strong>. Min value
<strong class="stats__value--max">({minValue}px)</strong>
starts at
<strong class="stats__value--max"> {start} px</strong>.
{/if}
</aside>
<style>
.stats {
font-family: var(--font-family-primary);
text-align: left;
}
.stats__value--min {
color: var(--color-secondary);
}
.stats__value--max {
color: var(--color-primary);
}
</style>
================================================
FILE: src/global.d.ts
================================================
/// <reference types="@sveltejs/kit" />
================================================
FILE: src/modules/code/Section.svelte
================================================
<script>
import Message from 'components/Message.svelte';
import { clampValue, minSize, maxSize, relativeSize } from 'src/modules/form/store';
</script>
{#if $minSize >= $maxSize}
<Message type="error">
Fluid snippet doesn't have any effect. Minimum size is larger than maximum size.
</Message>
{/if}
{#if $relativeSize > -1 && $relativeSize < 1}
<Message type="warning"
>It's recommended to set "Relative Size" to a value -1 or less or 1 and greater to support user
font size preferences.</Message
>
{/if}
================================================
FILE: src/modules/form/Form.svelte
================================================
<script>
import Input from 'components/InputWithRange.svelte';
import Message from 'src/components/Message.svelte';
import ShareButton from 'src/components/ShareButton.svelte';
import { fluidSize, maxSize, minSize, relativeSize, rootFontSize } from './store';
</script>
<ul class="form-list">
<li>
<Input
id="root-font-size"
unit="px"
label="Root font size"
min={1}
max={64}
value={rootFontSize}
>
{#if $rootFontSize <= 0}
<Message id="root-font-size" type="error">Incorrect font size value.</Message>
{/if}
</Input>
</li>
<li>
<Input id="min-size" unit="px" label="Min size" min={1} max={128} step={1} value={minSize}>
{#if $minSize > $maxSize}
<Message id="min-max-size" type="error">
Fluid snippet doesn't have any effect. Minimum size is larger than maximum size.
</Message>
{/if}
</Input>
</li>
<li>
<Input id="max-size" unit="px" label="Max size" min={1} max={128} step={1} value={maxSize}>
{#if $minSize > $maxSize}
<Message id="min-max-size" type="error">
Fluid snippet doesn't have any effect. Minimum size is larger than maximum size.
</Message>
{/if}
</Input>
</li>
<li>
<Input id="fluid-size" unit="vw" label="Fluid size" min={-5} max={5} value={fluidSize}>
{#if $fluidSize === 0}
<Message id="fluid-size" type="warning"
>Fluid snippet doesn't have any effect. Fluid size should be above 0</Message
>
{/if}
</Input>
</li>
<li>
<Input
id="relative-size"
unit="rem"
label="Relative size"
min={-3}
max={3}
step={0.25}
value={relativeSize}
>
{#if $relativeSize > -1 && $relativeSize < 1}
<Message id="relative-size" type="warning"
>Value should be -1 and less or 1 and more to support user font size settings.</Message
>
{/if}
</Input>
</li>
</ul>
<style>
.form-list {
margin-bottom: var(--spacing-2);
list-style: none;
padding: 0;
grid-template-columns: repeat(5, 1fr);
grid-gap: var(--spacing-2);
border: 2px solid var(--color-secondary-tint);
background: var(--color-secondary-faded);
border-radius: var(--spacing-n2);
padding: var(--spacing-1) var(--spacing-1) calc(var(--spacing-1) + var(--spacing-n2));
@media (--mq-mobileLandscape-min) and (--mq-tablet-max) {
display: grid;
grid-template-columns: repeat(2, 1fr);
}
@media (--mq-desktop-min) and (--mq-desktop-max) {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
@media (--mq-heightLarge) {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
}
.form-list li + li {
margin-top: var(--spacing-1);
@media (--mq-mobileLandscape-min) and (--mq-desktop-max) {
margin-top: 0;
}
@media (--mq-heightLarge) {
margin-top: 0;
}
}
</style>
================================================
FILE: src/modules/form/store.ts
================================================
import { getClampValue } from 'src/utils/getClampValue';
import { getShareUrl } from 'src/utils/getShareUrl';
import { parseQueryString } from 'src/utils/parseQueryString';
import { toPx } from 'src/utils/toPx';
import { toRem } from 'src/utils/toRem';
import { derived, writable } from 'svelte/store';
const rootFontSize = writable(parseQueryString('rootFontSize') || 16);
const minSize = writable(parseQueryString('minSize') || 24);
const maxSize = writable(parseQueryString('maxSize') || 36);
const fluidSize = writable(parseQueryString('fluidSize') || 2);
const relativeSize = writable(parseQueryString('relativeSize') || 1);
const minSizeRem = derived([minSize, rootFontSize], toRem);
const maxSizeRem = derived([maxSize, rootFontSize], toRem);
const relativeSizePx = derived([relativeSize, rootFontSize], toPx);
const clampValue = derived([minSizeRem, fluidSize, relativeSize, maxSizeRem], getClampValue);
const shareUrl = derived([rootFontSize, minSize, fluidSize, relativeSize, maxSize], getShareUrl);
export {
rootFontSize,
minSize,
maxSize,
fluidSize,
relativeSize,
minSizeRem,
maxSizeRem,
clampValue,
relativeSizePx,
shareUrl
};
================================================
FILE: src/modules/graph/Graph.svelte
================================================
<script>
import LineChart from 'components/LineChart.svelte';
import { CHART_OPTIONS } from './consts';
import { graphPoints } from './derived';
</script>
<LineChart data={$graphPoints} chartOptions={CHART_OPTIONS} />
================================================
FILE: src/modules/graph/consts.ts
================================================
import type { ChartConfiguration } from 'chart.js';
import { externalTooltipHandler } from './customTooltip';
export const CHART_OPTIONS: ChartConfiguration<'line'> = {
type: 'scatter',
data: {
datasets: [
{
borderColor: 'hsl(169, 82%, 69%)',
tension: 0,
showLine: true,
lineTension: 0,
interpolate: true,
pointRadius: 0,
borderWidth: 4,
borderJoinStyle: 'round',
fill: true
}
]
},
options: {
animation: false,
responsive: true,
plugins: {
legend: {
display: false
},
crosshair: {
line: {
color: 'hsl(182, 29%, 51%)',
width: 2
},
zoom: { enabled: false },
sync: { enabled: false }
},
tooltip: {
enabled: false,
mode: 'interpolate',
intersect: false,
yAlign: 'bottom',
external: externalTooltipHandler,
callbacks: {
title: function (a) {
const { x, y } = a[0].element;
return `${Math.round(y)}px at ${Math.round(x)}px`;
},
label: () => null
}
}
},
scales: {
x: {
min: 300,
suggestedMax: 1024,
type: 'linear',
title: {
text: 'Viewport width (pixels)',
display: true,
color: 'hsl(215, 22%, 85%)',
font: { size: 16, family: 'Ubuntu' }
},
grid: {
drawTicks: false,
lineWidth: 2,
borderWidth: 2,
color: 'hsla(182, 29%, 51%, 0.25)'
},
ticks: {
stepSize: 1,
count: 12,
precision: 0,
padding: 10,
color: (c) =>
c['tick']['value'] <= 1400 ? 'hsla(215, 22%, 85%, 0.8)' : 'hsla(215, 22%, 85%, 0.5)',
font: { size: 14 }
}
},
y: {
min: 0,
suggestedMin: 16,
suggestedMax: 48,
title: {
text: 'Fluid size (pixels)',
display: true,
color: 'hsl(215, 22%, 85%)',
font: { size: 16, family: 'Ubuntu' },
padding: 8
},
grid: {
drawTicks: false,
lineWidth: 2,
borderWidth: 2,
color: 'hsla(182, 29%, 51%, 0.25)'
},
ticks: {
padding: 8,
font: { size: 14 },
color: 'hsla(215, 22%, 85%, 0.6)',
callback: function (value, index) {
return index === 0 ? '' : value;
}
}
}
}
}
};
================================================
FILE: src/modules/graph/customTooltip.ts
================================================
export const getOrCreateTooltip = (chart) => {
let tooltipEl = chart.canvas.parentNode.querySelector('#chart-tooltip');
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'chart-tooltip';
tooltipEl.style.pointerEvents = 'none';
tooltipEl.style.position = 'absolute';
tooltipEl.style.top = '0px';
tooltipEl.style.border = '2px solid var(--color-secondary-tint)';
tooltipEl.style.color = 'var(--color-secondary)';
tooltipEl.style.background = 'var(--color-secondary-faded)';
tooltipEl.style.fontWeight = 'var(--font-weight-bold)';
tooltipEl.style.fontSize = 'var(--font-size-small)';
tooltipEl.style.padding = 'var(--spacing-n2)';
tooltipEl.style.lineHeight = '1';
tooltipEl.style.textAlign = 'center';
const span = document.createElement('span');
tooltipEl.appendChild(span);
chart.canvas.parentNode.appendChild(tooltipEl);
}
return tooltipEl;
};
export const externalTooltipHandler = (context) => {
const { chart, tooltip } = context;
const tooltipEl = getOrCreateTooltip(chart, tooltip);
tooltipEl.style.opacity = tooltip.opacity === 0 ? 0 : 1;
if (tooltip.body) {
const titleLines = tooltip.title || [];
let text;
titleLines.forEach((title) => {
text = document.createTextNode(title);
});
const tableRoot = tooltipEl.querySelector('span');
while (tableRoot.firstChild) {
tableRoot.firstChild.remove();
}
tableRoot.appendChild(text);
}
const { offsetLeft: positionX, offsetTop: positionY } = chart.canvas;
const isLeft = tooltip.caretX < chart.width / 2;
if (isLeft) {
tooltipEl.style.transform = 'translate3d(-1px,calc(-50% + 3px),0)';
tooltipEl.style.borderRadius = '4px 4px 4px 0';
} else {
tooltipEl.style.transform = 'translate3d(calc(-100% + 1px),calc(-50% + 3px),0)';
tooltipEl.style.borderRadius = '4px 4px 0 4px';
}
tooltipEl.style.top = '0';
tooltipEl.style.left = positionX + tooltip.caretX + 'px';
tooltipEl.style.minWidth = '20ch';
tooltipEl.style.top = positionY + 'px';
};
================================================
FILE: src/modules/graph/derived.ts
================================================
import { derived } from 'svelte/store';
import { fluidSize, maxSize, minSize, relativeSizePx } from 'src/modules/form/store';
import { clampRange } from 'src/utils/clampRange';
export const graphChangeStart = derived(
[minSize, maxSize, fluidSize, relativeSizePx],
([$minSize, $maxSize, $fluidSize, $relativeSizePx]) => {
if ($minSize >= $maxSize) {
return { x: 0, y: $minSize };
}
return { x: Math.round((100 * ($minSize - $relativeSizePx)) / $fluidSize), y: $minSize };
}
);
export const graphChangeEnd = derived(
[minSize, maxSize, fluidSize, relativeSizePx],
([$minSize, $maxSize, $fluidSize, $relativeSizePx]) => {
if ($minSize >= $maxSize) {
return { x: 1900, y: $minSize };
}
return { x: Math.round((100 * ($maxSize - $relativeSizePx)) / $fluidSize), y: $maxSize };
}
);
export const graphStart = derived(
[minSize, maxSize, fluidSize, relativeSizePx, graphChangeStart],
([$minSize, $maxSize, $fluidSize, $relativeSizePx, $graphChangeStart]) => {
if ($minSize >= $maxSize) {
return { x: 100, y: $minSize };
}
const x = Math.min($graphChangeStart.x - 100, 100);
return {
x,
y: clampRange(($fluidSize / 100) * x + $relativeSizePx, $minSize, $maxSize)
};
}
);
export const graphEnd = derived(
[minSize, maxSize, fluidSize, relativeSizePx, graphChangeEnd],
([$minSize, $maxSize, $fluidSize, $relativeSizePx, $graphChangeEnd]) => {
if ($minSize >= $maxSize) {
return { x: 1400, y: $minSize };
}
const x = Math.max($graphChangeEnd.x + 100, 1400);
return {
x,
y: clampRange(($fluidSize / 100) * x + $relativeSizePx, $minSize, $maxSize)
};
}
);
export const graphPoints = derived(
[graphStart, graphChangeStart, graphChangeEnd, graphEnd],
([$graphStart, $graphChangeStart, $graphChangeEnd, $graphEnd]) => {
return [$graphStart, $graphChangeStart, $graphChangeEnd, $graphEnd].sort((a, b) => a.x - b.x);
}
);
================================================
FILE: src/modules/graph/store.ts
================================================
import { writable } from 'svelte/store';
const minResolution = writable(300);
const maxResolution = writable(1920);
export { minResolution, maxResolution };
================================================
FILE: src/modules/graph/utils.ts
================================================
export const getScalesConfig = (y: { min: number; max: number; grid?: any }) => {
y.min = x.min + 10;
y.max = x.max + 10;
y.grid = { display: false };
return {
scales: {
x: { min: 200, max: 2000 },
y
}
};
};
================================================
FILE: src/modules/tabs/Tabs.svelte
================================================
<script>
export let tabs;
let activeTab = 0;
</script>
<article class="tabs-wrapper">
<div class="tabs-wrapper__utils">
<slot name="snippet" />
<slot name="share" />
</div>
<nav class="tabs">
{#each tabs as label, index}
<button
class:tab__button--active={index === activeTab}
class="tab__button"
on:click={() => {
activeTab = index;
}}>{label}</button
>
{/each}
</nav>
</article>
<slot {activeTab} />
<style>
.tabs-wrapper {
align-items: flex-end;
justify-content: space-between;
margin-bottom: var(--spacing-1);
isolation: isolate;
@media (--mq-desktopLarge-min) {
display: flex;
}
}
.tabs-wrapper__utils {
grid-gap: var(--spacing-1);
margin-bottom: var(--spacing-1);
display: grid;
@media (--mq-tablet-min) {
grid-template-columns: 1fr 1fr;
}
@media (--mq-desktopLarge-min) {
margin-bottom: 0;
grid-template-columns: auto auto;
}
}
.tabs {
display: flex;
margin-top: var(--spacing-1);
@media (--mq-desktop-min) {
margin-top: 0;
}
}
.tab__button {
background: transparent;
border-width: 0;
padding: var(--spacing-n1) var(--spacing-1);
color: var(--color-gray-light);
font-family: var(--font-family-primary);
cursor: pointer;
background-color: var(--color-gray-medium-faded);
text-align: center;
display: block;
border: 2px solid currentColor;
border-radius: var(--spacing-n1) 0 0 var(--spacing-n1);
flex-grow: 1;
@media (--mq-mobileLandscape-min) {
flex-grow: initial;
min-width: calc(2 * var(--spacing-4));
padding: var(--spacing-n1) var(--spacing-1);
}
}
.tab__button + .tab__button {
border-radius: 0 var(--spacing-n1) var(--spacing-n1) 0;
margin-left: -2px;
}
.tab__button--active {
color: var(--color-secondary);
background-color: var(--color-secondary-faded);
position: relative;
z-index: 2;
}
</style>
================================================
FILE: src/modules/tracker/AddValue.svelte
================================================
<script>
import Stats from 'src/components/Stats.svelte';
import { trackers } from './store';
import { generateUniqueId } from './utils';
let screenWidth;
let form;
let added = false;
const handleSubmit = (e) => {
e.preventDefault();
const id = generateUniqueId();
if (screenWidth <= 0) {
return;
}
trackers.update((v) => [...v, { id, width: screenWidth }]);
form.reset();
added = true;
setTimeout(() => {
added = false;
}, 1000);
};
</script>
<article class="form-wrapper">
<div>
<label class="form__label" for="track-screen-width">Add screen width to track</label>
</div>
<form class="form" bind:this={form} on:submit={handleSubmit}>
<button class="form__button" type="submit">
{#if added}
<i class="fa-solid fa-check" />
{:else}
<i class="fa-solid fa-plus" />
{/if}
</button>
<input
class="form__input"
id="track-screen-width"
type="number"
min={0}
required
bind:value={screenWidth}
/>
<span class="form__unit">px</span>
</form>
</article>
<style>
.form {
border-radius: var(--spacing-n2);
border: 2px solid var(--color-secondary);
display: inline-flex;
background-color: var(--color-secondary-faded);
margin-bottom: var(--spacing-1);
}
.form:focus-within {
box-shadow: 0 0 2px 1px var(--color-secondary);
}
.form__label {
font-family: var(--font-family-primary);
margin-bottom: var(--spacing-n2);
display: inline-block;
}
.form__input,
.form__button,
.form__unit {
background-color: transparent;
border-width: 0;
padding: var(--spacing-n1) var(--spacing-n1);
line-height: 1;
}
.form__input {
font-weight: var(--font-weight-bold);
color: var(--color-gray-light);
outline: 0;
}
.form__button {
color: var(--color-secondary);
font-size: var(--font-size-medium);
color: var(--color-secondary);
border-right: 2px solid var(--color-secondary);
aspect-ratio: 1;
min-width: calc(var(--spacing-2) + var(--spacing-n3));
cursor: pointer;
}
.form__unit {
font-weight: var(--font-weight-bold);
color: var(--color-secondary);
border-left: 2px solid var(--color-secondary);
line-height: 1.5;
padding: var(--spacing-n1);
aspect-ratio: 1;
}
</style>
================================================
FILE: src/modules/tracker/Sort.svelte
================================================
<script>
export let handleClick;
export let isAsc;
</script>
<button class="sort" class:sort--desc={!isAsc} class:sort--asc={isAsc} on:click={handleClick}>
{#if isAsc}
<i class="fa-solid fa-arrow-up" />
{:else}
<i class="fa-solid fa-arrow-down" />
{/if}
</button>
<style>
.sort {
margin-left: calc(-1 * var(--spacing-n5));
border: 2px solid currentColor;
background-color: transparent;
border-radius: var(--spacing-n4);
padding: var(--spacing-n4) var(--spacing-n3);
margin-right: var(--spacing-n4);
}
.sort--asc {
color: var(--color-secondary);
}
.sort--desc {
color: var(--color-primary);
}
</style>
================================================
FILE: src/modules/tracker/TableDataRow.svelte
================================================
<script>
import { setToPrecision } from 'src/utils/setToPrecision';
import { fluidSize, maxSize, minSize, relativeSizePx, rootFontSize } from '../form/store';
import { trackers } from './store';
import { calculateSizeValue } from './utils';
export let width;
export let id;
export let isAsc = false;
$: sizeValue = calculateSizeValue(width, $fluidSize, $relativeSizePx, $minSize, $maxSize);
const handleRemove = (e) => {
const id = parseInt(e.currentTarget.dataset.id);
if (!id || isNaN(id)) {
return;
}
trackers.update((v) => v.filter((item) => item.id !== id));
};
</script>
<tr
class="data"
class:data--asc={isAsc}
class:data--desc={!isAsc}
class:data--max={sizeValue === $maxSize}
class:data--min={sizeValue === $minSize}
>
<td>
{width} px
</td>
<td>
{sizeValue} px
</td>
<td>
{setToPrecision(sizeValue / $rootFontSize, 3)}rem
</td>
<td>
<button
class="data__button"
class:data__button--max={sizeValue === $maxSize}
class:data__button--min={sizeValue === $minSize}
on:click={handleRemove}
data-id={id}><i class="fa-solid fa-trash-can" /></button
>
</td>
</tr>
<style>
.data {
padding: var(--spacing-n2) var(--spacing-1);
background-color: var(--color-gray-medium-faded);
}
.data--max {
background-color: var(--color-primary-faded);
}
:global(.data--asc.data:not(.data--min):not(.data--max)) + .data--max {
border-top: 3px solid var(--color-primary-tint);
}
:global(.data--asc.data:not(.data--min):not(.data--max)) + .data--min {
border-top: 3px solid var(--color-secondary-tint);
}
:global(.data--desc.data:not(.data--max):not(.data--min)) + .data--min {
border-top: 3px solid var(--color-secondary-tint);
}
:global(.data--desc.data:not(.data--max):not(.data--min)) + .data--max {
border-top: 3px solid var(--color-primary-tint);
}
.data--min {
background-color: var(--color-secondary-faded);
}
.data--asc.data--min + :global(.data:not(.data--min)) {
border-top: 3px solid var(--color-secondary-tint);
}
.data--desc.data--max + :global(.data:not(.data--max)) {
border-top: 3px solid var(--color-primary-tint);
}
.data--desc.data--min + :global(.data:not(.data--min)) {
border-top: 3px solid var(--color-secondary-tint);
}
.data--asc.data--max + :global(.data:not(.data--max)) {
border-top: 3px solid var(--color-primary-tint);
}
.data__button {
color: var(--color-gray-light);
background: transparent;
border-width: 0;
cursor: pointer;
}
.data__button:hover,
.data__button:active {
color: var(--color-gray-lightest);
}
.data__button--min {
color: var(--color-secondary-tint);
}
.data__button--min:hover,
.data__button--min:active {
color: var(--color-secondary);
}
.data__button--max {
color: var(--color-primary-tint);
}
.data__button--max:hover,
.data__button--max:active {
color: var(--color-primary);
}
</style>
================================================
FILE: src/modules/tracker/Tracker.svelte
================================================
<script>
import { trackersAsc, trackersDesc } from './derived';
import Sort from './Sort.svelte';
import TableDataRow from './TableDataRow.svelte';
let isAsc = true;
$: items = isAsc ? $trackersAsc : $trackersDesc;
const handleClick = () => {
isAsc = !isAsc;
};
</script>
<div class:tracker-wrapper--overflow={items.length > 9} class="tracker-wrapper">
<table class="tracker">
<thead>
<tr>
<th>
<Sort {isAsc} {handleClick} />
Screen width
</th>
<th colspan="2">Fluid size value</th>
<th />
</tr>
</thead>
<tbody>
{#key `${isAsc ? 'asc' : 'desc'}`}
{#each items as item}
<TableDataRow {isAsc} {...item} />
{/each}
{/key}
</tbody>
</table>
</div>
<style>
.tracker-wrapper {
border-radius: var(--spacing-n5);
overflow: auto;
}
.tracker-wrapper--overflow {
max-height: 447px;
}
.tracker {
border-collapse: collapse;
font-weight: 700;
width: 100%;
min-width: calc((510 / 16) * 1rem);
}
.tracker thead {
position: sticky;
top: 0;
background-color: var(--color-gray-dark);
}
.tracker thead tr {
box-shadow: inset 0 0 0 2px var(--color-gray-medium);
}
.tracker :global(th) {
text-align: left;
font-family: var(--font-family-primary);
}
.tracker :global(th),
.tracker :global(td) {
line-height: 1;
padding: var(--spacing-n1) var(--spacing-1);
}
</style>
================================================
FILE: src/modules/tracker/derived.ts
================================================
import { derived } from 'svelte/store';
import { trackers } from './store';
export const trackersAsc = derived([trackers], ([$trackers]) => {
const sorted = $trackers.sort((a, b) => a.width - b.width);
return sorted;
});
export const trackersDesc = derived([trackersAsc], ([$trackersAsc]) => {
return [...$trackersAsc].reverse();
});
================================================
FILE: src/modules/tracker/store.ts
================================================
import { writable } from 'svelte/store';
export const trackers = writable([
{ id: 10, width: 300 },
{ id: 11, width: 360 },
{ id: 12, width: 480 },
{ id: 13, width: 568 },
{ id: 14, width: 768 },
{ id: 15, width: 920 },
{ id: 16, width: 1024 },
{ id: 17, width: 1280 },
{ id: 18, width: 1440 }
]);
================================================
FILE: src/modules/tracker/utils.ts
================================================
import { clampRange } from 'src/utils/clampRange';
export const generateUniqueId = () => Math.floor(Math.random() * Date.now());
export const calculateSizeValue = (screenSize, fluidSize, relativeSizePx, minValue, maxValue) => {
if (minValue >= maxValue) return minValue;
return clampRange(
Math.round((fluidSize / 100) * screenSize + relativeSizePx),
minValue,
maxValue
);
};
================================================
FILE: src/routes/__error.svelte
================================================
<main>
<div class="wrapper">
<h1 class="title">
<div class="title__text">Game over.<br /> Or is it?</div>
</h1>
<a class="notfound__link" href="/">Start again</a>
</div>
<div class="graphics" />
</main>
<style>
main {
position: relative;
overflow: hidden;
min-height: calc(100vh - 100px - var(--spacing-2));
display: flex;
justify-content: center;
align-items: center;
}
.wrapper {
text-align: center;
padding: 0 var(--spacing-n1);
@media (--mq-tablet-min) {
padding: 0 var(--spacing-2);
}
}
.title {
font-size: clamp(2rem, 6vw + 1rem, 32rem);
line-height: 1.25;
margin: 0;
}
.notfound__link {
color: var(--color-secondary);
background-color: var(--color-secondary-faded);
border: 2px solid currentColor;
padding: var(--spacing-1) var(--spacing-2);
font-family: var(--font-family-primary);
border-radius: var(--spacing-n2);
text-decoration: none;
}
.notfound__link:hover,
.notfound__link:active,
.notfound__link:focus {
box-shadow: 0 0 2px 1px var(--color-secondary);
}
.graphics {
min-width: 200vw;
height: 100%;
position: absolute;
left: -50%;
transform: perspective(50vh) rotate3d(1, 0, 0, 70deg);
background-image: repeating-linear-gradient(
90deg,
var(--color-secondary-faded) 0%,
transparent 2px,
transparent var(--spacing-2),
var(--color-secondary-faded) calc(var(--spacing-2) + 2px)
),
repeating-linear-gradient(
180deg,
var(--color-secondary-faded) 0%,
transparent 2px,
transparent var(--spacing-2),
var(--color-secondary-faded) calc(var(--spacing-2) + 2px)
);
z-index: var(--level-n1);
animation: movement 0.7s linear infinite;
}
.title__text {
width: fit-content;
text-align: center;
max-width: 10em;
line-height: 1.2;
margin-bottom: var(--spacing-4);
text-shadow: 0 0 var(--spacing-n2) var(--color-primary-tint);
animation: glow 2s infinite linear alternate;
}
@keyframes movement {
0% {
transform: perspective(50vh) rotate3d(1, 0, 0, 70deg) translate3d(0, -var(--spacing-2), 0);
}
100% {
transform: perspective(50vh) rotate3d(1, 0, 0, 70deg) translate3d(0, var(--spacing-2), 0);
}
}
@keyframes glow {
0% {
text-shadow: 0 0 0.1em var(--color-primary-tint);
}
100% {
text-shadow: 0 0 0.25em var(--color-primary-tint);
}
}
</style>
================================================
FILE: src/routes/__layout.svelte
================================================
<script>
import Footer from 'components/Footer.svelte';
import Header from 'components/Header.svelte';
</script>
<Header />
<slot />
<Footer />
<style lang="postcss">
@import 'src/styles/globals.pcss';
</style>
================================================
FILE: src/routes/about.svelte
================================================
<script>
import Image from 'svimg';
</script>
<main>
<h1 class="title">
<div class="title__text">About the project & user guide</div>
<div class="graphics" />
</h1>
<section class="intro">
<p>
I was going through Josh Comeau's <a
href="https://css-for-js.dev/"
target="_blank"
rel="noopener noreferrer"
>
CSS for JS devs
</a>course which is one of the best courses on CSS in general and I recommend checking it out.
In one of the lessions, Josh implemented a simple fluid typography editor, mainly for
demonstration purposes to showcase how fluid typography changes depending on the screen size.
</p>
<p>
I saw an opportunity for doing a <strong>really fun and useful project</strong>. I set out to
build upon Josh's concept and developed a fully-fledged tool that developers could use on a
day-to-day basis to fine-tune and keep track of their fluid typography and help to keep fluid
typography behavior consistent across the significant breakpoints.
</p>
</section>
<section>
<h2>Fluid typography</h2>
<p>
Fluid typography is a modern way of approaching responsive typography. Instead of setting
fixed typography values for individual screen sizes, we can set a single fluid value and let
the CSS render the appropriate values for a specific screen size constrained by minimum and
maximum values.
</p>
<p>
Try resizing the screen and notice how the "About the project & user guide" adapts to screen
size, but is constrained at some specific minimum and maximum value. Cool, isn't it?
</p>
</section>
<section>
<h2>CSS clamp and browser support</h2>
<p>
This editor relies heavily on <a
href="https://caniuse.com/?search=clamp()"
target="_blank"
rel="noopener noreferrer"
>CSS clamp
</a> and generates code using this property. Although this property has a solid browser support
(above 90% of globally used browsers), you might want to use a polyfill or a fallback value if
you need to support legacy browsers like Internet Explorer.
</p>
</section>
<section>
<h2>Configurable values</h2>
<pre>
<code>
clamp(min-value, fluid-value + relative-value, max-value);
</code>
</pre>
<dl>
<dt>min-value & max-value</dt>
<dd>Minimum and maximum value constraints.</dd>
<dt>fluid-value</dt>
<dd>
Change speed (rate). If a value is positive, the final value will increase from minimum
value to maximum value as screen width increases. If this value is negative, the final value
will decrease from maximum value to minimal value as screen width increases.
</dd>
<dt>relative-size</dt>
<dd>
Browser default root font size is 16px. This value can be changed by users in their browser
settings, usually for accessibility purposes. Positive or negative "rem" values should be
included to avoid locking font size to px value and to support user font size preferences.
</dd>
</dl>
</section>
<section>
<h2>Features</h2>
<p>Here is a short overview of some of the features of this editor:</p>
<ul>
<li>Adjust size constraints, rate, and relative size</li>
<li>Adapts to any root font size</li>
<li>Graphical overview of the final fluid values</li>
<li>Table view for keeping track of values on fixed screen width sizes.</li>
</ul>
<h3>Adjusting fluid settings</h3>
<p>
Fluid typography settings can be easily adjusted either by using numerical inputs for more
precise inputs or using range inputs for fine-tuning and smaller changes to easily track
changes on the graph or table.
</p>
<figure>
<Image src="images/editor.png" alt="Editor with text inputs with sample values set" />
<figcaption>
Use editor to configure min and max constraints, change rate and direction and relative
sizing for user font preferences
</figcaption>
</figure>
<h3>Code snippet</h3>
<p>
Based on the configured fluid settings, a CSS <code>clamp</code> code is generated. You can easily
copy the value by clicking the button on the left side or by selecting the value and copying it
manually.
</p>
<figure>
<Image
src="images/snippet.png"
alt="Generated clamp code snippet with sample values set. Values can be copied by clicking on a button or manually selecting and copying the value."
/>
<figcaption>
The code snippet can be copied by clicking the button or by selecting the text and copying
manually
</figcaption>
</figure>
<h3>Graph view</h3>
<p>
Graph view can give you a general overview of fluid typography behavior. By hovering over the
graph you can inspect individual values on specific screen sizes.
</p>
<figure>
<Image
src="images/graph-increase.png"
alt="Graphic overview of fluid typography behavior for default settings"
/>
<figcaption>
A high-level overview of fluid typography behavior. Fluid value starts increasing from
min-size to max size at around 400px of the viewport width and it stops at a maximum value
at around 1000px,
</figcaption>
</figure>
<p>
For a more detailed overview or tracking specific screen sizes, you can use the table view.
</p>
<h3>Table view</h3>
<p>
A table view can give you a more detailed overview of fluid font sizes for specific viewport
sizes. Viewport sizes can be easily added using the adjacent input. Likewise, individual
values can be removed from the list by clicking the remove button for a specific value.
</p>
<figure>
<Image
src="images/table.png"
alt="Table view of fluid behavior for specific set of screen sizes."
/>
<figcaption>
Minimum, maximum, and fluid values are indicated in the table and values can be sorted by
screen size in ascending or descending order.
</figcaption>
</figure>
</section>
<section>
<h2>Issues and contribution</h2>
<p>
Found any bugs or have a suggestion? Feel free to open an issue in
<a
href="https://github.com/codeAdrian/modern-fluid-typography-editor"
target="_blank"
rel="noopener noreferrer"
>
project's GitHub repository
</a>.
</p>
<p>
Feel free to contribute code to the project by
<a
href="https://github.com/codeAdrian/modern-fluid-typography-editor"
target="_blank"
rel="noopener noreferrer"
>
forking the source code
</a>. Please consult the "Issues" tab or contact me directly as unsolicited code contributions
may be rejected if they're not necessary or if they harm code quality, performance or
functionality.
</p>
</section>
</main>
<style>
main {
@media (--mq-tablet-min) {
font-size: var(--font-size-medium);
}
}
.title {
font-size: clamp(2rem, 6vw + 1rem, 32rem);
line-height: 1.25;
min-height: calc(100vh - 100px - var(--spacing-2));
display: flex;
justify-content: center;
align-items: center;
margin: 0;
position: relative;
overflow: hidden;
margin-bottom: var(--spacing-3);
border-bottom: 4px solid var(--color-secondary-faded);
}
.graphics {
min-width: 200vw;
height: 100%;
position: absolute;
left: -50%;
transform: perspective(50vh) rotate3d(1, 0, 0, 70deg);
background-image: repeating-linear-gradient(
90deg,
var(--color-secondary-faded) 0%,
transparent 2px,
transparent var(--spacing-2),
var(--color-secondary-faded) calc(var(--spacing-2) + 2px)
),
repeating-linear-gradient(
180deg,
var(--color-secondary-faded) 0%,
transparent 2px,
transparent var(--spacing-2),
var(--color-secondary-faded) calc(var(--spacing-2) + 2px)
);
z-index: var(--level-n1);
animation: movement 0.7s linear infinite;
}
.title__text {
width: fit-content;
text-align: center;
max-width: 10em;
line-height: 1.2;
margin-bottom: var(--spacing-4);
text-shadow: 0 0 var(--spacing-n2) var(--color-primary-tint);
animation: glow 2s infinite linear alternate;
}
h2 {
font-size: var(--font-size-large);
margin-bottom: var(--spacing-1);
}
h3 {
font-size: var(--font-size-medium);
margin-top: var(--spacing-1);
margin-bottom: var(--spacing-n1);
}
dt {
color: var(--color-secondary);
font-family: var(--font-family-mono);
margin-top: var(--spacing-1);
margin-bottom: var(--spacing-n2);
}
a {
color: var(--color-secondary);
text-decoration: none;
font-weight: var(--font-weight-bold);
}
a:hover,
a:active,
a:focus {
text-decoration: underline;
}
pre {
display: inline-block;
border: 2px solid var(--color-secondary);
background-color: var(--color-secondary-faded);
border-radius: var(--spacing-n2);
padding: var(--spacing-1);
font-weight: var(--font-weight-bold);
margin-bottom: var(--spacing-n1);
overflow: auto;
max-width: 100%;
}
section {
max-width: 820px;
margin: 0 auto;
margin-bottom: var(--spacing-2);
padding: 0 var(--spacing-n1);
@media (--mq-tablet-min) {
padding: 0 var(--spacing-2);
}
}
p + p {
margin-top: var(--spacing-1);
}
figure {
display: block;
margin: var(--spacing-2) 0;
@media (--mq-desktop-min) {
margin: var(--spacing-2) calc(-1 * var(--spacing-4));
width: calc(100% + 2 * var(--spacing-4));
}
}
figcaption {
text-align: center;
margin-top: var(--spacing-n1);
font-size: var(--font-size-small);
@media (--mq-tablet-min) {
font-size: var(--font-size-base);
}
@media (--mq-desktop-min) {
padding: 0 var(--spacing-3);
}
}
figure :global(img) {
max-width: 100%;
margin: 0 auto;
display: block;
}
@keyframes movement {
0% {
transform: perspective(50vh) rotate3d(1, 0, 0, 70deg) translate3d(0, -var(--spacing-2), 0);
}
100% {
transform: perspective(50vh) rotate3d(1, 0, 0, 70deg) translate3d(0, var(--spacing-2), 0);
}
}
@keyframes glow {
0% {
text-shadow: 0 0 0.1em var(--color-primary-tint);
}
100% {
text-shadow: 0 0 0.25em var(--color-primary-tint);
}
}
</style>
================================================
FILE: src/routes/index.svelte
================================================
<script>
import Form from 'modules/form/Form.svelte';
import Graph from 'modules/graph/Graph.svelte';
import Tabs from 'modules/tabs/Tabs.svelte';
import Legend from 'src/components/Legend.svelte';
import ShareButton from 'src/components/ShareButton.svelte';
import Snippet from 'src/components/Snippet.svelte';
import Stats from 'src/components/Stats.svelte';
import { clampValue, maxSize, minSize } from 'src/modules/form/store';
import { graphChangeEnd, graphChangeStart } from 'src/modules/graph/derived';
import AddValue from 'src/modules/tracker/AddValue.svelte';
import Tracker from 'src/modules/tracker/Tracker.svelte';
</script>
<main class="homepage">
<aside class="homepage__aside">
<Form />
</aside>
<section class="homepage__content">
<Tabs tabs={['Graph', 'Table']} let:activeTab>
{#if activeTab === 0}
<Stats
minValue={$minSize}
maxValue={$maxSize}
start={$graphChangeStart.x}
end={$graphChangeEnd.x}
/>
<Graph />
{:else}
<AddValue />
<article class="homepage__wrapper">
<Tracker />
<Legend />
</article>
{/if}
<Snippet text={$clampValue} slot="snippet" />
<ShareButton slot="share" />
</Tabs>
</section>
</main>
<style>
.homepage {
grid-template-columns: 250px auto;
grid-gap: var(--spacing-4);
padding: 0 var(--spacing-n1);
margin: 0 auto var(--spacing-2);
max-width: var(--container-max);
width: 100%;
@media (--mq-tablet-min) {
padding: 0 var(--spacing-2);
}
@media (--mq-desktopLarge-min) {
display: grid;
}
@media (--mq-heightLarge) {
display: revert;
}
}
.homepage__wrapper {
grid-template-columns: 520px 320px;
grid-gap: var(--spacing-2);
align-items: flex-start;
@media (--mq-desktop-min) {
display: grid;
}
}
</style>
================================================
FILE: src/stores/currentSubtitle.ts
================================================
import { writable } from 'svelte/store';
export const currentSubtitle = writable('');
================================================
FILE: src/styles/globals.pcss
================================================
@import './reset-custom.pcss';
@import './variables.pcss';
@import './icons.pcss';
@import './typography.pcss';
@import './scrollbar.pcss';
@import './range.pcss';
@import './page.pcss';
================================================
FILE: src/styles/icons.pcss
================================================
/*!
* Font Awesome Free 6.0.0-beta2 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
*/
.fa {
font-family: 'Font Awesome 6 Free';
font-family: var(--fa-style-family, 'Font Awesome 6 Free');
font-weight: 900;
font-weight: var(--fa-style, 900);
}
.fa,
.fa-brands,
.fa-duotone,
.fa-light,
.fa-regular,
.fa-solid,
.fa-thin,
.fab,
.fad,
.fal,
.far,
.fas,
.fat {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
display: var(--fa-display, inline-block);
font-style: normal;
font-variant: normal;
line-height: 1;
text-rendering: auto;
}
.fa-1x {
font-size: 1em;
}
.fa-2x {
font-size: 2em;
}
.fa-3x {
font-size: 3em;
}
.fa-4x {
font-size: 4em;
}
.fa-5x {
font-size: 5em;
}
.fa-6x {
font-size: 6em;
}
.fa-7x {
font-size: 7em;
}
.fa-8x {
font-size: 8em;
}
.fa-9x {
font-size: 9em;
}
.fa-10x {
font-size: 10em;
}
.fa-2xs {
font-size: 0.625em;
line-height: 0.1em;
vertical-align: 0.225em;
}
.fa-xs {
font-size: 0.75em;
line-height: 0.08333em;
vertical-align: 0.125em;
}
.fa-sm {
font-size: 0.875em;
line-height: 0.07143em;
vertical-align: 0.05357em;
}
.fa-lg {
font-size: 1.25em;
line-height: 0.05em;
vertical-align: -0.075em;
}
.fa-xl {
font-size: 1.5em;
line-height: 0.04167em;
vertical-align: -0.125em;
}
.fa-2xl {
font-size: 2em;
line-height: 0.03125em;
vertical-align: -0.1875em;
}
.fa-fw {
text-align: center;
width: 1.25em;
}
.fa-ul {
list-style-type: none;
margin-left: 2.5em;
margin-left: var(--fa-li-margin, 2.5em);
padding-left: 0;
}
.fa-ul > li {
position: relative;
}
.fa-li {
left: -2em;
left: calc(var(--fa-li-width, 2em) * -1);
position: absolute;
text-align: center;
width: 2em;
width: var(--fa-li-width, 2em);
line-height: inherit;
}
.fa-border {
border-radius: 0.1em;
border-radius: var(--fa-border-radius, 0.1em);
border: 0.08em solid #eee;
border: var(--fa-border-width, 0.08em) var(--fa-border-style, solid) var(--fa-border-color, #eee);
padding: 0.2em 0.25em 0.15em;
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em);
}
.fa-pull-left {
float: left;
margin-right: 0.3em;
margin-right: var(--fa-pull-margin, 0.3em);
}
.fa-pull-right {
float: right;
margin-left: 0.3em;
margin-left: var(--fa-pull-margin, 0.3em);
}
.fa-beat {
-webkit-animation-name: fa-beat;
animation-name: fa-beat;
-webkit-animation-delay: 0;
animation-delay: 0;
-webkit-animation-delay: var(--fa-animation-delay, 0);
animation-delay: var(--fa-animation-delay, 0);
-webkit-animation-direction: normal;
animation-direction: normal;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out);
}
.fa-fade {
-webkit-animation-name: fa-fade;
animation-name: fa-fade;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
}
.fa-fade,
.fa-flash {
-webkit-animation-delay: 0;
animation-delay: 0;
-webkit-animation-delay: var(--fa-animation-delay, 0);
animation-delay: var(--fa-animation-delay, 0);
-webkit-animation-direction: normal;
animation-direction: normal;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
}
.fa-flash {
-webkit-animation-name: fa-flash;
animation-name: fa-flash;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
animation-timing-function: cubic-bezier(0.4, 0, 0.6, 1);
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
}
.fa-flip {
-webkit-animation-name: fa-flip;
animation-name: fa-flip;
-webkit-animation-delay: 0;
animation-delay: 0;
-webkit-animation-delay: var(--fa-animation-delay, 0);
animation-delay: var(--fa-animation-delay, 0);
-webkit-animation-direction: normal;
animation-direction: normal;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: ease-in-out;
animation-timing-function: ease-in-out;
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
animation-timing-function: var(--fa-animation-timing, ease-in-out);
}
.fa-spin {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-delay: 0;
animation-delay: 0;
-webkit-animation-delay: var(--fa-animation-delay, 0);
animation-delay: var(--fa-animation-delay, 0);
-webkit-animation-direction: normal;
animation-direction: normal;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: 2s;
animation-duration: 2s;
-webkit-animation-duration: var(--fa-animation-duration, 2s);
animation-duration: var(--fa-animation-duration, 2s);
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
animation-timing-function: var(--fa-animation-timing, linear);
}
.fa-spin-reverse {
--fa-animation-direction: reverse;
}
.fa-pulse,
.fa-spin-pulse {
-webkit-animation-name: fa-spin;
animation-name: fa-spin;
-webkit-animation-direction: normal;
animation-direction: normal;
-webkit-animation-direction: var(--fa-animation-direction, normal);
animation-direction: var(--fa-animation-direction, normal);
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-duration: var(--fa-animation-duration, 1s);
animation-duration: var(--fa-animation-duration, 1s);
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
-webkit-animation-timing-function: steps(8);
animation-timing-function: steps(8);
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
animation-timing-function: var(--fa-animation-timing, steps(8));
}
@media (prefers-reduced-motion: reduce) {
.fa-beat,
.fa-fade,
.fa-flash,
.fa-flip,
.fa-pulse,
.fa-spin,
.fa-spin-pulse {
-webkit-animation-delay: -1ms;
animation-delay: -1ms;
-webkit-animation-duration: 1ms;
animation-duration: 1ms;
-webkit-animation-iteration-count: 1;
animation-iteration-count: 1;
-webkit-transition-delay: 0s;
transition-delay: 0s;
-webkit-transition-duration: 0s;
transition-duration: 0s;
}
}
@-webkit-keyframes fa-beat {
0%,
90% {
-webkit-transform: scale(1);
transform: scale(1);
}
45% {
-webkit-transform: scale(1.25);
transform: scale(1.25);
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25));
}
}
@keyframes fa-beat {
0%,
90% {
-webkit-transform: scale(1);
transform: scale(1);
}
45% {
-webkit-transform: scale(1.25);
transform: scale(1.25);
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
transform: scale(var(--fa-beat-scale, 1.25));
}
}
@-webkit-keyframes fa-fade {
50% {
opacity: 0.4;
opacity: var(--fa-fade-opacity, 0.4);
}
}
@keyframes fa-fade {
50% {
opacity: 0.4;
opacity: var(--fa-fade-opacity, 0.4);
}
}
@-webkit-keyframes fa-flash {
0%,
to {
opacity: 0.4;
opacity: var(--fa-flash-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 1;
-webkit-transform: scale(1.125);
transform: scale(1.125);
-webkit-transform: scale(var(--fa-flash-scale, 1.125));
transform: scale(var(--fa-flash-scale, 1.125));
}
}
@keyframes fa-flash {
0%,
to {
opacity: 0.4;
opacity: var(--fa-flash-opacity, 0.4);
-webkit-transform: scale(1);
transform: scale(1);
}
50% {
opacity: 1;
-webkit-transform: scale(1.125);
transform: scale(1.125);
-webkit-transform: scale(var(--fa-flash-scale, 1.125));
transform: scale(var(--fa-flash-scale, 1.125));
}
}
@-webkit-keyframes fa-flip {
50% {
-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
-webkit-transform: rotate3d(
var(--fa-flip-x, 0),
var(--fa-flip-y, 1),
var(--fa-flip-z, 0),
var(--fa-flip-angle, -180deg)
);
transform: rotate3d(
var(--fa-flip-x, 0),
var(--fa-flip-y, 1),
var(--fa-flip-z, 0),
var(--fa-flip-angle, -180deg)
);
}
}
@keyframes fa-flip {
50% {
-webkit-transform: rotateY(-180deg);
transform: rotateY(-180deg);
-webkit-transform: rotate3d(
var(--fa-flip-x, 0),
var(--fa-flip-y, 1),
var(--fa-flip-z, 0),
var(--fa-flip-angle, -180deg)
);
transform: rotate3d(
var(--fa-flip-x, 0),
var(--fa-flip-y, 1),
var(--fa-flip-z, 0),
var(--fa-flip-angle, -180deg)
);
}
}
@-webkit-keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
@keyframes fa-spin {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
.fa-rotate-90 {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
}
.fa-rotate-180 {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.fa-rotate-270 {
-webkit-transform: rotate(270deg);
transform: rotate(270deg);
}
.fa-flip-horizontal {
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
.fa-flip-vertical {
-webkit-transform: scaleY(-1);
transform: scaleY(-1);
}
.fa-flip-both,
.fa-flip-horizontal.fa-flip-vertical {
-webkit-transform: scale(-1);
transform: scale(-1);
}
.fa-rotate-by {
-webkit-transform: rotate(none);
transform: rotate(none);
-webkit-transform: rotate(var(--fa-rotate-angle, none));
transform: rotate(var(--fa-rotate-angle, none));
}
.fa-stack {
display: inline-block;
height: 2em;
line-height: 2em;
position: relative;
vertical-align: middle;
width: 2.5em;
}
.fa-stack-1x,
.fa-stack-2x {
left: 0;
position: absolute;
text-align: center;
width: 100%;
z-index: auto;
z-index: var(--fa-stack-z-index, auto);
}
.fa-stack-1x {
line-height: inherit;
}
.fa-stack-2x {
font-size: 2em;
}
.fa-inverse {
color: #fff;
color: var(--fa-inverse, #fff);
}
.fa-0:before {
content: '\30';
}
.fa-1:before {
content: '\31';
}
.fa-2:before {
content: '\32';
}
.fa-3:before {
content: '\33';
}
.fa-4:before {
content: '\34';
}
.fa-5:before {
content: '\35';
}
.fa-6:before {
content: '\36';
}
.fa-7:before {
content: '\37';
}
.fa-8:before {
content: '\38';
}
.fa-9:before {
content: '\39';
}
.fa-a:before {
content: '\41';
}
.fa-address-book:before,
.fa-contact-book:before {
content: '\f2b9';
}
.fa-address-card:before,
.fa-contact-card:before,
.fa-vcard:before {
content: '\f2bb';
}
.fa-align-center:before {
content: '\f037';
}
.fa-align-justify:before {
content: '\f039';
}
.fa-align-left:before {
content: '\f036';
}
.fa-align-right:before {
content: '\f038';
}
.fa-anchor:before {
content: '\f13d';
}
.fa-angle-down:before {
content: '\f107';
}
.fa-angle-left:before {
content: '\f104';
}
.fa-angle-right:before {
content: '\f105';
}
.fa-angle-up:before {
content: '\f106';
}
.fa-angle-double-down:before,
.fa-angles-down:before {
content: '\f103';
}
.fa-angle-double-left:before,
.fa-angles-left:before {
content: '\f100';
}
.fa-angle-double-right:before,
.fa-angles-right:before {
content: '\f101';
}
.fa-angle-double-up:before,
.fa-angles-up:before {
content: '\f102';
}
.fa-ankh:before {
content: '\f644';
}
.fa-apple-alt:before,
.fa-apple-whole:before {
content: '\f5d1';
}
.fa-archway:before {
content: '\f557';
}
.fa-arrow-down:before {
content: '\f063';
}
.fa-arrow-down-1-9:before,
.fa-sort-numeric-asc:before,
.fa-sort-numeric-down:before {
content: '\f162';
}
.fa-arrow-down-9-1:before,
.fa-sort-numeric-desc:before,
.fa-sort-numeric-down-alt:before {
content: '\f886';
}
.fa-arrow-down-a-z:before,
.fa-sort-alpha-asc:before,
.fa-sort-alpha-down:before {
content: '\f15d';
}
.fa-arrow-down-short-wide:before,
.fa-sort-amount-desc:before,
.fa-sort-amount-down-alt:before {
content: '\f884';
}
.fa-arrow-down-wide-short:before,
.fa-sort-amount-asc:before,
.fa-sort-amount-down:before {
content: '\f160';
}
.fa-arrow-down-z-a:before,
.fa-sort-alpha-desc:before,
.fa-sort-alpha-down-alt:before {
content: '\f881';
}
.fa-arrow-left:before {
content: '\f060';
}
.fa-arrow-pointer:before,
.fa-mouse-pointer:before {
content: '\f245';
}
.fa-arrow-right:before {
content: '\f061';
}
.fa-arrow-left-rotate:before,
.fa-arrow-rotate-back:before,
.fa-arrow-rotate-backward:before,
.fa-arrow-rotate-left:before,
.fa-undo:before {
content: '\f0e2';
}
.fa-arrow-right-rotate:before,
.fa-arrow-rotate-forward:before,
.fa-arrow-rotate-right:before,
.fa-redo:before {
content: '\f01e';
}
.fa-arrow-trend-down:before {
content: '\e097';
}
.fa-arrow-trend-up:before {
content: '\e098';
}
.fa-arrow-up:before {
content: '\f062';
}
.fa-arrow-up-1-9:before,
.fa-sort-numeric-up:before {
content: '\f163';
}
.fa-arrow-up-9-1:before,
.fa-sort-numeric-up-alt:before {
content: '\f887';
}
.fa-arrow-up-a-z:before,
.fa-sort-alpha-up:before {
content: '\f15e';
}
.fa-arrow-up-from-bracket:before {
content: '\e09a';
}
.fa-arrow-up-short-wide:before,
.fa-sort-amount-up-alt:before {
content: '\f885';
}
.fa-arrow-up-wide-short:before,
.fa-sort-amount-up:before {
content: '\f161';
}
.fa-arrow-up-z-a:before,
.fa-sort-alpha-up-alt:before {
content: '\f882';
}
.fa-arrows-rotate:before,
.fa-refresh:before,
.fa-sync:before {
content: '\f021';
}
.fa-asterisk:before {
content: '\2a';
}
.fa-at:before {
content: '\40';
}
.fa-atom:before {
content: '\f5d2';
}
.fa-audio-description:before {
content: '\f29e';
}
.fa-austral-sign:before {
content: '\e0a9';
}
.fa-award:before {
content: '\f559';
}
.fa-b:before {
content: '\42';
}
.fa-baby:before {
content: '\f77c';
}
.fa-baby-carriage:before,
.fa-carriage-baby:before {
content: '\f77d';
}
.fa-backward:before {
content: '\f04a';
}
.fa-backward-fast:before,
.fa-fast-backward:before {
content: '\f049';
}
.fa-backward-step:before,
.fa-step-backward:before {
content: '\f048';
}
.fa-bacon:before {
content: '\f7e5';
}
.fa-bacteria:before {
content: '\e059';
}
.fa-bacterium:before {
content: '\e05a';
}
.fa-bag-shopping:before,
.fa-shopping-bag:before {
content: '\f290';
}
.fa-bahai:before {
content: '\f666';
}
.fa-baht-sign:before {
content: '\e0ac';
}
.fa-ban:before,
.fa-cancel:before {
content: '\f05e';
}
.fa-ban-smoking:before,
.fa-smoking-ban:before {
content: '\f54d';
}
.fa-band-aid:before,
.fa-bandage:before {
content: '\f462';
}
.fa-bank:before,
.fa-institution:before,
.fa-university:before {
content: '\f19c';
}
.fa-barcode:before {
content: '\f02a';
}
.fa-bars:before,
.fa-navicon:before {
content: '\f0c9';
}
.fa-bars-staggered:before,
.fa-reorder:before,
.fa-stream:before {
content: '\f550';
}
.fa-baseball-ball:before,
.fa-baseball:before {
content: '\f433';
}
.fa-basket-shopping:before,
.fa-shopping-basket:before {
content: '\f291';
}
.fa-basketball-ball:before,
.fa-basketball:before {
content: '\f434';
}
.fa-bath:before,
.fa-bathtub:before {
content: '\f2cd';
}
.fa-battery-0:before,
.fa-battery-empty:before {
content: '\f244';
}
.fa-battery-5:before,
.fa-battery-full:before,
.fa-battery:before {
content: '\f240';
}
.fa-battery-3:before,
.fa-battery-half:before {
content: '\f242';
}
.fa-battery-2:before,
.fa-battery-quarter:before {
content: '\f243';
}
.fa-battery-4:before,
.fa-battery-three-quarters:before {
content: '\f241';
}
.fa-bed:before {
content: '\f236';
}
.fa-bed-pulse:before,
.fa-procedures:before {
content: '\f487';
}
.fa-beer-mug-empty:before,
.fa-beer:before {
content: '\f0fc';
}
.fa-bell:before {
content: '\f0f3';
}
.fa-bell-concierge:before,
.fa-concierge-bell:before {
content: '\f562';
}
.fa-bell-slash:before {
content: '\f1f6';
}
.fa-bezier-curve:before {
content: '\f55b';
}
.fa-bicycle:before {
content: '\f206';
}
.fa-binoculars:before {
content: '\f1e5';
}
.fa-biohazard:before {
content: '\f780';
}
.fa-bitcoin-sign:before {
content: '\e0b4';
}
.fa-blender:before {
content: '\f517';
}
.fa-blender-phone:before {
content: '\f6b6';
}
.fa-blog:before {
content: '\f781';
}
.fa-bold:before {
content: '\f032';
}
.fa-bolt:before,
.fa-flash:before {
content: '\f0e7';
}
.fa-bomb:before {
content: '\f1e2';
}
.fa-bone:before {
content: '\f5d7';
}
.fa-bong:before {
content: '\f55c';
}
.fa-book:before {
content: '\f02d';
}
.fa-atlas:before,
.fa-book-atlas:before {
content: '\f558';
}
.fa-bible:before,
.fa-book-bible:before {
content: '\f647';
}
.fa-book-journal-whills:before,
.fa-journal-whills:before {
content: '\f66a';
}
.fa-book-medical:before {
content: '\f7e6';
}
.fa-book-open:before {
content: '\f518';
}
.fa-book-open-reader:before,
.fa-book-reader:before {
content: '\f5da';
}
.fa-book-quran:before,
.fa-quran:before {
content: '\f687';
}
.fa-book-dead:before,
.fa-book-skull:before {
content: '\f6b7';
}
.fa-bookmark:before {
content: '\f02e';
}
.fa-border-all:before {
content: '\f84c';
}
.fa-border-none:before {
content: '\f850';
}
.fa-border-style:before,
.fa-border-top-left:before {
content: '\f853';
}
.fa-bowling-ball:before {
content: '\f436';
}
.fa-box:before {
content: '\f466';
}
.fa-archive:before,
.fa-box-archive:before {
content: '\f187';
}
.fa-box-open:before {
content: '\f49e';
}
.fa-box-tissue:before {
content: '\e05b';
}
.fa-boxes-alt:before,
.fa-boxes-stacked:before,
.fa-boxes:before {
content: '\f468';
}
.fa-braille:before {
content: '\f2a1';
}
.fa-brain:before {
content: '\f5dc';
}
.fa-bread-slice:before {
content: '\f7ec';
}
.fa-briefcase:before {
content: '\f0b1';
}
.fa-briefcase-medical:before {
content: '\f469';
}
.fa-broom:before {
content: '\f51a';
}
.fa-brush:before {
content: '\f55d';
}
.fa-bug:before {
content: '\f188';
}
.fa-building:before {
content: '\f1ad';
}
.fa-bullhorn:before {
content: '\f0a1';
}
.fa-bullseye:before {
content: '\f140';
}
.fa-burger:before,
.fa-hamburger:before {
content: '\f805';
}
.fa-bus:before {
content: '\f207';
}
.fa-bus-alt:before,
.fa-bus-simple:before {
content: '\f55e';
}
.fa-briefcase-clock:before,
.fa-business-time:before {
content: '\f64a';
}
.fa-c:before {
content: '\43';
}
.fa-birthday-cake:before,
.fa-cake-candles:before {
content: '\f1fd';
}
.fa-calculator:before {
content: '\f1ec';
}
.fa-calendar:before {
content: '\f133';
}
.fa-calendar-check:before {
content: '\f274';
}
.fa-calendar-day:before {
content: '\f783';
}
.fa-calendar-alt:before,
.fa-calendar-days:before {
content: '\f073';
}
.fa-calendar-minus:before {
content: '\f272';
}
.fa-calendar-plus:before {
content: '\f271';
}
.fa-calendar-week:before {
content: '\f784';
}
.fa-calendar-times:before,
.fa-calendar-xmark:before {
content: '\f273';
}
.fa-camera-alt:before,
.fa-camera:before {
content: '\f030';
}
.fa-camera-retro:before {
content: '\f083';
}
.fa-camera-rotate:before {
content: '\e0d8';
}
.fa-campground:before {
content: '\f6bb';
}
.fa-candy-cane:before {
content: '\f786';
}
.fa-cannabis:before {
content: '\f55f';
}
.fa-capsules:before {
content: '\f46b';
}
.fa-automobile:before,
.fa-car:before {
content: '\f1b9';
}
.fa-battery-car:before,
.fa-car-battery:before {
content: '\f5df';
}
.fa-car-crash:before {
content: '\f5e1';
}
.fa-car-alt:before,
.fa-car-rear:before {
content: '\f5de';
}
.fa-car-side:before {
content: '\f5e4';
}
.fa-caravan:before {
content: '\f8ff';
}
.fa-caret-down:before {
content: '\f0d7';
}
.fa-caret-left:before {
content: '\f0d9';
}
.fa-caret-right:before {
content: '\f0da';
}
.fa-caret-up:before {
content: '\f0d8';
}
.fa-carrot:before {
content: '\f787';
}
.fa-cart-arrow-down:before {
content: '\f218';
}
.fa-cart-flatbed:before,
.fa-dolly-flatbed:before {
content: '\f474';
}
.fa-cart-flatbed-suitcase:before,
.fa-luggage-cart:before {
content: '\f59d';
}
.fa-cart-plus:before {
content: '\f217';
}
.fa-cart-shopping:before,
.fa-shopping-cart:before {
content: '\f07a';
}
.fa-cash-register:before {
content: '\f788';
}
.fa-cat:before {
content: '\f6be';
}
.fa-cedi-sign:before {
content: '\e0df';
}
.fa-cent-sign:before {
content: '\e3f5';
}
.fa-certificate:before {
content: '\f0a3';
}
.fa-chair:before {
content: '\f6c0';
}
.fa-blackboard:before,
.fa-chalkboard:before {
content: '\f51b';
}
.fa-chalkboard-teacher:before,
.fa-chalkboard-user:before {
content: '\f51c';
}
.fa-champagne-glasses:before,
.fa-glass-cheers:before {
content: '\f79f';
}
.fa-charging-station:before {
content: '\f5e7';
}
.fa-area-chart:before,
.fa-chart-area:before {
content: '\f1fe';
}
.fa-bar-chart:before,
.fa-chart-bar:before {
content: '\f080';
}
.fa-chart-gantt:before {
content: '\e0e4';
}
.fa-chart-line:before,
.fa-line-chart:before {
content: '\f201';
}
.fa-chart-pie:before,
.fa-pie-chart:before {
content: '\f200';
}
.fa-check:before {
content: '\f00c';
}
.fa-check-double:before {
content: '\f560';
}
.fa-check-to-slot:before,
.fa-vote-yea:before {
content: '\f772';
}
.fa-cheese:before {
content: '\f7ef';
}
.fa-chess:before {
content: '\f439';
}
.fa-chess-bishop:before {
content: '\f43a';
}
.fa-chess-board:before {
content: '\f43c';
}
.fa-chess-king:before {
content: '\f43f';
}
.fa-chess-knight:before {
content: '\f441';
}
.fa-chess-pawn:before {
content: '\f443';
}
.fa-chess-queen:before {
content: '\f445';
}
.fa-chess-rook:before {
content: '\f447';
}
.fa-chevron-down:before {
content: '\f078';
}
.fa-chevron-left:before {
content: '\f053';
}
.fa-chevron-right:before {
content: '\f054';
}
.fa-chevron-up:before {
content: '\f077';
}
.fa-child:before {
content: '\f1ae';
}
.fa-church:before {
content: '\f51d';
}
.fa-circle:before {
content: '\f111';
}
.fa-arrow-circle-down:before,
.fa-circle-arrow-down:before {
content: '\f0ab';
}
.fa-arrow-circle-left:before,
.fa-circle-arrow-left:before {
content: '\f0a8';
}
.fa-arrow-circle-right:before,
.fa-circle-arrow-right:before {
content: '\f0a9';
}
.fa-arrow-circle-up:before,
.fa-circle-arrow-up:before {
content: '\f0aa';
}
.fa-check-circle:before,
.fa-circle-check:before {
content: '\f058';
}
.fa-chevron-circle-down:before,
.fa-circle-chevron-down:before {
content: '\f13a';
}
.fa-chevron-circle-left:before,
.fa-circle-chevron-left:before {
content: '\f137';
}
.fa-chevron-circle-right:before,
.fa-circle-chevron-right:before {
content: '\f138';
}
.fa-chevron-circle-up:before,
.fa-circle-chevron-up:before {
content: '\f139';
}
.fa-circle-dollar-to-slot:before,
.fa-donate:before {
content: '\f4b9';
}
.fa-circle-dot:before,
.fa-dot-circle:before {
content: '\f192';
}
.fa-arrow-alt-circle-down:before,
.fa-circle-down:before {
content: '\f358';
}
.fa-circle-exclamation:before,
.fa-exclamation-circle:before {
content: '\f06a';
}
.fa-circle-h:before,
.fa-hospital-symbol:before {
content: '\f47e';
}
.fa-adjust:before,
.fa-circle-half-stroke:before {
content: '\f042';
}
.fa-circle-info:before,
.fa-info-circle:before {
content: '\f05a';
}
.fa-arrow-alt-circle-left:before,
.fa-circle-left:before {
content: '\f359';
}
.fa-circle-minus:before,
.fa-minus-circle:before {
content: '\f056';
}
.fa-circle-notch:before {
content: '\f1ce';
}
.fa-circle-pause:before,
.fa-pause-circle:before {
content: '\f28b';
}
.fa-circle-play:before,
.fa-play-circle:before {
content: '\f144';
}
.fa-circle-plus:before,
.fa-plus-circle:before {
content: '\f055';
}
.fa-circle-question:before,
.fa-question-circle:before {
content: '\f059';
}
.fa-circle-radiation:before,
.fa-radiation-alt:before {
content: '\f7ba';
}
.fa-arrow-alt-circle-right:before,
.fa-circle-right:before {
content: '\f35a';
}
.fa-circle-stop:before,
.fa-stop-circle:before {
content: '\f28d';
}
.fa-arrow-alt-circle-up:before,
.fa-circle-up:before {
content: '\f35b';
}
.fa-circle-user:before,
.fa-user-circle:before {
content: '\f2bd';
}
.fa-circle-xmark:before,
.fa-times-circle:before,
.fa-xmark-circle:before {
content: '\f057';
}
.fa-city:before {
content: '\f64f';
}
.fa-clapperboard:before {
content: '\e131';
}
.fa-clipboard:before {
content: '\f328';
}
.fa-clipboard-check:before {
content: '\f46c';
}
.fa-clipboard-list:before {
content: '\f46d';
}
.fa-clock-four:before,
.fa-clock:before {
content: '\f017';
}
.fa-clock-rotate-left:before,
.fa-history:before {
content: '\f1da';
}
.fa-clone:before {
content: '\f24d';
}
.fa-closed-captioning:before {
content: '\f20a';
}
.fa-cloud:before {
content: '\f0c2';
}
.fa-cloud-arrow-down:before,
.fa-cloud-download-alt:before,
.fa-cloud-download:before {
content: '\f0ed';
}
.fa-cloud-arrow-up:before,
.fa-cloud-upload-alt:before,
.fa-cloud-upload:before {
content: '\f0ee';
}
.fa-cloud-meatball:before {
content: '\f73b';
}
.fa-cloud-moon:before {
content: '\f6c3';
}
.fa-cloud-moon-rain:before {
content: '\f73c';
}
.fa-cloud-rain:before {
content: '\f73d';
}
.fa-cloud-showers-heavy:before {
content: '\f740';
}
.fa-cloud-sun:before {
content: '\f6c4';
}
.fa-cloud-sun-rain:before {
content: '\f743';
}
.fa-clover:before {
content: '\e139';
}
.fa-code:before {
content: '\f121';
}
.fa-code-branch:before {
content: '\f126';
}
.fa-code-commit:before {
content: '\f386';
}
.fa-code-compare:before {
content: '\e13a';
}
.fa-code-fork:before {
content: '\e13b';
}
.fa-code-merge:before {
content: '\f387';
}
.fa-code-pull-request:before {
content: '\e13c';
}
.fa-coins:before {
content: '\f51e';
}
.fa-colon-sign:before {
content: '\e140';
}
.fa-comment:before {
content: '\f075';
}
.fa-comment-dollar:before {
content: '\f651';
}
.fa-comment-dots:before,
.fa-commenting:before {
content: '\f4ad';
}
.fa-comment-medical:before {
content: '\f7f5';
}
.fa-comment-slash:before {
content: '\f4b3';
}
.fa-comment-sms:before,
.fa-sms:before {
content: '\f7cd';
}
.fa-comments:before {
content: '\f086';
}
.fa-comments-dollar:before {
content: '\f653';
}
.fa-compact-disc:before {
content: '\f51f';
}
.fa-compass:before {
content: '\f14e';
}
.fa-compass-drafting:before,
.fa-drafting-compass:before {
content: '\f568';
}
.fa-compress:before {
content: '\f066';
}
.fa-computer-mouse:before,
.fa-mouse:before {
content: '\f8cc';
}
.fa-cookie:before {
content: '\f563';
}
.fa-cookie-bite:before {
content: '\f564';
}
.fa-copy:before {
content: '\f0c5';
}
.fa-copyright:before {
content: '\f1f9';
}
.fa-couch:before {
content: '\f4b8';
}
.fa-credit-card-alt:before,
.fa-credit-card:before {
content: '\f09d';
}
.fa-crop:before {
content: '\f125';
}
.fa-crop-alt:before,
.fa-crop-simple:before {
content: '\f565';
}
.fa-cross:before {
content: '\f654';
}
.fa-crosshairs:before {
content: '\f05b';
}
.fa-crow:before {
content: '\f520';
}
.fa-crown:before {
content: '\f521';
}
.fa-crutch:before {
content: '\f7f7';
}
.fa-cruzeiro-sign:before {
content: '\e152';
}
.fa-cube:before {
content: '\f1b2';
}
.fa-cubes:before {
content: '\f1b3';
}
.fa-d:before {
content: '\44';
}
.fa-database:before {
content: '\f1c0';
}
.fa-backspace:before,
.fa-delete-left:before {
content: '\f55a';
}
.fa-democrat:before {
content: '\f747';
}
.fa-desktop-alt:before,
.fa-desktop:before {
content: '\f390';
}
.fa-dharmachakra:before {
content: '\f655';
}
.fa-diagram-project:before,
.fa-project-diagram:before {
content: '\f542';
}
.fa-diamond-turn-right:before,
.fa-directions:before {
content: '\f5eb';
}
.fa-dice:before {
content: '\f522';
}
.fa-dice-d20:before {
content: '\f6cf';
}
.fa-dice-d6:before {
content: '\f6d1';
}
.fa-dice-five:before {
content: '\f523';
}
.fa-dice-four:before {
content: '\f524';
}
.fa-dice-one:before {
content: '\f525';
}
.fa-dice-six:before {
content: '\f526';
}
.fa-dice-three:before {
content: '\f527';
}
.fa-dice-two:before {
content: '\f528';
}
.fa-disease:before {
content: '\f7fa';
}
.fa-divide:before {
content: '\f529';
}
.fa-dna:before {
content: '\f471';
}
.fa-dog:before {
content: '\f6d3';
}
.fa-dollar-sign:before,
.fa-dollar:before,
.fa-usd:before {
content: '\24';
}
.fa-dolly-box:before,
.fa-dolly:before {
content: '\f472';
}
.fa-dong-sign:before {
content: '\e169';
}
.fa-door-closed:before {
content: '\f52a';
}
.fa-door-open:before {
content: '\f52b';
}
.fa-dove:before {
content: '\f4ba';
}
.fa-compress-alt:before,
.fa-down-left-and-up-right-to-center:before {
content: '\f422';
}
.fa-down-long:before,
.fa-long-arrow-alt-down:before {
content: '\f309';
}
.fa-download:before {
content: '\f019';
}
.fa-dragon:before {
content: '\f6d5';
}
.fa-draw-polygon:before {
content: '\f5ee';
}
.fa-droplet:before,
.fa-tint:before {
content: '\f043';
}
.fa-droplet-slash:before,
.fa-tint-slash:before {
content: '\f5c7';
}
.fa-drum:before {
content: '\f569';
}
.fa-drum-steelpan:before {
content: '\f56a';
}
.fa-drumstick-bite:before {
content: '\f6d7';
}
.fa-dumbbell:before {
content: '\f44b';
}
.fa-dumpster:before {
content: '\f793';
}
.fa-dumpster-fire:before {
content: '\f794';
}
.fa-dungeon:before {
content: '\f6d9';
}
.fa-e:before {
content: '\45';
}
.fa-deaf:before,
.fa-deafness:before,
.fa-ear-deaf:before,
.fa-hard-of-hearing:before {
content: '\f2a4';
}
.fa-assistive-listening-systems:before,
.fa-ear-listen:before {
content: '\f2a2';
}
.fa-earth-africa:before,
.fa-globe-africa:before {
content: '\f57c';
}
.fa-earth-americas:before,
.fa-earth:before,
.fa-globe-americas:before {
content: '\f57d';
}
.fa-earth-asia:before,
.fa-globe-asia:before {
content: '\f57e';
}
.fa-earth-europa:before,
.fa-globe-europe:before {
content: '\f7a2';
}
.fa-egg:before {
content: '\f7fb';
}
.fa-eject:before {
content: '\f052';
}
.fa-elevator:before {
content: '\e16d';
}
.fa-ellipsis-h:before,
.fa-ellipsis:before {
content: '\f141';
}
.fa-ellipsis-v:before,
.fa-ellipsis-vertical:before {
content: '\f142';
}
.fa-envelope:before {
content: '\f0e0';
}
.fa-envelope-open:before {
content: '\f2b6';
}
.fa-envelope-open-text:before {
content: '\f658';
}
.fa-envelopes-bulk:before,
.fa-mail-bulk:before {
content: '\f674';
}
.fa-equals:before {
content: '\3d';
}
.fa-eraser:before {
content: '\f12d';
}
.fa-ethernet:before {
content: '\f796';
}
.fa-eur:before,
.fa-euro-sign:before,
.fa-euro:before {
content: '\f153';
}
.fa-exclamation:before {
content: '\21';
}
.fa-expand:before {
content: '\f065';
}
.fa-eye:before {
content: '\f06e';
}
.fa-eye-dropper-empty:before,
.fa-eye-dropper:before,
.fa-eyedropper:before {
content: '\f1fb';
}
.fa-eye-low-vision:before,
.fa-low-vision:before {
content: '\f2a8';
}
.fa-eye-slash:before {
content: '\f070';
}
.fa-f:before {
content: '\46';
}
.fa-angry:before,
.fa-face-angry:before {
content: '\f556';
}
.fa-dizzy:before,
.fa-face-dizzy:before {
content: '\f567';
}
.fa-face-flushed:before,
.fa-flushed:before {
content: '\f579';
}
.fa-face-frown:before,
.fa-frown:before {
content: '\f119';
}
.fa-face-frown-open:before,
.fa-frown-open:before {
content: '\f57a';
}
.fa-face-grimace:before,
.fa-grimace:before {
content: '\f57f';
}
.fa-face-grin:before,
.fa-grin:before {
content: '\f580';
}
.fa-face-grin-beam:before,
.fa-grin-beam:before {
content: '\f582';
}
.fa-face-grin-beam-sweat:before,
.fa-grin-beam-sweat:before {
content: '\f583';
}
.fa-face-grin-hearts:before,
.fa-grin-hearts:before {
content: '\f584';
}
.fa-face-grin-squint:before,
.fa-grin-squint:before {
content: '\f585';
}
.fa-face-grin-squint-tears:before,
.fa-grin-squint-tears:before {
content: '\f586';
}
.fa-face-grin-stars:before,
.fa-grin-stars:before {
content: '\f587';
}
.fa-face-grin-tears:before,
.fa-grin-tears:before {
content: '\f588';
}
.fa-face-grin-tongue:before,
.fa-grin-tongue:before {
content: '\f589';
}
.fa-face-grin-tongue-squint:before,
.fa-grin-tongue-squint:before {
content: '\f58a';
}
.fa-face-grin-tongue-wink:before,
.fa-grin-tongue-wink:before {
content: '\f58b';
}
.fa-face-grin-wide:before,
.fa-grin-alt:before {
content: '\f581';
}
.fa-face-grin-wink:before,
.fa-grin-wink:before {
content: '\f58c';
}
.fa-face-kiss:before,
.fa-kiss:before {
content: '\f596';
}
.fa-face-kiss-beam:before,
.fa-kiss-beam:before {
content: '\f597';
}
.fa-face-kiss-wink-heart:before,
.fa-kiss-wink-heart:before {
content: '\f598';
}
.fa-face-laugh:before,
.fa-laugh:before {
content: '\f599';
}
.fa-face-laugh-beam:before,
.fa-laugh-beam:before {
content: '\f59a';
}
.fa-face-laugh-squint:before,
.fa-laugh-squint:before {
content: '\f59b';
}
.fa-face-laugh-wink:before,
.fa-laugh-wink:before {
content: '\f59c';
}
.fa-face-meh:before,
.fa-meh:before {
content: '\f11a';
}
.fa-face-meh-blank:before,
.fa-meh-blank:before {
content: '\f5a4';
}
.fa-face-rolling-eyes:before,
.fa-meh-rolling-eyes:before {
content: '\f5a5';
}
.fa-face-sad-cry:before,
.fa-sad-cry:before {
content: '\f5b3';
}
.fa-face-sad-tear:before,
.fa-sad-tear:before {
content: '\f5b4';
}
.fa-face-smile:before,
.fa-smile:before {
content: '\f118';
}
.fa-face-smile-beam:before,
.fa-smile-beam:before {
content: '\f5b8';
}
.fa-face-smile-wink:before,
.fa-smile-wink:before {
content: '\f4da';
}
.fa-face-surprise:before,
.fa-surprise:before {
content: '\f5c2';
}
.fa-face-tired:before,
.fa-tired:before {
content: '\f5c8';
}
.fa-fan:before {
content: '\f863';
}
.fa-faucet:before {
content: '\e005';
}
.fa-fax:before {
content: '\f1ac';
}
.fa-feather:before {
content: '\f52d';
}
.fa-feather-alt:before,
.fa-feather-pointed:before {
content: '\f56b';
}
.fa-file:before {
content: '\f15b';
}
.fa-file-arrow-down:before,
.fa-file-download:before {
content: '\f56d';
}
.fa-file-arrow-up:before,
.fa-file-upload:before {
content: '\f574';
}
.fa-file-audio:before {
content: '\f1c7';
}
.fa-file-code:before {
content: '\f1c9';
}
.fa-file-contract:before {
content: '\f56c';
}
.fa-file-csv:before {
content: '\f6dd';
}
.fa-file-excel:before {
content: '\f1c3';
}
.fa-arrow-right-from-file:before,
.fa-file-export:before {
content: '\f56e';
}
.fa-file-image:before {
content: '\f1c5';
}
.fa-arrow-right-to-file:before,
.fa-file-import:before {
content: '\f56f';
}
.fa-file-invoice:before {
content: '\f570';
}
.fa-file-invoice-dollar:before {
content: '\f571';
}
.fa-file-alt:before,
.fa-file-lines:before,
.fa-file-text:before {
content: '\f15c';
}
.fa-file-medical:before {
content: '\f477';
}
.fa-file-pdf:before {
content: '\f1c1';
}
.fa-file-powerpoint:before {
content: '\f1c4';
}
.fa-file-prescription:before {
content: '\f572';
}
.fa-file-signature:before {
content: '\f573';
}
.fa-file-video:before {
content: '\f1c8';
}
.fa-file-medical-alt:before,
.fa-file-waveform:before {
content: '\f478';
}
.fa-file-word:before {
content: '\f1c2';
}
.fa-file-archive:before,
.fa-file-zipper:before {
content: '\f1c6';
}
.fa-fill:before {
content: '\f575';
}
.fa-fill-drip:before {
content: '\f576';
}
.fa-film:before {
content: '\f008';
}
.fa-filter:before {
content: '\f0b0';
}
.fa-filter-circle-dollar:before,
.fa-funnel-dollar:before {
content: '\f662';
}
.fa-filter-circle-xmark:before {
content: '\e17b';
}
.fa-fingerprint:before {
content: '\f577';
}
.fa-fire:before {
content: '\f06d';
}
.fa-fire-extinguisher:before {
content: '\f134';
}
.fa-fire-alt:before,
.fa-fire-flame-curved:before {
content: '\f7e4';
}
.fa-burn:before,
.fa-fire-flame-simple:before {
content: '\f46a';
}
.fa-fish:before {
content: '\f578';
}
.fa-flag:before {
content: '\f024';
}
.fa-flag-checkered:before {
content: '\f11e';
}
.fa-flag-usa:before {
content: '\f74d';
}
.fa-flask:before {
content: '\f0c3';
}
.fa-floppy-disk:before,
.fa-save:before {
content: '\f0c7';
}
.fa-florin-sign:before {
content: '\e184';
}
.fa-folder:before {
content: '\f07b';
}
.fa-folder-minus:before {
content: '\f65d';
}
.fa-folder-open:before {
content: '\f07c';
}
.fa-folder-plus:before {
content: '\f65e';
}
.fa-folder-tree:before {
content: '\f802';
}
.fa-font:before {
content: '\f031';
}
.fa-football-ball:before,
.fa-football:before {
content: '\f44e';
}
.fa-forward:before {
content: '\f04e';
}
.fa-fast-forward:before,
.fa-forward-fast:before {
content: '\f050';
}
.fa-forward-step:before,
.fa-step-forward:before {
content: '\f051';
}
.fa-franc-sign:before {
content: '\e18f';
}
.fa-frog:before {
content: '\f52e';
}
.fa-futbol-ball:before,
.fa-futbol:before,
.fa-soccer-ball:before {
content: '\f1e3';
}
.fa-g:before {
content: '\47';
}
.fa-gamepad:before {
content: '\f11b';
}
.fa-gas-pump:before {
content: '\f52f';
}
.fa-gauge-simple-high:before,
.fa-gauge-simple:before,
.fa-tachometer:before {
content: '\f62a';
}
.fa-gavel:before,
.fa-legal:before {
content: '\f0e3';
}
.fa-cog:before,
.fa-gear:before {
content: '\f013';
}
.fa-cogs:before,
.fa-gears:before {
content: '\f085';
}
.fa-gem:before {
content: '\f3a5';
}
.fa-genderless:before {
content: '\f22d';
}
.fa-ghost:before {
content: '\f6e2';
}
.fa-gift:before {
content: '\f06b';
}
.fa-gifts:before {
content: '\f79c';
}
.fa-glasses:before {
content: '\f530';
}
.fa-globe:before {
content: '\f0ac';
}
.fa-golf-ball-tee:before,
.fa-golf-ball:before {
content: '\f450';
}
.fa-gopuram:before {
content: '\f664';
}
.fa-graduation-cap:before,
.fa-mortar-board:before {
content: '\f19d';
}
.fa-greater-than:before {
content: '\3e';
}
.fa-greater-than-equal:before {
content: '\f532';
}
.fa-grip-horizontal:before,
.fa-grip:before {
content: '\f58d';
}
.fa-grip-lines:before {
content: '\f7a4';
}
.fa-grip-lines-vertical:before {
content: '\f7a5';
}
.fa-grip-vertical:before {
content: '\f58e';
}
.fa-guarani-sign:before {
content: '\e19a';
}
.fa-guitar:before {
content: '\f7a6';
}
.fa-gun:before {
content: '\e19b';
}
.fa-h:before {
content: '\48';
}
.fa-hammer:before {
content: '\f6e3';
}
.fa-hamsa:before {
content: '\f665';
}
.fa-hand-paper:before,
.fa-hand:before {
content: '\f256';
}
.fa-hand-back-fist:before,
.fa-hand-rock:before {
content: '\f255';
}
.fa-allergies:before,
.fa-hand-dots:before {
content: '\f461';
}
.fa-fist-raised:before,
.fa-hand-fist:before {
content: '\f6de';
}
.fa-hand-holding:before {
content: '\f4bd';
}
.fa-hand-holding-dollar:before,
.fa-hand-holding-usd:before {
content: '\f4c0';
}
.fa-hand-holding-droplet:before,
.fa-hand-holding-water:before {
content: '\f4c1';
}
.fa-hand-holding-heart:before {
content: '\f4be';
}
.fa-hand-holding-medical:before {
content: '\e05c';
}
.fa-hand-lizard:before {
content: '\f258';
}
.fa-hand-middle-finger:before {
content: '\f806';
}
.fa-hand-peace:before {
content: '\f25b';
}
.fa-hand-point-down:before {
content: '\f0a7';
}
.fa-hand-point-left:before {
content: '\f0a5';
}
.fa-hand-point-right:before {
content: '\f0a4';
}
.fa-hand-point-up:before {
content: '\f0a6';
}
.fa-hand-pointer:before {
content: '\f25a';
}
.fa-hand-scissors:before {
content: '\f257';
}
.fa-hand-sparkles:before {
content: '\e05d';
}
.fa-hand-spock:before {
content: '\f259';
}
.fa-hands:before,
.fa-sign-language:before,
.fa-signing:before {
content: '\f2a7';
}
.fa-american-sign-language-interpreting:before,
.fa-asl-interpreting:before,
.fa-hands-american-sign-language-interpreting:before,
.fa-hands-asl-interpreting:before {
content: '\f2a3';
}
.fa-hands-bubbles:before,
.fa-hands-wash:before {
content: '\e05e';
}
.fa-hands-clapping:before {
content: '\e1a8';
}
.fa-hands-holding:before {
content: '\f4c2';
}
.fa-hands-praying:before,
.fa-praying-hands:before {
content: '\f684';
}
.fa-handshake:before {
content: '\f2b5';
}
.fa-hands-helping:before,
.fa-handshake-angle:before {
content: '\f4c4';
}
.fa-handshake-alt-slash:before,
.fa-handshake-simple-slash:before {
content: '\e05f';
}
.fa-handshake-slash:before {
content: '\e060';
}
.fa-hanukiah:before {
content: '\f6e6';
}
.fa-hard-drive:before,
.fa-hdd:before {
content: '\f0a0';
}
.fa-hashtag:before {
content: '\23';
}
.fa-hat-cowboy:before {
content: '\f8c0';
}
.fa-hat-cowboy-side:before {
content: '\f8c1';
}
.fa-hat-wizard:before {
content: '\f6e8';
}
.fa-head-side-cough:before {
content: '\e061';
}
.fa-head-side-cough-slash:before {
content: '\e062';
}
.fa-head-side-mask:before {
content: '\e063';
}
.fa-head-side-virus:before {
content: '\e064';
}
.fa-header:before,
.fa-heading:before {
content: '\f1dc';
}
.fa-headphones:before {
content: '\f025';
}
.fa-headphones-alt:before,
.fa-headphones-simple:before {
content: '\f58f';
}
.fa-headset:before {
content: '\f590';
}
.fa-heart:before {
content: '\f004';
}
.fa-heart-broken:before,
.fa-heart-crack:before {
content: '\f7a9';
}
.fa-heart-pulse:before,
.fa-heartbeat:before {
content: '\f21e';
}
.fa-helicopter:before {
content: '\f533';
}
.fa-hard-hat:before,
.fa-hat-hard:before,
.fa-helmet-safety:before {
content: '\f807';
}
.fa-highlighter:before {
content: '\f591';
}
.fa-hippo:before {
content: '\f6ed';
}
.fa-hockey-puck:before {
content: '\f453';
}
.fa-holly-berry:before {
content: '\f7aa';
}
.fa-horse:before {
content: '\f6f0';
}
.fa-horse-head:before {
content: '\f7ab';
}
.fa-hospital:before {
content: '\f0f8';
}
.fa-hospital-user:before {
content: '\f80d';
}
.fa-hospital-alt:before,
.fa-hospital-wide:before {
content: '\f47d';
}
.fa-hot-tub-person:before,
.fa-hot-tub:before {
content: '\f593';
}
.fa-hotdog:before {
content: '\f80f';
}
.fa-hotel:before {
content: '\f594';
}
.fa-hourglass-2:before,
.fa-hourglass-half:before,
.fa-hourglass:before {
content: '\f254';
}
.fa-hourglass-empty:before {
content: '\f252';
}
.fa-hourglass-3:before,
.fa-hourglass-end:before {
content: '\f253';
}
.fa-hourglass-1:before,
.fa-hourglass-start:before {
content: '\f251';
}
.fa-home:before,
.fa-house:before {
content: '\f015';
}
.fa-home-lg:before,
.fa-house-chimney:before {
content: '\e3af';
}
.fa-house-crack:before {
content: '\e3b1';
}
.fa-house-laptop:before,
.fa-laptop-house:before {
content: '\e066';
}
.fa-house-medical:before {
content: '\e3b2';
}
.fa-home-user:before,
.fa-house-user:before {
content: '\e1b0';
}
.fa-hryvnia-sign:before,
.fa-hryvnia:before {
content: '\f6f2';
}
.fa-i:before {
content: '\49';
}
.fa-i-cursor:before {
content: '\f246';
}
.fa-ice-cream:before {
content: '\f810';
}
.fa-icicles:before {
content: '\f7ad';
}
.fa-heart-music-camera-bolt:before,
.fa-icons:before {
content: '\f86d';
}
.fa-id-badge:before {
content: '\f2c1';
}
.fa-drivers-license:before,
.fa-id-card:before {
content: '\f2c2';
}
.fa-id-card-alt:before,
.fa-id-card-clip:before {
content: '\f47f';
}
.fa-igloo:before {
content: '\f7ae';
}
.fa-image:before {
content: '\f03e';
}
.fa-image-portrait:before,
.fa-portrait:before {
content: '\f3e0';
}
.fa-images:before {
content: '\f302';
}
.fa-inbox:before {
content: '\f01c';
}
.fa-indent:before {
content: '\f03c';
}
.fa-indian-rupee-sign:before,
.fa-indian-rupee:before,
.fa-inr:before {
content: '\e1bc';
}
.fa-industry:before {
content: '\f275';
}
.fa-infinity:before {
content: '\f534';
}
.fa-info:before {
content: '\f129';
}
.fa-italic:before {
content: '\f033';
}
.fa-j:before {
content: '\4a';
}
.fa-jedi:before {
content: '\f669';
}
.fa-fighter-jet:before,
.fa-jet-fighter:before {
content: '\f0fb';
}
.fa-joint:before {
content: '\f595';
}
.fa-k:before {
content: '\4b';
}
.fa-kaaba:before {
content: '\f66b';
}
.fa-key:before {
content: '\f084';
}
.fa-keyboard:before {
content: '\f11c';
}
.fa-khanda:before {
content: '\f66d';
}
.fa-kip-sign:before {
content: '\e1c4';
}
.fa-first-aid:before,
.fa-kit-medical:before {
content: '\f479';
}
.fa-kiwi-bird:before {
content: '\f535';
}
.fa-l:before {
content: '\4c';
}
.fa-landmark:before {
content: '\f66f';
}
.fa-language:before {
content: '\f1ab';
}
.fa-laptop:before {
content: '\f109';
}
.fa-laptop-code:before {
content: '\f5fc';
}
.fa-laptop-medical:before {
content: '\f812';
}
.fa-lari-sign:before {
content: '\e1c8';
}
.fa-layer-group:before {
content: '\f5fd';
}
.fa-leaf:before {
content: '\f06c';
}
.fa-left-long:before,
.fa-long-arrow-alt-left:before {
content: '\f30a';
}
.fa-arrows-alt-h:before,
.fa-left-right:before {
content: '\f337';
}
.fa-lemon:before {
content: '\f094';
}
.fa-less-than:before {
content: '\3c';
}
.fa-less-than-equal:before {
content: '\f537';
}
.fa-life-ring:before {
content: '\f1cd';
}
.fa-lightbulb:before {
content: '\f0eb';
}
.fa-chain:before,
.fa-link:before {
content: '\f0c1';
}
.fa-chain-broken:before,
.fa-chain-slash:before,
.fa-link-slash:before,
.fa-unlink:before {
content: '\f127';
}
.fa-lira-sign:before {
content: '\f195';
}
.fa-list-squares:before,
.fa-list:before {
content: '\f03a';
}
.fa-list-check:before,
.fa-tasks:before {
content: '\f0ae';
}
.fa-list-1-2:before,
.fa-list-numeric:before,
.fa-list-ol:before {
content: '\f0cb';
}
.fa-list-dots:before,
.fa-list-ul:before {
content: '\f0ca';
}
.fa-litecoin-sign:before {
content: '\e1d3';
}
.fa-location-arrow:before {
content: '\f124';
}
.fa-location-crosshairs:before,
.fa-location:before {
content: '\f601';
}
.fa-location-dot:before,
.fa-map-marker-alt:before {
content: '\f3c5';
}
.fa-location-pin:before,
.fa-map-marker:before {
content: '\f041';
}
.fa-lock:before {
content: '\f023';
}
.fa-lock-open:before {
content: '\f3c1';
}
.fa-lungs:before {
content: '\f604';
}
.fa-lungs-virus:before {
content: '\e067';
}
.fa-m:before {
content: '\4d';
}
.fa-magnet:before {
content: '\f076';
}
.fa-magnifying-glass:before,
.fa-search:before {
content: '\f002';
}
.fa-magnifying-glass-dollar:before,
.fa-search-dollar:before {
content: '\f688';
}
.fa-magnifying-glass-location:before,
.fa-search-location:before {
content: '\f689';
}
.fa-magnifying-glass-minus:before,
.fa-search-minus:before {
content: '\f010';
}
.fa-magnifying-glass-plus:before,
.fa-search-plus:before {
content: '\f00e';
}
.fa-manat-sign:before {
content: '\e1d5';
}
.fa-map:before {
content: '\f279';
}
.fa-map-location:before,
.fa-map-marked:before {
content: '\f59f';
}
.fa-map-location-dot:before,
.fa-map-marked-alt:before {
content: '\f5a0';
}
.fa-map-pin:before {
content: '\f276';
}
.fa-marker:before {
content: '\f5a1';
}
.fa-mars:before {
content: '\f222';
}
.fa-mars-and-venus:before {
content: '\f224';
}
.fa-mars-double:before {
content: '\f227';
}
.fa-mars-stroke:before {
content: '\f229';
}
.fa-mars-stroke-h:before,
.fa-mars-stroke-right:before {
content: '\f22b';
}
.fa-mars-stroke-up:before,
.fa-mars-stroke-v:before {
content: '\f22a';
}
.fa-glass-martini-alt:before,
.fa-martini-glass:before {
content: '\f57b';
}
.fa-cocktail:before,
.fa-martini-glass-citrus:before {
content: '\f561';
}
.fa-glass-martini:before,
.fa-martini-glass-empty:before {
content: '\f000';
}
.fa-mask:before {
content: '\f6fa';
}
.fa-mask-face:before {
content: '\e1d7';
}
.fa-masks-theater:before,
.fa-theater-masks:before {
content: '\f630';
}
.fa-expand-arrows-alt:before,
.fa-maximize:before {
content: '\f31e';
}
.fa-medal:before {
content: '\f5a2';
}
.fa-memory:before {
content: '\f538';
}
.fa-menorah:before {
content: '\f676';
}
.fa-mercury:before {
content: '\f223';
}
.fa-comment-alt:before,
.fa-message:before {
content: '\f27a';
}
.fa-meteor:before {
content: '\f753';
}
.fa-microchip:before {
content: '\f2db';
}
.fa-microphone:before {
content: '\f130';
}
.fa-microphone-alt:before,
.fa-microphone-lines:before {
content: '\f3c9';
}
.fa-microphone-alt-slash:before,
.fa-microphone-lines-slash:before {
content: '\f539';
}
.fa-microphone-slash:before {
content: '\f131';
}
.fa-microscope:before {
content: '\f610';
}
.fa-mill-sign:before {
content: '\e1ed';
}
.fa-compress-arrows-alt:before,
.fa-minimize:before {
content: '\f78c';
}
.fa-minus:before,
.fa-subtract:before {
content: '\f068';
}
.fa-mitten:before {
content: '\f7b5';
}
.fa-mobile-button:before {
content: '\f10b';
}
.fa-mobile-alt:before,
.fa-mobile-screen-button:before {
content: '\f3cd';
}
.fa-money-bill:before {
content: '\f0d6';
}
.fa-money-bill-1:before,
.fa-money-bill-alt:before {
content: '\f3d1';
}
.fa-money-bill-1-wave:before,
.fa-money-bill-wave-alt:before {
content: '\f53b';
}
.fa-money-bill-wave:before {
content: '\f53a';
}
.fa-money-check:before {
content: '\f53c';
}
.fa-money-check-alt:before,
.fa-money-check-dollar:before {
content: '\f53d';
}
.fa-monument:before {
content: '\f5a6';
}
.fa-moon:before {
content: '\f186';
}
.fa-mortar-pestle:before {
content: '\f5a7';
}
.fa-mosque:before {
content: '\f678';
}
.fa-motorcycle:before {
content: '\f21c';
}
.fa-mountain:before {
content: '\f6fc';
}
.fa-mug-hot:before {
content: '\f7b6';
}
.fa-coffee:before,
.fa-mug-saucer:before {
content: '\f0f4';
}
.fa-music:before {
content: '\f001';
}
.fa-n:before {
content: '\4e';
}
.fa-naira-sign:before {
content: '\e1f6';
}
.fa-network-wired:before {
content: '\f6ff';
}
.fa-neuter:before {
content: '\f22c';
}
.fa-newspaper:before {
content: '\f1ea';
}
.fa-not-equal:before {
content: '\f53e';
}
.fa-note-sticky:before,
.fa-sticky-note:before {
content: '\f249';
}
.fa-notes-medical:before {
content: '\f481';
}
.fa-o:before {
content: '\4f';
}
.fa-object-group:before {
content: '\f247';
}
.fa-object-ungroup:before {
content: '\f248';
}
.fa-oil-can:before {
content: '\f613';
}
.fa-om:before {
content: '\f679';
}
.fa-otter:before {
content: '\f700';
}
.fa-dedent:before,
.fa-outdent:before {
content: '\f03b';
}
.fa-p:before {
content: '\50';
}
.fa-pager:before {
content: '\f815';
}
.fa-paint-brush:before {
content: '\f1fc';
}
.fa-paint-roller:before {
content: '\f5aa';
}
.fa-palette:before {
content: '\f53f';
}
.fa-pallet:before {
content: '\f482';
}
.fa-panorama:before {
content: '\e209';
}
.fa-paper-plane:before {
content: '\f1d8';
}
.fa-paperclip:before {
content: '\f0c6';
}
.fa-parachute-box:before {
content: '\f4cd';
}
.fa-paragraph:before {
content: '\f1dd';
}
.fa-passport:before {
content: '\f5ab';
}
.fa-file-clipboard:before,
.fa-paste:before {
content: '\f0ea';
}
.fa-pause:before {
content: '\f04c';
}
.fa-paw:before {
content: '\f1b0';
}
.fa-peace:before {
content: '\f67c';
}
.fa-pen:before {
content: '\f304';
}
.fa-pen-alt:before,
.fa-pen-clip:before {
content: '\f305';
}
.fa-pen-fancy:before {
content: '\f5ac';
}
.fa-pen-nib:before {
content: '\f5ad';
}
.fa-pen-ruler:before,
.fa-pencil-ruler:before {
content: '\f5ae';
}
.fa-edit:before,
.fa-pen-to-square:before {
content: '\f044';
}
.fa-pencil-alt:before,
.fa-pencil:before {
content: '\f303';
}
.fa-people-arrows-left-right:before,
.fa-people-arrows:before {
content: '\e068';
}
.fa-people-carry-box:before,
.fa-people-carry:before {
content: '\f4ce';
}
.fa-pepper-hot:before {
content: '\f816';
}
.fa-percent:before,
.fa-percentage:before {
content: '\25';
}
.fa-male:before,
.fa-person:before {
content: '\f183';
}
.fa-biking:before,
.fa-person-biking:before {
content: '\f84a';
}
.fa-person-booth:before {
content: '\f756';
}
.fa-diagnoses:before,
.fa-person-dots-from-line:before {
content: '\f470';
}
.fa-female:before,
.fa-person-dress:before {
content: '\f182';
}
.fa-hiking:before,
.fa-person-hiking:before {
content: '\f6ec';
}
.fa-person-praying:before,
.fa-pray:before {
content: '\f683';
}
.fa-person-running:before,
.fa-running:before {
content: '\f70c';
}
.fa-person-skating:before,
.fa-skating:before {
content: '\f7c5';
}
.fa-person-skiing:before,
.fa-skiing:before {
content: '\f7c9';
}
.fa-person-skiing-nordic:before,
.fa-skiing-nordic:before {
content: '\f7ca';
}
.fa-person-snowboarding:before,
.fa-snowboarding:before {
content: '\f7ce';
}
.fa-person-swimming:before,
.fa-swimmer:before {
content: '\f5c4';
}
.fa-person-walking:before,
.fa-walking:before {
content: '\f554';
}
.fa-blind:before,
.fa-person-walking-with-cane:before {
content: '\f29d';
}
.fa-peseta-sign:before {
content: '\e221';
}
.fa-peso-sign:before {
content: '\e222';
}
.fa-phone:before {
content: '\f095';
}
.fa-phone-alt:before,
.fa-phone-flip:before {
content: '\f879';
}
.fa-phone-slash:before {
content: '\f3dd';
}
.fa-phone-volume:before,
.fa-volume-control-phone:before {
content: '\f2a0';
}
.fa-photo-film:before,
.fa-photo-video:before {
content: '\f87c';
}
.fa-piggy-bank:before {
content: '\f4d3';
}
.fa-pills:before {
content: '\f484';
}
.fa-pizza-slice:before {
content: '\f818';
}
.fa-place-of-worship:before {
content: '\f67f';
}
.fa-plane:before {
content: '\f072';
}
.fa-plane-arrival:before {
content: '\f5af';
}
.fa-plane-departure:before {
content: '\f5b0';
}
.fa-plane-slash:before {
content: '\e069';
}
.fa-play:before {
content: '\f04b';
}
.fa-plug:before {
content: '\f1e6';
}
.fa-add:before,
.fa-plus:before {
content: '\2b';
}
.fa-plus-minus:before {
content: '\e43c';
}
.fa-podcast:before {
content: '\f2ce';
}
.fa-poo:before {
content: '\f2fe';
}
.fa-poo-bolt:before,
.fa-poo-storm:before {
content: '\f75a';
}
.fa-poop:before {
content: '\f619';
}
.fa-power-off:before {
content: '\f011';
}
.fa-prescription:before {
content: '\f5b1';
}
.fa-prescription-bottle:before {
content: '\f485';
}
.fa-prescription-bottle-alt:before,
.fa-prescription-bottle-medical:before {
content: '\f486';
}
.fa-print:before {
content: '\f02f';
}
.fa-pump-medical:before {
content: '\e06a';
}
.fa-pump-soap:before {
content: '\e06b';
}
.fa-puzzle-piece:before {
content: '\f12e';
}
.fa-q:before {
content: '\51';
}
.fa-qrcode:before {
content: '\f029';
}
.fa-question:before {
content: '\3f';
}
.fa-broom-ball:before,
.fa-quidditch-broom-ball:before,
.fa-quidditch:before {
content: '\f458';
}
.fa-quote-left-alt:before,
.fa-quote-left:before {
content: '\f10d';
}
.fa-quote-right-alt:before,
.fa-quote-right:before {
content: '\f10e';
}
.fa-r:before {
content: '\52';
}
.fa-radiation:before {
content: '\f7b9';
}
.fa-rainbow:before {
content: '\f75b';
}
.fa-receipt:before {
content: '\f543';
}
.fa-record-vinyl:before {
content: '\f8d9';
}
.fa-ad:before,
.fa-rectangle-ad:before {
content: '\f641';
}
.fa-list-alt:before,
.fa-rectangle-list:before {
content: '\f022';
}
.fa-rectangle-times:before,
.fa-rectangle-xmark:before,
.fa-times-rectangle:before,
.fa-window-close:before {
content: '\f410';
}
.fa-recycle:before {
content: '\f1b8';
}
.fa-registered:before {
content: '\f25d';
}
.fa-repeat:before {
content: '\f363';
}
.fa-mail-reply:before,
.fa-reply:before {
content: '\f3e5';
}
.fa-mail-reply-all:before,
.fa-reply-all:before {
content: '\f122';
}
.fa-republican:before {
content: '\f75e';
}
.fa-restroom:before {
content: '\f7bd';
}
.fa-retweet:before {
content: '\f079';
}
.fa-ribbon:before {
content: '\f4d6';
}
.fa-right-from-bracket:before,
.fa-sign-out-alt:before {
content: '\f2f5';
}
.fa-exchange-alt:before,
.fa-right-left:before {
content: '\f362';
}
.fa-long-arrow-alt-right:before,
.fa-right-long:before {
content: '\f30b';
}
.fa-right-to-bracket:before,
.fa-sign-in-alt:before {
content: '\f2f6';
}
.fa-ring:before {
content: '\f70b';
}
.fa-road:before {
content: '\f018';
}
.fa-robot:before {
content: '\f544';
}
.fa-rocket:before {
content: '\f135';
}
.fa-rotate:before,
.fa-sync-alt:before {
content: '\f2f1';
}
.fa-rotate-back:before,
.fa-rotate-backward:before,
.fa-rotate-left:before,
.fa-undo-alt:before {
content: '\f2ea';
}
.fa-route:before {
content: '\f4d7';
}
.fa-feed:before,
.fa-rss:before {
content: '\f09e';
}
.fa-rouble:before,
.fa-rub:before,
.fa-ruble-sign:before,
.fa-ruble:before {
content: '\f158';
}
.fa-ruler:before {
content: '\f545';
}
.fa-ruler-combined:before {
content: '\f546';
}
.fa-ruler-horizontal:before {
content: '\f547';
}
.fa-ruler-vertical:before {
content: '\f548';
}
.fa-rupee-sign:before,
.fa-rupee:before {
content: '\f156';
}
.fa-rupiah-sign:before {
content: '\e23d';
}
.fa-s:before {
content: '\53';
}
.fa-sailboat:before {
content: '\e445';
}
.fa-satellite:before {
content: '\f7bf';
}
.fa-satellite-dish:before {
content: '\f7c0';
}
.fa-balance-scale:before,
.fa-scale-balanced:before {
content: '\f24e';
}
.fa-balance-scale-left:before,
.fa-scale-unbalanced:before {
content: '\f515';
}
.fa-balance-scale-right:before,
.fa-scale-unbalanced-flip:before {
content: '\f516';
}
.fa-school:before {
content: '\f549';
}
.fa-cut:before,
.fa-scissors:before {
content: '\f0c4';
}
.fa-screwdriver:before {
content: '\f54a';
}
.fa-screwdriver-wrench:before,
.fa-tools:before {
content: '\f7d9';
}
.fa-scroll:before {
content: '\f70e';
}
.fa-scroll-torah:before,
.fa-torah:before {
content: '\f6a0';
}
.fa-sd-card:before {
content: '\f7c2';
}
.fa-section:before {
content: '\e447';
}
.fa-seedling:before,
.fa-sprout:before {
content: '\f4d8';
}
.fa-server:before {
content: '\f233';
}
.fa-shapes:before,
.fa-triangle-circle-square:before {
content: '\f61f';
}
.fa-arrow-turn-right:before,
.fa-mail-forward:before,
.fa-share:before {
content: '\f064';
}
.fa-share-from-square:before,
.fa-share-square:before {
content: '\f14d';
}
.fa-share-alt:before,
.fa-share-nodes:before {
content: '\f1e0';
}
.fa-ils:before,
.fa-shekel-sign:before,
.fa-shekel:before,
.fa-sheqel-sign:before,
.fa-sheqel:before {
content: '\f20b';
}
.fa-shield-alt:before,
.fa-shield-blank:before {
content: '\f3ed';
}
.fa-shield-virus:before {
content: '\e06c';
}
.fa-ship:before {
content: '\f21a';
}
.fa-shirt:before,
.fa-t-shirt:before,
.fa-tshirt:before {
content: '\f553';
}
.fa-shoe-prints:before {
content: '\f54b';
}
.fa-shop:before,
.fa-store-alt:before {
content: '\f54f';
}
.fa-shop-slash:before,
.fa-store-alt-slash:before {
content: '\e070';
}
.fa-shower:before {
content: '\f2cc';
}
.fa-random:before,
.fa-shuffle:before {
content: '\f074';
}
.fa-shuttle-space:before,
.fa-space-shuttle:before {
content: '\f197';
}
.fa-sign-hanging:before,
.fa-sign:before {
content: '\f4d9';
}
.fa-signal-5:before,
.fa-signal-perfect:before,
.fa-signal:before {
content: '\f012';
}
.fa-signature:before {
content: '\f5b7';
}
.fa-map-signs:before,
.fa-signs-post:before {
content: '\f277';
}
.fa-sim-card:before {
content: '\f7c4';
}
.fa-sink:before {
content: '\e06d';
}
.fa-sitemap:before {
content: '\f0e8';
}
.fa-skull:before {
content: '\f54c';
}
.fa-skull-crossbones:before {
content: '\f714';
}
.fa-slash:before {
content: '\f715';
}
.fa-sleigh:before {
content: '\f7cc';
}
.fa-sliders-h:before,
.fa-sliders:before {
content: '\f1de';
}
.fa-smog:before {
content: '\f75f';
}
.fa-smoking:before {
content: '\f48d';
}
.fa-snowflake:before {
content: '\f2dc';
}
.fa-snowman:before {
content: '\f7d0';
}
.fa-snowplow:before {
content: '\f7d2';
}
.fa-soap:before {
content: '\e06e';
}
.fa-socks:before {
content: '\f696';
}
.fa-solar-panel:before {
content: '\f5ba';
}
.fa-sort:before,
.fa-unsorted:before {
content: '\f0dc';
}
.fa-sort-desc:before,
.fa-sort-down:before {
content: '\f0dd';
}
.fa-sort-asc:before,
.fa-sort-up:before {
content: '\f0de';
}
.fa-spa:before {
content: '\f5bb';
}
.fa-pastafarianism:before,
.fa-spaghetti-monster-flying:before {
content: '\f67b';
}
.fa-spell-check:before {
content: '\f891';
}
.fa-spider:before {
content: '\f717';
}
.fa-spinner:before {
content: '\f110';
}
.fa-splotch:before {
content: '\f5bc';
}
.fa-spoon:before,
.fa-utensil-spoon:before {
content: '\f2e5';
}
.fa-spray-can:before {
content: '\f5bd';
}
.fa-air-freshener:before,
.fa-spray-can-sparkles:before {
content: '\f5d0';
}
.fa-square:before {
content: '\f0c8';
}
.fa-caret-square-down:before,
.fa-square-caret-down:before {
content: '\f150';
}
.fa-caret-square-left:before,
.fa-square-caret-left:before {
content: '\f191';
}
.fa-caret-square-right:before,
.fa-square-caret-right:before {
content: '\f152';
}
.fa-caret-square-up:before,
.fa-square-caret-up:before {
content: '\f151';
}
.fa-check-square:before,
.fa-square-check:before {
content: '\f14a';
}
.fa-envelope-square:before,
.fa-square-envelope:before {
content: '\f199';
}
.fa-square-full:before {
content: '\f45c';
}
.fa-h-square:before,
.fa-square-h:before {
content: '\f0fd';
}
.fa-minus-square:before,
.fa-square-minus:before {
content: '\f146';
}
.fa-parking:before,
.fa-square-parking:before {
content: '\f540';
}
.fa-pen-square:before,
.fa-pencil-square:before,
.fa-square-pen:before {
content: '\f14b';
}
.fa-phone-square:before,
.fa-square-phone:before {
content: '\f098';
}
.fa-phone-square-alt:before,
.fa-square-phone-flip:before {
content: '\f87b';
}
.fa-plus-square:before,
.fa-square-plus:before {
content: '\f0fe';
}
.fa-poll-h:before,
.fa-square-poll-horizontal:before {
content: '\f682';
}
.fa-poll:before,
.fa-square-poll-vertical:before {
content: '\f681';
}
.fa-square-root-alt:before,
.fa-square-root-variable:before {
content: '\f698';
}
.fa-rss-square:before,
.fa-square-rss:before {
content: '\f143';
}
.fa-share-alt-square:before,
.fa-square-share-nodes:before {
content: '\f1e1';
}
.fa-external-link-square-alt:before,
.fa-square-up-right:before {
content: '\f360';
}
.fa-stairs:before {
content: '\e289';
}
.fa-stamp:before {
content: '\f5bf';
}
.fa-star:before {
content: '\f005';
}
.fa-star-and-crescent:before {
content: '\f699';
}
.fa-star-half:before {
content: '\f089';
}
.fa-star-half-alt:before,
.fa-star-half-stroke:before {
content: '\f5c0';
}
.fa-star-of-david:before {
content: '\f69a';
}
.fa-star-of-life:before {
content: '\f621';
}
.fa-gbp:before,
.fa-pound-sign:before,
.fa-sterling-sign:before {
content: '\f154';
}
.fa-stethoscope:before {
content: '\f0f1';
}
.fa-stop:before {
content: '\f04d';
}
.fa-stopwatch:before {
content: '\f2f2';
}
.fa-stopwatch-20:before {
content: '\e06f';
}
.fa-store:before {
content: '\f54e';
}
.fa-store-slash:before {
content: '\e071';
}
.fa-street-view:before {
content: '\f21d';
}
.fa-strikethrough:before {
content: '\f0cc';
}
.fa-stroopwafel:before {
content: '\f551';
}
.fa-subscript:before {
content: '\f12c';
}
.fa-suitcase:before {
content: '\f0f2';
}
.fa-medkit:before,
.fa-suitcase-medical:before {
content: '\f0fa';
}
.fa-suitcase-rolling:before {
content: '\f5c1';
}
.fa-sun:before {
content: '\f185';
}
.fa-superscript:before {
content: '\f12b';
}
.fa-swatchbook:before {
content: '\f5c3';
}
.fa-synagogue:before {
content: '\f69b';
}
.fa-syringe:before {
content: '\f48e';
}
.fa-t:before {
content: '\54';
}
.fa-table:before {
content: '\f0ce';
}
.fa-table-cells:before,
.fa-th:before {
content: '\f00a';
}
.fa-table-cells-large:before,
.fa-th-large:before {
content: '\f009';
}
.fa-columns:before,
.fa-table-columns:before {
content: '\f0db';
}
.fa-table-list:before,
.fa-th-list:before {
content: '\f00b';
}
.fa-ping-pong-paddle-ball:before,
.fa-table-tennis-paddle-ball:before,
.fa-table-tennis:before {
content: '\f45d';
}
.fa-tablet-button:before {
content: '\f10a';
}
.fa-tablet-alt:before,
.fa-tablet-screen-button:before {
content: '\f3fa';
}
.fa-tablets:before {
content: '\f490';
}
.fa-digital-tachograph:before,
.fa-tachograph-digital:before {
content: '\f566';
}
.fa-tag:before {
content: '\f02b';
}
.fa-tags:before {
content: '\f02c';
}
.fa-tape:before {
content: '\f4db';
}
.fa-cab:before,
.fa-taxi:before {
content: '\f1ba';
}
.fa-teeth:before {
content: '\f62e';
}
.fa-teeth-open:before {
content: '\f62f';
}
.fa-temperature-0:before,
.fa-temperature-empty:before,
.fa-thermometer-0:before,
.fa-thermometer-empty:before {
content: '\f2cb';
}
.fa-temperature-4:before,
.fa-temperature-full:before,
.fa-thermometer-4:before,
.fa-thermometer-full:before {
content: '\f2c7';
}
.fa-temperature-2:before,
.fa-temperature-half:before,
.fa-thermometer-2:before,
.fa-thermometer-half:before {
content: '\f2c9';
}
.fa-temperature-high:before {
content: '\f769';
}
.fa-temperature-low:before {
content: '\f76b';
}
.fa-temperature-1:before,
.fa-temperature-quarter:before,
.fa-thermometer-1:before,
.fa-thermometer-quarter:before {
content: '\f2ca';
}
.fa-temperature-3:before,
.fa-temperature-three-quarters:before,
.fa-thermometer-3:before,
.fa-thermometer-three-quarters:before {
content: '\f2c8';
}
.fa-tenge-sign:before,
.fa-tenge:before {
content: '\f7d7';
}
.fa-terminal:before {
content: '\f120';
}
.fa-text-height:before {
content: '\f034';
}
.fa-remove-format:before,
.fa-text-slash:before {
content: '\f87d';
}
.fa-text-width:before {
content: '\f035';
}
.fa-thermometer:before {
content: '\f491';
}
.fa-thumbs-down:before {
content: '\f165';
}
.fa-thumbs-up:before {
content: '\f164';
}
.fa-thumb-tack:before,
.fa-thumbtack:before {
content: '\f08d';
}
.fa-ticket-alt:before,
.fa-ticket-simple:before {
content: '\f3ff';
}
.fa-timeline:before {
content: '\e29c';
}
.fa-toggle-off:before {
content: '\f204';
}
.fa-toggle-on:before {
content: '\f205';
}
.fa-toilet:before {
content: '\f7d8';
}
.fa-toilet-paper:before {
content: '\f71e';
}
.fa-toilet-paper-slash:before {
content: '\e072';
}
.fa-toolbox:before {
content: '\f552';
}
.fa-tooth:before {
content: '\f5c9';
}
.fa-torii-gate:before {
content: '\f6a1';
}
.fa-broadcast-tower:before,
.fa-tower-broadcast:before {
content: '\f519';
}
.fa-tractor:before {
content: '\f722';
}
.fa-trademark:before {
content: '\f25c';
}
.fa-traffic-light:before {
content: '\f637';
}
.fa-trailer:before {
content: '\e041';
}
.fa-train:before {
content: '\f238';
}
.fa-subway:before,
.fa-train-subway:before {
content: '\f239';
}
.fa-train-tram:before,
.fa-tram:before {
content: '\f7da';
}
.fa-transgender-alt:before,
.fa-transgender:before {
content: '\f225';
}
.fa-trash:before {
content: '\f1f8';
}
.fa-trash-arrow-up:before,
.fa-trash-restore:before {
content: '\f829';
}
.fa-trash-alt:before,
.fa-trash-can:before {
content: '\f2ed';
}
.fa-trash-can-arrow-up:before,
.fa-trash-restore-alt:before {
content: '\f82a';
}
.fa-tree:before {
content: '\f1bb';
}
.fa-exclamation-triangle:before,
.fa-triangle-exclamation:before,
.fa-warning:before {
content: '\f071';
}
.fa-trophy:before {
content: '\f091';
}
.fa-truck:before {
content: '\f0d1';
}
.fa-shipping-fast:before,
.fa-truck-fast:before {
content: '\f48b';
}
.fa-ambulance:before,
.fa-truck-medical:before {
content: '\f0f9';
}
.fa-truck-monster:before {
content: '\f63b';
}
.fa-truck-moving:before {
content: '\f4df';
}
.fa-truck-pickup:before {
content: '\f63c';
}
.fa-truck-loading:before,
.fa-truck-ramp-box:before {
content: '\f4de';
}
.fa-teletype:before,
.fa-tty:before {
content: '\f1e4';
}
.fa-try:before,
.fa-turkish-lira-sign:before,
.fa-turkish-lira:before {
content: '\e2bb';
}
.fa-level-down-alt:before,
.fa-turn-down:before {
content: '\f3be';
}
.fa-level-up-alt:before,
.fa-turn-up:before {
content: '\f3bf';
}
.fa-television:before,
.fa-tv-alt:before,
.fa-tv:before {
content: '\f26c';
}
.fa-u:before {
content: '\55';
}
.fa-umbrella:before {
content: '\f0e9';
}
.fa-umbrella-beach:before {
content: '\f5ca';
}
.fa-underline:before {
content: '\f0cd';
}
.fa-universal-access:before {
content: '\f29a';
}
.fa-unlock:before {
content: '\f09c';
}
.fa-unlock-alt:before,
.fa-unlock-keyhole:before {
content: '\f13e';
}
.fa-arrows-alt-v:before,
.fa-up-down:before {
content: '\f338';
}
.fa-arrows-alt:before,
.fa-up-down-left-right:before {
content: '\f0b2';
}
.fa-long-arrow-alt-up:before,
.fa-up-long:before {
content: '\f30c';
}
.fa-expand-alt:before,
.fa-up-right-and-down-left-from-center:before {
content: '\f424';
}
.fa-external-link-alt:before,
.fa-up-right-from-square:before {
content: '\f35d';
}
.fa-upload:before {
content: '\f093';
}
.fa-user:before {
content: '\f007';
}
.fa-user-astronaut:before {
content: '\f4fb';
}
.fa-user-check:before {
content: '\f4fc';
}
.fa-user-clock:before {
content: '\f4fd';
}
.fa-user-doctor:before,
.fa-user-md:before {
content: '\f0f0';
}
.fa-user-cog:before,
.fa-user-gear:before {
content: '\f4fe';
}
.fa-user-graduate:before {
content: '\f501';
}
.fa-user-friends:before,
.fa-user-group:before {
content: '\f500';
}
.fa-user-injured:before {
content: '\f728';
}
.fa-user-alt:before,
.fa-user-large:before {
content: '\f406';
}
.fa-user-alt-slash:before,
.fa-user-large-slash:before {
content: '\f4fa';
}
.fa-user-lock:before {
content: '\f502';
}
.fa-user-minus:before {
content: '\f503';
}
.fa-user-ninja:before {
content: '\f504';
}
.fa-user-nurse:before {
content: '\f82f';
}
.fa-user-edit:before,
.fa-user-pen:before {
content: '\f4ff';
}
.fa-user-plus:before {
content: '\f234';
}
.fa-user-secret:before {
content: '\f21b';
}
.fa-user-shield:before {
content: '\f505';
}
.fa-user-slash:before {
content: '\f506';
}
.fa-user-tag:before {
content: '\f507';
}
.fa-user-tie:before {
content: '\f508';
}
.fa-user-times:before,
.fa-user-xmark:before {
content: '\f235';
}
.fa-group:before,
.fa-users:before {
content: '\f0c0';
}
.fa-users-cog:before,
.fa-users-gear:before {
content: '\f509';
}
.fa-users-slash:before {
content: '\e073';
}
.fa-cutlery:before,
.fa-utensils:before {
content: '\f2e7';
}
.fa-v:before {
content: '\56';
}
.fa-shuttle-van:before,
.fa-van-shuttle:before {
content: '\f5b6';
}
.fa-vault:before {
content: '\e2c5';
}
.fa-vector-square:before {
content: '\f5cb';
}
.fa-venus:before {
content: '\f221';
}
.fa-venus-double:before {
content: '\f226';
}
.fa-venus-mars:before {
content: '\f228';
}
.fa-vest:before {
content: '\e085';
}
.fa-vest-patches:before {
content: '\e086';
}
.fa-vial:before {
content: '\f492';
}
.fa-vials:before {
content: '\f493';
}
.fa-video-camera:before,
.fa-video:before {
content: '\f03d';
}
.fa-video-slash:before {
content: '\f4e2';
}
.fa-vihara:before {
content: '\f6a7';
}
.fa-virus:before {
content: '\e074';
}
.fa-virus-slash:before {
content: '\e075';
}
.fa-viruses:before {
content: '\e076';
}
.fa-voicemail:before {
content: '\f897';
}
.fa-volleyball-ball:before,
.fa-volleyball:before {
content: '\f45f';
}
.fa-volume-high:before,
.fa-volume-up:before {
content: '\f028';
}
.fa-volume-down:before,
.fa-volume-low:before {
content: '\f027';
}
.fa-volume-off:before {
content: '\f026';
}
.fa-volume-mute:before,
.fa-volume-times:before,
.fa-volume-xmark:before {
content: '\f6a9';
}
.fa-vr-cardboard:before {
content: '\f729';
}
.fa-w:before {
content: '\57';
}
.fa-wallet:before {
content: '\f555';
}
.fa-magic:before,
.fa-wand-magic:before {
content: '\f0d0';
}
.fa-warehouse:before {
content: '\f494';
}
.fa-water:before {
content: '\f773';
}
.fa-ladder-water:before,
.fa-swimming-pool:before,
.fa-water-ladder:before {
content: '\f5c5';
}
.fa-wave-square:before {
content: '\f83e';
}
.fa-weight-hanging:before {
content: '\f5cd';
}
.fa-weight-scale:before,
.fa-weight:before {
content: '\f496';
}
.fa-wheelchair:before {
content: '\f193';
}
.fa-glass-whiskey:before,
.fa-whiskey-glass:before {
content: '\f7a0';
}
.fa-wifi-3:before,
.fa-wifi-strong:before,
.fa-wifi:before {
content: '\f1eb';
}
.fa-wind:before {
content: '\f72e';
}
.fa-window-maximize:before {
content: '\f2d0';
}
.fa-window-minimize:before {
content: '\f2d1';
}
.fa-window-restore:before {
content: '\f2d2';
}
.fa-wine-bottle:before {
content: '\f72f';
}
.fa-wine-glass:before {
content: '\f4e3';
}
.fa-wine-glass-alt:before,
.fa-wine-glass-empty:before {
content: '\f5ce';
}
.fa-krw:before,
.fa-won-sign:before,
.fa-won:before {
content: '\f159';
}
.fa-wrench:before {
content: '\f0ad';
}
.fa-x:before {
content: '\58';
}
.fa-x-ray:before {
content: '\f497';
}
.fa-close:before,
.fa-multiply:before,
.fa-remove:before,
.fa-times:before,
.fa-xmark:before {
content: '\f00d';
}
.fa-y:before {
content: '\59';
}
.fa-cny:before,
.fa-jpy:before,
.fa-rmb:before,
.fa-yen-sign:before,
.fa-yen:before {
content: '\f157';
}
.fa-yin-yang:before {
content: '\f6ad';
}
.fa-z:before {
content: '\5a';
}
.fa-sr-only,
.fa-sr-only-focusable:not(:focus),
.sr-only,
.sr-only-focusable:not(:focus) {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
@font-face {
font-family: 'Font Awesome 6 Brands';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(/webfonts/fa-brands-400.woff2) format('woff2'),
url(/webfonts/fa-brands-400.ttf) format('truetype');
}
.fa-brands,
.fab {
font-family: 'Font Awesome 6 Brands';
font-weight: 400;
}
.fa-42-group:before,
.fa-innosoft:before {
content: '\e080';
}
.fa-500px:before {
content: '\f26e';
}
.fa-accessible-icon:before {
content: '\f368';
}
.fa-accusoft:before {
content: '\f369';
}
.fa-acquisitions-incorporated:before {
content: '\f6af';
}
.fa-adn:before {
content: '\f170';
}
.fa-adversal:before {
content: '\f36a';
}
.fa-affiliatetheme:before {
content: '\f36b';
}
.fa-airbnb:before {
content: '\f834';
}
.fa-algolia:before {
content: '\f36c';
}
.fa-alipay:before {
content: '\f642';
}
.fa-amazon:before {
content: '\f270';
}
.fa-amazon-pay:before {
content: '\f42c';
}
.fa-amilia:before {
content: '\f36d';
}
.fa-android:before {
content: '\f17b';
}
.fa-angellist:before {
content: '\f209';
}
.fa-angrycreative:before {
content: '\f36e';
}
.fa-angular:before {
content: '\f420';
}
.fa-app-store:before {
content: '\f36f';
}
.fa-app-store-ios:before {
content: '\f370';
}
.fa-apper:before {
content: '\f371';
}
.fa-apple:before {
content: '\f179';
}
.fa-apple-pay:before {
content: '\f415';
}
.fa-artstation:before {
content: '\f77a';
}
.fa-asymmetrik:before {
content: '\f372';
}
.fa-atlassian:before {
content: '\f77b';
}
.fa-audible:before {
content: '\f373';
}
.fa-autoprefixer:before {
content: '\f41c';
}
.fa-avianex:before {
content: '\f374';
}
.fa-aviato:before {
content: '\f421';
}
.fa-aws:before {
content: '\f375';
}
.fa-bandcamp:before {
content: '\f2d5';
}
.fa-battle-net:before {
content: '\f835';
}
.fa-behance:before {
content: '\f1b4';
}
.fa-behance-square:before {
content: '\f1b5';
}
.fa-bilibili:before {
content: '\e3d9';
}
.fa-bimobject:before {
content: '\f378';
}
.fa-bitbucket:before {
content: '\f171';
}
.fa-bitcoin:before {
content: '\f379';
}
.fa-bity:before {
content: '\f37a';
}
.fa-black-tie:before {
content: '\f27e';
}
.fa-blackberry:before {
content: '\f37b';
}
.fa-blogger:before {
content: '\f37c';
}
.fa-blogger-b:before {
content: '\f37d';
}
.fa-bluetooth:before {
content: '\f293';
}
.fa-bluetooth-b:before {
content: '\f294';
}
.fa-bootstrap:before {
content: '\f836';
}
.fa-bots:before {
content: '\e340';
}
.fa-btc:before {
content: '\f15a';
}
.fa-buffer:before {
content: '\f837';
}
.fa-buromobelexperte:before {
content: '\f37f';
}
.fa-buy-n-large:before {
content: '\f8a6';
}
.fa-buysellads:before {
content: '\f20d';
}
.fa-canadian-maple-leaf:before {
content: '\f785';
}
.fa-cc-amazon-pay:before {
content: '\f42d';
}
.fa-cc-amex:before {
content: '\f1f3';
}
.fa-cc-apple-pay:before {
content: '\f416';
}
.fa-cc-diners-club:before {
content: '\f24c';
}
.fa-cc-discover:before {
content: '\f1f2';
}
.fa-cc-jcb:before {
content: '\f24b';
}
.fa-cc-mastercard:before {
content: '\f1f1';
}
.fa-cc-paypal:before {
content: '\f1f4';
}
.fa-cc-stripe:before {
content: '\f1f5';
}
.fa-cc-visa:before {
content: '\f1f0';
}
.fa-centercode:before {
content: '\f380';
}
.fa-centos:before {
content: '\f789';
}
.fa-chrome:before {
content: '\f268';
}
.fa-chromecast:before {
content: '\f838';
}
.fa-cloudflare:before {
content: '\e07d';
}
.fa-cloudscale:before {
content: '\f383';
}
.fa-cloudsmith:before {
content: '\f384';
}
.fa-cloudversify:before {
content: '\f385';
}
.fa-cmplid:before {
content: '\e360';
}
.fa-codepen:before {
content: '\f1cb';
}
.fa-codiepie:before {
content: '\f284';
}
.fa-confluence:before {
content: '\f78d';
}
.fa-connectdevelop:before {
content: '\f20e';
}
.fa-contao:before {
content: '\f26d';
}
.fa-cotton-bureau:before {
content: '\f89e';
}
.fa-cpanel:before {
content: '\f388';
}
.fa-creative-commons:before {
content: '\f25e';
}
.fa-creative-commons-by:before {
content: '\f4e7';
}
.fa-creative-commons-nc:before {
content: '\f4e8';
}
.fa-creative-commons-nc-eu:before {
content: '\f4e9';
}
.fa-creative-commons-nc-jp:before {
content: '\f4ea';
}
.fa-creative-commons-nd:before {
content: '\f4eb';
}
.fa-creative-commons-pd:before {
content: '\f4ec';
}
.fa-creative-commons-pd-alt:before {
content: '\f4ed';
}
.fa-creative-commons-remix:before {
content: '\f4ee';
}
.fa-creative-commons-sa:before {
content: '\f4ef';
}
.fa-creative-commons-sampling:before {
content: '\f4f0';
}
.fa-creative-commons-sampling-plus:before {
content: '\f4f1';
}
.fa-creative-commons-share:before {
content: '\f4f2';
}
.fa-creative-commons-zero:before {
content: '\f4f3';
}
.fa-critical-role:before {
content: '\f6c9';
}
.fa-css3:before {
content: '\f13c';
}
.fa-css3-alt:before {
content: '\f38b';
}
.fa-cuttlefish:before {
content: '\f38c';
}
.fa-d-and-d:before {
content: '\f38d';
}
.fa-d-and-d-beyond:before {
content: '\f6ca';
}
.fa-dailymotion:before {
content: '\e052';
}
.fa-dashcube:before {
content: '\f210';
}
.fa-deezer:before {
content: '\e077';
}
.fa-delicious:before {
content: '\f1a5';
}
.fa-deploydog:before {
content: '\f38e';
}
.fa-deskpro:before {
content: '\f38f';
}
.fa-dev:before {
content: '\f6cc';
}
.fa-deviantart:before {
content: '\f1bd';
}
.fa-dhl:before {
content: '\f790';
}
.fa-diaspora:before {
content: '\f791';
}
.fa-digg:before {
content: '\f1a6';
}
.fa-digital-ocean:before {
content: '\f391';
}
.fa-discord:before {
content: '\f392';
}
.fa-discourse:before {
content: '\f393';
}
.fa-dochub:before {
content: '\f394';
}
.fa-docker:before {
content: '\f395';
}
.fa-draft2digital:before {
content: '\f396';
}
.fa-dribbble:before {
content: '\f17d';
}
.fa-dribbble-square:before {
content: '\f397';
}
.fa-dropbox:before {
content: '\f16b';
}
.fa-drupal:before {
content: '\f1a9';
}
.fa-dyalog:before {
content: '\f399';
}
.fa-earlybirds:before {
content: '\f39a';
}
.fa-ebay:before {
content: '\f4f4';
}
.fa-edge:before {
content: '\f282';
}
.fa-edge-legacy:before {
content: '\e078';
}
.fa-elementor:before {
content: '\f430';
}
.fa-ello:before {
content: '\f5f1';
}
.fa-ember:before {
content: '\f423';
}
.fa-empire:before {
content: '\f1d1';
}
.fa-envira:before {
content: '\f299';
}
.fa-erlang:before {
content: '\f39d';
}
.fa-ethereum:before {
content: '\f42e';
}
.fa-etsy:before {
content: '\f2d7';
}
.fa-evernote:before {
content: '\f839';
}
.fa-expeditedssl:before {
content: '\f23e';
}
.fa-facebook:before {
content: '\f09a';
}
.fa-facebook-f:before {
content: '\f39e';
}
.fa-facebook-messenger:before {
content: '\f39f';
}
.fa-facebook-square:before {
content: '\f082';
}
.fa-fantasy-flight-games:before {
content: '\f6dc';
}
.fa-fedex:before {
content: '\f797';
}
.fa-fedora:before {
content: '\f798';
}
.fa-figma:before {
content: '\f799';
}
.fa-firefox:before {
content: '\f269';
}
.fa-firefox-browser:before {
content: '\e007';
}
.fa-first-order:before {
content: '\f2b0';
}
.fa-first-order-alt:before {
content: '\f50a';
}
.fa-firstdraft:before {
content: '\f3a1';
}
.fa-flickr:before {
content: '\f16e';
}
.fa-flipboard:before {
content: '\f44d';
}
.fa-fly:before {
content: '\f417';
}
.fa-font-awesome-flag:before,
.fa-font-awesome-logo-full:before,
.fa-font-awesome:before {
content: '\f2b4';
}
.fa-fonticons:before {
content: '\f280';
}
.fa-fonticons-fi:before {
content: '\f3a2';
}
.fa-fort-awesome:before {
content: '\f286';
}
.fa-fort-awesome-alt:before {
content: '\f3a3';
}
.fa-forumbee:before {
content: '\f211';
}
.fa-foursquare:before {
content: '\f180';
}
.fa-free-code-camp:before {
content: '\f2c5';
}
.fa-freebsd:before {
content: '\f3a4';
}
.fa-fulcrum:before {
content: '\f50b';
}
.fa-galactic-republic:before {
content: '\f50c';
}
.fa-galactic-senate:before {
content: '\f50d';
}
.fa-get-pocket:before {
content: '\f265';
}
.fa-gg:before {
content: '\f260';
}
.fa-gg-circle:before {
content: '\f261';
}
.fa-git:before {
content: '\f1d3';
}
.fa-git-alt:before {
content: '\f841';
}
.fa-git-square:before {
content: '\f1d2';
}
.fa-github:before {
content: '\f09b';
}
.fa-github-alt:before {
content: '\f113';
}
.fa-github-square:before {
content: '\f092';
}
.fa-gitkraken:before {
content: '\f3a6';
}
.fa-gitlab:before {
content: '\f296';
}
.fa-gitter:before {
content: '\f426';
}
.fa-glide:before {
content: '\f2a5';
}
.fa-glide-g:before {
content: '\f2a6';
}
.fa-gofore:before {
content: '\f3a7';
}
.fa-golang:before {
content: '\e40f';
}
.fa-goodreads:before {
content: '\f3a8';
}
.fa-goodreads-g:before {
content: '\f3a9';
}
.fa-google:before {
content: '\f1a0';
}
.fa-google-drive:before {
content: '\f3aa';
}
.fa-google-pay:before {
content: '\e079';
}
.fa-google-play:before {
content: '\f3ab';
}
.fa-google-plus:before {
content: '\f2b3';
}
.fa-google-plus-g:before {
content: '\f0d5';
}
.fa-google-plus-square:before {
content: '\f0d4';
}
.fa-google-wallet:before {
content: '\f1ee';
}
.fa-gratipay:before {
content: '\f184';
}
.fa-grav:before {
content: '\f2d6';
}
.fa-gripfire:before {
content: '\f3ac';
}
.fa-grunt:before {
content: '\f3ad';
}
.fa-guilded:before {
content: '\e07e';
}
.fa-gulp:before {
content: '\f3ae';
}
.fa-hacker-news:before {
content: '\f1d4';
}
.fa-hacker-news-square:before {
content: '\f3af';
}
.fa-hackerrank:before {
content: '\f5f7';
}
.fa-hips:before {
content: '\f452';
}
.fa-hire-a-helper:before {
content: '\f3b0';
}
.fa-hive:before {
content: '\e07f';
}
.fa-hooli:before {
content: '\f427';
}
.fa-hornbill:before {
content: '\f592';
}
.fa-hotjar:before {
content: '\f3b1';
}
.fa-houzz:before {
content: '\f27c';
}
.fa-html5:before {
content: '\f13b';
}
.fa-hubspot:before {
content: '\f3b2';
}
.fa-ideal:before {
content: '\e013';
}
.fa-imdb:before {
content: '\f2d8';
}
.fa-instagram:before {
content: '\f16d';
}
.fa-instagram-square:before {
content: '\e055';
}
.fa-instalod:before {
content: '\e081';
}
.fa-intercom:before {
content: '\f7af';
}
.fa-internet-explorer:before {
content: '\f26b';
}
.fa-invision:before {
content: '\f7b0';
}
.fa-ioxhost:before {
content: '\f208';
}
.fa-itch-io:before {
content: '\f83a';
}
.fa-itunes:before {
content: '\f3b4';
}
.fa-itunes-note:before {
content: '\f3b5';
}
.fa-java:before {
content: '\f4e4';
}
.fa-jedi-order:before {
content: '\f50e';
}
.fa-jenkins:before {
content: '\f3b6';
}
.fa-jira:before {
content: '\f7b1';
}
.fa-joget:before {
content: '\f3b7';
}
.fa-joomla:before {
content: '\f1aa';
}
.fa-js:before {
content: '\f3b8';
}
.fa-js-square:before {
content: '\f3b9';
}
.fa-jsfiddle:before {
content: '\f1cc';
}
.fa-kaggle:before {
content: '\f5fa';
}
.fa-keybase:before {
content: '\f4f5';
}
.fa-keycdn:before {
content: '\f3ba';
}
.fa-kickstarter:before {
content: '\f3bb';
}
.fa-kickstarter-k:before {
content: '\f3bc';
}
.fa-korvue:before {
content: '\f42f';
}
.fa-laravel:before {
content: '\f3bd';
}
.fa-lastfm:before {
content: '\f202';
}
.fa-lastfm-square:before {
content: '\f203';
}
.fa-leanpub:before {
content: '\f212';
}
.fa-less:before {
content: '\f41d';
}
.fa-line:before {
content: '\f3c0';
}
.fa-linkedin:before {
content: '\f08c';
}
.fa-linkedin-in:before {
content: '\f0e1';
}
.fa-linode:before {
content: '\f2b8';
}
.fa-linux:before {
content: '\f17c';
}
.fa-lyft:before {
content: '\f3c3';
}
.fa-magento:before {
content: '\f3c4';
}
.fa-mailchimp:before {
content: '\f59e';
}
.fa-mandalorian:before {
content: '\f50f';
}
.fa-markdown:before {
content: '\f60f';
}
.fa-mastodon:before {
content: '\f4f6';
}
.fa-maxcdn:before {
content: '\f136';
}
.fa-mdb:before {
content: '\f8ca';
}
.fa-medapps:before {
content: '\f3c6';
}
.fa-medium-m:before,
.fa-medium:before {
content: '\f23a';
}
.fa-medrt:before {
content: '\f3c8';
}
.fa-meetup:before {
content: '\f2e0';
}
.fa-megaport:before {
content: '\f5a3';
}
.fa-mendeley:before {
content: '\f7b3';
}
.fa-microblog:before {
content: '\e01a';
}
.fa-microsoft:before {
content: '\f3ca';
}
.fa-mix:before {
content: '\f3cb';
}
.fa-mixcloud:before {
content: '\f289';
}
.fa-mixer:before {
content: '\e056';
}
.fa-mizuni:before {
content: '\f3cc';
}
.fa-modx:before {
content: '\f285';
}
.fa-monero:before {
content: '\f3d0';
}
.fa-napster:before {
content: '\f3d2';
}
.fa-neos:before {
content: '\f612';
}
.fa-nimblr:before {
content: '\f5a8';
}
.fa-node:before {
content: '\f419';
}
.fa-node-js:before {
content: '\f3d3';
}
.fa-npm:before {
content: '\f3d4';
}
.fa-ns8:before {
content: '\f3d5';
}
.fa-nutritionix:before {
content: '\f3d6';
}
.fa-octopus-deploy:before {
content: '\e082';
}
.fa-odnoklassniki:before {
content: '\f263';
}
.fa-odnoklassniki-square:before {
content: '\f264';
}
.fa-old-republic:before {
content: '\f510';
}
.fa-opencart:before {
content: '\f23d';
}
.fa-openid:before {
content: '\f19b';
}
.fa-opera:before {
content: '\f26a';
}
.fa-optin-monster:before {
content: '\f23c';
}
.fa-orcid:before {
content: '\f8d2';
}
.fa-osi:before {
content: '\f41a';
}
.fa-page4:before {
content: '\f3d7';
}
.fa-pagelines:before {
content: '\f18c';
}
.fa-palfed:before {
content: '\f3d8';
}
.fa-patreon:before {
content: '\f3d9';
}
.fa-paypal:before {
content: '\f1ed';
}
.fa-penny-arcade:before {
content: '\f704';
}
.fa-perbyte:before {
content: '\e083';
}
.fa-periscope:before {
content: '\f3da';
}
.fa-phabricator:before {
content: '\f3db';
}
.fa-phoenix-framework:before {
content: '\f3dc';
}
.fa-phoenix-squadron:before {
content: '\f511';
}
.fa-php:before {
content: '\f457';
}
.fa-pied-piper:before {
content: '\f2ae';
}
.fa-pied-piper-alt:before {
content: '\f1a8';
}
.fa-pied-piper-hat:before {
content: '\f4e5';
}
.fa-pied-piper-pp:before {
content: '\f1a7';
}
.fa-pied-piper-square:before {
content: '\e01e';
}
.fa-pinterest:before {
content: '\f0d2';
}
.fa-pinterest-p:before {
content: '\f231';
}
.fa-pinterest-square:before {
content: '\f0d3';
}
.fa-pix:before {
content: '\e43a';
}
.fa-playstation:before {
content: '\f3df';
}
.fa-product-hunt:before {
content: '\f288';
}
.fa-pushed:before {
content: '\f3e1';
}
.fa-python:before {
content: '\f3e2';
}
.fa-qq:before {
content: '\f1d6';
}
.fa-quinscape:before {
content: '\f459';
}
.fa-quora:before {
content: '\f2c4';
}
.fa-r-project:before {
content: '\f4f7';
}
.fa-raspberry-pi:before {
content: '\f7bb';
}
.fa-ravelry:before {
content: '\f2d9';
}
.fa-react:before {
content: '\f41b';
}
.fa-reacteurope:before {
content: '\f75d';
}
.fa-readme:before {
content: '\f4d5';
}
.fa-rebel:before {
content: '\f1d0';
}
.fa-red-river:before {
content: '\f3e3';
}
.fa-reddit:before {
content: '\f1a1';
}
.fa-reddit-alien:before {
content: '\f281';
}
.fa-reddit-square:before {
content: '\f1a2';
}
.fa-redhat:before {
content: '\f7bc';
}
.fa-renren:before {
content: '\f18b';
}
.fa-replyd:before {
content: '\f3e6';
}
.fa-researchgate:before {
content: '\f4f8';
}
.fa-resolving:before {
content: '\f3e7';
}
.fa-rev:before {
content: '\f5b2';
}
.fa-rocketchat:before {
content: '\f3e8';
}
.fa-rockrms:before {
content: '\f3e9';
}
.fa-rust:before {
content: '\e07a';
}
.fa-safari:before {
content: '\f267';
}
.fa-salesforce:before {
content: '\f83b';
}
.fa-sass:before {
content: '\f41e';
}
.fa-schlix:before {
content: '\f3ea';
}
.fa-scribd:before {
content: '\f28a';
}
.fa-searchengin:before {
content: '\f3eb';
}
.fa-sellcast:before {
content: '\f2da';
}
.fa-sellsy:before {
content: '\f213';
}
.fa-servicestack:before {
content: '\f3ec';
}
.fa-shirtsinbulk:before {
content: '\f214';
}
.fa-shopify:before {
content: '\e057';
}
.fa-shopware:before {
content: '\f5b5';
}
.fa-simplybuilt:before {
content: '\f215';
}
.fa-sistrix:before {
content: '\f3ee';
}
.fa-sith:before {
content: '\f512';
}
.fa-sitrox:before {
content: '\e44a';
}
.fa-sketch:before {
content: '\f7c6';
}
.fa-skyatlas:before {
content: '\f216';
}
.fa-skype:before {
content: '\f17e';
}
.fa-slack-hash:before,
.fa-slack:before {
content: '\f198';
}
.fa-slideshare:before {
content: '\f1e7';
}
.fa-snapchat-ghost:before,
.fa-snapchat:before {
content: '\f2ab';
}
.fa-snapchat-square:before {
content: '\f2ad';
}
.fa-soundcloud:before {
content: '\f1be';
}
.fa-sourcetree:before {
content: '\f7d3';
}
.fa-speakap:before {
content: '\f3f3';
}
.fa-speaker-deck:before {
content: '\f83c';
}
.fa-spotify:before {
content: '\f1bc';
}
.fa-square-font-awesome:before {
content: '\f425';
}
.fa-font-awesome-alt:before,
.fa-square-font-awesome-stroke:before {
content: '\f35c';
}
.fa-squarespace:before {
content: '\f5be';
}
.fa-stack-exchange:before {
content: '\f18d';
}
.fa-stack-overflow:before {
content: '\f16c';
}
.fa-stackpath:before {
content: '\f842';
}
.fa-staylinked:before {
content: '\f3f5';
}
.fa-steam:before {
content: '\f1b6';
}
.fa-steam-square:before {
content: '\f1b7';
}
.fa-steam-symbol:before {
content: '\f3f6';
}
.fa-sticker-mule:before {
content: '\f3f7';
}
.fa-strava:before {
content: '\f428';
}
.fa-stripe:before {
content: '\f429';
}
.fa-stripe-s:before {
content: '\f42a';
}
.fa-studiovinari:before {
content: '\f3f8';
}
.fa-stumbleupon:before {
content: '\f1a4';
}
.fa-stumbleupon-circle:before {
content: '\f1a3';
}
.fa-superpowers:before {
content: '\f2dd';
}
.fa-supple:before {
content: '\f3f9';
}
.fa-suse:before {
content: '\f7d6';
}
.fa-swift:before {
content: '\f8e1';
}
.fa-symfony:before {
content: '\f83d';
}
.fa-teamspeak:before {
content: '\f4f9';
}
.fa-telegram-plane:before,
.fa-telegram:before {
content: '\f2c6';
}
.fa-tencent-weibo:before {
content: '\f1d5';
}
.fa-the-red-yeti:before {
content: '\f69d';
}
.fa-themeco:before {
content: '\f5c6';
}
.fa-themeisle:before {
content: '\f2b2';
}
.fa-think-peaks:before {
content: '\f731';
}
.fa-tiktok:before {
content: '\e07b';
}
.fa-trade-federation:before {
content: '\f513';
}
.fa-trello:before {
content: '\f181';
}
.fa-tumblr:before {
content: '\f173';
}
.fa-tumblr-square:before {
content: '\f174';
}
.fa-twitch:before {
content: '\f1e8';
}
.fa-twitter:before {
content: '\f099';
}
.fa-twitter-square:before {
content: '\f081';
}
.fa-typo3:before {
content: '\f42b';
}
.fa-uber:before {
content: '\f402';
}
.fa-ubuntu:before {
content: '\f7df';
}
.fa-uikit:before {
content: '\f403';
}
.fa-umbraco:before {
content: '\f8e8';
}
.fa-uncharted:before {
content: '\e084';
}
.fa-uniregistry:before {
content: '\f404';
}
.fa-unity:before {
content: '\e049';
}
.fa-unsplash:before {
content: '\e07c';
}
.fa-untappd:before {
content: '\f405';
}
.fa-ups:before {
content: '\f7e0';
}
.fa-usb:before {
content: '\f287';
}
.fa-usps:before {
content: '\f7e1';
}
.fa-ussunnah:before {
content: '\f407';
}
.fa-vaadin:before {
content: '\f408';
}
.fa-viacoin:before {
content: '\f237';
}
.fa-viadeo:before {
content: '\f2a9';
}
.fa-viadeo-square:before {
content: '\f2aa';
}
.fa-viber:before {
content: '\f409';
}
.fa-vimeo:before {
content: '\f40a';
}
.fa-vimeo-square:before {
content: '\f194';
}
.fa-vimeo-v:before {
content: '\f27d';
}
.fa-vine:before {
content: '\f1ca';
}
.fa-vk:before {
content: '\f189';
}
.fa-vnv:before {
content: '\f40b';
}
.fa-vuejs:before {
content: '\f41f';
}
.fa-watchman-monitoring:before {
content: '\e087';
}
.fa-waze:before {
content: '\f83f';
}
.fa-weebly:before {
content: '\f5cc';
}
.fa-weibo:before {
content: '\f18a';
}
.fa-weixin:before {
content: '\f1d7';
}
.fa-whatsapp:before {
content: '\f232';
}
.fa-whatsapp-square:before {
content: '\f40c';
}
.fa-whmcs:before {
content: '\f40d';
}
.fa-wikipedia-w:before {
content: '\f266';
}
.fa-windows:before {
content: '\f17a';
}
.fa-wirsindhandwerk:before,
.fa-wsh:before {
content: '\e2d0';
}
.fa-wix:before {
content: '\f5cf';
}
.fa-wizards-of-the-coast:before {
content: '\f730';
}
.fa-wodu:before {
content: '\e088';
}
.fa-wolf-pack-battalion:before {
content: '\f514';
}
.fa-wordpress:before {
content: '\f19a';
}
.fa-wordpress-simple:before {
content: '\f411';
}
.fa-wpbeginner:before {
content: '\f297';
}
.fa-wpexplorer:before {
content: '\f2de';
}
.fa-wpforms:before {
content: '\f298';
}
.fa-wpressr:before {
content: '\f3e4';
}
.fa-xbox:before {
content: '\f412';
}
.fa-xing:before {
content: '\f168';
}
.fa-xing-square:before {
content: '\f169';
}
.fa-y-combinator:before {
content: '\f23b';
}
.fa-yahoo:before {
content: '\f19e';
}
.fa-yammer:before {
content: '\f840';
}
.fa-yandex:before {
content: '\f413';
}
.fa-yandex-international:before {
content: '\f414';
}
.fa-yarn:before {
content: '\f7e3';
}
.fa-yelp:before {
content: '\f1e9';
}
.fa-yoast:before {
content: '\f2b1';
}
.fa-youtube:before {
content: '\f167';
}
.fa-youtube-square:before {
content: '\f431';
}
.fa-zhihu:before {
content: '\f63f';
}
@font-face {
font-family: 'Font Awesome 6 Free';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(/webfonts/fa-regular-400.woff2) format('woff2'),
url(/webfonts/fa-regular-400.ttf) format('truetype');
}
.fa-regular,
.far {
font-weight: 400;
}
@font-face {
font-family: 'Font Awesome 6 Free';
font-style: normal;
font-weight: 900;
font-display: block;
src: url(/webfonts/fa-solid-900.woff2) format('woff2'),
url(/webfonts/fa-solid-900.ttf) format('truetype');
}
.fa-regular,
.fa-solid,
.far,
.fas {
font-family: 'Font Awesome 6 Free';
}
.fa-solid,
.fas {
font-weight: 900;
}
================================================
FILE: src/styles/media.pcss
================================================
@custom-media --mq-phablet-min (min-width: 22.5rem); /* 360px */
@custom-media --mq-phablet-max (max-width: 26.1875rem); /* 419px */
@custom-media --mq-mobileLandscape-min (min-width: 35.5rem); /* 568px */
@custom-media --mq-tablet-min (min-width: 48rem); /* 768px */
@custom-media --mq-tablet-max (max-width: 64rem); /* 1024px */
@custom-media --mq-desktop-min (min-width: 64.063rem); /* 1025 px */
@custom-media --mq-desktop-max (max-width: 85.3125rem); /* 1365px */
@custom-media --mq-desktopLarge-min (min-width: 85.375rem); /* 1366px */
@custom-media --mq-heightLarge (min-width: 64rem) and (min-height: 68rem); /* 1088px */
================================================
FILE: src/styles/normalize.pcss
================================================
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input {
/* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select {
/* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type='button'],
[type='reset'],
[type='submit'] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type='button']::-moz-focus-inner,
[type='reset']::-moz-focus-inner,
[type='submit']::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type='button']:-moz-focusring,
[type='reset']:-moz-focusring,
[type='submit']:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type='checkbox'],
[type='radio'] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type='number']::-webkit-inner-spin-button,
[type='number']::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type='search'] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type='search']::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}
================================================
FILE: src/styles/page.pcss
================================================
html {
min-height: 100%;
}
body {
background-color: var(--color-gray-dark);
color: var(--color-gray-light);
height: 100%;
display: flex;
flex-direction: column;
}
main {
flex-grow: 1;
}
================================================
FILE: src/styles/range.pcss
================================================
input[type=range] {
background: transparent;
-webkit-appearance: none;
width: 100%;
margin-top: calc(var(--spacing-1) - var(--spacing-n4));
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;;
background: var(--color-gray-medium);
border: 0.2px solid var(--color-gray-medium);
}
input[type=range]::-webkit-slider-thumb {
border: 1px solid var(--color-gray-light);
height: 16px;
width: 16px;
background: var(--color-gray-light);
cursor: pointer;
-webkit-appearance: none;
margin-top: -8px;
border-radius: 16px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: var(--color-gray-light);
}
input[type=range]::-moz-range-track {
width: 100%;
height: 4px;
cursor: pointer;
background: var(--color-gray-medium);
border: 0.2px solid var(--color-gray-medium);
}
input[type=range]::-moz-range-thumb {
border: 1px solid var(--color-gray-light);
height: 16px;
width: 16px;
background: var(--color-gray-light);
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 4px;
cursor: pointer;
background: transparent;
border-color: transparent;
border-width: 16px 0;
color: transparent;
}
input[type=range]::-ms-fill-lower {
background: var(--color-gray-light);
border: 0.2px solid var(--color-gray-light);
}
input[type=range]::-ms-fill-upper {
background: var(--color-gray-light);
border: 0.2px solid var(--color-gray-light);
}
input[type=range]::-ms-thumb {
border: 1px solid var(--color-gray-light);
height: 16px;
width: 16px;
background: var(--color-gray-light);
cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
background: var(--color-gray-light);
}
input[type=range]:focus::-ms-fill-upper {
background: var(--color-gray-light);
}
================================================
FILE: src/styles/reset-custom.pcss
================================================
/*
1. Use a more-intuitive box-sizing model.
*/
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
2. Remove default margin
*/
* {
margin: 0;
}
/*
3. Allow percentage-based heights in the application
*/
html,
body {
height: 100%;
}
/*
Typographic tweaks!
4. Add accessible line-height
5. Improve text rendering
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
6. Improve media defaults
*/
img,
picture,
video,
svg {
display: block;
max-width: 100%;
}
/*
7. Remove built-in form typography styles
*/
input,
button,
textarea,
select {
font: inherit;
}
/*
8. Avoid text overflows
*/
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}
/*
9. Create a root stacking context
*/
#svelte {
isolation: isolate;
}
================================================
FILE: src/styles/scrollbar.pcss
================================================
::-webkit-scrollbar {
width: var(--spacing-n1);
}
::-webkit-scrollbar-track {
background: var(--color-gray-medium-faded);
}
::-webkit-scrollbar-thumb {
background: var(--color-gray-medium);
border-radius: var(--spacing-1);
}
::-webkit-scrollbar-thumb:hover {
background: var(--color-gray-medium);
}
================================================
FILE: src/styles/typography.pcss
================================================
body {
font-family: var(--font-family-secondary);
font-weight: var(--font-weight-regular);
font-size: var(--font-size-base);
line-height: var(--typography-lineHeight);
}
h1,
h2,
h3 {
font-family: var(--font-family-primary);
font-weight: var(--font-weight-regular);
color: var(--color-primary);
line-height: 1.25;
}
================================================
FILE: src/styles/variables.pcss
================================================
:root {
--color-primary: hsl(308, 82%, 55%);
--color-primary-tint: hsl(308, 82%, 40%);
--color-primary-faded: hsl(308, 82%, 44%, 0.1);
--color-secondary: hsl(169, 82%, 69%);
--color-secondary-tint: hsl(182, 29%, 51%);
--color-secondary-faded: hsla(182, 29%, 51%, 0.1);
--color-tertiary: hsl(60, 82%, 47%);
--color-tertiary-tint: hsl(60, 80%, 29%);
--color-tertiary-faded: hsl(60, 80%, 29%, 0.15);
--color-gray-dark: hsl(254, 21%, 20%);
--color-gray-medium: hsl(246, 11%, 32%);
--color-gray-light: hsl(215, 22%, 85%);
--color-gray-lightest: hsl(215, 22%, 95%);
--color-gray-light-faded: hsla(215, 22%, 85%, 0.7);
--color-gray-medium-faded: hsl(246, 11%, 32%, 0.2);
--font-family-primary: 'Ubuntu', sans-serif;
--font-family-secondary: 'Nanum Gothic', sans-serif;
--font-family-mono: 'Ubuntu Mono', monospace;
--font-family-icons: 'Material Icons';
--font-weight-regular: 400;
--font-weight-semi-bold: 600;
--font-weight-bold: 700;
}
:root {
--typography-lineHeight: 1.5;
--typography-fontSize-px: 16;
--typography-scale: 1.414;
--typography-fontSize: calc((var(--typography-fontSize-px) / 16));
--typography-scale-1: var(--typography-scale);
--typography-scale-2: calc(var(--typography-scale-1) * var(--typography-scale));
--typography-scale-3: calc(var(--typography-scale-2) * var(--typography-scale));
--typography-scale-4: calc(var(--typography-scale-3) * var(--typography-scale));
--typography-scale-5: calc(var(--typography-scale-4) * var(--typography-scale));
--typography-scale-6: calc(var(--typography-scale-5) * var(--typography-scale));
--font-size-smallest: calc((1 / var(--typography-scale-3)) * 1rem);
--font-size-smaller: calc((1 / var(--typography-scale-2)) * 1rem);
--font-size-small: calc((1 / var(--typography-scale-1)) * 1rem);
--font-size-base: 1rem;
--font-size-medium: calc(var(--typography-scale-1) * 1rem);
--font-size-larger: calc(var(--typography-scale-2) * 1rem);
--font-size-large: calc(var(--typography-scale-3) * 1rem);
--font-size-xlarge: calc(var(--typography-scale-4) * 1rem);
--font-size-xxlarge: calc(var(--typography-scale-5) * 1rem);
--font-size-xxxlarge: calc(var(--typography-scale-6) * 1rem);
}
:root {
--rhythmUnit: calc(var(--typography-lineHeight) * 1rem);
--spacing-n5: calc(var(--rhythmUnit) / 6);
--spacing-n4: calc(var(--rhythmUnit) / 5);
--spacing-n3: calc(var(--rhythmUnit) / 4);
--spacing-n2: calc(var(--rhythmUnit) / 3);
--spacing-n1: calc(var(--rhythmUnit) / 2);
--spacing-1: var(--rhythmUnit);
--spacing-2: calc(2 * var(--rhythmUnit));
--spacing-3: calc(3 * var(--rhythmUnit));
--spacing-4: calc(4 * var(--rhythmUnit));
--spacing-5: calc(5 * var(--rhythmUnit));
--spacing-6: calc(6 * var(--rhythmUnit));
--spacing-7: calc(7 * var(--rhythmUnit));
--spacing-8: calc(8 * var(--rhythmUnit));
--spacing-9: calc(9 * var(--rhythmUnit));
--spacing-10: calc(10 * var(--rhythmUnit));
}
:root {
--level-n1: -1;
--level-2: 2;
--level-3: 3;
--level-4: 4;
}
:root {
--container-max: 1600px;
}
================================================
FILE: src/utils/clampRange.ts
================================================
export const clampRange = (num, min, max) => Math.min(Math.max(num, min), max);
================================================
FILE: src/utils/clickOutside.ts
================================================
export const clickOutside = (node) => {
const handleClick = (event) => {
if (node && !node.contains(event.target) && !event.defaultPrevented) {
node.dispatchEvent(new CustomEvent('click_outside', node));
}
};
document.addEventListener('click', handleClick, true);
return {
destroy() {
document.removeEventListener('click', handleClick, true);
}
};
};
================================================
FILE: src/utils/getClampValue.ts
================================================
import { setToPrecision } from './setToPrecision';
const getDynamicValue = (fluid: number, relative: number) => {
if (relative === 0 || !relative) {
return `${fluid}vw`;
}
return relative < 0 ? `${fluid}vw - ${-1 * relative}rem` : `${fluid}vw + ${relative}rem`;
};
export const getClampValue = ([min, fluid, relative, max]: [number, number, number, number]) =>
`clamp(${setToPrecision(min, 3)}rem, ${getDynamicValue(fluid, relative)}, ${setToPrecision(
max,
3
)}rem);`;
================================================
FILE: src/utils/getShareUrl.ts
================================================
export const getShareUrl = ([rootFontSize, min, fluid, relative, max]: [
number,
number,
number,
number,
number
]) =>
`https://modern-fluid-typography.vercel.app?rootFontSize=${rootFontSize}&minSize=${min}&fluidSize=${fluid}&relativeSize=${relative}&maxSize=${max}`;
================================================
FILE: src/utils/parseQueryString.ts
================================================
import { browser } from '$app/env';
export const parseQueryString = (item: string) => {
if (!browser) {
return;
}
const searchParams = new URLSearchParams(window.location.search);
const result = parseInt(searchParams.get(item));
if (isNaN(result)) {
return;
}
return searchParams.get(item);
};
================================================
FILE: src/utils/setToPrecision.ts
================================================
export const setToPrecision = (num, decimals) =>
Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);
================================================
FILE: src/utils/toPx.ts
================================================
export const toPx = ([relativeSize, rootFontSize]: [number, number]) => relativeSize * rootFontSize;
================================================
FILE: src/utils/toRem.ts
================================================
export const toRem = ([value, root]: [number, number]) => value / root;
================================================
FILE: static/browserconfig.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#37314b</TileColor>
</tile>
</msapplication>
</browserconfig>
================================================
FILE: static/google6e1010a8fae63903.html
================================================
google-site-verification: google6e1010a8fae63903.html
================================================
FILE: static/robots.txt
================================================
User-agent: *
Allow: /
Sitemap: https://modern-fluid-typography.vercel.app//sitemap.xml
================================================
FILE: static/site.webmanifest
================================================
{
"name": "Modern Fluid Typography Editor",
"short_name": "Modern Fluid Typography Editor",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#37314b",
"background_color": "#37314b",
"display": "standalone"
}
================================================
FILE: static/sitemap.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://modern-fluid-typography.vercel.app/</loc>
<lastmod>2021-12-06T07:32:10+00:00</lastmod>
<priority>1.00</priority>
</url>
<url>
<loc>https://modern-fluid-typography.vercel.app/about</loc>
<lastmod>2021-12-06T07:32:10+00:00</lastmod>
<priority>0.80</priority>
</url>
</urlset>
================================================
FILE: svelte.config.js
================================================
import preprocess from 'svelte-preprocess';
import imagePreprocessor from 'svimg';
import path from 'path';
import fs from 'fs';
import vercel from '@sveltejs/adapter-vercel';
const mediaQueries = fs.readFileSync('./src/styles/media.pcss').toString();
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: [
imagePreprocessor({
inputDir: 'static',
outputDir: 'static/g',
webp: true,
avif: true
}),
preprocess({
postcss: {
prependData: mediaQueries
}
})
],
kit: {
adapter: vercel(),
// hydrate the <div id="svelte"> element in src/app.html
target: '#svelte',
vite: {
resolve: {
alias: {
src: path.resolve('./src'),
assets: path.resolve('./src/assets'),
components: path.resolve('./src/components'),
modules: path.resolve('./src/modules'),
models: path.resolve('./src/models'),
utils: path.resolve('./src/utils')
}
}
}
}
};
export default config;
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"moduleResolution": "node",
"module": "es2020",
"lib": ["es2020", "DOM"],
"target": "es2020",
/**
svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript
to enforce using \`import type\` instead of \`import\` for Types.
*/
"importsNotUsedAsValues": "error",
"isolatedModules": true,
"resolveJsonModule": true,
/**
To have warnings/errors of the Svelte compiler at the correct position,
enable source maps by default.
*/
"sourceMap": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"allowJs": true,
"checkJs": true,
"paths": {
"$lib": ["src/lib"],
"$lib/*": ["src/lib/*"]
}
},
"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"]
}
gitextract_d9euyxbe/ ├── .eslintrc.cjs ├── .gitignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── package.json ├── postcss.config.cjs ├── src/ │ ├── app.html │ ├── components/ │ │ ├── Footer.svelte │ │ ├── Header.svelte │ │ ├── InputWithRange.svelte │ │ ├── Legend.svelte │ │ ├── LineChart.svelte │ │ ├── Message.svelte │ │ ├── ShareButton.svelte │ │ ├── Snippet.svelte │ │ └── Stats.svelte │ ├── global.d.ts │ ├── modules/ │ │ ├── code/ │ │ │ └── Section.svelte │ │ ├── form/ │ │ │ ├── Form.svelte │ │ │ └── store.ts │ │ ├── graph/ │ │ │ ├── Graph.svelte │ │ │ ├── consts.ts │ │ │ ├── customTooltip.ts │ │ │ ├── derived.ts │ │ │ ├── store.ts │ │ │ └── utils.ts │ │ ├── tabs/ │ │ │ └── Tabs.svelte │ │ └── tracker/ │ │ ├── AddValue.svelte │ │ ├── Sort.svelte │ │ ├── TableDataRow.svelte │ │ ├── Tracker.svelte │ │ ├── derived.ts │ │ ├── store.ts │ │ └── utils.ts │ ├── routes/ │ │ ├── __error.svelte │ │ ├── __layout.svelte │ │ ├── about.svelte │ │ └── index.svelte │ ├── stores/ │ │ └── currentSubtitle.ts │ ├── styles/ │ │ ├── globals.pcss │ │ ├── icons.pcss │ │ ├── media.pcss │ │ ├── normalize.pcss │ │ ├── page.pcss │ │ ├── range.pcss │ │ ├── reset-custom.pcss │ │ ├── scrollbar.pcss │ │ ├── typography.pcss │ │ └── variables.pcss │ └── utils/ │ ├── clampRange.ts │ ├── clickOutside.ts │ ├── getClampValue.ts │ ├── getShareUrl.ts │ ├── parseQueryString.ts │ ├── setToPrecision.ts │ ├── toPx.ts │ └── toRem.ts ├── static/ │ ├── browserconfig.xml │ ├── g/ │ │ └── images/ │ │ ├── editor.5a8f99a.2bb048a65192a85028ae21e277cf3ba1.avif │ │ ├── editor.668f068.2bb048a65192a85028ae21e277cf3ba1.avif │ │ ├── editor.a1d08c9.2bb048a65192a85028ae21e277cf3ba1.avif │ │ ├── editor.d9015d2.2bb048a65192a85028ae21e277cf3ba1.avif │ │ ├── graph-increase.5a8f99a.3e7989db31c3fb99059f7341810d53eb.avif │ │ ├── graph-increase.5eb441f.3e7989db31c3fb99059f7341810d53eb.avif │ │ ├── graph-increase.a1d08c9.3e7989db31c3fb99059f7341810d53eb.avif │ │ ├── graph-increase.d9015d2.3e7989db31c3fb99059f7341810d53eb.avif │ │ ├── snippet.8509b1a.63b149124717d1f23fc75f409f86c762.avif │ │ ├── snippet.a1d08c9.63b149124717d1f23fc75f409f86c762.avif │ │ ├── table.48e1f11.c30557c7f994bcd0da96c3395c69ff71.avif │ │ ├── table.5a8f99a.c30557c7f994bcd0da96c3395c69ff71.avif │ │ ├── table.a1d08c9.c30557c7f994bcd0da96c3395c69ff71.avif │ │ └── table.d9015d2.c30557c7f994bcd0da96c3395c69ff71.avif │ ├── google6e1010a8fae63903.html │ ├── robots.txt │ ├── site.webmanifest │ └── sitemap.xml ├── svelte.config.js └── tsconfig.json
SYMBOL INDEX (2 symbols across 2 files)
FILE: src/modules/graph/consts.ts
constant CHART_OPTIONS (line 4) | const CHART_OPTIONS: ChartConfiguration<'line'> = {
FILE: src/utils/clickOutside.ts
method destroy (line 11) | destroy() {
Condensed preview — 79 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (196K chars).
[
{
"path": ".eslintrc.cjs",
"chars": 494,
"preview": "module.exports = {\n\troot: true,\n\tparser: '@typescript-eslint/parser',\n\textends: ['eslint:recommended', 'plugin:@typescri"
},
{
"path": ".gitignore",
"chars": 64,
"preview": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n"
},
{
"path": ".prettierrc",
"chars": 89,
"preview": "{\n\t\"useTabs\": true,\n\t\"singleQuote\": true,\n\t\"trailingComma\": \"none\",\n\t\"printWidth\": 100\n}\n"
},
{
"path": "LICENSE.md",
"chars": 1068,
"preview": "MIT License\n\nCopyright (c) 2021 Adrian Bece\n\nPermission is hereby granted, free of charge, to any person obtaining a cop"
},
{
"path": "README.md",
"chars": 533,
"preview": "# Modern Fluid Typography Editor\n\n<p align=\"center\">\n<img src=\"./static/socials-default.jpg\" alt=\"drawing\" width=\"480\"/>"
},
{
"path": "package.json",
"chars": 1381,
"preview": "{\n\t\"name\": \"modern-fluid-typography-editor\",\n\t\"version\": \"0.0.1\",\n\t\"scripts\": {\n\t\t\"dev\": \"svelte-kit dev\",\n\t\t\"build\": \"s"
},
{
"path": "postcss.config.cjs",
"chars": 344,
"preview": "module.exports = {\n plugins: [\n require('postcss-preset-env')({\n stage: 3,\n features: {\n"
},
{
"path": "src/app.html",
"chars": 2815,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<meta name=\"robots\" content=\"index, follow\" />\n\n\t\t"
},
{
"path": "src/components/Footer.svelte",
"chars": 3224,
"preview": "<footer class=\"footer\">\n\t<p class=\"footer__section\">\n\t\tInspired by\n\t\t<a\n\t\t\tclass=\"footer__link footer__link--primary\"\n\t\t"
},
{
"path": "src/components/Header.svelte",
"chars": 4904,
"preview": "<script>\n\timport { currentSubtitle } from 'src/stores/currentSubtitle';\n\n\timport { onMount } from 'svelte';\n\n\tconst subt"
},
{
"path": "src/components/InputWithRange.svelte",
"chars": 1491,
"preview": "<script lang=\"ts\">\n\texport let label;\n\texport let id;\n\texport let unit = '';\n\texport let value;\n</script>\n\n<label class="
},
{
"path": "src/components/Legend.svelte",
"chars": 1402,
"preview": "<aside class=\"legend-wrapper\">\n\t<strong>Legend</strong>\n\t<ul class=\"legend\">\n\t\t<li class=\"legend__box legend__box--min\">"
},
{
"path": "src/components/LineChart.svelte",
"chars": 1224,
"preview": "<script>\n\timport { Chart, registerables, Interaction } from 'chart.js';\n\timport { onMount } from 'svelte';\n\timport { Cro"
},
{
"path": "src/components/Message.svelte",
"chars": 2218,
"preview": "<script>\n\timport { computePosition } from '@floating-ui/dom';\n\timport { clickOutside } from 'src/utils/clickOutside';\n\ti"
},
{
"path": "src/components/ShareButton.svelte",
"chars": 1128,
"preview": "<script>\n\timport { shareUrl } from 'src/modules/form/store';\n\timport Clipboard from 'svelte-clipboard';\n\n\tlet hasCopied "
},
{
"path": "src/components/Snippet.svelte",
"chars": 2053,
"preview": "<script>\n\timport Clipboard from 'svelte-clipboard';\n\texport let text;\n\n\tlet isAnimated = false;\n\n\tconst handleCopyAnimat"
},
{
"path": "src/components/Stats.svelte",
"chars": 998,
"preview": "<script>\n\timport { fluidSize } from 'src/modules/form/store';\n\n\texport let start = 0;\n\texport let minValue = 0;\n\texport "
},
{
"path": "src/global.d.ts",
"chars": 40,
"preview": "/// <reference types=\"@sveltejs/kit\" />\n"
},
{
"path": "src/modules/code/Section.svelte",
"chars": 521,
"preview": "<script>\n\timport Message from 'components/Message.svelte';\n\timport { clampValue, minSize, maxSize, relativeSize } from '"
},
{
"path": "src/modules/form/Form.svelte",
"chars": 2746,
"preview": "<script>\n\timport Input from 'components/InputWithRange.svelte';\n\timport Message from 'src/components/Message.svelte';\n\ti"
},
{
"path": "src/modules/form/store.ts",
"chars": 1155,
"preview": "import { getClampValue } from 'src/utils/getClampValue';\nimport { getShareUrl } from 'src/utils/getShareUrl';\nimport { p"
},
{
"path": "src/modules/graph/Graph.svelte",
"chars": 222,
"preview": "<script>\n\timport LineChart from 'components/LineChart.svelte';\n\timport { CHART_OPTIONS } from './consts';\n\timport { grap"
},
{
"path": "src/modules/graph/consts.ts",
"chars": 2151,
"preview": "import type { ChartConfiguration } from 'chart.js';\nimport { externalTooltipHandler } from './customTooltip';\n\nexport co"
},
{
"path": "src/modules/graph/customTooltip.ts",
"chars": 2009,
"preview": "export const getOrCreateTooltip = (chart) => {\n\tlet tooltipEl = chart.canvas.parentNode.querySelector('#chart-tooltip');"
},
{
"path": "src/modules/graph/derived.ts",
"chars": 1888,
"preview": "import { derived } from 'svelte/store';\nimport { fluidSize, maxSize, minSize, relativeSizePx } from 'src/modules/form/st"
},
{
"path": "src/modules/graph/store.ts",
"chars": 159,
"preview": "import { writable } from 'svelte/store';\n\nconst minResolution = writable(300);\nconst maxResolution = writable(1920);\n\nex"
},
{
"path": "src/modules/graph/utils.ts",
"chars": 224,
"preview": "export const getScalesConfig = (y: { min: number; max: number; grid?: any }) => {\n\ty.min = x.min + 10;\n\ty.max = x.max + "
},
{
"path": "src/modules/tabs/Tabs.svelte",
"chars": 1877,
"preview": "<script>\n\texport let tabs;\n\n\tlet activeTab = 0;\n</script>\n\n<article class=\"tabs-wrapper\">\n\t<div class=\"tabs-wrapper__uti"
},
{
"path": "src/modules/tracker/AddValue.svelte",
"chars": 2206,
"preview": "<script>\n\timport Stats from 'src/components/Stats.svelte';\n\timport { trackers } from './store';\n\timport { generateUnique"
},
{
"path": "src/modules/tracker/Sort.svelte",
"chars": 636,
"preview": "<script>\n\texport let handleClick;\n\texport let isAsc;\n</script>\n\n<button class=\"sort\" class:sort--desc={!isAsc} class:sor"
},
{
"path": "src/modules/tracker/TableDataRow.svelte",
"chars": 2881,
"preview": "<script>\n\timport { setToPrecision } from 'src/utils/setToPrecision';\n\timport { fluidSize, maxSize, minSize, relativeSize"
},
{
"path": "src/modules/tracker/Tracker.svelte",
"chars": 1371,
"preview": "<script>\n\timport { trackersAsc, trackersDesc } from './derived';\n\timport Sort from './Sort.svelte';\n\timport TableDataRow"
},
{
"path": "src/modules/tracker/derived.ts",
"chars": 339,
"preview": "import { derived } from 'svelte/store';\nimport { trackers } from './store';\n\nexport const trackersAsc = derived([tracker"
},
{
"path": "src/modules/tracker/store.ts",
"chars": 308,
"preview": "import { writable } from 'svelte/store';\n\nexport const trackers = writable([\n\t{ id: 10, width: 300 },\n\t{ id: 11, width: "
},
{
"path": "src/modules/tracker/utils.ts",
"chars": 388,
"preview": "import { clampRange } from 'src/utils/clampRange';\n\nexport const generateUniqueId = () => Math.floor(Math.random() * Dat"
},
{
"path": "src/routes/__error.svelte",
"chars": 2338,
"preview": "<main>\n\t<div class=\"wrapper\">\n\t\t<h1 class=\"title\">\n\t\t\t<div class=\"title__text\">Game over.<br /> Or is it?</div>\n\t\t</h1>\n"
},
{
"path": "src/routes/__layout.svelte",
"chars": 218,
"preview": "<script>\n\timport Footer from 'components/Footer.svelte';\n\timport Header from 'components/Header.svelte';\n</script>\n\n<Hea"
},
{
"path": "src/routes/about.svelte",
"chars": 9921,
"preview": "<script>\n\timport Image from 'svimg';\n</script>\n\n<main>\n\t<h1 class=\"title\">\n\t\t<div class=\"title__text\">About the project "
},
{
"path": "src/routes/index.svelte",
"chars": 1792,
"preview": "<script>\n\timport Form from 'modules/form/Form.svelte';\n\timport Graph from 'modules/graph/Graph.svelte';\n\timport Tabs fro"
},
{
"path": "src/stores/currentSubtitle.ts",
"chars": 87,
"preview": "import { writable } from 'svelte/store';\n\nexport const currentSubtitle = writable('');\n"
},
{
"path": "src/styles/globals.pcss",
"chars": 191,
"preview": "@import './reset-custom.pcss';\n\n@import './variables.pcss';\n@import './icons.pcss';\n\n@import './typography.pcss';\n\n@impo"
},
{
"path": "src/styles/icons.pcss",
"chars": 94961,
"preview": "/*!\n * Font Awesome Free 6.0.0-beta2 by @fontawesome - https://fontawesome.com\n * License - https://fontawesome.com/lice"
},
{
"path": "src/styles/media.pcss",
"chars": 630,
"preview": "@custom-media --mq-phablet-min (min-width: 22.5rem); /* 360px */\n@custom-media --mq-phablet-max (max-width: 26.1875rem);"
},
{
"path": "src/styles/normalize.pcss",
"chars": 6251,
"preview": "/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */\n\n/* Document\n ==========================="
},
{
"path": "src/styles/page.pcss",
"chars": 195,
"preview": "html {\n\tmin-height: 100%;\n}\n\nbody {\n\tbackground-color: var(--color-gray-dark);\n\tcolor: var(--color-gray-light);\n\theight:"
},
{
"path": "src/styles/range.pcss",
"chars": 1851,
"preview": "input[type=range] {\n\tbackground: transparent;\n\t-webkit-appearance: none;\n\twidth: 100%;\n\tmargin-top: calc(var(--spacing-1"
},
{
"path": "src/styles/reset-custom.pcss",
"chars": 795,
"preview": "/*\n 1. Use a more-intuitive box-sizing model.\n*/\n*,\n*::before,\n*::after {\n\tbox-sizing: border-box;\n}\n/*\n 2. Remove d"
},
{
"path": "src/styles/scrollbar.pcss",
"chars": 345,
"preview": "\n::-webkit-scrollbar {\n width: var(--spacing-n1);\n }\n \n\n ::-webkit-scrollbar-track {\n background: var(--color-g"
},
{
"path": "src/styles/typography.pcss",
"chars": 324,
"preview": "body {\n\tfont-family: var(--font-family-secondary);\n\tfont-weight: var(--font-weight-regular);\n\tfont-size: var(--font-size"
},
{
"path": "src/styles/variables.pcss",
"chars": 3007,
"preview": ":root {\n\t--color-primary: hsl(308, 82%, 55%);\n\t--color-primary-tint: hsl(308, 82%, 40%);\n\t--color-primary-faded: hsl(308"
},
{
"path": "src/utils/clampRange.ts",
"chars": 80,
"preview": "export const clampRange = (num, min, max) => Math.min(Math.max(num, min), max);\n"
},
{
"path": "src/utils/clickOutside.ts",
"chars": 372,
"preview": "export const clickOutside = (node) => {\n\tconst handleClick = (event) => {\n\t\tif (node && !node.contains(event.target) && "
},
{
"path": "src/utils/getClampValue.ts",
"chars": 484,
"preview": "import { setToPrecision } from './setToPrecision';\n\nconst getDynamicValue = (fluid: number, relative: number) => {\n\tif ("
},
{
"path": "src/utils/getShareUrl.ts",
"chars": 273,
"preview": "export const getShareUrl = ([rootFontSize, min, fluid, relative, max]: [\n\tnumber,\n\tnumber,\n\tnumber,\n\tnumber,\n\tnumber\n]) "
},
{
"path": "src/utils/parseQueryString.ts",
"chars": 310,
"preview": "import { browser } from '$app/env';\n\nexport const parseQueryString = (item: string) => {\n\tif (!browser) {\n\t\treturn;\n\t}\n\n"
},
{
"path": "src/utils/setToPrecision.ts",
"chars": 117,
"preview": "export const setToPrecision = (num, decimals) =>\n\tMath.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals);\n"
},
{
"path": "src/utils/toPx.ts",
"chars": 101,
"preview": "export const toPx = ([relativeSize, rootFontSize]: [number, number]) => relativeSize * rootFontSize;\n"
},
{
"path": "src/utils/toRem.ts",
"chars": 72,
"preview": "export const toRem = ([value, root]: [number, number]) => value / root;\n"
},
{
"path": "static/browserconfig.xml",
"chars": 246,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<browserconfig>\n <msapplication>\n <tile>\n <square150x150logo"
},
{
"path": "static/google6e1010a8fae63903.html",
"chars": 53,
"preview": "google-site-verification: google6e1010a8fae63903.html"
},
{
"path": "static/robots.txt",
"chars": 88,
"preview": "User-agent: *\nAllow: /\n\nSitemap: https://modern-fluid-typography.vercel.app//sitemap.xml"
},
{
"path": "static/site.webmanifest",
"chars": 387,
"preview": "{\n\t\"name\": \"Modern Fluid Typography Editor\",\n\t\"short_name\": \"Modern Fluid Typography Editor\",\n\t\"icons\": [\n\t\t{\n\t\t\t\"src\": "
},
{
"path": "static/sitemap.xml",
"chars": 629,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\"\r\n xmlns:xsi=\"http:/"
},
{
"path": "svelte.config.js",
"chars": 1062,
"preview": "import preprocess from 'svelte-preprocess';\nimport imagePreprocessor from 'svimg';\nimport path from 'path';\nimport fs fr"
},
{
"path": "tsconfig.json",
"chars": 840,
"preview": "{\n\t\"compilerOptions\": {\n\t\t\"moduleResolution\": \"node\",\n\t\t\"module\": \"es2020\",\n\t\t\"lib\": [\"es2020\", \"DOM\"],\n\t\t\"target\": \"es2"
}
]
// ... and 14 more files (download for full content)
About this extraction
This page contains the full source code of the codeAdrian/modern-fluid-typography-editor GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 79 files (170.5 KB), approximately 56.2k tokens, and a symbol index with 2 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.