├── migrations
├── .gitignore
├── Version20210510171213.php
├── Version20210523174745.php
├── Version20210523175734.php
├── Version20210510163646.php
└── Version20210510155228.php
├── src
├── Entity
│ ├── .gitignore
│ ├── Distribution.php
│ └── Dataset.php
├── Controller
│ ├── .gitignore
│ ├── SupplierController.php
│ └── ApiController.php
├── Repository
│ ├── .gitignore
│ ├── DistributionRepository.php
│ └── DatasetRepository.php
├── Api
│ ├── Entity
│ │ ├── Request
│ │ │ ├── ApiRequestInterface.php
│ │ │ ├── ApiDatasetRequest.php
│ │ │ ├── ApiGetDatasetRequest.php
│ │ │ └── ApiSearchRequest.php
│ │ └── Response
│ │ │ ├── ApiResponseInterface.php
│ │ │ ├── ApiSuccessResponse.php
│ │ │ ├── ApiGetDatasetResponse.php
│ │ │ └── ApiDatasetsResponse.php
│ └── Builder
│ │ ├── ApiRequestBuilder.php
│ │ └── ApiResponseBuilder.php
├── SupplierFacade
│ ├── Exception
│ │ ├── AbstractCoreSupplierException.php
│ │ └── UnnecessaryDistributionCoreSupplierException.php
│ └── DataEu
│ │ ├── Bridge
│ │ ├── GetDataset
│ │ │ └── DataEuGetDatasetResponseBridge.php
│ │ ├── Search
│ │ │ └── DataEuSearchResponseBridge.php
│ │ └── Common
│ │ │ ├── DataEuDistributionResponseBridge.php
│ │ │ └── DataEuDatasetResponseBridge.php
│ │ ├── RequestBuilder
│ │ └── DataEuSearchRequestBuilder.php
│ │ ├── DataEuSupplierFacade.php
│ │ └── MethodFacade
│ │ ├── DataEuSearchMethodFacade.php
│ │ └── DataEuGetDatasetMethodFacade.php
├── Supplier
│ └── DataEu
│ │ ├── DataEuConst.php
│ │ ├── Common
│ │ ├── Collection
│ │ │ ├── DataEuDatasetCollection.php
│ │ │ └── DataEuDistributionCollection.php
│ │ ├── DataEuFormat.php
│ │ ├── DataEuCountry.php
│ │ ├── DataEuDistribution.php
│ │ ├── DataEuDescription.php
│ │ └── DataEuDataset.php
│ │ ├── GetDataset
│ │ └── DataEuGetDatasetResponse.php
│ │ └── Search
│ │ ├── DataEuSearchResponse.php
│ │ └── DataEuResultResponse.php
├── Utils
│ └── StringCollection.php
├── Base
│ ├── CollectionInterface.php
│ └── AbstractCollection.php
└── Kernel.php
├── translations
└── .gitignore
├── public
├── assets
│ ├── js
│ │ ├── main.js
│ │ ├── observe.js
│ │ └── import.js
│ └── lib
│ │ └── bootstrap
│ │ └── css
│ │ ├── bootstrap-reboot.min.css
│ │ ├── bootstrap-reboot.rtl.min.css
│ │ ├── bootstrap-reboot.rtl.css
│ │ ├── bootstrap-reboot.css
│ │ ├── bootstrap-reboot.min.css.map
│ │ └── bootstrap-reboot.rtl.min.css.map
├── index.php
└── .htaccess
├── Procfile
├── config
├── packages
│ ├── test
│ │ ├── twig.yaml
│ │ ├── validator.yaml
│ │ ├── framework.yaml
│ │ ├── web_profiler.yaml
│ │ ├── doctrine.yaml
│ │ └── monolog.yaml
│ ├── twig.yaml
│ ├── mailer.yaml
│ ├── prod
│ │ ├── routing.yaml
│ │ ├── jms_serializer.yaml
│ │ ├── deprecations.yaml
│ │ ├── monolog.yaml
│ │ └── doctrine.yaml
│ ├── sensio_framework_extra.yaml
│ ├── dev
│ │ ├── web_profiler.yaml
│ │ ├── jms_serializer.yaml
│ │ ├── debug.yaml
│ │ └── monolog.yaml
│ ├── translation.yaml
│ ├── routing.yaml
│ ├── validator.yaml
│ ├── doctrine_migrations.yaml
│ ├── doctrine.yaml
│ ├── notifier.yaml
│ ├── framework.yaml
│ ├── jms_serializer.yaml
│ ├── cache.yaml
│ └── security.yaml
├── routes.yaml
├── routes
│ ├── dev
│ │ ├── framework.yaml
│ │ └── web_profiler.yaml
│ └── annotations.yaml
├── preload.php
├── bundles.php
└── services.yaml
├── .env.test
├── tests
└── bootstrap.php
├── .gitignore
├── bin
├── phpunit
└── console
├── templates
├── page
│ ├── observe.html.twig
│ └── import.html.twig
└── base.html.twig
├── phpunit.xml.dist
├── .env.dist
├── composer.json
└── symfony.lock
/migrations/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Entity/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/translations/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/assets/js/main.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Controller/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Repository/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: vendor/bin/heroku-php-apache2 public/
--------------------------------------------------------------------------------
/config/packages/test/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | strict_variables: true
3 |
--------------------------------------------------------------------------------
/config/packages/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | default_path: '%kernel.project_dir%/templates'
3 |
--------------------------------------------------------------------------------
/config/packages/mailer.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | mailer:
3 | dsn: '%env(MAILER_DSN)%'
4 |
--------------------------------------------------------------------------------
/config/packages/prod/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: null
4 |
--------------------------------------------------------------------------------
/config/routes.yaml:
--------------------------------------------------------------------------------
1 | #index:
2 | # path: /
3 | # controller: App\Controller\DefaultController::index
4 |
--------------------------------------------------------------------------------
/config/packages/sensio_framework_extra.yaml:
--------------------------------------------------------------------------------
1 | sensio_framework_extra:
2 | router:
3 | annotations: false
4 |
--------------------------------------------------------------------------------
/config/packages/test/validator.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | validation:
3 | not_compromised_password: false
4 |
--------------------------------------------------------------------------------
/config/packages/test/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: true
3 | session:
4 | storage_id: session.storage.mock_file
5 |
--------------------------------------------------------------------------------
/config/routes/dev/framework.yaml:
--------------------------------------------------------------------------------
1 | _errors:
2 | resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
3 | prefix: /_error
4 |
--------------------------------------------------------------------------------
/src/Api/Entity/Request/ApiRequestInterface.php:
--------------------------------------------------------------------------------
1 | dataset = $dataset;
16 | }
17 | }
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | bootEnv(dirname(__DIR__).'/.env');
11 | }
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | /.idea/
3 |
4 | ###> symfony/framework-bundle ###
5 | /.env.local
6 | /.env.local.php
7 | /.env.*.local
8 | /config/secrets/prod/prod.decrypt.private.php
9 | /public/bundles/
10 | /var/
11 | /vendor/
12 | ###< symfony/framework-bundle ###
13 |
14 | ###> symfony/phpunit-bridge ###
15 | .phpunit
16 | .phpunit.result.cache
17 | /phpunit.xml
18 | .env
19 | ###< symfony/phpunit-bridge ###
20 |
--------------------------------------------------------------------------------
/config/packages/test/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: fingers_crossed
5 | action_level: error
6 | handler: nested
7 | excluded_http_codes: [404, 405]
8 | channels: ["!event"]
9 | nested:
10 | type: stream
11 | path: "%kernel.logs_dir%/%kernel.environment%.log"
12 | level: debug
13 |
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Common/Collection/DataEuDatasetCollection.php:
--------------------------------------------------------------------------------
1 | dataset;
18 | }
19 | }
--------------------------------------------------------------------------------
/bin/phpunit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | title;
20 | }
21 |
22 | public function getId(): string
23 | {
24 | return $this->id;
25 | }
26 | }
--------------------------------------------------------------------------------
/config/packages/doctrine.yaml:
--------------------------------------------------------------------------------
1 | doctrine:
2 | dbal:
3 | # IMPORTANT: DATABASE_URL *must* define the server version
4 | url: '%env(resolve:DATABASE_URL)%'
5 | orm:
6 | auto_generate_proxy_classes: true
7 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
8 | auto_mapping: true
9 | mappings:
10 | App:
11 | is_bundle: false
12 | type: annotation
13 | dir: '%kernel.project_dir%/src/Entity'
14 | prefix: 'App\Entity'
15 | alias: App
16 |
--------------------------------------------------------------------------------
/config/packages/notifier.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | notifier:
3 | #chatter_transports:
4 | # slack: '%env(SLACK_DSN)%'
5 | # telegram: '%env(TELEGRAM_DSN)%'
6 | #texter_transports:
7 | # twilio: '%env(TWILIO_DSN)%'
8 | # nexmo: '%env(NEXMO_DSN)%'
9 | channel_policy:
10 | # use chat/slack, chat/telegram, sms/twilio or sms/nexmo
11 | urgent: ['email']
12 | high: ['email']
13 | medium: ['email']
14 | low: ['email']
15 | admin_recipients:
16 | - { email: admin@example.com }
17 |
--------------------------------------------------------------------------------
/src/Api/Entity/Request/ApiGetDatasetRequest.php:
--------------------------------------------------------------------------------
1 | externalId;
20 | }
21 |
22 | public function usePersist(): bool
23 | {
24 | return $this->usePersist;
25 | }
26 | }
--------------------------------------------------------------------------------
/config/packages/framework.yaml:
--------------------------------------------------------------------------------
1 | # see https://symfony.com/doc/current/reference/configuration/framework.html
2 | framework:
3 | secret: '%env(APP_SECRET)%'
4 | #csrf_protection: true
5 | #http_method_override: true
6 |
7 | # Enables session support. Note that the session will ONLY be started if you read or write from it.
8 | # Remove or comment this section to explicitly disable session support.
9 | session:
10 | handler_id: null
11 | cookie_secure: auto
12 | cookie_samesite: lax
13 |
14 | #esi: true
15 | #fragments: true
16 | php_errors:
17 | log: true
18 |
--------------------------------------------------------------------------------
/templates/page/observe.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block javascripts %}
4 |
5 | {% endblock %}
6 |
7 | {% block body %}
8 |
9 |
10 |
11 | #
12 | Країна
13 | Опис(EN)
14 | Опис(DE)
15 | Опис(FR)
16 | Доступні формати
17 |
18 |
19 |
20 |
21 | {% endblock %}
--------------------------------------------------------------------------------
/config/packages/prod/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: fingers_crossed
5 | action_level: error
6 | handler: nested
7 | excluded_http_codes: [404, 405]
8 | buffer_size: 50 # How many messages should be saved? Prevent memory leaks
9 | nested:
10 | type: stream
11 | path: php://stderr
12 | level: debug
13 | formatter: monolog.formatter.json
14 | console:
15 | type: console
16 | process_psr_3_messages: false
17 | channels: ["!event", "!doctrine"]
18 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | bootEnv(dirname(__DIR__).'/.env');
11 |
12 | if ($_SERVER['APP_DEBUG']) {
13 | umask(0000);
14 |
15 | Debug::enable();
16 | }
17 |
18 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
19 | $request = Request::createFromGlobals();
20 | $response = $kernel->handle($request);
21 | $response->send();
22 | $kernel->terminate($request, $response);
23 |
--------------------------------------------------------------------------------
/config/packages/prod/doctrine.yaml:
--------------------------------------------------------------------------------
1 | doctrine:
2 | orm:
3 | auto_generate_proxy_classes: false
4 | metadata_cache_driver:
5 | type: pool
6 | pool: doctrine.system_cache_pool
7 | query_cache_driver:
8 | type: pool
9 | pool: doctrine.system_cache_pool
10 | result_cache_driver:
11 | type: pool
12 | pool: doctrine.result_cache_pool
13 |
14 | framework:
15 | cache:
16 | pools:
17 | doctrine.result_cache_pool:
18 | adapter: cache.app
19 | doctrine.system_cache_pool:
20 | adapter: cache.system
21 |
--------------------------------------------------------------------------------
/src/Api/Builder/ApiRequestBuilder.php:
--------------------------------------------------------------------------------
1 | serializer = $serializer;
17 | }
18 |
19 | public function build(string $requestClass, string $data): ApiRequestInterface
20 | {
21 | /** @var ApiRequestInterface $request */
22 | return $this->serializer->deserialize($data, $requestClass, 'json');
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Supplier/DataEu/GetDataset/DataEuGetDatasetResponse.php:
--------------------------------------------------------------------------------
1 | success;
21 | }
22 |
23 | public function getResult(): DataEuDataset
24 | {
25 | return $this->result;
26 | }
27 | }
--------------------------------------------------------------------------------
/config/packages/jms_serializer.yaml:
--------------------------------------------------------------------------------
1 | jms_serializer:
2 | visitors:
3 | xml_serialization:
4 | format_output: '%kernel.debug%'
5 | json_serialization:
6 | options: [JSON_UNESCAPED_UNICODE]
7 | json_deserialization:
8 | options: [JSON_UNESCAPED_UNICODE]
9 | # metadata:
10 | # auto_detection: false
11 | # directories:
12 | # any-name:
13 | # namespace_prefix: "My\\FooBundle"
14 | # path: "@MyFooBundle/Resources/config/serializer"
15 | # another-name:
16 | # namespace_prefix: "My\\BarBundle"
17 | # path: "@MyBarBundle/Resources/config/serializer"
18 |
--------------------------------------------------------------------------------
/config/packages/dev/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: stream
5 | path: "%kernel.logs_dir%/%kernel.environment%.log"
6 | level: debug
7 | channels: ["!event"]
8 | # uncomment to get logging in your browser
9 | # you may have to allow bigger header sizes in your Web server configuration
10 | #firephp:
11 | # type: firephp
12 | # level: info
13 | #chromephp:
14 | # type: chromephp
15 | # level: info
16 | console:
17 | type: console
18 | process_psr_3_messages: false
19 | channels: ["!event", "!doctrine", "!console"]
20 |
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Search/DataEuSearchResponse.php:
--------------------------------------------------------------------------------
1 | success;
21 | }
22 |
23 | public function getResult(): DataEuResultResponse
24 | {
25 | return $this->result;
26 | }
27 | }
--------------------------------------------------------------------------------
/src/Api/Entity/Request/ApiSearchRequest.php:
--------------------------------------------------------------------------------
1 | query;
23 | }
24 |
25 | public function getPage(): int
26 | {
27 | return $this->page;
28 | }
29 |
30 | public function getPerPage(): int
31 | {
32 | return $this->perPage;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Common/DataEuCountry.php:
--------------------------------------------------------------------------------
1 | title;
20 | }
21 |
22 | public function setTitle(string $title): void
23 | {
24 | $this->title = $title;
25 | }
26 |
27 | public function getId(): string
28 | {
29 | return $this->id;
30 | }
31 |
32 | public function setId(string $id): void
33 | {
34 | $this->id = $id;
35 | }
36 | }
--------------------------------------------------------------------------------
/config/packages/cache.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | cache:
3 | # Unique name of your app: used to compute stable namespaces for cache keys.
4 | #prefix_seed: your_vendor_name/app_name
5 |
6 | # The "app" cache stores to the filesystem by default.
7 | # The data in this cache should persist between deploys.
8 | # Other options include:
9 |
10 | # Redis
11 | #app: cache.adapter.redis
12 | #default_redis_provider: redis://localhost
13 |
14 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
15 | #app: cache.adapter.apcu
16 |
17 | # Namespaced pools use the above "app" backend by default
18 | #pools:
19 | #my.dedicated.cache: null
20 |
--------------------------------------------------------------------------------
/src/Api/Entity/Response/ApiDatasetsResponse.php:
--------------------------------------------------------------------------------
1 | ") */
13 | private Collection $datasetCollection;
14 |
15 | private ?int $totalDatasetsAmount = null;
16 |
17 | public function setDatasetCollection(Collection $datasetCollection): void
18 | {
19 | $this->datasetCollection = $datasetCollection;
20 | }
21 |
22 | public function setTotalDatasetsAmount(int $totalDatasetsAmount): void
23 | {
24 | $this->totalDatasetsAmount = $totalDatasetsAmount;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/Bridge/GetDataset/DataEuGetDatasetResponseBridge.php:
--------------------------------------------------------------------------------
1 | datasetResponseBridge = $datasetResponseBridge;
18 | }
19 |
20 | public function build(DataEuGetDatasetResponse $response): Dataset
21 | {
22 | return $this->datasetResponseBridge->build($response->getResult());
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Common/DataEuDistribution.php:
--------------------------------------------------------------------------------
1 | access_url;
23 | }
24 |
25 | public function getFormat(): ?DataEuFormat
26 | {
27 | return $this->format;
28 | }
29 |
30 | public function getId(): string
31 | {
32 | return $this->id;
33 | }
34 | }
--------------------------------------------------------------------------------
/migrations/Version20210510171213.php:
--------------------------------------------------------------------------------
1 | addSql('ALTER TABLE dataset ADD external_id LONGTEXT DEFAULT NULL');
24 | }
25 |
26 | public function down(Schema $schema): void
27 | {
28 | // this down() migration is auto-generated, please modify it to your needs
29 | $this->addSql('ALTER TABLE dataset DROP external_id');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/migrations/Version20210523174745.php:
--------------------------------------------------------------------------------
1 | addSql('ALTER TABLE distribution ADD payload LONGTEXT NOT NULL');
24 | }
25 |
26 | public function down(Schema $schema): void
27 | {
28 | // this down() migration is auto-generated, please modify it to your needs
29 | $this->addSql('ALTER TABLE distribution DROP payload');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/migrations/Version20210523175734.php:
--------------------------------------------------------------------------------
1 | addSql('ALTER TABLE distribution ADD external_id VARCHAR(255) NOT NULL');
24 | }
25 |
26 | public function down(Schema $schema): void
27 | {
28 | // this down() migration is auto-generated, please modify it to your needs
29 | $this->addSql('ALTER TABLE distribution DROP external_id');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Search/DataEuResultResponse.php:
--------------------------------------------------------------------------------
1 | ")
15 | * @var DataEuDataset[]|DataEuDatasetCollection
16 | */
17 | private $results = [];
18 |
19 | /** @Serializer\Type("int") */
20 | private int $count;
21 |
22 | public function getResults(): DataEuDatasetCollection
23 | {
24 | if (!$this->results instanceof DataEuDatasetCollection) {
25 | $this->results = new DataEuDatasetCollection($this->results);
26 | }
27 |
28 | return $this->results;
29 | }
30 |
31 | public function getCount(): int
32 | {
33 | return $this->count;
34 | }
35 | }
--------------------------------------------------------------------------------
/config/packages/security.yaml:
--------------------------------------------------------------------------------
1 | security:
2 | # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
3 | providers:
4 | users_in_memory: { memory: null }
5 | firewalls:
6 | dev:
7 | pattern: ^/(_(profiler|wdt)|css|images|js)/
8 | security: false
9 | main:
10 | anonymous: true
11 | lazy: true
12 | provider: users_in_memory
13 |
14 | # activate different ways to authenticate
15 | # https://symfony.com/doc/current/security.html#firewalls-authentication
16 |
17 | # https://symfony.com/doc/current/security/impersonating_user.html
18 | # switch_user: true
19 |
20 | # Easy way to control access for large sections of your site
21 | # Note: Only the *first* access control that matches will be used
22 | access_control:
23 | # - { path: ^/admin, roles: ROLE_ADMIN }
24 | # - { path: ^/profile, roles: ROLE_USER }
25 |
--------------------------------------------------------------------------------
/config/bundles.php:
--------------------------------------------------------------------------------
1 | ['all' => true],
5 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
6 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
7 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
8 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
9 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
10 | Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
11 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
12 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
13 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
14 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
15 | JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
16 | ];
17 |
--------------------------------------------------------------------------------
/src/Api/Builder/ApiResponseBuilder.php:
--------------------------------------------------------------------------------
1 | serializer = $serializer;
19 | }
20 |
21 | public function build(ApiResponseInterface $response): JsonResponse
22 | {
23 | $statusCode = $response->isSuccess() ? Response::HTTP_OK : Response::HTTP_INTERNAL_SERVER_ERROR;
24 | $data = $this->buildJsonString($response);
25 |
26 | return new JsonResponse($data, $statusCode, [], true);
27 | }
28 |
29 | public function buildJsonString(ApiResponseInterface $response): string
30 | {
31 | return $this->serializer->serialize($response, 'json');
32 | }
33 | }
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Common/DataEuDescription.php:
--------------------------------------------------------------------------------
1 | en;
23 | }
24 |
25 | public function setEn(string $en): void
26 | {
27 | $this->en = $en;
28 | }
29 |
30 | public function getDe(): ?string
31 | {
32 | return $this->de;
33 | }
34 |
35 | public function setDe(string $de): void
36 | {
37 | $this->de = $de;
38 | }
39 |
40 | public function getFr(): ?string
41 | {
42 | return $this->fr;
43 | }
44 |
45 | public function setFr(string $fr): void
46 | {
47 | $this->fr = $fr;
48 | }
49 | }
--------------------------------------------------------------------------------
/templates/page/import.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block javascripts %}
4 |
5 | {% endblock %}
6 |
7 | {% block body %}
8 |
9 | Пошук
10 |
11 | Шукати
12 |
13 |
14 |
15 |
16 |
17 | #
18 | Країна
19 | Опис(EN)
20 | Опис(DE)
21 | Опис(FR)
22 | Доступні формати
23 | Дія
24 |
25 |
26 |
27 |
28 |
29 | <
30 |
31 | >
32 |
33 | {% endblock %}
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/RequestBuilder/DataEuSearchRequestBuilder.php:
--------------------------------------------------------------------------------
1 | getQuery()) {
18 | $query['q'] = $searchRequest->getQuery();
19 | }
20 | $query['page'] = $searchRequest->getPage();
21 | $query['limit'] = $searchRequest->getPerPage();
22 | $query['sort'] = self::SORT_BY;
23 | $query['filter'] = self::FILTER_DATASET;
24 | $query['facets'] = $this->buildFacets($searchRequest);
25 |
26 | return $query;
27 | }
28 |
29 | private function buildFacets(ApiSearchRequest $searchRequest): string
30 | {
31 | $facets['format'] = DataEuConst::SUPPORTABLE_FORMATS;
32 |
33 | return json_encode($facets, JSON_THROW_ON_ERROR);
34 | }
35 | }
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/Bridge/Search/DataEuSearchResponseBridge.php:
--------------------------------------------------------------------------------
1 | datasetResponseBridge = $datasetResponseBridge;
21 | }
22 |
23 | /** @return Dataset[]|Collection */
24 | public function build(DataEuSearchResponse $searchResponse): Collection
25 | {
26 | $result = new ArrayCollection();
27 |
28 | /** @var DataEuDataset $dataset */
29 | foreach ($searchResponse->getResult()->getResults() as $dataset) {
30 | $dataset = $this->datasetResponseBridge->build($dataset);
31 | $result->add($dataset);
32 | }
33 |
34 | return $result;
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Supplier/DataEu/Common/DataEuDataset.php:
--------------------------------------------------------------------------------
1 | ")
24 | */
25 | private $distributions;
26 |
27 | public function getCountry(): DataEuCountry
28 | {
29 | return $this->country;
30 | }
31 |
32 | public function getDescription(): DataEuDescription
33 | {
34 | return $this->description;
35 | }
36 |
37 | public function getDistributions()
38 | {
39 | return $this->distributions;
40 | }
41 |
42 | public function getId(): string
43 | {
44 | return $this->id;
45 | }
46 | }
--------------------------------------------------------------------------------
/src/Base/CollectionInterface.php:
--------------------------------------------------------------------------------
1 | searchMethodFacade = $searchMethodFacade;
23 | $this->getDatasetMethodFacade = $getDatasetMethodFacade;
24 | }
25 |
26 | public function search(ApiSearchRequest $searchRequest): ApiDatasetsResponse
27 | {
28 | return $this->searchMethodFacade->commit($searchRequest);
29 | }
30 |
31 | public function getDataset(ApiGetDatasetRequest $getDatasetRequest): ApiSuccessResponse
32 | {
33 | return $this->getDatasetMethodFacade->commit($getDatasetRequest);
34 | }
35 | }
--------------------------------------------------------------------------------
/migrations/Version20210510163646.php:
--------------------------------------------------------------------------------
1 | addSql('ALTER TABLE dataset CHANGE description_en description_en LONGTEXT DEFAULT NULL, CHANGE description_de description_de LONGTEXT DEFAULT NULL, CHANGE description_fr description_fr LONGTEXT DEFAULT NULL');
24 | }
25 |
26 | public function down(Schema $schema): void
27 | {
28 | // this down() migration is auto-generated, please modify it to your needs
29 | $this->addSql('ALTER TABLE dataset CHANGE description_en description_en VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, CHANGE description_de description_de VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, CHANGE description_fr description_fr VARCHAR(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`');
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/public/assets/js/observe.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 | loadDatasets();
3 | });
4 |
5 | async function loadDatasets() {
6 | const response = await fetch('/api/get-all-datasets', {
7 | method: 'GET',
8 | headers: {
9 | 'Content-Type': 'application/json;charset=utf-8'
10 | }
11 | });
12 |
13 | const result = await response.json();
14 | const datasetsTbody = $('#datasets-table tbody');
15 | datasetsTbody.empty();
16 | result.dataset_collection.forEach(function (elem, index) {
17 | datasetsTbody.append(`
18 | ${index + 1}
19 | ${elem.country_code}
20 | ${elem.description_en || 'N/A'}
21 | ${elem.description_de || 'N/A'}
22 | ${elem.description_fr || 'N/A'}
23 | ${getDistributionsString(elem.distributions)}
24 | `);
25 | });
26 |
27 | $('#page-number').html(page);
28 | }
29 |
30 | function getDistributionsString(distributions) {
31 | let result = [];
32 |
33 | distributions.forEach(function (elem) {
34 | result.push(`${elem.format} `);
35 | })
36 |
37 | return result.join(', ');
38 | }
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | tests
21 |
22 |
23 |
24 |
25 |
26 | src
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
40 |
41 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | getParameterOption(['--env', '-e'], null, true)) {
24 | putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
25 | }
26 |
27 | if ($input->hasParameterOption('--no-debug', true)) {
28 | putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
29 | }
30 |
31 | (new Dotenv())->bootEnv(dirname(__DIR__).'/.env');
32 |
33 | if ($_SERVER['APP_DEBUG']) {
34 | umask(0000);
35 |
36 | if (class_exists(Debug::class)) {
37 | Debug::enable();
38 | }
39 | }
40 |
41 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
42 | $application = new Application($kernel);
43 | $application->run($input);
44 |
--------------------------------------------------------------------------------
/config/services.yaml:
--------------------------------------------------------------------------------
1 | # This file is the entry point to configure your own services.
2 | # Files in the packages/ subdirectory configure your dependencies.
3 |
4 | # Put parameters here that don't need to change on each machine where the app is deployed
5 | # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
6 | parameters:
7 |
8 | services:
9 | # default configuration for services in *this* file
10 | _defaults:
11 | autowire: true # Automatically injects dependencies in your services.
12 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
13 |
14 | # makes classes in src/ available to be used as services
15 | # this creates a service per class whose id is the fully-qualified class name
16 | App\:
17 | resource: '../src/'
18 | exclude:
19 | - '../src/DependencyInjection/'
20 | - '../src/Entity/'
21 | - '../src/Kernel.php'
22 | - '../src/Tests/'
23 |
24 | # controllers are imported separately to make sure services can be injected
25 | # as action arguments even if you don't extend any base controller class
26 | App\Controller\:
27 | resource: '../src/Controller/'
28 | tags: ['controller.service_arguments']
29 |
30 | # add more service definitions when explicit configuration is needed
31 | # please note that last definitions always *replace* previous ones
32 |
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/Bridge/Common/DataEuDistributionResponseBridge.php:
--------------------------------------------------------------------------------
1 | setExternalId($supplierDistribution->getId());
19 |
20 | $format = $supplierDistribution->getFormat();
21 | if (!$format || !$this->isFormatAllowed($format->getId())) {
22 | throw new UnnecessaryDistributionCoreSupplierException();
23 | }
24 | $distribution->setFormat($format->getId());
25 |
26 | $accessUrl = $supplierDistribution->getAccessUrl();
27 | if (!$accessUrl) {
28 | throw new UnnecessaryDistributionCoreSupplierException();
29 | }
30 | $distribution->setDownloadUrl($supplierDistribution->getAccessUrl());
31 |
32 | return $distribution;
33 | }
34 |
35 | private function isFormatAllowed(string $format): bool
36 | {
37 | foreach (DataEuConst::SUPPORTABLE_FORMATS as $supportableFormat) {
38 | if (strcasecmp($format, $supportableFormat) === 0) {
39 | return true;
40 | }
41 | }
42 |
43 | return false;
44 | }
45 | }
--------------------------------------------------------------------------------
/src/Kernel.php:
--------------------------------------------------------------------------------
1 | import('../config/{packages}/*.yaml');
17 | $container->import('../config/{packages}/'.$this->environment.'/*.yaml');
18 |
19 | if (is_file(\dirname(__DIR__).'/config/services.yaml')) {
20 | $container->import('../config/services.yaml');
21 | $container->import('../config/{services}_'.$this->environment.'.yaml');
22 | } elseif (is_file($path = \dirname(__DIR__).'/config/services.php')) {
23 | (require $path)($container->withPath($path), $this);
24 | }
25 | }
26 |
27 | protected function configureRoutes(RoutingConfigurator $routes): void
28 | {
29 | $routes->import('../config/{routes}/'.$this->environment.'/*.yaml');
30 | $routes->import('../config/{routes}/*.yaml');
31 |
32 | if (is_file(\dirname(__DIR__).'/config/routes.yaml')) {
33 | $routes->import('../config/routes.yaml');
34 | } elseif (is_file($path = \dirname(__DIR__).'/config/routes.php')) {
35 | (require $path)($routes->withPath($path), $this);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/.env.dist:
--------------------------------------------------------------------------------
1 | # In all environments, the following files are loaded if they exist,
2 | # the latter taking precedence over the former:
3 | #
4 | # * .env contains default values for the environment variables needed by the app
5 | # * .env.local uncommitted file with local overrides
6 | # * .env.$APP_ENV committed environment-specific defaults
7 | # * .env.$APP_ENV.local uncommitted environment-specific overrides
8 | #
9 | # Real environment variables win over .env files.
10 | #
11 | # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
12 | #
13 | # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
14 | # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
15 |
16 | ###> symfony/framework-bundle ###
17 | APP_ENV=dev
18 | APP_SECRET=ca69f36ecdc0a6dfad72471ddb5336df
19 | ###< symfony/framework-bundle ###
20 |
21 | ###> symfony/mailer ###
22 | # MAILER_DSN=smtp://localhost
23 | ###< symfony/mailer ###
24 |
25 | ###> doctrine/doctrine-bundle ###
26 | # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
27 | # IMPORTANT: DATABASE_URL *must* define the server version
28 | #
29 | # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
30 | DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7"
31 | #DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8"
32 | ###< doctrine/doctrine-bundle ###
33 |
--------------------------------------------------------------------------------
/src/Repository/DistributionRepository.php:
--------------------------------------------------------------------------------
1 | createQueryBuilder('d')
29 | ->andWhere('d.exampleField = :val')
30 | ->setParameter('val', $value)
31 | ->orderBy('d.id', 'ASC')
32 | ->setMaxResults(10)
33 | ->getQuery()
34 | ->getResult()
35 | ;
36 | }
37 | */
38 |
39 | /*
40 | public function findOneBySomeField($value): ?Distribution
41 | {
42 | return $this->createQueryBuilder('d')
43 | ->andWhere('d.exampleField = :val')
44 | ->setParameter('val', $value)
45 | ->getQuery()
46 | ->getOneOrNullResult()
47 | ;
48 | }
49 | */
50 | }
51 |
--------------------------------------------------------------------------------
/migrations/Version20210510155228.php:
--------------------------------------------------------------------------------
1 | addSql('CREATE TABLE dataset (id INT AUTO_INCREMENT NOT NULL, country_code VARCHAR(255) NOT NULL, description_en VARCHAR(255) DEFAULT NULL, description_de VARCHAR(255) DEFAULT NULL, description_fr VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
24 | $this->addSql('CREATE TABLE distribution (id INT AUTO_INCREMENT NOT NULL, dataset_id INT NOT NULL, format VARCHAR(255) NOT NULL, download_url VARCHAR(255) NOT NULL, INDEX IDX_A4483781D47C2D1B (dataset_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
25 | $this->addSql('ALTER TABLE distribution ADD CONSTRAINT FK_A4483781D47C2D1B FOREIGN KEY (dataset_id) REFERENCES dataset (id)');
26 | }
27 |
28 | public function down(Schema $schema): void
29 | {
30 | // this down() migration is auto-generated, please modify it to your needs
31 | $this->addSql('ALTER TABLE distribution DROP FOREIGN KEY FK_A4483781D47C2D1B');
32 | $this->addSql('DROP TABLE dataset');
33 | $this->addSql('DROP TABLE distribution');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Repository/DatasetRepository.php:
--------------------------------------------------------------------------------
1 | findBy([], ['id' => 'desc']));
26 | }
27 |
28 | // /**
29 | // * @return Dataset[] Returns an array of Dataset objects
30 | // */
31 | /*
32 | public function findByExampleField($value)
33 | {
34 | return $this->createQueryBuilder('d')
35 | ->andWhere('d.exampleField = :val')
36 | ->setParameter('val', $value)
37 | ->orderBy('d.id', 'ASC')
38 | ->setMaxResults(10)
39 | ->getQuery()
40 | ->getResult()
41 | ;
42 | }
43 | */
44 |
45 | /*
46 | public function findOneBySomeField($value): ?Dataset
47 | {
48 | return $this->createQueryBuilder('d')
49 | ->andWhere('d.exampleField = :val')
50 | ->setParameter('val', $value)
51 | ->getQuery()
52 | ->getOneOrNullResult()
53 | ;
54 | }
55 | */
56 | }
57 |
--------------------------------------------------------------------------------
/templates/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {% block title %}{% endblock %}
6 |
7 |
8 | {% block stylesheets %}
9 | {% endblock %}
10 |
11 |
12 |
13 |
14 | {% block javascripts %}
15 | {% endblock %}
16 |
17 |
18 |
19 |
20 |
Меню
21 |
22 |
23 |
24 |
34 |
35 |
36 | {% block body %}{% endblock %}
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/Bridge/Common/DataEuDatasetResponseBridge.php:
--------------------------------------------------------------------------------
1 | distributionResponseBridge = $distributionResponseBridge;
21 | $this->logger = $logger;
22 | }
23 |
24 | public function build(DataEuDataset $supplierDataset): Dataset
25 | {
26 | $dataset = new Dataset();
27 |
28 | $dataset->setExternalId($supplierDataset->getId());
29 |
30 | $countryCode = strtoupper($supplierDataset->getCountry()->getId());
31 | $dataset->setCountryCode($countryCode);
32 |
33 | $description = $supplierDataset->getDescription();
34 | $dataset->setDescriptionEn($description->getEn());
35 | $dataset->setDescriptionDe($description->getDe());
36 | $dataset->setDescriptionFr($description->getFr());
37 |
38 | foreach ($supplierDataset->getDistributions() as $supplierDistribution) {
39 | try {
40 | $distribution = $this->distributionResponseBridge->build($supplierDistribution);
41 | $dataset->addDistribution($distribution);
42 | } catch (UnnecessaryDistributionCoreSupplierException $throwable) {
43 | $this->logger->info('Distribution was ignored due to empty download url');
44 | }
45 | }
46 |
47 | return $dataset;
48 | }
49 | }
--------------------------------------------------------------------------------
/src/Controller/SupplierController.php:
--------------------------------------------------------------------------------
1 | requestBuilder = $requestBuilder;
30 | $this->responseBuilder = $responseBuilder;
31 | $this->dataEuSupplierFacade = $dataEuSupplierFacade;
32 | }
33 |
34 | /**
35 | * @Route("/search", name="search", methods={"POST"})
36 | */
37 | public function search(Request $request): Response
38 | {
39 | $data = $request->getContent();
40 | /** @var ApiSearchRequest $searchRequest */
41 | $searchRequest = $this->requestBuilder->build(ApiSearchRequest::class, $data);
42 |
43 | $response = $this->dataEuSupplierFacade->search($searchRequest);
44 |
45 | return $this->responseBuilder->build($response);
46 | }
47 |
48 | /**
49 | * @Route("/get-dataset", name="import_dataset", methods={"POST"})
50 | */
51 | public function getDataset(Request $request): Response
52 | {
53 | $data = $request->getContent();
54 | /** @var ApiGetDatasetRequest $getDatasetRequest */
55 | $getDatasetRequest = $this->requestBuilder->build(ApiGetDatasetRequest::class, $data);
56 |
57 | $response = $this->dataEuSupplierFacade->getDataset($getDatasetRequest);
58 |
59 | return $this->responseBuilder->build($response);
60 | }
61 | }
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/MethodFacade/DataEuSearchMethodFacade.php:
--------------------------------------------------------------------------------
1 | serializer = $serializer;
30 | $this->searchResponseBridge = $searchResponseBridge;
31 | $this->searchRequestBuilder = $searchRequestBuilder;
32 | }
33 |
34 | public function commit(ApiSearchRequest $searchRequest): ApiDatasetsResponse
35 | {
36 | $stringResponse = $this->sendAndGetStringResponse($searchRequest);
37 |
38 | /** @var DataEuSearchResponse $response */
39 | $response = $this->serializer->deserialize($stringResponse, DataEuSearchResponse::class, 'json');
40 | $datasetCollection = $this->searchResponseBridge->build($response);
41 | $totalDatasetsAmount = $response->getResult()->getCount();
42 |
43 | $apiSearchResponse = new ApiDatasetsResponse();
44 | $apiSearchResponse->setDatasetCollection($datasetCollection);
45 | $apiSearchResponse->setTotalDatasetsAmount($totalDatasetsAmount);
46 |
47 | return $apiSearchResponse;
48 | }
49 |
50 | private function sendAndGetStringResponse(ApiSearchRequest $searchRequest): string
51 | {
52 | $client = new Client(['base_uri' => DataEuConst::BASE_URI]);
53 |
54 | $response = $client->get(
55 | 'search',
56 | [
57 | 'query' => $this->searchRequestBuilder->build($searchRequest),
58 | ]
59 | );
60 |
61 | return $response->getBody();
62 | }
63 | }
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 | RewriteEngine On
2 |
3 | Header always add Access-Control-Allow-Origin "*"
4 | Header always add Access-Control-Allow-Headers: "content-type, Referer, Accept, User-Agent"
5 | Header always add Access-Control-Allow-Methods: "POST, GET, OPTIONS, DELETE, PUT"
6 |
7 | # Redirect to URI without front controller to prevent duplicate content
8 | # (with and without `/app.php`). Only do this redirect on the initial
9 | # rewrite by Apache and not on subsequent cycles. Otherwise we would get an
10 | # endless redirect loop (request -> rewrite to front controller ->
11 | # redirect -> request -> ...).
12 | # So in case you get a "too many redirects" error or you always get redirected
13 | # to the startpage because your Apache does not expose the REDIRECT_STATUS
14 | # environment variable, you have 2 choices:
15 | # - disable this feature by commenting the following 2 lines or
16 | # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
17 | # following RewriteCond (best solution)
18 | RewriteCond %{ENV:REDIRECT_STATUS} ^$
19 | RewriteRule ^index\.php(/(.*)|$) %{CONTEXT_PREFIX}/$2 [R=301,L]
20 |
21 | # If the requested filename exists, simply serve it.
22 | # We only want to let Apache serve files and not directories.
23 | RewriteCond %{REQUEST_FILENAME} -f
24 | RewriteRule .? - [L]
25 |
26 | RewriteCond %{REQUEST_METHOD} OPTIONS
27 | RewriteRule ^(.*)$ $1 [R=200,L]
28 |
29 | # cache-bust assets url rewrite
30 | # Example format: /cpv-10/js/test123.js -> /js/test123.js
31 | # This allows us to change the asset version and "bust" intermediate caches (like varnish)
32 | # See http://symfony.com/doc/current/reference/configuration/framework.html#ref-framework-assets-version
33 | # See http://symfony.com/doc/current/reference/configuration/framework.html#assets-version-format
34 | RewriteCond %{REQUEST_FILENAME} !-f
35 | RewriteCond %{REQUEST_FILENAME} !-d
36 | RewriteRule ^cpv-\d+\/(.+)$ $1 [L]
37 |
38 | RewriteCond %{REQUEST_FILENAME} -f
39 | RewriteRule ^(.*)$ index.php [QSA,L]
40 |
41 | # The following rewrites all other queries to the front controller. The
42 | # condition ensures that if you are using Apache aliases to do mass virtual
43 | # hosting, the base path will be prepended to allow proper resolution of the
44 | # app.php file; it will work in non-aliased environments as well, providing
45 | # a safe, one-size fits all solution.
46 | RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
47 | RewriteRule ^(.*) - [E=BASE:%1]
48 | RewriteRule .? %{ENV:BASE}index.php [L]
49 |
--------------------------------------------------------------------------------
/src/Controller/ApiController.php:
--------------------------------------------------------------------------------
1 | requestBuilder = $requestBuilder;
34 | $this->responseBuilder = $responseBuilder;
35 | }
36 |
37 | /**
38 | * @Route("/datasets", name="get_all_datasets", methods={"GET"})
39 | */
40 | public function getAllDatasets(DatasetRepository $datasetRepository): Response
41 | {
42 | $datasets = $datasetRepository->findAll();
43 |
44 | $response = new ApiDatasetsResponse();
45 | $response->setDatasetCollection($datasets);
46 |
47 | return $this->responseBuilder->build($response);
48 | }
49 |
50 | /**
51 | * @Route("/datasets/{id}")
52 | * @ParamConverter("dataset", class="App\Entity\Dataset")
53 | */
54 | public function getDataset(Dataset $dataset): Response
55 | {
56 | $response = new ApiGetDatasetResponse($dataset);
57 |
58 | return $this->responseBuilder->build($response);
59 | }
60 |
61 | /**
62 | * @Route("/datasets", name="get_dataset", methods={"PUT"})
63 | */
64 | public function saveDataset(Request $request, EntityManagerInterface $em): Response
65 | {
66 | $data = $request->getContent();
67 | /** @var ApiDatasetRequest $requestObj */
68 | $requestObj = $this->requestBuilder->build(ApiDatasetRequest::class, $data);
69 | $dataset = $requestObj->getDataset();
70 |
71 | $em->persist($dataset);
72 | $em->flush();
73 |
74 | $response = new ApiSuccessResponse();
75 |
76 | return $this->responseBuilder->build($response);
77 | }
78 | }
--------------------------------------------------------------------------------
/public/assets/js/import.js:
--------------------------------------------------------------------------------
1 | const perPage = 15;
2 | let page = 1;
3 | let query = null;
4 |
5 | $(document).ready(function () {
6 | $('#search-button').click(function () {
7 | query = $('#search-input').val();
8 | loadDatasets();
9 | });
10 |
11 | $(document).on('click', '.dataset-import-button', function () {
12 | const externalId = $(this).closest('tr').data('external_id');
13 |
14 | fetch('/api/import-dataset', {
15 | method: 'POST',
16 | headers: {
17 | 'Content-Type': 'application/json;charset=utf-8'
18 | },
19 | body: JSON.stringify({
20 | 'external_id': externalId
21 | })
22 | }).then(function (response) {
23 | if (response.status === 200) {
24 | alert('Successfully imported')
25 | }
26 | })
27 | });
28 |
29 | $('#next-button').click(() => changePage(1));
30 | $('#prev-button').click(() => changePage(-1));
31 | });
32 |
33 | async function loadDatasets() {
34 | const response = await fetch('/api/search', {
35 | method: 'POST',
36 | headers: {
37 | 'Content-Type': 'application/json;charset=utf-8'
38 | },
39 | body: JSON.stringify({
40 | 'query': query,
41 | 'page': page,
42 | 'per_page': perPage
43 | })
44 | });
45 |
46 | const result = await response.json();
47 | const datasetsTbody = $('#datasets-table tbody');
48 | datasetsTbody.empty();
49 | result.dataset_collection.forEach(function (elem, index) {
50 | datasetsTbody.append(`
51 | ${index + 1}
52 | ${elem.country_code}
53 | ${elem.description_en || 'N/A'}
54 | ${elem.description_de || 'N/A'}
55 | ${elem.description_fr || 'N/A'}
56 | ${getDistributionsString(elem.distributions)}
57 | Імпорт
58 | `);
59 | });
60 |
61 | $('#page-number').html(page);
62 | }
63 |
64 | function getDistributionsString(distributions) {
65 | let result = [];
66 |
67 | distributions.forEach(function (elem) {
68 | result.push(`${elem.format} `);
69 | })
70 |
71 | return result.join(', ');
72 | }
73 |
74 | function changePage(pageIncrement) {
75 | page += pageIncrement;
76 | loadDatasets();
77 | }
--------------------------------------------------------------------------------
/src/Entity/Distribution.php:
--------------------------------------------------------------------------------
1 | id;
54 | }
55 |
56 | public function getFormat(): ?string
57 | {
58 | return $this->format;
59 | }
60 |
61 | public function setFormat(string $format): self
62 | {
63 | $this->format = $format;
64 |
65 | return $this;
66 | }
67 |
68 | public function getDownloadUrl(): ?string
69 | {
70 | return $this->downloadUrl;
71 | }
72 |
73 | public function setDownloadUrl(string $downloadUrl): self
74 | {
75 | $this->downloadUrl = $downloadUrl;
76 |
77 | return $this;
78 | }
79 |
80 | public function getDataset(): Dataset
81 | {
82 | return $this->dataset;
83 | }
84 |
85 | public function setDataset(Dataset $dataset): self
86 | {
87 | $this->dataset = $dataset;
88 |
89 | return $this;
90 | }
91 |
92 | public function getPayload(): ?string
93 | {
94 | return $this->payload;
95 | }
96 |
97 | public function setPayload(string $payload): void
98 | {
99 | $this->payload = $payload;
100 | }
101 |
102 | public function getExternalId(): string
103 | {
104 | return $this->externalId;
105 | }
106 |
107 | public function setExternalId(string $externalId): void
108 | {
109 | $this->externalId = $externalId;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "project",
3 | "license": "proprietary",
4 | "minimum-stability": "dev",
5 | "prefer-stable": true,
6 | "require": {
7 | "php": ">=7.2.5",
8 | "ext-ctype": "*",
9 | "ext-iconv": "*",
10 | "composer/package-versions-deprecated": "1.11.99.1",
11 | "doctrine/annotations": "^1.0",
12 | "doctrine/doctrine-bundle": "^2.3",
13 | "doctrine/doctrine-migrations-bundle": "^3.1",
14 | "doctrine/orm": "^2.8",
15 | "guzzlehttp/guzzle": "^7.3",
16 | "jms/serializer-bundle": "^3.9.0",
17 | "phpdocumentor/reflection-docblock": "^5.2",
18 | "sensio/framework-extra-bundle": "^5.1",
19 | "symfony/asset": "5.2.*",
20 | "symfony/console": "5.2.*",
21 | "symfony/dotenv": "5.2.*",
22 | "symfony/expression-language": "5.2.*",
23 | "symfony/flex": "^1.3.1",
24 | "symfony/form": "5.2.*",
25 | "symfony/framework-bundle": "5.2.*",
26 | "symfony/http-client": "5.2.*",
27 | "symfony/intl": "5.2.*",
28 | "symfony/mailer": "5.2.*",
29 | "symfony/mime": "5.2.*",
30 | "symfony/monolog-bundle": "^3.1",
31 | "symfony/notifier": "5.2.*",
32 | "symfony/process": "5.2.*",
33 | "symfony/property-access": "5.2.*",
34 | "symfony/property-info": "5.2.*",
35 | "symfony/proxy-manager-bridge": "5.2.*",
36 | "symfony/security-bundle": "5.2.*",
37 | "symfony/serializer": "5.2.*",
38 | "symfony/string": "5.2.*",
39 | "symfony/translation": "5.2.*",
40 | "symfony/twig-bundle": "^5.2",
41 | "symfony/validator": "5.2.*",
42 | "symfony/web-link": "5.2.*",
43 | "symfony/yaml": "5.2.*",
44 | "twig/extra-bundle": "^2.12|^3.0",
45 | "twig/twig": "^2.12|^3.0",
46 | "ext-json": "*"
47 | },
48 | "require-dev": {
49 | "symfony/browser-kit": "^5.2",
50 | "symfony/css-selector": "^5.2",
51 | "symfony/debug-bundle": "^5.2",
52 | "symfony/maker-bundle": "^1.0",
53 | "symfony/phpunit-bridge": "^5.2",
54 | "symfony/stopwatch": "^5.2",
55 | "symfony/var-dumper": "^5.2",
56 | "symfony/web-profiler-bundle": "^5.2"
57 | },
58 | "config": {
59 | "optimize-autoloader": true,
60 | "preferred-install": {
61 | "*": "dist"
62 | },
63 | "sort-packages": true
64 | },
65 | "autoload": {
66 | "psr-4": {
67 | "App\\": "src/"
68 | }
69 | },
70 | "autoload-dev": {
71 | "psr-4": {
72 | "App\\Tests\\": "tests/"
73 | }
74 | },
75 | "replace": {
76 | "symfony/polyfill-ctype": "*",
77 | "symfony/polyfill-iconv": "*",
78 | "symfony/polyfill-php72": "*"
79 | },
80 | "scripts": {
81 | "auto-scripts": {
82 | "cache:clear": "symfony-cmd",
83 | "assets:install %PUBLIC_DIR%": "symfony-cmd"
84 | },
85 | "post-install-cmd": [
86 | "@auto-scripts"
87 | ],
88 | "post-update-cmd": [
89 | "@auto-scripts"
90 | ]
91 | },
92 | "conflict": {
93 | "symfony/symfony": "*"
94 | },
95 | "extra": {
96 | "symfony": {
97 | "allow-contrib": false,
98 | "require": "5.2.*"
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Entity/Dataset.php:
--------------------------------------------------------------------------------
1 | ")
58 | */
59 | private Collection $distributions;
60 |
61 | public function __construct()
62 | {
63 | $this->distributions = new ArrayCollection();
64 | }
65 |
66 | public function getId(): ?int
67 | {
68 | return $this->id;
69 | }
70 |
71 | public function getCountryCode(): ?string
72 | {
73 | return $this->countryCode;
74 | }
75 |
76 | public function setCountryCode(string $countryCode): self
77 | {
78 | $this->countryCode = $countryCode;
79 |
80 | return $this;
81 | }
82 |
83 | public function getDescriptionEn(): ?string
84 | {
85 | return $this->descriptionEn;
86 | }
87 |
88 | public function setDescriptionEn(?string $descriptionEn): self
89 | {
90 | $this->descriptionEn = $descriptionEn;
91 |
92 | return $this;
93 | }
94 |
95 | public function getDescriptionDe(): ?string
96 | {
97 | return $this->descriptionDe;
98 | }
99 |
100 | public function setDescriptionDe(?string $descriptionDe): self
101 | {
102 | $this->descriptionDe = $descriptionDe;
103 |
104 | return $this;
105 | }
106 |
107 | public function getDescriptionFr(): ?string
108 | {
109 | return $this->descriptionFr;
110 | }
111 |
112 | public function setDescriptionFr(?string $descriptionFr): self
113 | {
114 | $this->descriptionFr = $descriptionFr;
115 |
116 | return $this;
117 | }
118 |
119 | public function getExternalId(): string
120 | {
121 | return $this->externalId;
122 | }
123 |
124 | public function setExternalId(string $externalId): void
125 | {
126 | $this->externalId = $externalId;
127 | }
128 |
129 | /**
130 | * @return Collection|Distribution[]
131 | */
132 | public function getDistributions(): Collection
133 | {
134 | return $this->distributions;
135 | }
136 |
137 | public function addDistribution(Distribution $distribution): self
138 | {
139 | if (!$this->distributions->contains($distribution)) {
140 | $this->distributions[] = $distribution;
141 | $distribution->setDataset($this);
142 | }
143 |
144 | return $this;
145 | }
146 |
147 | /**
148 | * @ORM\PreFlush()
149 | */
150 | public function doOnPreFlush(): void
151 | {
152 | foreach ($this->getDistributions() as $distribution) {
153 | $distribution->setDataset($this);
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/src/SupplierFacade/DataEu/MethodFacade/DataEuGetDatasetMethodFacade.php:
--------------------------------------------------------------------------------
1 | 'PostmanRuntime/7.26.8'];
26 |
27 | private SerializerInterface $serializer;
28 |
29 | private DataEuGetDatasetResponseBridge $getDatasetResponseBridge;
30 |
31 | private EntityManagerInterface $entityManager;
32 |
33 | public function __construct(
34 | SerializerInterface $serializer,
35 | DataEuGetDatasetResponseBridge $getDatasetResponseBridge,
36 | EntityManagerInterface $entityManager
37 | ) {
38 | $this->serializer = $serializer;
39 | $this->getDatasetResponseBridge = $getDatasetResponseBridge;
40 | $this->entityManager = $entityManager;
41 | }
42 |
43 | public function commit(ApiGetDatasetRequest $getDatasetRequest): ApiSuccessResponse
44 | {
45 | $stringResponse = $this->sendAndGetStringResponse($getDatasetRequest);
46 |
47 | $response = $this->serializer->deserialize($stringResponse, DataEuGetDatasetResponse::class, 'json');
48 | $dataset = $this->getDatasetResponseBridge->build($response);
49 |
50 | $this->loadDistributionPayloads($dataset);
51 |
52 | if ($getDatasetRequest->usePersist()) {
53 | $this->entityManager->persist($dataset);
54 | $this->entityManager->flush();
55 | }
56 |
57 | return new ApiGetDatasetResponse($dataset);
58 | }
59 |
60 | private function sendAndGetStringResponse(ApiGetDatasetRequest $getDatasetRequest): string
61 | {
62 | $client = new Client(['base_uri' => DataEuConst::BASE_URI]);
63 |
64 | $uri = sprintf(self::URI_PATTERN, $getDatasetRequest->getExternalId());
65 | $response = $client->get($uri);
66 |
67 | return $response->getBody();
68 | }
69 |
70 | private function loadDistributionPayloads(Dataset $dataset): void
71 | {
72 | $client = new Client();
73 | $promises = [];
74 |
75 | foreach ($dataset->getDistributions() as $distribution) {
76 | $promises[$distribution->getExternalId()] = $client->getAsync($distribution->getDownloadUrl(), ['headers' => self::DOWNLOAD_HEADERS]);
77 | }
78 |
79 | $responses = Promise\Utils::settle($promises)->wait();
80 |
81 | foreach ($dataset->getDistributions() as $distribution) {
82 | try {
83 | $content = $this->getResponseContent($responses[$distribution->getExternalId()]);
84 | $distribution->setPayload($content);
85 | } catch (UnexpectedValueException $exception) {
86 | $dataset->getDistributions()->removeElement($distribution);
87 | }
88 | }
89 | }
90 |
91 | private function getResponseContent(array $response): string
92 | {
93 | $responseState = $response['state'];
94 | if ($responseState !== Promise\Promise::FULFILLED) {
95 | throw new UnexpectedValueException();
96 | }
97 |
98 | /** @var Response $responseObj */
99 | $responseObj = $response['value'];
100 | $body = $responseObj->getBody();
101 | if (!$body) {
102 | throw new UnexpectedValueException();
103 | }
104 |
105 | $content = $body->getContents();
106 | if (mb_detect_encoding($content, null, true) === false) {
107 | throw new UnexpectedValueException();
108 | }
109 |
110 | return $content;
111 | }
112 | }
--------------------------------------------------------------------------------
/public/assets/lib/bootstrap/css/bootstrap-reboot.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */
--------------------------------------------------------------------------------
/public/assets/lib/bootstrap/css/bootstrap-reboot.rtl.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}
8 | /*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */
--------------------------------------------------------------------------------
/src/Base/AbstractCollection.php:
--------------------------------------------------------------------------------
1 | validateElement($element);
24 | }
25 | $this->elements = $elements;
26 | }
27 |
28 | protected function validateElement($element): void
29 | {
30 | if (!$this->isValidElement($element)) {
31 | $this->throwInvalidObjectClassException($element);
32 | }
33 | }
34 |
35 | protected function isValidElement($element): bool
36 | {
37 | $typeName = $this->getTypeName();
38 |
39 | if ($typeName === "string") {
40 | return is_string($element);
41 | }
42 |
43 | return $element instanceof $typeName;
44 | }
45 |
46 | protected function throwInvalidObjectClassException($invalidElementData): void
47 | {
48 | $errorMessage = sprintf(
49 | self::ELEMENT_TYPE_MISMATCHED_TEMPLATE,
50 | $this->getTypeName(),
51 | gettype($invalidElementData),
52 | var_export($invalidElementData, true)
53 | );
54 | throw new InvalidArgumentException($errorMessage);
55 | }
56 |
57 | public function addCollection(AbstractCollection $collectionToMerge): void
58 | {
59 | foreach ($collectionToMerge as $item) {
60 | $this->add($item);
61 | }
62 | }
63 |
64 | public function add($element): void
65 | {
66 | $this->validateElement($element);
67 | $this->elements[] = $element;
68 | }
69 |
70 | public function set(string $key, $element): void
71 | {
72 | $this->validateElement($element);
73 | $this->elements[$key] = $element;
74 | }
75 |
76 | public function isValid(): bool
77 | {
78 | foreach ($this as $element) {
79 | if (!$this->isValidElement($element)) {
80 | return false;
81 | }
82 | }
83 |
84 | return true;
85 | }
86 |
87 | public function offsetSet($offset, $value): void
88 | {
89 | if (!isset($offset)) {
90 | $this->add($value);
91 |
92 | return;
93 | }
94 |
95 | $this->set($offset, $value);
96 | }
97 |
98 | public function clear(): void
99 | {
100 | $this->elements = [];
101 | }
102 |
103 | public function contains($element): bool
104 | {
105 | return in_array($element, $this->elements, true);
106 | }
107 |
108 | public function filter(Closure $p): AbstractCollection
109 | {
110 | return $this->createFrom(array_filter($this->elements, $p, ARRAY_FILTER_USE_BOTH));
111 | }
112 |
113 | protected function createFrom(array $elements): AbstractCollection
114 | {
115 | return new static($elements);
116 | }
117 |
118 | public function isEmpty(): bool
119 | {
120 | return empty($this->elements);
121 | }
122 |
123 | public function remove($key)
124 | {
125 | if (!isset($this->elements[$key]) && !array_key_exists($key, $this->elements)) {
126 | return null;
127 | }
128 |
129 | $removed = $this->elements[$key];
130 | unset($this->elements[$key]);
131 |
132 | return $removed;
133 | }
134 |
135 | public function removeElement($element): bool
136 | {
137 | $key = array_search($element, $this->elements, true);
138 |
139 | if ($key === false) {
140 | return false;
141 | }
142 |
143 | unset($this->elements[$key]);
144 |
145 | return true;
146 | }
147 |
148 | public function containsKey($key): bool
149 | {
150 | return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
151 | }
152 |
153 | public function get($key)
154 | {
155 | return $this->elements[$key] ?? null;
156 | }
157 |
158 | public function getKeys(): array
159 | {
160 | return array_keys($this->elements);
161 | }
162 |
163 | public function getValues(): array
164 | {
165 | return array_values($this->elements);
166 | }
167 |
168 | public function toArray(): array
169 | {
170 | return $this->elements;
171 | }
172 |
173 | public function key()
174 | {
175 | return key($this->elements);
176 | }
177 |
178 | public function first()
179 | {
180 | $first = reset($this->elements);
181 |
182 | return $first !== false ? $first : null;
183 | }
184 |
185 | public function last()
186 | {
187 | $end = end($this->elements);
188 |
189 | return $end !== false ? $end : null;
190 | }
191 |
192 | public function current()
193 | {
194 | $current = current($this->elements);
195 |
196 | return $current !== false ? $current : null;
197 | }
198 |
199 | public function next()
200 | {
201 | $next = next($this->elements);
202 |
203 | return $next !== false ? $next : null;
204 | }
205 |
206 | public function getIterator(): ArrayIterator
207 | {
208 | return new ArrayIterator($this->elements);
209 | }
210 |
211 | public function offsetExists($offset): bool
212 | {
213 | return $this->containsKey($offset);
214 | }
215 |
216 | public function offsetGet($offset)
217 | {
218 | return $this->get($offset);
219 | }
220 |
221 | public function offsetUnset($offset): void
222 | {
223 | $this->remove($offset);
224 | }
225 |
226 | public function count(): int
227 | {
228 | return count($this->elements);
229 | }
230 | }
--------------------------------------------------------------------------------
/public/assets/lib/bootstrap/css/bootstrap-reboot.rtl.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | *,
9 | *::before,
10 | *::after {
11 | box-sizing: border-box;
12 | }
13 |
14 | @media (prefers-reduced-motion: no-preference) {
15 | :root {
16 | scroll-behavior: smooth;
17 | }
18 | }
19 |
20 | body {
21 | margin: 0;
22 | font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
23 | font-size: 1rem;
24 | font-weight: 400;
25 | line-height: 1.5;
26 | color: #212529;
27 | background-color: #fff;
28 | -webkit-text-size-adjust: 100%;
29 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
30 | }
31 |
32 | hr {
33 | margin: 1rem 0;
34 | color: inherit;
35 | background-color: currentColor;
36 | border: 0;
37 | opacity: 0.25;
38 | }
39 |
40 | hr:not([size]) {
41 | height: 1px;
42 | }
43 |
44 | h6, h5, h4, h3, h2, h1 {
45 | margin-top: 0;
46 | margin-bottom: 0.5rem;
47 | font-weight: 500;
48 | line-height: 1.2;
49 | }
50 |
51 | h1 {
52 | font-size: calc(1.375rem + 1.5vw);
53 | }
54 | @media (min-width: 1200px) {
55 | h1 {
56 | font-size: 2.5rem;
57 | }
58 | }
59 |
60 | h2 {
61 | font-size: calc(1.325rem + 0.9vw);
62 | }
63 | @media (min-width: 1200px) {
64 | h2 {
65 | font-size: 2rem;
66 | }
67 | }
68 |
69 | h3 {
70 | font-size: calc(1.3rem + 0.6vw);
71 | }
72 | @media (min-width: 1200px) {
73 | h3 {
74 | font-size: 1.75rem;
75 | }
76 | }
77 |
78 | h4 {
79 | font-size: calc(1.275rem + 0.3vw);
80 | }
81 | @media (min-width: 1200px) {
82 | h4 {
83 | font-size: 1.5rem;
84 | }
85 | }
86 |
87 | h5 {
88 | font-size: 1.25rem;
89 | }
90 |
91 | h6 {
92 | font-size: 1rem;
93 | }
94 |
95 | p {
96 | margin-top: 0;
97 | margin-bottom: 1rem;
98 | }
99 |
100 | abbr[title],
101 | abbr[data-bs-original-title] {
102 | -webkit-text-decoration: underline dotted;
103 | text-decoration: underline dotted;
104 | cursor: help;
105 | -webkit-text-decoration-skip-ink: none;
106 | text-decoration-skip-ink: none;
107 | }
108 |
109 | address {
110 | margin-bottom: 1rem;
111 | font-style: normal;
112 | line-height: inherit;
113 | }
114 |
115 | ol,
116 | ul {
117 | padding-right: 2rem;
118 | }
119 |
120 | ol,
121 | ul,
122 | dl {
123 | margin-top: 0;
124 | margin-bottom: 1rem;
125 | }
126 |
127 | ol ol,
128 | ul ul,
129 | ol ul,
130 | ul ol {
131 | margin-bottom: 0;
132 | }
133 |
134 | dt {
135 | font-weight: 700;
136 | }
137 |
138 | dd {
139 | margin-bottom: 0.5rem;
140 | margin-right: 0;
141 | }
142 |
143 | blockquote {
144 | margin: 0 0 1rem;
145 | }
146 |
147 | b,
148 | strong {
149 | font-weight: bolder;
150 | }
151 |
152 | small {
153 | font-size: 0.875em;
154 | }
155 |
156 | mark {
157 | padding: 0.2em;
158 | background-color: #fcf8e3;
159 | }
160 |
161 | sub,
162 | sup {
163 | position: relative;
164 | font-size: 0.75em;
165 | line-height: 0;
166 | vertical-align: baseline;
167 | }
168 |
169 | sub {
170 | bottom: -0.25em;
171 | }
172 |
173 | sup {
174 | top: -0.5em;
175 | }
176 |
177 | a {
178 | color: #0d6efd;
179 | text-decoration: underline;
180 | }
181 | a:hover {
182 | color: #0a58ca;
183 | }
184 |
185 | a:not([href]):not([class]), a:not([href]):not([class]):hover {
186 | color: inherit;
187 | text-decoration: none;
188 | }
189 |
190 | pre,
191 | code,
192 | kbd,
193 | samp {
194 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
195 | font-size: 1em;
196 | direction: ltr ;
197 | unicode-bidi: bidi-override;
198 | }
199 |
200 | pre {
201 | display: block;
202 | margin-top: 0;
203 | margin-bottom: 1rem;
204 | overflow: auto;
205 | font-size: 0.875em;
206 | }
207 | pre code {
208 | font-size: inherit;
209 | color: inherit;
210 | word-break: normal;
211 | }
212 |
213 | code {
214 | font-size: 0.875em;
215 | color: #d63384;
216 | word-wrap: break-word;
217 | }
218 | a > code {
219 | color: inherit;
220 | }
221 |
222 | kbd {
223 | padding: 0.2rem 0.4rem;
224 | font-size: 0.875em;
225 | color: #fff;
226 | background-color: #212529;
227 | border-radius: 0.2rem;
228 | }
229 | kbd kbd {
230 | padding: 0;
231 | font-size: 1em;
232 | font-weight: 700;
233 | }
234 |
235 | figure {
236 | margin: 0 0 1rem;
237 | }
238 |
239 | img,
240 | svg {
241 | vertical-align: middle;
242 | }
243 |
244 | table {
245 | caption-side: bottom;
246 | border-collapse: collapse;
247 | }
248 |
249 | caption {
250 | padding-top: 0.5rem;
251 | padding-bottom: 0.5rem;
252 | color: #6c757d;
253 | text-align: right;
254 | }
255 |
256 | th {
257 | text-align: inherit;
258 | text-align: -webkit-match-parent;
259 | }
260 |
261 | thead,
262 | tbody,
263 | tfoot,
264 | tr,
265 | td,
266 | th {
267 | border-color: inherit;
268 | border-style: solid;
269 | border-width: 0;
270 | }
271 |
272 | label {
273 | display: inline-block;
274 | }
275 |
276 | button {
277 | border-radius: 0;
278 | }
279 |
280 | button:focus:not(:focus-visible) {
281 | outline: 0;
282 | }
283 |
284 | input,
285 | button,
286 | select,
287 | optgroup,
288 | textarea {
289 | margin: 0;
290 | font-family: inherit;
291 | font-size: inherit;
292 | line-height: inherit;
293 | }
294 |
295 | button,
296 | select {
297 | text-transform: none;
298 | }
299 |
300 | [role=button] {
301 | cursor: pointer;
302 | }
303 |
304 | select {
305 | word-wrap: normal;
306 | }
307 | select:disabled {
308 | opacity: 1;
309 | }
310 |
311 | [list]::-webkit-calendar-picker-indicator {
312 | display: none;
313 | }
314 |
315 | button,
316 | [type=button],
317 | [type=reset],
318 | [type=submit] {
319 | -webkit-appearance: button;
320 | }
321 | button:not(:disabled),
322 | [type=button]:not(:disabled),
323 | [type=reset]:not(:disabled),
324 | [type=submit]:not(:disabled) {
325 | cursor: pointer;
326 | }
327 |
328 | ::-moz-focus-inner {
329 | padding: 0;
330 | border-style: none;
331 | }
332 |
333 | textarea {
334 | resize: vertical;
335 | }
336 |
337 | fieldset {
338 | min-width: 0;
339 | padding: 0;
340 | margin: 0;
341 | border: 0;
342 | }
343 |
344 | legend {
345 | float: right;
346 | width: 100%;
347 | padding: 0;
348 | margin-bottom: 0.5rem;
349 | font-size: calc(1.275rem + 0.3vw);
350 | line-height: inherit;
351 | }
352 | @media (min-width: 1200px) {
353 | legend {
354 | font-size: 1.5rem;
355 | }
356 | }
357 | legend + * {
358 | clear: right;
359 | }
360 |
361 | ::-webkit-datetime-edit-fields-wrapper,
362 | ::-webkit-datetime-edit-text,
363 | ::-webkit-datetime-edit-minute,
364 | ::-webkit-datetime-edit-hour-field,
365 | ::-webkit-datetime-edit-day-field,
366 | ::-webkit-datetime-edit-month-field,
367 | ::-webkit-datetime-edit-year-field {
368 | padding: 0;
369 | }
370 |
371 | ::-webkit-inner-spin-button {
372 | height: auto;
373 | }
374 |
375 | [type=search] {
376 | outline-offset: -2px;
377 | -webkit-appearance: textfield;
378 | }
379 |
380 | [type="tel"],
381 | [type="url"],
382 | [type="email"],
383 | [type="number"] {
384 | direction: ltr;
385 | }
386 | ::-webkit-search-decoration {
387 | -webkit-appearance: none;
388 | }
389 |
390 | ::-webkit-color-swatch-wrapper {
391 | padding: 0;
392 | }
393 |
394 | ::file-selector-button {
395 | font: inherit;
396 | }
397 |
398 | ::-webkit-file-upload-button {
399 | font: inherit;
400 | -webkit-appearance: button;
401 | }
402 |
403 | output {
404 | display: inline-block;
405 | }
406 |
407 | iframe {
408 | border: 0;
409 | }
410 |
411 | summary {
412 | display: list-item;
413 | cursor: pointer;
414 | }
415 |
416 | progress {
417 | vertical-align: baseline;
418 | }
419 |
420 | [hidden] {
421 | display: none !important;
422 | }
423 | /*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
--------------------------------------------------------------------------------
/public/assets/lib/bootstrap/css/bootstrap-reboot.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)
3 | * Copyright 2011-2021 The Bootstrap Authors
4 | * Copyright 2011-2021 Twitter, Inc.
5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
7 | */
8 | *,
9 | *::before,
10 | *::after {
11 | box-sizing: border-box;
12 | }
13 |
14 | @media (prefers-reduced-motion: no-preference) {
15 | :root {
16 | scroll-behavior: smooth;
17 | }
18 | }
19 |
20 | body {
21 | margin: 0;
22 | font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
23 | font-size: 1rem;
24 | font-weight: 400;
25 | line-height: 1.5;
26 | color: #212529;
27 | background-color: #fff;
28 | -webkit-text-size-adjust: 100%;
29 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
30 | }
31 |
32 | hr {
33 | margin: 1rem 0;
34 | color: inherit;
35 | background-color: currentColor;
36 | border: 0;
37 | opacity: 0.25;
38 | }
39 |
40 | hr:not([size]) {
41 | height: 1px;
42 | }
43 |
44 | h6, h5, h4, h3, h2, h1 {
45 | margin-top: 0;
46 | margin-bottom: 0.5rem;
47 | font-weight: 500;
48 | line-height: 1.2;
49 | }
50 |
51 | h1 {
52 | font-size: calc(1.375rem + 1.5vw);
53 | }
54 | @media (min-width: 1200px) {
55 | h1 {
56 | font-size: 2.5rem;
57 | }
58 | }
59 |
60 | h2 {
61 | font-size: calc(1.325rem + 0.9vw);
62 | }
63 | @media (min-width: 1200px) {
64 | h2 {
65 | font-size: 2rem;
66 | }
67 | }
68 |
69 | h3 {
70 | font-size: calc(1.3rem + 0.6vw);
71 | }
72 | @media (min-width: 1200px) {
73 | h3 {
74 | font-size: 1.75rem;
75 | }
76 | }
77 |
78 | h4 {
79 | font-size: calc(1.275rem + 0.3vw);
80 | }
81 | @media (min-width: 1200px) {
82 | h4 {
83 | font-size: 1.5rem;
84 | }
85 | }
86 |
87 | h5 {
88 | font-size: 1.25rem;
89 | }
90 |
91 | h6 {
92 | font-size: 1rem;
93 | }
94 |
95 | p {
96 | margin-top: 0;
97 | margin-bottom: 1rem;
98 | }
99 |
100 | abbr[title],
101 | abbr[data-bs-original-title] {
102 | -webkit-text-decoration: underline dotted;
103 | text-decoration: underline dotted;
104 | cursor: help;
105 | -webkit-text-decoration-skip-ink: none;
106 | text-decoration-skip-ink: none;
107 | }
108 |
109 | address {
110 | margin-bottom: 1rem;
111 | font-style: normal;
112 | line-height: inherit;
113 | }
114 |
115 | ol,
116 | ul {
117 | padding-left: 2rem;
118 | }
119 |
120 | ol,
121 | ul,
122 | dl {
123 | margin-top: 0;
124 | margin-bottom: 1rem;
125 | }
126 |
127 | ol ol,
128 | ul ul,
129 | ol ul,
130 | ul ol {
131 | margin-bottom: 0;
132 | }
133 |
134 | dt {
135 | font-weight: 700;
136 | }
137 |
138 | dd {
139 | margin-bottom: 0.5rem;
140 | margin-left: 0;
141 | }
142 |
143 | blockquote {
144 | margin: 0 0 1rem;
145 | }
146 |
147 | b,
148 | strong {
149 | font-weight: bolder;
150 | }
151 |
152 | small {
153 | font-size: 0.875em;
154 | }
155 |
156 | mark {
157 | padding: 0.2em;
158 | background-color: #fcf8e3;
159 | }
160 |
161 | sub,
162 | sup {
163 | position: relative;
164 | font-size: 0.75em;
165 | line-height: 0;
166 | vertical-align: baseline;
167 | }
168 |
169 | sub {
170 | bottom: -0.25em;
171 | }
172 |
173 | sup {
174 | top: -0.5em;
175 | }
176 |
177 | a {
178 | color: #0d6efd;
179 | text-decoration: underline;
180 | }
181 | a:hover {
182 | color: #0a58ca;
183 | }
184 |
185 | a:not([href]):not([class]), a:not([href]):not([class]):hover {
186 | color: inherit;
187 | text-decoration: none;
188 | }
189 |
190 | pre,
191 | code,
192 | kbd,
193 | samp {
194 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
195 | font-size: 1em;
196 | direction: ltr /* rtl:ignore */;
197 | unicode-bidi: bidi-override;
198 | }
199 |
200 | pre {
201 | display: block;
202 | margin-top: 0;
203 | margin-bottom: 1rem;
204 | overflow: auto;
205 | font-size: 0.875em;
206 | }
207 | pre code {
208 | font-size: inherit;
209 | color: inherit;
210 | word-break: normal;
211 | }
212 |
213 | code {
214 | font-size: 0.875em;
215 | color: #d63384;
216 | word-wrap: break-word;
217 | }
218 | a > code {
219 | color: inherit;
220 | }
221 |
222 | kbd {
223 | padding: 0.2rem 0.4rem;
224 | font-size: 0.875em;
225 | color: #fff;
226 | background-color: #212529;
227 | border-radius: 0.2rem;
228 | }
229 | kbd kbd {
230 | padding: 0;
231 | font-size: 1em;
232 | font-weight: 700;
233 | }
234 |
235 | figure {
236 | margin: 0 0 1rem;
237 | }
238 |
239 | img,
240 | svg {
241 | vertical-align: middle;
242 | }
243 |
244 | table {
245 | caption-side: bottom;
246 | border-collapse: collapse;
247 | }
248 |
249 | caption {
250 | padding-top: 0.5rem;
251 | padding-bottom: 0.5rem;
252 | color: #6c757d;
253 | text-align: left;
254 | }
255 |
256 | th {
257 | text-align: inherit;
258 | text-align: -webkit-match-parent;
259 | }
260 |
261 | thead,
262 | tbody,
263 | tfoot,
264 | tr,
265 | td,
266 | th {
267 | border-color: inherit;
268 | border-style: solid;
269 | border-width: 0;
270 | }
271 |
272 | label {
273 | display: inline-block;
274 | }
275 |
276 | button {
277 | border-radius: 0;
278 | }
279 |
280 | button:focus:not(:focus-visible) {
281 | outline: 0;
282 | }
283 |
284 | input,
285 | button,
286 | select,
287 | optgroup,
288 | textarea {
289 | margin: 0;
290 | font-family: inherit;
291 | font-size: inherit;
292 | line-height: inherit;
293 | }
294 |
295 | button,
296 | select {
297 | text-transform: none;
298 | }
299 |
300 | [role=button] {
301 | cursor: pointer;
302 | }
303 |
304 | select {
305 | word-wrap: normal;
306 | }
307 | select:disabled {
308 | opacity: 1;
309 | }
310 |
311 | [list]::-webkit-calendar-picker-indicator {
312 | display: none;
313 | }
314 |
315 | button,
316 | [type=button],
317 | [type=reset],
318 | [type=submit] {
319 | -webkit-appearance: button;
320 | }
321 | button:not(:disabled),
322 | [type=button]:not(:disabled),
323 | [type=reset]:not(:disabled),
324 | [type=submit]:not(:disabled) {
325 | cursor: pointer;
326 | }
327 |
328 | ::-moz-focus-inner {
329 | padding: 0;
330 | border-style: none;
331 | }
332 |
333 | textarea {
334 | resize: vertical;
335 | }
336 |
337 | fieldset {
338 | min-width: 0;
339 | padding: 0;
340 | margin: 0;
341 | border: 0;
342 | }
343 |
344 | legend {
345 | float: left;
346 | width: 100%;
347 | padding: 0;
348 | margin-bottom: 0.5rem;
349 | font-size: calc(1.275rem + 0.3vw);
350 | line-height: inherit;
351 | }
352 | @media (min-width: 1200px) {
353 | legend {
354 | font-size: 1.5rem;
355 | }
356 | }
357 | legend + * {
358 | clear: left;
359 | }
360 |
361 | ::-webkit-datetime-edit-fields-wrapper,
362 | ::-webkit-datetime-edit-text,
363 | ::-webkit-datetime-edit-minute,
364 | ::-webkit-datetime-edit-hour-field,
365 | ::-webkit-datetime-edit-day-field,
366 | ::-webkit-datetime-edit-month-field,
367 | ::-webkit-datetime-edit-year-field {
368 | padding: 0;
369 | }
370 |
371 | ::-webkit-inner-spin-button {
372 | height: auto;
373 | }
374 |
375 | [type=search] {
376 | outline-offset: -2px;
377 | -webkit-appearance: textfield;
378 | }
379 |
380 | /* rtl:raw:
381 | [type="tel"],
382 | [type="url"],
383 | [type="email"],
384 | [type="number"] {
385 | direction: ltr;
386 | }
387 | */
388 | ::-webkit-search-decoration {
389 | -webkit-appearance: none;
390 | }
391 |
392 | ::-webkit-color-swatch-wrapper {
393 | padding: 0;
394 | }
395 |
396 | ::file-selector-button {
397 | font: inherit;
398 | }
399 |
400 | ::-webkit-file-upload-button {
401 | font: inherit;
402 | -webkit-appearance: button;
403 | }
404 |
405 | output {
406 | display: inline-block;
407 | }
408 |
409 | iframe {
410 | border: 0;
411 | }
412 |
413 | summary {
414 | display: list-item;
415 | cursor: pointer;
416 | }
417 |
418 | progress {
419 | vertical-align: baseline;
420 | }
421 |
422 | [hidden] {
423 | display: none !important;
424 | }
425 |
426 | /*# sourceMappingURL=bootstrap-reboot.css.map */
--------------------------------------------------------------------------------
/symfony.lock:
--------------------------------------------------------------------------------
1 | {
2 | "composer/package-versions-deprecated": {
3 | "version": "1.11.99.1"
4 | },
5 | "doctrine/annotations": {
6 | "version": "1.0",
7 | "recipe": {
8 | "repo": "github.com/symfony/recipes",
9 | "branch": "master",
10 | "version": "1.0",
11 | "ref": "a2759dd6123694c8d901d0ec80006e044c2e6457"
12 | },
13 | "files": [
14 | "./config/routes/annotations.yaml"
15 | ]
16 | },
17 | "doctrine/cache": {
18 | "version": "1.11.0"
19 | },
20 | "doctrine/collections": {
21 | "version": "1.6.7"
22 | },
23 | "doctrine/common": {
24 | "version": "3.1.2"
25 | },
26 | "doctrine/dbal": {
27 | "version": "2.13.1"
28 | },
29 | "doctrine/deprecations": {
30 | "version": "v0.5.3"
31 | },
32 | "doctrine/doctrine-bundle": {
33 | "version": "2.3",
34 | "recipe": {
35 | "repo": "github.com/symfony/recipes",
36 | "branch": "master",
37 | "version": "2.3",
38 | "ref": "8a111cea2eeca8b427ae227bbbf35f368327a664"
39 | },
40 | "files": [
41 | "./config/packages/doctrine.yaml",
42 | "./config/packages/prod/doctrine.yaml",
43 | "./config/packages/test/doctrine.yaml",
44 | "./src/Entity/.gitignore",
45 | "./src/Repository/.gitignore"
46 | ]
47 | },
48 | "doctrine/doctrine-migrations-bundle": {
49 | "version": "3.1",
50 | "recipe": {
51 | "repo": "github.com/symfony/recipes",
52 | "branch": "master",
53 | "version": "3.1",
54 | "ref": "ee609429c9ee23e22d6fa5728211768f51ed2818"
55 | },
56 | "files": [
57 | "./config/packages/doctrine_migrations.yaml",
58 | "./migrations/.gitignore"
59 | ]
60 | },
61 | "doctrine/event-manager": {
62 | "version": "1.1.1"
63 | },
64 | "doctrine/inflector": {
65 | "version": "2.0.3"
66 | },
67 | "doctrine/instantiator": {
68 | "version": "1.4.0"
69 | },
70 | "doctrine/lexer": {
71 | "version": "1.2.1"
72 | },
73 | "doctrine/migrations": {
74 | "version": "3.1.2"
75 | },
76 | "doctrine/orm": {
77 | "version": "2.8.4"
78 | },
79 | "doctrine/persistence": {
80 | "version": "2.1.0"
81 | },
82 | "doctrine/sql-formatter": {
83 | "version": "1.1.1"
84 | },
85 | "egulias/email-validator": {
86 | "version": "3.1.1"
87 | },
88 | "friendsofphp/proxy-manager-lts": {
89 | "version": "v1.0.3"
90 | },
91 | "guzzlehttp/guzzle": {
92 | "version": "7.3.0"
93 | },
94 | "guzzlehttp/promises": {
95 | "version": "1.4.1"
96 | },
97 | "guzzlehttp/psr7": {
98 | "version": "1.8.2"
99 | },
100 | "jms/metadata": {
101 | "version": "2.5.0"
102 | },
103 | "jms/serializer": {
104 | "version": "3.12.3"
105 | },
106 | "jms/serializer-bundle": {
107 | "version": "3.0",
108 | "recipe": {
109 | "repo": "github.com/symfony/recipes-contrib",
110 | "branch": "master",
111 | "version": "3.0",
112 | "ref": "384cec52df45f3bfd46a09930d6960a58872b268"
113 | },
114 | "files": [
115 | "./config/packages/dev/jms_serializer.yaml",
116 | "./config/packages/jms_serializer.yaml",
117 | "./config/packages/prod/jms_serializer.yaml"
118 | ]
119 | },
120 | "laminas/laminas-code": {
121 | "version": "4.2.2"
122 | },
123 | "laminas/laminas-eventmanager": {
124 | "version": "3.3.1"
125 | },
126 | "laminas/laminas-zendframework-bridge": {
127 | "version": "1.2.0"
128 | },
129 | "monolog/monolog": {
130 | "version": "2.2.0"
131 | },
132 | "nikic/php-parser": {
133 | "version": "v4.10.5"
134 | },
135 | "php": {
136 | "version": "7.4"
137 | },
138 | "phpdocumentor/reflection-common": {
139 | "version": "2.2.0"
140 | },
141 | "phpdocumentor/reflection-docblock": {
142 | "version": "5.2.2"
143 | },
144 | "phpdocumentor/type-resolver": {
145 | "version": "1.4.0"
146 | },
147 | "phpstan/phpdoc-parser": {
148 | "version": "0.5.4"
149 | },
150 | "psr/cache": {
151 | "version": "1.0.1"
152 | },
153 | "psr/container": {
154 | "version": "1.1.1"
155 | },
156 | "psr/event-dispatcher": {
157 | "version": "1.0.0"
158 | },
159 | "psr/http-client": {
160 | "version": "1.0.1"
161 | },
162 | "psr/http-message": {
163 | "version": "1.0.1"
164 | },
165 | "psr/link": {
166 | "version": "1.0.0"
167 | },
168 | "psr/log": {
169 | "version": "1.1.4"
170 | },
171 | "ralouphie/getallheaders": {
172 | "version": "3.0.3"
173 | },
174 | "sensio/framework-extra-bundle": {
175 | "version": "5.2",
176 | "recipe": {
177 | "repo": "github.com/symfony/recipes",
178 | "branch": "master",
179 | "version": "5.2",
180 | "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
181 | },
182 | "files": [
183 | "./config/packages/sensio_framework_extra.yaml"
184 | ]
185 | },
186 | "symfony/asset": {
187 | "version": "v5.2.7"
188 | },
189 | "symfony/browser-kit": {
190 | "version": "v5.2.7"
191 | },
192 | "symfony/cache": {
193 | "version": "v5.2.7"
194 | },
195 | "symfony/cache-contracts": {
196 | "version": "v2.4.0"
197 | },
198 | "symfony/config": {
199 | "version": "v5.2.7"
200 | },
201 | "symfony/console": {
202 | "version": "5.1",
203 | "recipe": {
204 | "repo": "github.com/symfony/recipes",
205 | "branch": "master",
206 | "version": "5.1",
207 | "ref": "c6d02bdfba9da13c22157520e32a602dbee8a75c"
208 | },
209 | "files": [
210 | "./bin/console"
211 | ]
212 | },
213 | "symfony/css-selector": {
214 | "version": "v5.2.7"
215 | },
216 | "symfony/debug-bundle": {
217 | "version": "4.1",
218 | "recipe": {
219 | "repo": "github.com/symfony/recipes",
220 | "branch": "master",
221 | "version": "4.1",
222 | "ref": "0ce7a032d344fb7b661cd25d31914cd703ad445b"
223 | },
224 | "files": [
225 | "./config/packages/dev/debug.yaml"
226 | ]
227 | },
228 | "symfony/debug-pack": {
229 | "version": "v1.0.9"
230 | },
231 | "symfony/dependency-injection": {
232 | "version": "v5.2.7"
233 | },
234 | "symfony/deprecation-contracts": {
235 | "version": "v2.4.0"
236 | },
237 | "symfony/doctrine-bridge": {
238 | "version": "v5.2.7"
239 | },
240 | "symfony/dom-crawler": {
241 | "version": "v5.2.4"
242 | },
243 | "symfony/dotenv": {
244 | "version": "v5.2.4"
245 | },
246 | "symfony/error-handler": {
247 | "version": "v5.2.7"
248 | },
249 | "symfony/event-dispatcher": {
250 | "version": "v5.2.4"
251 | },
252 | "symfony/event-dispatcher-contracts": {
253 | "version": "v2.4.0"
254 | },
255 | "symfony/expression-language": {
256 | "version": "v5.2.7"
257 | },
258 | "symfony/filesystem": {
259 | "version": "v5.2.7"
260 | },
261 | "symfony/finder": {
262 | "version": "v5.2.4"
263 | },
264 | "symfony/flex": {
265 | "version": "1.0",
266 | "recipe": {
267 | "repo": "github.com/symfony/recipes",
268 | "branch": "master",
269 | "version": "1.0",
270 | "ref": "c0eeb50665f0f77226616b6038a9b06c03752d8e"
271 | },
272 | "files": [
273 | "./.env"
274 | ]
275 | },
276 | "symfony/form": {
277 | "version": "v5.2.7"
278 | },
279 | "symfony/framework-bundle": {
280 | "version": "5.2",
281 | "recipe": {
282 | "repo": "github.com/symfony/recipes",
283 | "branch": "master",
284 | "version": "5.2",
285 | "ref": "6ec87563dcc85cd0c48856dcfbfc29610506d250"
286 | },
287 | "files": [
288 | "./config/packages/cache.yaml",
289 | "./config/packages/framework.yaml",
290 | "./config/packages/test/framework.yaml",
291 | "./config/preload.php",
292 | "./config/routes/dev/framework.yaml",
293 | "./config/services.yaml",
294 | "./public/index.php",
295 | "./src/Controller/.gitignore",
296 | "./src/Kernel.php"
297 | ]
298 | },
299 | "symfony/http-client": {
300 | "version": "v5.2.7"
301 | },
302 | "symfony/http-client-contracts": {
303 | "version": "v2.4.0"
304 | },
305 | "symfony/http-foundation": {
306 | "version": "v5.2.7"
307 | },
308 | "symfony/http-kernel": {
309 | "version": "v5.2.7"
310 | },
311 | "symfony/intl": {
312 | "version": "v5.2.7"
313 | },
314 | "symfony/mailer": {
315 | "version": "4.3",
316 | "recipe": {
317 | "repo": "github.com/symfony/recipes",
318 | "branch": "master",
319 | "version": "4.3",
320 | "ref": "15658c2a0176cda2e7dba66276a2030b52bd81b2"
321 | },
322 | "files": [
323 | "./config/packages/mailer.yaml"
324 | ]
325 | },
326 | "symfony/maker-bundle": {
327 | "version": "1.0",
328 | "recipe": {
329 | "repo": "github.com/symfony/recipes",
330 | "branch": "master",
331 | "version": "1.0",
332 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
333 | }
334 | },
335 | "symfony/mime": {
336 | "version": "v5.2.7"
337 | },
338 | "symfony/monolog-bridge": {
339 | "version": "v5.2.7"
340 | },
341 | "symfony/monolog-bundle": {
342 | "version": "3.7",
343 | "recipe": {
344 | "repo": "github.com/symfony/recipes",
345 | "branch": "master",
346 | "version": "3.7",
347 | "ref": "329f6a5ef2e7aa033f802be833ef8d1268dd0848"
348 | },
349 | "files": [
350 | "./config/packages/dev/monolog.yaml",
351 | "./config/packages/prod/deprecations.yaml",
352 | "./config/packages/prod/monolog.yaml",
353 | "./config/packages/test/monolog.yaml"
354 | ]
355 | },
356 | "symfony/notifier": {
357 | "version": "5.0",
358 | "recipe": {
359 | "repo": "github.com/symfony/recipes",
360 | "branch": "master",
361 | "version": "5.0",
362 | "ref": "c31585e252b32fe0e1f30b1f256af553f4a06eb9"
363 | },
364 | "files": [
365 | "./config/packages/notifier.yaml"
366 | ]
367 | },
368 | "symfony/options-resolver": {
369 | "version": "v5.2.4"
370 | },
371 | "symfony/orm-pack": {
372 | "version": "v2.1.0"
373 | },
374 | "symfony/phpunit-bridge": {
375 | "version": "5.1",
376 | "recipe": {
377 | "repo": "github.com/symfony/recipes",
378 | "branch": "master",
379 | "version": "5.1",
380 | "ref": "bf16921ef8309a81d9f046e9b6369c46bcbd031f"
381 | },
382 | "files": [
383 | "./.env.test",
384 | "./bin/phpunit",
385 | "./phpunit.xml.dist",
386 | "./tests/bootstrap.php"
387 | ]
388 | },
389 | "symfony/polyfill-intl-grapheme": {
390 | "version": "v1.22.1"
391 | },
392 | "symfony/polyfill-intl-icu": {
393 | "version": "v1.22.1"
394 | },
395 | "symfony/polyfill-intl-idn": {
396 | "version": "v1.22.1"
397 | },
398 | "symfony/polyfill-intl-normalizer": {
399 | "version": "v1.22.1"
400 | },
401 | "symfony/polyfill-mbstring": {
402 | "version": "v1.22.1"
403 | },
404 | "symfony/polyfill-php73": {
405 | "version": "v1.22.1"
406 | },
407 | "symfony/polyfill-php80": {
408 | "version": "v1.22.1"
409 | },
410 | "symfony/process": {
411 | "version": "v5.2.7"
412 | },
413 | "symfony/profiler-pack": {
414 | "version": "v1.0.5"
415 | },
416 | "symfony/property-access": {
417 | "version": "v5.2.4"
418 | },
419 | "symfony/property-info": {
420 | "version": "v5.2.7"
421 | },
422 | "symfony/proxy-manager-bridge": {
423 | "version": "v5.2.4"
424 | },
425 | "symfony/routing": {
426 | "version": "5.1",
427 | "recipe": {
428 | "repo": "github.com/symfony/recipes",
429 | "branch": "master",
430 | "version": "5.1",
431 | "ref": "b4f3e7c95e38b606eef467e8a42a8408fc460c43"
432 | },
433 | "files": [
434 | "./config/packages/prod/routing.yaml",
435 | "./config/packages/routing.yaml",
436 | "./config/routes.yaml"
437 | ]
438 | },
439 | "symfony/security-bundle": {
440 | "version": "5.1",
441 | "recipe": {
442 | "repo": "github.com/symfony/recipes",
443 | "branch": "master",
444 | "version": "5.1",
445 | "ref": "0a4bae19389d3b9cba1ca0102e3b2bccea724603"
446 | },
447 | "files": [
448 | "./config/packages/security.yaml"
449 | ]
450 | },
451 | "symfony/security-core": {
452 | "version": "v5.2.7"
453 | },
454 | "symfony/security-csrf": {
455 | "version": "v5.2.7"
456 | },
457 | "symfony/security-guard": {
458 | "version": "v5.2.4"
459 | },
460 | "symfony/security-http": {
461 | "version": "v5.2.7"
462 | },
463 | "symfony/serializer": {
464 | "version": "v5.2.7"
465 | },
466 | "symfony/serializer-pack": {
467 | "version": "v1.0.4"
468 | },
469 | "symfony/service-contracts": {
470 | "version": "v2.4.0"
471 | },
472 | "symfony/stopwatch": {
473 | "version": "v5.2.7"
474 | },
475 | "symfony/string": {
476 | "version": "v5.2.6"
477 | },
478 | "symfony/test-pack": {
479 | "version": "v1.0.7"
480 | },
481 | "symfony/translation": {
482 | "version": "3.3",
483 | "recipe": {
484 | "repo": "github.com/symfony/recipes",
485 | "branch": "master",
486 | "version": "3.3",
487 | "ref": "2ad9d2545bce8ca1a863e50e92141f0b9d87ffcd"
488 | },
489 | "files": [
490 | "./config/packages/translation.yaml",
491 | "./translations/.gitignore"
492 | ]
493 | },
494 | "symfony/translation-contracts": {
495 | "version": "v2.4.0"
496 | },
497 | "symfony/twig-bridge": {
498 | "version": "v5.2.7"
499 | },
500 | "symfony/twig-bundle": {
501 | "version": "5.0",
502 | "recipe": {
503 | "repo": "github.com/symfony/recipes",
504 | "branch": "master",
505 | "version": "5.0",
506 | "ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d"
507 | },
508 | "files": [
509 | "./config/packages/test/twig.yaml",
510 | "./config/packages/twig.yaml",
511 | "./templates/base.html.twig"
512 | ]
513 | },
514 | "symfony/twig-pack": {
515 | "version": "v1.0.1"
516 | },
517 | "symfony/validator": {
518 | "version": "4.3",
519 | "recipe": {
520 | "repo": "github.com/symfony/recipes",
521 | "branch": "master",
522 | "version": "4.3",
523 | "ref": "d902da3e4952f18d3bf05aab29512eb61cabd869"
524 | },
525 | "files": [
526 | "./config/packages/test/validator.yaml",
527 | "./config/packages/validator.yaml"
528 | ]
529 | },
530 | "symfony/var-dumper": {
531 | "version": "v5.2.7"
532 | },
533 | "symfony/var-exporter": {
534 | "version": "v5.2.7"
535 | },
536 | "symfony/web-link": {
537 | "version": "v5.2.5"
538 | },
539 | "symfony/web-profiler-bundle": {
540 | "version": "3.3",
541 | "recipe": {
542 | "repo": "github.com/symfony/recipes",
543 | "branch": "master",
544 | "version": "3.3",
545 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
546 | },
547 | "files": [
548 | "./config/packages/dev/web_profiler.yaml",
549 | "./config/packages/test/web_profiler.yaml",
550 | "./config/routes/dev/web_profiler.yaml"
551 | ]
552 | },
553 | "symfony/yaml": {
554 | "version": "v5.2.7"
555 | },
556 | "twbs/bootstrap": {
557 | "version": "v5.0.0"
558 | },
559 | "twig/extra-bundle": {
560 | "version": "v3.3.0"
561 | },
562 | "twig/twig": {
563 | "version": "v3.3.0"
564 | },
565 | "webmozart/assert": {
566 | "version": "1.10.0"
567 | }
568 | }
569 |
--------------------------------------------------------------------------------
/public/assets/lib/bootstrap/css/bootstrap-reboot.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss"],"names":[],"mappings":"AAAA;;;;;;ACeA,ECNA,QADA,SDUE,WAAA,WAaE,8CAJJ,MAKM,gBAAA,QAaN,KACE,OAAA,EACA,YAAA,SAAA,CAAA,aAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,iBAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBE4MI,UAAA,KF1MJ,YAAA,IACA,YAAA,IACA,MAAA,QAEA,iBAAA,KACA,yBAAA,KACA,4BAAA,YASF,GACE,OAAA,KAAA,EACA,MAAA,QACA,iBAAA,aACA,OAAA,EACA,QAAA,IAGF,eACE,OAAA,IAUF,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAGA,YAAA,IACA,YAAA,IAIF,GEkKQ,UAAA,uBAlKJ,0BFAJ,GEyKQ,UAAA,QFpKR,GE6JQ,UAAA,sBAlKJ,0BFKJ,GEoKQ,UAAA,MF/JR,GEwJQ,UAAA,oBAlKJ,0BFUJ,GE+JQ,UAAA,SF1JR,GEmJQ,UAAA,sBAlKJ,0BFeJ,GE0JQ,UAAA,QFrJR,GE0IM,UAAA,QFrIN,GEqIM,UAAA,KF1HN,EACE,WAAA,EACA,cAAA,KC/BF,6BD0CA,YAEE,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,iCAAA,KAAA,yBAAA,KAMF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAMF,GC9CA,GDgDE,aAAA,KC1CF,GD6CA,GC9CA,GDiDE,WAAA,EACA,cAAA,KAGF,MC7CA,MACA,MAFA,MDkDE,cAAA,EAGF,GACE,YAAA,IAKF,GACE,cAAA,MACA,YAAA,EAMF,WACE,OAAA,EAAA,EAAA,KAQF,ECxDA,OD0DE,YAAA,OAQF,MEsCM,UAAA,OF/BN,KACE,QAAA,KACA,iBAAA,QASF,ICtEA,IDwEE,SAAA,SEkBI,UAAA,MFhBJ,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAKN,EACE,MAAA,QACA,gBAAA,UAEA,QACE,MAAA,QAWF,2BAAA,iCAEE,MAAA,QACA,gBAAA,KC1EJ,KACA,IDgFA,IC/EA,KDmFE,YAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UExBI,UAAA,IF0BJ,UAAA,IACA,aAAA,cAOF,IACE,QAAA,MACA,WAAA,EACA,cAAA,KACA,SAAA,KEtCI,UAAA,OF2CJ,SE3CI,UAAA,QF6CF,MAAA,QACA,WAAA,OAIJ,KElDM,UAAA,OFoDJ,MAAA,QACA,UAAA,WAGA,OACE,MAAA,QAIJ,IACE,QAAA,MAAA,ME9DI,UAAA,OFgEJ,MAAA,KACA,iBAAA,QGzSE,cAAA,MH4SF,QACE,QAAA,EErEE,UAAA,IFuEF,YAAA,IASJ,OACE,OAAA,EAAA,EAAA,KAMF,ICnGA,IDqGE,eAAA,OAQF,MACE,aAAA,OACA,gBAAA,SAGF,QACE,YAAA,MACA,eAAA,MACA,MAAA,QACA,WAAA,KAOF,GAEE,WAAA,QACA,WAAA,qBC1GF,MAGA,GAFA,MAGA,GDyGA,MC3GA,GDiHE,aAAA,QACA,aAAA,MACA,aAAA,EAQF,MACE,QAAA,aAMF,OAEE,cAAA,EAQF,iCACE,QAAA,ECxHF,OD6HA,MC3HA,SADA,OAEA,SD+HE,OAAA,EACA,YAAA,QEpKI,UAAA,QFsKJ,YAAA,QAIF,OC9HA,ODgIE,eAAA,KAKF,cACE,OAAA,QAGF,OAGE,UAAA,OAGA,gBACE,QAAA,EAOJ,0CACE,QAAA,KCpIF,cACA,aACA,cD0IA,OAIE,mBAAA,OC1IF,6BACA,4BACA,6BD2II,sBACE,OAAA,QAON,mBACE,QAAA,EACA,aAAA,KAKF,SACE,OAAA,SAUF,SACE,UAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,EAQF,OACE,MAAA,KACA,MAAA,KACA,QAAA,EACA,cAAA,MEzPM,UAAA,sBF4PN,YAAA,QE9ZE,0BFuZJ,OE9OQ,UAAA,QFuPN,SACE,MAAA,KClJJ,kCDyJA,uCC1JA,mCADA,+BAGA,oCAJA,6BAKA,mCD8JE,QAAA,EAGF,4BACE,OAAA,KASF,cACE,eAAA,KACA,mBAAA,UAmBF,4BACE,mBAAA,KAKF,+BACE,QAAA,EAMF,uBACE,KAAA,QAMF,6BACE,KAAA,QACA,mBAAA,OAKF,OACE,QAAA,aAKF,OACE,OAAA,EAOF,QACE,QAAA,UACA,OAAA,QAQF,SACE,eAAA,SAQF,SACE,QAAA","sourcesContent":["/*!\n * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n// Prevent the usage of custom properties since we don't add them to `:root` in reboot\n$font-family-base: $font-family-sans-serif; // stylelint-disable-line scss/dollar-variable-default\n$font-family-code: $font-family-monospace; // stylelint-disable-line scss/dollar-variable-default\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n\n// Root\n//\n// Ability to the value of the root font sizes, affecting the value of `rem`.\n// null by default, thus nothing is generated.\n\n:root {\n font-size: $font-size-root;\n\n @if $enable-smooth-scroll {\n @media (prefers-reduced-motion: no-preference) {\n scroll-behavior: smooth;\n }\n }\n}\n\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Prevent adjustments of font size after orientation changes in iOS.\n// 4. Change the default tap highlight to be completely transparent in iOS.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: $body-text-align;\n background-color: $body-bg; // 2\n -webkit-text-size-adjust: 100%; // 3\n -webkit-tap-highlight-color: rgba($black, 0); // 4\n}\n\n\n// Content grouping\n//\n// 1. Reset Firefox's gray color\n// 2. Set correct height and prevent the `size` attribute to make the `hr` look like an input field\n\nhr {\n margin: $hr-margin-y 0;\n color: $hr-color; // 1\n background-color: currentColor;\n border: 0;\n opacity: $hr-opacity;\n}\n\nhr:not([size]) {\n height: $hr-height; // 2\n}\n\n\n// Typography\n//\n// 1. Remove top margins from headings\n// By default, ``-`` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n\n%heading {\n margin-top: 0; // 1\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-style: $headings-font-style;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1 {\n @extend %heading;\n @include font-size($h1-font-size);\n}\n\nh2 {\n @extend %heading;\n @include font-size($h2-font-size);\n}\n\nh3 {\n @extend %heading;\n @include font-size($h3-font-size);\n}\n\nh4 {\n @extend %heading;\n @include font-size($h4-font-size);\n}\n\nh5 {\n @extend %heading;\n @include font-size($h5-font-size);\n}\n\nh6 {\n @extend %heading;\n @include font-size($h6-font-size);\n}\n\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on ` `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-bs-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-bs-original-title] { // 1\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n text-decoration-skip-ink: none; // 4\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n\n &:hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n direction: ltr #{\"/* rtl:ignore */\"};\n unicode-bidi: bidi-override;\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `
` alignment by inheriting `text-align`.\n// 3. Fix alignment for Safari\n\nth {\n font-weight: $table-th-font-weight; // 1\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\n\n// Forms\n//\n// 1. Allow labels to use `margin` for spacing.\n\nlabel {\n display: inline-block; // 1\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n// See https://github.com/twbs/bootstrap/issues/24093\n\nbutton {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n}\n\n// Explicitly remove focus outline in Chromium when it shouldn't be\n// visible (e.g. as result of mouse click or touch tap). It already\n// should be doing this automatically, but seems to currently be\n// confused and applies its very visible two-tone outline anyway.\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\n// 1. Remove the margin in Firefox and Safari\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // 1\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\n// Remove the inheritance of text transform in Firefox\nbutton,\nselect {\n text-transform: none;\n}\n// Set the cursor for non-`` buttons\n//\n// Details at https://github.com/twbs/bootstrap/pull/30562\n[role=\"button\"] {\n cursor: pointer;\n}\n\nselect {\n // Remove the inheritance of word-wrap in Safari.\n // See https://github.com/twbs/bootstrap/issues/24990\n word-wrap: normal;\n\n // Undo the opacity change from Chrome\n &:disabled {\n opacity: 1;\n }\n}\n\n// Remove the dropdown arrow in Chrome from inputs built with datalists.\n// See https://stackoverflow.com/a/54997118\n\n[list]::-webkit-calendar-picker-indicator {\n display: none;\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\n// 3. Opinionated: add \"hand\" cursor to non-disabled button elements.\n\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n\n @if $enable-button-pointers {\n &:not(:disabled) {\n cursor: pointer; // 3\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\n\n::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\n// 1. Textareas should really only resize vertically so they don't break their (horizontal) containers.\n\ntextarea {\n resize: vertical; // 1\n}\n\n// 1. Browsers set a default `min-width: min-content;` on fieldsets,\n// unlike e.g. ``s, which have `min-width: 0;` by default.\n// So we reset that to ensure fieldsets behave more like a standard block element.\n// See https://github.com/twbs/bootstrap/issues/12359\n// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n// 2. Reset the default outline behavior of fieldsets so they don't affect page layout.\n\nfieldset {\n min-width: 0; // 1\n padding: 0; // 2\n margin: 0; // 2\n border: 0; // 2\n}\n\n// 1. By using `float: left`, the legend will behave like a block element.\n// This way the border of a fieldset wraps around the legend if present.\n// 2. Fix wrapping bug.\n// See https://github.com/twbs/bootstrap/issues/29712\n\nlegend {\n float: left; // 1\n width: 100%;\n padding: 0;\n margin-bottom: $legend-margin-bottom;\n @include font-size($legend-font-size);\n font-weight: $legend-font-weight;\n line-height: inherit;\n\n + * {\n clear: left; // 2\n }\n}\n\n// Fix height of inputs with a type of datetime-local, date, month, week, or time\n// See https://github.com/twbs/bootstrap/issues/18842\n\n::-webkit-datetime-edit-fields-wrapper,\n::-webkit-datetime-edit-text,\n::-webkit-datetime-edit-minute,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-year-field {\n padding: 0;\n}\n\n::-webkit-inner-spin-button {\n height: auto;\n}\n\n// 1. Correct the outline style in Safari.\n// 2. This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\n[type=\"search\"] {\n outline-offset: -2px; // 1\n -webkit-appearance: textfield; // 2\n}\n\n// 1. A few input types should stay LTR\n// See https://rtlstyling.com/posts/rtl-styling#form-inputs\n// 2. RTL only output\n// See https://rtlcss.com/learn/usage-guide/control-directives/#raw\n\n/* rtl:raw:\n[type=\"tel\"],\n[type=\"url\"],\n[type=\"email\"],\n[type=\"number\"] {\n direction: ltr;\n}\n*/\n\n// Remove the inner padding in Chrome and Safari on macOS.\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n// Remove padding around color pickers in webkit browsers\n\n::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n\n// Inherit font family and line height for file input buttons\n\n::file-selector-button {\n font: inherit;\n}\n\n// 1. Change font properties to `inherit`\n// 2. Correct the inability to style clickable types in iOS and Safari.\n\n::-webkit-file-upload-button {\n font: inherit; // 1\n -webkit-appearance: button; // 2\n}\n\n// Correct element displays\n\noutput {\n display: inline-block;\n}\n\n// Remove border from iframe\n\niframe {\n border: 0;\n}\n\n// Summary\n//\n// 1. Add the correct display in all browsers\n\nsummary {\n display: list-item; // 1\n cursor: pointer;\n}\n\n\n// Progress\n//\n// Add the correct vertical alignment in Chrome, Firefox, and Opera.\n\nprogress {\n vertical-align: baseline;\n}\n\n\n// Hidden attribute\n//\n// Always hide an element with the `hidden` HTML attribute.\n\n[hidden] {\n display: none !important;\n}\n","/*!\n * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n :root {\n scroll-behavior: smooth;\n }\n}\n\nbody {\n margin: 0;\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", \"Liberation Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n background-color: #fff;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nhr {\n margin: 1rem 0;\n color: inherit;\n background-color: currentColor;\n border: 0;\n opacity: 0.25;\n}\n\nhr:not([size]) {\n height: 1px;\n}\n\nh6, h5, h4, h3, h2, h1 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n font-weight: 500;\n line-height: 1.2;\n}\n\nh1 {\n font-size: calc(1.375rem + 1.5vw);\n}\n@media (min-width: 1200px) {\n h1 {\n font-size: 2.5rem;\n }\n}\n\nh2 {\n font-size: calc(1.325rem + 0.9vw);\n}\n@media (min-width: 1200px) {\n h2 {\n font-size: 2rem;\n }\n}\n\nh3 {\n font-size: calc(1.3rem + 0.6vw);\n}\n@media (min-width: 1200px) {\n h3 {\n font-size: 1.75rem;\n }\n}\n\nh4 {\n font-size: calc(1.275rem + 0.3vw);\n}\n@media (min-width: 1200px) {\n h4 {\n font-size: 1.5rem;\n }\n}\n\nh5 {\n font-size: 1.25rem;\n}\n\nh6 {\n font-size: 1rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-bs-original-title] {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n -webkit-text-decoration-skip-ink: none;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: 0.5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 0.875em;\n}\n\nmark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 0.75em;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\na {\n color: #0d6efd;\n text-decoration: underline;\n}\na:hover {\n color: #0a58ca;\n}\n\na:not([href]):not([class]), a:not([href]):not([class]):hover {\n color: inherit;\n text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n direction: ltr /* rtl:ignore */;\n unicode-bidi: bidi-override;\n}\n\npre {\n display: block;\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n font-size: 0.875em;\n}\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\ncode {\n font-size: 0.875em;\n color: #d63384;\n word-wrap: break-word;\n}\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 0.875em;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\nkbd kbd {\n padding: 0;\n font-size: 1em;\n font-weight: 700;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n color: #6c757d;\n text-align: left;\n}\n\nth {\n text-align: inherit;\n text-align: -webkit-match-parent;\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\nlabel {\n display: inline-block;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\n[role=button] {\n cursor: pointer;\n}\n\nselect {\n word-wrap: normal;\n}\nselect:disabled {\n opacity: 1;\n}\n\n[list]::-webkit-calendar-picker-indicator {\n display: none;\n}\n\nbutton,\n[type=button],\n[type=reset],\n[type=submit] {\n -webkit-appearance: button;\n}\nbutton:not(:disabled),\n[type=button]:not(:disabled),\n[type=reset]:not(:disabled),\n[type=submit]:not(:disabled) {\n cursor: pointer;\n}\n\n::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ntextarea {\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n float: left;\n width: 100%;\n padding: 0;\n margin-bottom: 0.5rem;\n font-size: calc(1.275rem + 0.3vw);\n line-height: inherit;\n}\n@media (min-width: 1200px) {\n legend {\n font-size: 1.5rem;\n }\n}\nlegend + * {\n clear: left;\n}\n\n::-webkit-datetime-edit-fields-wrapper,\n::-webkit-datetime-edit-text,\n::-webkit-datetime-edit-minute,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-year-field {\n padding: 0;\n}\n\n::-webkit-inner-spin-button {\n height: auto;\n}\n\n[type=search] {\n outline-offset: -2px;\n -webkit-appearance: textfield;\n}\n\n/* rtl:raw:\n[type=\"tel\"],\n[type=\"url\"],\n[type=\"email\"],\n[type=\"number\"] {\n direction: ltr;\n}\n*/\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n::file-selector-button {\n font: inherit;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\niframe {\n border: 0;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated responsive values for font sizes, paddings, margins and much more\n//\n// Licensed under MIT (https://github.com/twbs/rfs/blob/master/LICENSE)\n\n// Configuration\n\n// Base value\n$rfs-base-value: 1.25rem !default;\n$rfs-unit: rem !default;\n\n@if $rfs-unit != rem and $rfs-unit != px {\n @error \"`#{$rfs-unit}` is not a valid unit for $rfs-unit. Use `px` or `rem`.\";\n}\n\n// Breakpoint at where values start decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n@if $rfs-breakpoint-unit != px and $rfs-breakpoint-unit != em and $rfs-breakpoint-unit != rem {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n}\n\n// Resize values based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != number or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Mode. Possibilities: \"min-media-query\", \"max-media-query\"\n$rfs-mode: min-media-query !default;\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-rfs to false\n$enable-rfs: true !default;\n\n// Cache $rfs-base-value unit\n$rfs-base-value-unit: unit($rfs-base-value);\n\n// Remove px-unit from $rfs-base-value for calculations\n@if $rfs-base-value-unit == px {\n $rfs-base-value: $rfs-base-value / ($rfs-base-value * 0 + 1);\n}\n@else if $rfs-base-value-unit == rem {\n $rfs-base-value: $rfs-base-value / ($rfs-base-value * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == px {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == rem or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Calculate the media query value\n$rfs-mq-value: if($rfs-breakpoint-unit == px, #{$rfs-breakpoint}px, #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit});\n$rfs-mq-property-width: if($rfs-mode == max-media-query, max-width, min-width);\n$rfs-mq-property-height: if($rfs-mode == max-media-query, max-height, min-height);\n\n// Internal mixin used to determine which media query needs to be used\n@mixin _rfs-media-query {\n @if $rfs-two-dimensional {\n @if $rfs-mode == max-media-query {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}), (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {\n @content;\n }\n }\n @else {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) and (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {\n @content;\n }\n }\n }\n @else {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) {\n @content;\n }\n }\n}\n\n// Internal mixin that adds disable classes to the selector if needed.\n@mixin _rfs-rule {\n @if $rfs-class == disable and $rfs-mode == max-media-query {\n // Adding an extra class increases specificity, which prevents the media query to override the property\n &,\n .disable-rfs &,\n &.disable-rfs {\n @content;\n }\n }\n @else if $rfs-class == enable and $rfs-mode == min-media-query {\n .enable-rfs &,\n &.enable-rfs {\n @content;\n }\n }\n @else {\n @content;\n }\n}\n\n// Internal mixin that adds enable classes to the selector if needed.\n@mixin _rfs-media-query-rule {\n\n @if $rfs-class == enable {\n @if $rfs-mode == min-media-query {\n @content;\n }\n\n @include _rfs-media-query {\n .enable-rfs &,\n &.enable-rfs {\n @content;\n }\n }\n }\n @else {\n @if $rfs-class == disable and $rfs-mode == min-media-query {\n .disable-rfs &,\n &.disable-rfs {\n @content;\n }\n }\n @include _rfs-media-query {\n @content;\n }\n }\n}\n\n// Helper function to get the formatted non-responsive value\n@function rfs-value($values) {\n // Convert to list\n $values: if(type-of($values) != list, ($values,), $values);\n\n $val: '';\n\n // Loop over each value and calculate value\n @each $value in $values {\n @if $value == 0 {\n $val: $val + ' 0';\n }\n @else {\n // Cache $value unit\n $unit: if(type-of($value) == \"number\", unit($value), false);\n\n @if $unit == px {\n // Convert to rem if needed\n $val: $val + ' ' + if($rfs-unit == rem, #{$value / ($value * 0 + $rfs-rem-value)}rem, $value);\n }\n @else if $unit == rem {\n // Convert to px if needed\n $val: $val + ' ' + if($rfs-unit == px, #{$value / ($value * 0 + 1) * $rfs-rem-value}px, $value);\n }\n @else {\n // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n $val: $val + ' ' + $value;\n }\n }\n }\n\n // Remove first space\n @return unquote(str-slice($val, 2));\n}\n\n// Helper function to get the responsive value calculated by RFS\n@function rfs-fluid-value($values) {\n // Convert to list\n $values: if(type-of($values) != list, ($values,), $values);\n\n $val: '';\n\n // Loop over each value and calculate value\n @each $value in $values {\n @if $value == 0 {\n $val: $val + ' 0';\n }\n\n @else {\n // Cache $value unit\n $unit: if(type-of($value) == \"number\", unit($value), false);\n\n // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $unit or $unit != px and $unit != rem {\n $val: $val + ' ' + $value;\n }\n\n @else {\n // Remove unit from $value for calculations\n $value: $value / ($value * 0 + if($unit == px, 1, 1 / $rfs-rem-value));\n\n // Only add the media query if the value is greater than the minimum value\n @if abs($value) <= $rfs-base-value or not $enable-rfs {\n $val: $val + ' ' + if($rfs-unit == rem, #{$value / $rfs-rem-value}rem, #{$value}px);\n }\n @else {\n // Calculate the minimum value\n $value-min: $rfs-base-value + (abs($value) - $rfs-base-value) / $rfs-factor;\n\n // Calculate difference between $value and the minimum value\n $value-diff: abs($value) - $value-min;\n\n // Base value formatting\n $min-width: if($rfs-unit == rem, #{$value-min / $rfs-rem-value}rem, #{$value-min}px);\n\n // Use negative value if needed\n $min-width: if($value < 0, -$min-width, $min-width);\n\n // Use `vmin` if two-dimensional is enabled\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$value-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Return the calculated value\n $val: $val + ' calc(' + $min-width + if($value < 0, ' - ', ' + ') + $variable-width + ')';\n }\n }\n }\n }\n\n // Remove first space\n @return unquote(str-slice($val, 2));\n}\n\n// RFS mixin\n@mixin rfs($values, $property: font-size) {\n @if $values != null {\n $val: rfs-value($values);\n $fluidVal: rfs-fluid-value($values);\n\n // Do not print the media query if responsive & non-responsive values are the same\n @if $val == $fluidVal {\n #{$property}: $val;\n }\n @else {\n @include _rfs-rule {\n #{$property}: if($rfs-mode == max-media-query, $val, $fluidVal);\n\n // Include safari iframe resize fix if needed\n min-width: if($rfs-safari-iframe-resize-bug-fix, (0 * 1vw), null);\n }\n\n @include _rfs-media-query-rule {\n #{$property}: if($rfs-mode == max-media-query, $fluidVal, $val);\n }\n }\n }\n}\n\n// Shorthand helper mixins\n@mixin font-size($value) {\n @include rfs($value);\n}\n\n@mixin padding($value) {\n @include rfs($value, padding);\n}\n\n@mixin padding-top($value) {\n @include rfs($value, padding-top);\n}\n\n@mixin padding-right($value) {\n @include rfs($value, padding-right);\n}\n\n@mixin padding-bottom($value) {\n @include rfs($value, padding-bottom);\n}\n\n@mixin padding-left($value) {\n @include rfs($value, padding-left);\n}\n\n@mixin margin($value) {\n @include rfs($value, margin);\n}\n\n@mixin margin-top($value) {\n @include rfs($value, margin-top);\n}\n\n@mixin margin-right($value) {\n @include rfs($value, margin-right);\n}\n\n@mixin margin-bottom($value) {\n @include rfs($value, margin-bottom);\n}\n\n@mixin margin-left($value) {\n @include rfs($value, margin-left);\n}\n","// stylelint-disable property-disallowed-list\n// Single side border-radius\n\n// Helper function to replace negative values with 0\n@function valid-radius($radius) {\n $return: ();\n @each $value in $radius {\n @if type-of($value) == number {\n $return: append($return, max($value, 0));\n } @else {\n $return: append($return, $value);\n }\n }\n @return $return;\n}\n\n// scss-docs-start border-radius-mixins\n@mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {\n @if $enable-rounded {\n border-radius: valid-radius($radius);\n }\n @else if $fallback-border-radius != false {\n border-radius: $fallback-border-radius;\n }\n}\n\n@mixin border-top-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-left-radius: valid-radius($radius);\n border-top-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-end-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-right-radius: valid-radius($radius);\n border-bottom-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-bottom-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-bottom-right-radius: valid-radius($radius);\n border-bottom-left-radius: valid-radius($radius);\n }\n}\n\n@mixin border-start-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-left-radius: valid-radius($radius);\n border-bottom-left-radius: valid-radius($radius);\n }\n}\n\n@mixin border-top-start-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-left-radius: valid-radius($radius);\n }\n}\n\n@mixin border-top-end-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-bottom-end-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-bottom-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-bottom-start-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-bottom-left-radius: valid-radius($radius);\n }\n}\n// scss-docs-end border-radius-mixins\n"]}
--------------------------------------------------------------------------------
/public/assets/lib/bootstrap/css/bootstrap-reboot.rtl.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.rtl.css","../../scss/vendor/_rfs.scss","../../scss/mixins/_border-radius.scss","bootstrap-reboot.css"],"names":[],"mappings":"AAAA;;;;;;ACeA,ECNA,QADA,SDUE,WAAA,WAaE,8CAJJ,MAKM,gBAAA,QAaN,KACE,OAAA,EACA,YAAA,SAAA,CAAA,aAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,WAAA,CAAA,iBAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBE4MI,UAAA,KF1MJ,YAAA,IACA,YAAA,IACA,MAAA,QAEA,iBAAA,KACA,yBAAA,KACA,4BAAA,YASF,GACE,OAAA,KAAA,EACA,MAAA,QACA,iBAAA,aACA,OAAA,EACA,QAAA,IAGF,eACE,OAAA,IAUF,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAGA,YAAA,IACA,YAAA,IAIF,GEkKQ,UAAA,uBAlKJ,0BFAJ,GEyKQ,UAAA,QFpKR,GE6JQ,UAAA,sBAlKJ,0BFKJ,GEoKQ,UAAA,MF/JR,GEwJQ,UAAA,oBAlKJ,0BFUJ,GE+JQ,UAAA,SF1JR,GEmJQ,UAAA,sBAlKJ,0BFeJ,GE0JQ,UAAA,QFrJR,GE0IM,UAAA,QFrIN,GEqIM,UAAA,KF1HN,EACE,WAAA,EACA,cAAA,KC/BF,6BD0CA,YAEE,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,iCAAA,KAAA,yBAAA,KAMF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QAMF,GC9CA,GDgDE,cAAA,KC1CF,GD6CA,GC9CA,GDiDE,WAAA,EACA,cAAA,KAGF,MC7CA,MACA,MAFA,MDkDE,cAAA,EAGF,GACE,YAAA,IAKF,GACE,cAAA,MACA,aAAA,EAMF,WACE,OAAA,EAAA,EAAA,KAQF,ECxDA,OD0DE,YAAA,OAQF,MEsCM,UAAA,OF/BN,KACE,QAAA,KACA,iBAAA,QASF,ICtEA,IDwEE,SAAA,SEkBI,UAAA,MFhBJ,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAKN,EACE,MAAA,QACA,gBAAA,UAEA,QACE,MAAA,QAWF,2BAAA,iCAEE,MAAA,QACA,gBAAA,KC1EJ,KACA,IDgFA,IC/EA,KDmFE,YAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UExBI,UAAA,IF0BJ,UAAA,IACA,aAAA,cAOF,IACE,QAAA,MACA,WAAA,EACA,cAAA,KACA,SAAA,KEtCI,UAAA,OF2CJ,SE3CI,UAAA,QF6CF,MAAA,QACA,WAAA,OAIJ,KElDM,UAAA,OFoDJ,MAAA,QACA,UAAA,WAGA,OACE,MAAA,QAIJ,IACE,QAAA,MAAA,ME9DI,UAAA,OFgEJ,MAAA,KACA,iBAAA,QGzSE,cAAA,MH4SF,QACE,QAAA,EErEE,UAAA,IFuEF,YAAA,IASJ,OACE,OAAA,EAAA,EAAA,KAMF,ICnGA,IDqGE,eAAA,OAQF,MACE,aAAA,OACA,gBAAA,SAGF,QACE,YAAA,MACA,eAAA,MACA,MAAA,QACA,WAAA,MAOF,GAEE,WAAA,QACA,WAAA,qBC1GF,MAGA,GAFA,MAGA,GDyGA,MC3GA,GDiHE,aAAA,QACA,aAAA,MACA,aAAA,EAQF,MACE,QAAA,aAMF,OAEE,cAAA,EAQF,iCACE,QAAA,ECxHF,OD6HA,MC3HA,SADA,OAEA,SD+HE,OAAA,EACA,YAAA,QEpKI,UAAA,QFsKJ,YAAA,QAIF,OC9HA,ODgIE,eAAA,KAKF,cACE,OAAA,QAGF,OAGE,UAAA,OAGA,gBACE,QAAA,EAOJ,0CACE,QAAA,KCpIF,cACA,aACA,cD0IA,OAIE,mBAAA,OC1IF,6BACA,4BACA,6BD2II,sBACE,OAAA,QAON,mBACE,QAAA,EACA,aAAA,KAKF,SACE,OAAA,SAUF,SACE,UAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,EAQF,OACE,MAAA,MACA,MAAA,KACA,QAAA,EACA,cAAA,MEzPM,UAAA,sBF4PN,YAAA,QE9ZE,0BFuZJ,OE9OQ,UAAA,QFuPN,SACE,MAAA,MClJJ,kCDyJA,uCC1JA,mCADA,+BAGA,oCAJA,6BAKA,mCD8JE,QAAA,EAGF,4BACE,OAAA,KASF,cACE,eAAA,KACA,mBAAA,UC9JF,aACA,cG7XA,WH2XA,WGvXE,UAAA,IJyiBF,4BACE,mBAAA,KAKF,+BACE,QAAA,EAMF,uBACE,KAAA,QAMF,6BACE,KAAA,QACA,mBAAA,OAKF,OACE,QAAA,aAKF,OACE,OAAA,EAOF,QACE,QAAA,UACA,OAAA,QAQF,SACE,eAAA,SAQF,SACE,QAAA","sourcesContent":["/*!\n * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n// Prevent the usage of custom properties since we don't add them to `:root` in reboot\n$font-family-base: $font-family-sans-serif; // stylelint-disable-line scss/dollar-variable-default\n$font-family-code: $font-family-monospace; // stylelint-disable-line scss/dollar-variable-default\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n\n// Root\n//\n// Ability to the value of the root font sizes, affecting the value of `rem`.\n// null by default, thus nothing is generated.\n\n:root {\n font-size: $font-size-root;\n\n @if $enable-smooth-scroll {\n @media (prefers-reduced-motion: no-preference) {\n scroll-behavior: smooth;\n }\n }\n}\n\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Prevent adjustments of font size after orientation changes in iOS.\n// 4. Change the default tap highlight to be completely transparent in iOS.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n @include font-size($font-size-base);\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: $body-text-align;\n background-color: $body-bg; // 2\n -webkit-text-size-adjust: 100%; // 3\n -webkit-tap-highlight-color: rgba($black, 0); // 4\n}\n\n\n// Content grouping\n//\n// 1. Reset Firefox's gray color\n// 2. Set correct height and prevent the `size` attribute to make the `hr` look like an input field\n\nhr {\n margin: $hr-margin-y 0;\n color: $hr-color; // 1\n background-color: currentColor;\n border: 0;\n opacity: $hr-opacity;\n}\n\nhr:not([size]) {\n height: $hr-height; // 2\n}\n\n\n// Typography\n//\n// 1. Remove top margins from headings\n// By default, `
`-`` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n\n%heading {\n margin-top: 0; // 1\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-style: $headings-font-style;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1 {\n @extend %heading;\n @include font-size($h1-font-size);\n}\n\nh2 {\n @extend %heading;\n @include font-size($h2-font-size);\n}\n\nh3 {\n @extend %heading;\n @include font-size($h3-font-size);\n}\n\nh4 {\n @extend %heading;\n @include font-size($h4-font-size);\n}\n\nh5 {\n @extend %heading;\n @include font-size($h5-font-size);\n}\n\nh6 {\n @extend %heading;\n @include font-size($h6-font-size);\n}\n\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on ` `s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\n\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n\n// Abbreviations\n//\n// 1. Duplicate behavior to the data-bs-* attribute for our tooltip plugin\n// 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Prevent the text-decoration to be skipped.\n\nabbr[title],\nabbr[data-bs-original-title] { // 1\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n text-decoration-skip-ink: none; // 4\n}\n\n\n// Address\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\n\n// Lists\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\n// 1. Undo browser default\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // 1\n}\n\n\n// Blockquote\n\nblockquote {\n margin: 0 0 1rem;\n}\n\n\n// Strong\n//\n// Add the correct font weight in Chrome, Edge, and Safari\n\nb,\nstrong {\n font-weight: $font-weight-bolder;\n}\n\n\n// Small\n//\n// Add the correct font size in all browsers\n\nsmall {\n @include font-size($small-font-size);\n}\n\n\n// Mark\n\nmark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n// Sub and Sup\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n\nsub,\nsup {\n position: relative;\n @include font-size($sub-sup-font-size);\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n// Links\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n\n &:hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([class]) {\n &,\n &:hover {\n color: inherit;\n text-decoration: none;\n }\n}\n\n\n// Code\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-code;\n @include font-size(1em); // Correct the odd `em` font sizing in all browsers.\n direction: ltr #{\"/* rtl:ignore */\"};\n unicode-bidi: bidi-override;\n}\n\n// 1. Remove browser default top margin\n// 2. Reset browser default of `1em` to use `rem`s\n// 3. Don't allow content to break outside\n\npre {\n display: block;\n margin-top: 0; // 1\n margin-bottom: 1rem; // 2\n overflow: auto; // 3\n @include font-size($code-font-size);\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n @include font-size(inherit);\n color: inherit;\n word-break: normal;\n }\n}\n\ncode {\n @include font-size($code-font-size);\n color: $code-color;\n word-wrap: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n @include font-size($kbd-font-size);\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n\n kbd {\n padding: 0;\n @include font-size(1em);\n font-weight: $nested-kbd-font-weight;\n }\n}\n\n\n// Figures\n//\n// Apply a consistent margin strategy (matches our type styles).\n\nfigure {\n margin: 0 0 1rem;\n}\n\n\n// Images and content\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\n\n// Tables\n//\n// Prevent double borders\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: $table-cell-padding-y;\n padding-bottom: $table-cell-padding-y;\n color: $table-caption-color;\n text-align: left;\n}\n\n// 1. Removes font-weight bold by inheriting\n// 2. Matches default `
` alignment by inheriting `text-align`.\n// 3. Fix alignment for Safari\n\nth {\n font-weight: $table-th-font-weight; // 1\n text-align: inherit; // 2\n text-align: -webkit-match-parent; // 3\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\n\n// Forms\n//\n// 1. Allow labels to use `margin` for spacing.\n\nlabel {\n display: inline-block; // 1\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n// See https://github.com/twbs/bootstrap/issues/24093\n\nbutton {\n // stylelint-disable-next-line property-disallowed-list\n border-radius: 0;\n}\n\n// Explicitly remove focus outline in Chromium when it shouldn't be\n// visible (e.g. as result of mouse click or touch tap). It already\n// should be doing this automatically, but seems to currently be\n// confused and applies its very visible two-tone outline anyway.\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\n// 1. Remove the margin in Firefox and Safari\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // 1\n font-family: inherit;\n @include font-size(inherit);\n line-height: inherit;\n}\n\n// Remove the inheritance of text transform in Firefox\nbutton,\nselect {\n text-transform: none;\n}\n// Set the cursor for non-`` buttons\n//\n// Details at https://github.com/twbs/bootstrap/pull/30562\n[role=\"button\"] {\n cursor: pointer;\n}\n\nselect {\n // Remove the inheritance of word-wrap in Safari.\n // See https://github.com/twbs/bootstrap/issues/24990\n word-wrap: normal;\n\n // Undo the opacity change from Chrome\n &:disabled {\n opacity: 1;\n }\n}\n\n// Remove the dropdown arrow in Chrome from inputs built with datalists.\n// See https://stackoverflow.com/a/54997118\n\n[list]::-webkit-calendar-picker-indicator {\n display: none;\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\n// 3. Opinionated: add \"hand\" cursor to non-disabled button elements.\n\nbutton,\n[type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n\n @if $enable-button-pointers {\n &:not(:disabled) {\n cursor: pointer; // 3\n }\n }\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\n\n::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\n// 1. Textareas should really only resize vertically so they don't break their (horizontal) containers.\n\ntextarea {\n resize: vertical; // 1\n}\n\n// 1. Browsers set a default `min-width: min-content;` on fieldsets,\n// unlike e.g. ``s, which have `min-width: 0;` by default.\n// So we reset that to ensure fieldsets behave more like a standard block element.\n// See https://github.com/twbs/bootstrap/issues/12359\n// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n// 2. Reset the default outline behavior of fieldsets so they don't affect page layout.\n\nfieldset {\n min-width: 0; // 1\n padding: 0; // 2\n margin: 0; // 2\n border: 0; // 2\n}\n\n// 1. By using `float: left`, the legend will behave like a block element.\n// This way the border of a fieldset wraps around the legend if present.\n// 2. Fix wrapping bug.\n// See https://github.com/twbs/bootstrap/issues/29712\n\nlegend {\n float: left; // 1\n width: 100%;\n padding: 0;\n margin-bottom: $legend-margin-bottom;\n @include font-size($legend-font-size);\n font-weight: $legend-font-weight;\n line-height: inherit;\n\n + * {\n clear: left; // 2\n }\n}\n\n// Fix height of inputs with a type of datetime-local, date, month, week, or time\n// See https://github.com/twbs/bootstrap/issues/18842\n\n::-webkit-datetime-edit-fields-wrapper,\n::-webkit-datetime-edit-text,\n::-webkit-datetime-edit-minute,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-year-field {\n padding: 0;\n}\n\n::-webkit-inner-spin-button {\n height: auto;\n}\n\n// 1. Correct the outline style in Safari.\n// 2. This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\n[type=\"search\"] {\n outline-offset: -2px; // 1\n -webkit-appearance: textfield; // 2\n}\n\n// 1. A few input types should stay LTR\n// See https://rtlstyling.com/posts/rtl-styling#form-inputs\n// 2. RTL only output\n// See https://rtlcss.com/learn/usage-guide/control-directives/#raw\n\n/* rtl:raw:\n[type=\"tel\"],\n[type=\"url\"],\n[type=\"email\"],\n[type=\"number\"] {\n direction: ltr;\n}\n*/\n\n// Remove the inner padding in Chrome and Safari on macOS.\n\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n// Remove padding around color pickers in webkit browsers\n\n::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n\n// Inherit font family and line height for file input buttons\n\n::file-selector-button {\n font: inherit;\n}\n\n// 1. Change font properties to `inherit`\n// 2. Correct the inability to style clickable types in iOS and Safari.\n\n::-webkit-file-upload-button {\n font: inherit; // 1\n -webkit-appearance: button; // 2\n}\n\n// Correct element displays\n\noutput {\n display: inline-block;\n}\n\n// Remove border from iframe\n\niframe {\n border: 0;\n}\n\n// Summary\n//\n// 1. Add the correct display in all browsers\n\nsummary {\n display: list-item; // 1\n cursor: pointer;\n}\n\n\n// Progress\n//\n// Add the correct vertical alignment in Chrome, Firefox, and Opera.\n\nprogress {\n vertical-align: baseline;\n}\n\n\n// Hidden attribute\n//\n// Always hide an element with the `hidden` HTML attribute.\n\n[hidden] {\n display: none !important;\n}\n","/*!\n * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n :root {\n scroll-behavior: smooth;\n }\n}\n\nbody {\n margin: 0;\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", \"Liberation Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n background-color: #fff;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nhr {\n margin: 1rem 0;\n color: inherit;\n background-color: currentColor;\n border: 0;\n opacity: 0.25;\n}\n\nhr:not([size]) {\n height: 1px;\n}\n\nh6, h5, h4, h3, h2, h1 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n font-weight: 500;\n line-height: 1.2;\n}\n\nh1 {\n font-size: calc(1.375rem + 1.5vw);\n}\n@media (min-width: 1200px) {\n h1 {\n font-size: 2.5rem;\n }\n}\n\nh2 {\n font-size: calc(1.325rem + 0.9vw);\n}\n@media (min-width: 1200px) {\n h2 {\n font-size: 2rem;\n }\n}\n\nh3 {\n font-size: calc(1.3rem + 0.6vw);\n}\n@media (min-width: 1200px) {\n h3 {\n font-size: 1.75rem;\n }\n}\n\nh4 {\n font-size: calc(1.275rem + 0.3vw);\n}\n@media (min-width: 1200px) {\n h4 {\n font-size: 1.5rem;\n }\n}\n\nh5 {\n font-size: 1.25rem;\n}\n\nh6 {\n font-size: 1rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-bs-original-title] {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n -webkit-text-decoration-skip-ink: none;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul {\n padding-right: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: 0.5rem;\n margin-right: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 0.875em;\n}\n\nmark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 0.75em;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\na {\n color: #0d6efd;\n text-decoration: underline;\n}\na:hover {\n color: #0a58ca;\n}\n\na:not([href]):not([class]), a:not([href]):not([class]):hover {\n color: inherit;\n text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n direction: ltr ;\n unicode-bidi: bidi-override;\n}\n\npre {\n display: block;\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n font-size: 0.875em;\n}\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\ncode {\n font-size: 0.875em;\n color: #d63384;\n word-wrap: break-word;\n}\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 0.875em;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\nkbd kbd {\n padding: 0;\n font-size: 1em;\n font-weight: 700;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n color: #6c757d;\n text-align: right;\n}\n\nth {\n text-align: inherit;\n text-align: -webkit-match-parent;\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\nlabel {\n display: inline-block;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\n[role=button] {\n cursor: pointer;\n}\n\nselect {\n word-wrap: normal;\n}\nselect:disabled {\n opacity: 1;\n}\n\n[list]::-webkit-calendar-picker-indicator {\n display: none;\n}\n\nbutton,\n[type=button],\n[type=reset],\n[type=submit] {\n -webkit-appearance: button;\n}\nbutton:not(:disabled),\n[type=button]:not(:disabled),\n[type=reset]:not(:disabled),\n[type=submit]:not(:disabled) {\n cursor: pointer;\n}\n\n::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ntextarea {\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n float: right;\n width: 100%;\n padding: 0;\n margin-bottom: 0.5rem;\n font-size: calc(1.275rem + 0.3vw);\n line-height: inherit;\n}\n@media (min-width: 1200px) {\n legend {\n font-size: 1.5rem;\n }\n}\nlegend + * {\n clear: right;\n}\n\n::-webkit-datetime-edit-fields-wrapper,\n::-webkit-datetime-edit-text,\n::-webkit-datetime-edit-minute,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-year-field {\n padding: 0;\n}\n\n::-webkit-inner-spin-button {\n height: auto;\n}\n\n[type=search] {\n outline-offset: -2px;\n -webkit-appearance: textfield;\n}\n\n[type=\"tel\"],\n[type=\"url\"],\n[type=\"email\"],\n[type=\"number\"] {\n direction: ltr;\n}\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n::file-selector-button {\n font: inherit;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\niframe {\n border: 0;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[hidden] {\n display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */","// stylelint-disable property-blacklist, scss/dollar-variable-default\n\n// SCSS RFS mixin\n//\n// Automated responsive values for font sizes, paddings, margins and much more\n//\n// Licensed under MIT (https://github.com/twbs/rfs/blob/master/LICENSE)\n\n// Configuration\n\n// Base value\n$rfs-base-value: 1.25rem !default;\n$rfs-unit: rem !default;\n\n@if $rfs-unit != rem and $rfs-unit != px {\n @error \"`#{$rfs-unit}` is not a valid unit for $rfs-unit. Use `px` or `rem`.\";\n}\n\n// Breakpoint at where values start decreasing if screen width is smaller\n$rfs-breakpoint: 1200px !default;\n$rfs-breakpoint-unit: px !default;\n\n@if $rfs-breakpoint-unit != px and $rfs-breakpoint-unit != em and $rfs-breakpoint-unit != rem {\n @error \"`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.\";\n}\n\n// Resize values based on screen height and width\n$rfs-two-dimensional: false !default;\n\n// Factor of decrease\n$rfs-factor: 10 !default;\n\n@if type-of($rfs-factor) != number or $rfs-factor <= 1 {\n @error \"`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.\";\n}\n\n// Mode. Possibilities: \"min-media-query\", \"max-media-query\"\n$rfs-mode: min-media-query !default;\n\n// Generate enable or disable classes. Possibilities: false, \"enable\" or \"disable\"\n$rfs-class: false !default;\n\n// 1 rem = $rfs-rem-value px\n$rfs-rem-value: 16 !default;\n\n// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14\n$rfs-safari-iframe-resize-bug-fix: false !default;\n\n// Disable RFS by setting $enable-rfs to false\n$enable-rfs: true !default;\n\n// Cache $rfs-base-value unit\n$rfs-base-value-unit: unit($rfs-base-value);\n\n// Remove px-unit from $rfs-base-value for calculations\n@if $rfs-base-value-unit == px {\n $rfs-base-value: $rfs-base-value / ($rfs-base-value * 0 + 1);\n}\n@else if $rfs-base-value-unit == rem {\n $rfs-base-value: $rfs-base-value / ($rfs-base-value * 0 + 1 / $rfs-rem-value);\n}\n\n// Cache $rfs-breakpoint unit to prevent multiple calls\n$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);\n\n// Remove unit from $rfs-breakpoint for calculations\n@if $rfs-breakpoint-unit-cache == px {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);\n}\n@else if $rfs-breakpoint-unit-cache == rem or $rfs-breakpoint-unit-cache == \"em\" {\n $rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);\n}\n\n// Calculate the media query value\n$rfs-mq-value: if($rfs-breakpoint-unit == px, #{$rfs-breakpoint}px, #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit});\n$rfs-mq-property-width: if($rfs-mode == max-media-query, max-width, min-width);\n$rfs-mq-property-height: if($rfs-mode == max-media-query, max-height, min-height);\n\n// Internal mixin used to determine which media query needs to be used\n@mixin _rfs-media-query {\n @if $rfs-two-dimensional {\n @if $rfs-mode == max-media-query {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}), (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {\n @content;\n }\n }\n @else {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) and (#{$rfs-mq-property-height}: #{$rfs-mq-value}) {\n @content;\n }\n }\n }\n @else {\n @media (#{$rfs-mq-property-width}: #{$rfs-mq-value}) {\n @content;\n }\n }\n}\n\n// Internal mixin that adds disable classes to the selector if needed.\n@mixin _rfs-rule {\n @if $rfs-class == disable and $rfs-mode == max-media-query {\n // Adding an extra class increases specificity, which prevents the media query to override the property\n &,\n .disable-rfs &,\n &.disable-rfs {\n @content;\n }\n }\n @else if $rfs-class == enable and $rfs-mode == min-media-query {\n .enable-rfs &,\n &.enable-rfs {\n @content;\n }\n }\n @else {\n @content;\n }\n}\n\n// Internal mixin that adds enable classes to the selector if needed.\n@mixin _rfs-media-query-rule {\n\n @if $rfs-class == enable {\n @if $rfs-mode == min-media-query {\n @content;\n }\n\n @include _rfs-media-query {\n .enable-rfs &,\n &.enable-rfs {\n @content;\n }\n }\n }\n @else {\n @if $rfs-class == disable and $rfs-mode == min-media-query {\n .disable-rfs &,\n &.disable-rfs {\n @content;\n }\n }\n @include _rfs-media-query {\n @content;\n }\n }\n}\n\n// Helper function to get the formatted non-responsive value\n@function rfs-value($values) {\n // Convert to list\n $values: if(type-of($values) != list, ($values,), $values);\n\n $val: '';\n\n // Loop over each value and calculate value\n @each $value in $values {\n @if $value == 0 {\n $val: $val + ' 0';\n }\n @else {\n // Cache $value unit\n $unit: if(type-of($value) == \"number\", unit($value), false);\n\n @if $unit == px {\n // Convert to rem if needed\n $val: $val + ' ' + if($rfs-unit == rem, #{$value / ($value * 0 + $rfs-rem-value)}rem, $value);\n }\n @else if $unit == rem {\n // Convert to px if needed\n $val: $val + ' ' + if($rfs-unit == px, #{$value / ($value * 0 + 1) * $rfs-rem-value}px, $value);\n }\n @else {\n // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n $val: $val + ' ' + $value;\n }\n }\n }\n\n // Remove first space\n @return unquote(str-slice($val, 2));\n}\n\n// Helper function to get the responsive value calculated by RFS\n@function rfs-fluid-value($values) {\n // Convert to list\n $values: if(type-of($values) != list, ($values,), $values);\n\n $val: '';\n\n // Loop over each value and calculate value\n @each $value in $values {\n @if $value == 0 {\n $val: $val + ' 0';\n }\n\n @else {\n // Cache $value unit\n $unit: if(type-of($value) == \"number\", unit($value), false);\n\n // If $value isn't a number (like inherit) or $value has a unit (not px or rem, like 1.5em) or $ is 0, just print the value\n @if not $unit or $unit != px and $unit != rem {\n $val: $val + ' ' + $value;\n }\n\n @else {\n // Remove unit from $value for calculations\n $value: $value / ($value * 0 + if($unit == px, 1, 1 / $rfs-rem-value));\n\n // Only add the media query if the value is greater than the minimum value\n @if abs($value) <= $rfs-base-value or not $enable-rfs {\n $val: $val + ' ' + if($rfs-unit == rem, #{$value / $rfs-rem-value}rem, #{$value}px);\n }\n @else {\n // Calculate the minimum value\n $value-min: $rfs-base-value + (abs($value) - $rfs-base-value) / $rfs-factor;\n\n // Calculate difference between $value and the minimum value\n $value-diff: abs($value) - $value-min;\n\n // Base value formatting\n $min-width: if($rfs-unit == rem, #{$value-min / $rfs-rem-value}rem, #{$value-min}px);\n\n // Use negative value if needed\n $min-width: if($value < 0, -$min-width, $min-width);\n\n // Use `vmin` if two-dimensional is enabled\n $variable-unit: if($rfs-two-dimensional, vmin, vw);\n\n // Calculate the variable width between 0 and $rfs-breakpoint\n $variable-width: #{$value-diff * 100 / $rfs-breakpoint}#{$variable-unit};\n\n // Return the calculated value\n $val: $val + ' calc(' + $min-width + if($value < 0, ' - ', ' + ') + $variable-width + ')';\n }\n }\n }\n }\n\n // Remove first space\n @return unquote(str-slice($val, 2));\n}\n\n// RFS mixin\n@mixin rfs($values, $property: font-size) {\n @if $values != null {\n $val: rfs-value($values);\n $fluidVal: rfs-fluid-value($values);\n\n // Do not print the media query if responsive & non-responsive values are the same\n @if $val == $fluidVal {\n #{$property}: $val;\n }\n @else {\n @include _rfs-rule {\n #{$property}: if($rfs-mode == max-media-query, $val, $fluidVal);\n\n // Include safari iframe resize fix if needed\n min-width: if($rfs-safari-iframe-resize-bug-fix, (0 * 1vw), null);\n }\n\n @include _rfs-media-query-rule {\n #{$property}: if($rfs-mode == max-media-query, $fluidVal, $val);\n }\n }\n }\n}\n\n// Shorthand helper mixins\n@mixin font-size($value) {\n @include rfs($value);\n}\n\n@mixin padding($value) {\n @include rfs($value, padding);\n}\n\n@mixin padding-top($value) {\n @include rfs($value, padding-top);\n}\n\n@mixin padding-right($value) {\n @include rfs($value, padding-right);\n}\n\n@mixin padding-bottom($value) {\n @include rfs($value, padding-bottom);\n}\n\n@mixin padding-left($value) {\n @include rfs($value, padding-left);\n}\n\n@mixin margin($value) {\n @include rfs($value, margin);\n}\n\n@mixin margin-top($value) {\n @include rfs($value, margin-top);\n}\n\n@mixin margin-right($value) {\n @include rfs($value, margin-right);\n}\n\n@mixin margin-bottom($value) {\n @include rfs($value, margin-bottom);\n}\n\n@mixin margin-left($value) {\n @include rfs($value, margin-left);\n}\n","// stylelint-disable property-disallowed-list\n// Single side border-radius\n\n// Helper function to replace negative values with 0\n@function valid-radius($radius) {\n $return: ();\n @each $value in $radius {\n @if type-of($value) == number {\n $return: append($return, max($value, 0));\n } @else {\n $return: append($return, $value);\n }\n }\n @return $return;\n}\n\n// scss-docs-start border-radius-mixins\n@mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {\n @if $enable-rounded {\n border-radius: valid-radius($radius);\n }\n @else if $fallback-border-radius != false {\n border-radius: $fallback-border-radius;\n }\n}\n\n@mixin border-top-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-left-radius: valid-radius($radius);\n border-top-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-end-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-right-radius: valid-radius($radius);\n border-bottom-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-bottom-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-bottom-right-radius: valid-radius($radius);\n border-bottom-left-radius: valid-radius($radius);\n }\n}\n\n@mixin border-start-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-left-radius: valid-radius($radius);\n border-bottom-left-radius: valid-radius($radius);\n }\n}\n\n@mixin border-top-start-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-left-radius: valid-radius($radius);\n }\n}\n\n@mixin border-top-end-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-top-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-bottom-end-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-bottom-right-radius: valid-radius($radius);\n }\n}\n\n@mixin border-bottom-start-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-bottom-left-radius: valid-radius($radius);\n }\n}\n// scss-docs-end border-radius-mixins\n","/*!\n * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/)\n * Copyright 2011-2021 The Bootstrap Authors\n * Copyright 2011-2021 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n :root {\n scroll-behavior: smooth;\n }\n}\n\nbody {\n margin: 0;\n font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", \"Liberation Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n background-color: #fff;\n -webkit-text-size-adjust: 100%;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nhr {\n margin: 1rem 0;\n color: inherit;\n background-color: currentColor;\n border: 0;\n opacity: 0.25;\n}\n\nhr:not([size]) {\n height: 1px;\n}\n\nh6, h5, h4, h3, h2, h1 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n font-weight: 500;\n line-height: 1.2;\n}\n\nh1 {\n font-size: calc(1.375rem + 1.5vw);\n}\n@media (min-width: 1200px) {\n h1 {\n font-size: 2.5rem;\n }\n}\n\nh2 {\n font-size: calc(1.325rem + 0.9vw);\n}\n@media (min-width: 1200px) {\n h2 {\n font-size: 2rem;\n }\n}\n\nh3 {\n font-size: calc(1.3rem + 0.6vw);\n}\n@media (min-width: 1200px) {\n h3 {\n font-size: 1.75rem;\n }\n}\n\nh4 {\n font-size: calc(1.275rem + 0.3vw);\n}\n@media (min-width: 1200px) {\n h4 {\n font-size: 1.5rem;\n }\n}\n\nh5 {\n font-size: 1.25rem;\n}\n\nh6 {\n font-size: 1rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-bs-original-title] {\n text-decoration: underline dotted;\n cursor: help;\n text-decoration-skip-ink: none;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul {\n padding-left: 2rem;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: 0.5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 0.875em;\n}\n\nmark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 0.75em;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -0.25em;\n}\n\nsup {\n top: -0.5em;\n}\n\na {\n color: #0d6efd;\n text-decoration: underline;\n}\na:hover {\n color: #0a58ca;\n}\n\na:not([href]):not([class]), a:not([href]):not([class]):hover {\n color: inherit;\n text-decoration: none;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n direction: ltr /* rtl:ignore */;\n unicode-bidi: bidi-override;\n}\n\npre {\n display: block;\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n font-size: 0.875em;\n}\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\ncode {\n font-size: 0.875em;\n color: #d63384;\n word-wrap: break-word;\n}\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 0.875em;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\nkbd kbd {\n padding: 0;\n font-size: 1em;\n font-weight: 700;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg,\nsvg {\n vertical-align: middle;\n}\n\ntable {\n caption-side: bottom;\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n color: #6c757d;\n text-align: left;\n}\n\nth {\n text-align: inherit;\n text-align: -webkit-match-parent;\n}\n\nthead,\ntbody,\ntfoot,\ntr,\ntd,\nth {\n border-color: inherit;\n border-style: solid;\n border-width: 0;\n}\n\nlabel {\n display: inline-block;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus:not(:focus-visible) {\n outline: 0;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\n[role=button] {\n cursor: pointer;\n}\n\nselect {\n word-wrap: normal;\n}\nselect:disabled {\n opacity: 1;\n}\n\n[list]::-webkit-calendar-picker-indicator {\n display: none;\n}\n\nbutton,\n[type=button],\n[type=reset],\n[type=submit] {\n -webkit-appearance: button;\n}\nbutton:not(:disabled),\n[type=button]:not(:disabled),\n[type=reset]:not(:disabled),\n[type=submit]:not(:disabled) {\n cursor: pointer;\n}\n\n::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ntextarea {\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n float: left;\n width: 100%;\n padding: 0;\n margin-bottom: 0.5rem;\n font-size: calc(1.275rem + 0.3vw);\n line-height: inherit;\n}\n@media (min-width: 1200px) {\n legend {\n font-size: 1.5rem;\n }\n}\nlegend + * {\n clear: left;\n}\n\n::-webkit-datetime-edit-fields-wrapper,\n::-webkit-datetime-edit-text,\n::-webkit-datetime-edit-minute,\n::-webkit-datetime-edit-hour-field,\n::-webkit-datetime-edit-day-field,\n::-webkit-datetime-edit-month-field,\n::-webkit-datetime-edit-year-field {\n padding: 0;\n}\n\n::-webkit-inner-spin-button {\n height: auto;\n}\n\n[type=search] {\n outline-offset: -2px;\n -webkit-appearance: textfield;\n}\n\n/* rtl:raw:\n[type=\"tel\"],\n[type=\"url\"],\n[type=\"email\"],\n[type=\"number\"] {\n direction: ltr;\n}\n*/\n::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-color-swatch-wrapper {\n padding: 0;\n}\n\n::file-selector-button {\n font: inherit;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\niframe {\n border: 0;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */\n"]}
--------------------------------------------------------------------------------