Compare commits

...

181 Commits

Author SHA1 Message Date
c9da9de528 Merge branch 'dev' into main 2025-02-10 07:33:39 +03:00
63809ffa0f Add Epikhin and Kuznetsov 2025-02-09 22:41:37 +03:00
3cbe5cfa20 Upload files to "data/magprog/images/mentors" 2025-02-09 22:40:32 +03:00
03304f0b17 Add description for card "Team"
Test example for Arina
2025-01-10 16:12:16 +03:00
b5f2a7fb5a Replace NPM with SPC in magprog.
Remove BMK pages
2024-11-30 12:25:49 +03:00
ac88bdf0b7 Use Logo instead of text 2024-10-05 17:24:39 +03:00
3d9b379fd9 Merge pull request 'Varvara Kaplenko info attempt 2' (#3) from vviora/varvara_kaplenko:main into dev
Reviewed-on: SPC/spc-site#3
2024-08-14 14:45:42 +03:00
06bed316b5 Merge remote-tracking branch 'upstream/dev' 2024-08-14 14:42:39 +03:00
a711e44aea Merge https://git.sciprog.center/SPC/spc-site 2024-08-14 14:19:16 +03:00
2f9f94fec2 Обновить data/home/content/people/Kaplenko[info].md 2024-08-14 13:56:08 +03:00
692e5f722e Обновить data/home/content/people/Kaplenko.md 2024-08-14 13:55:43 +03:00
042218d1b8 Update 2024-08-10 13:02:47 +03:00
2d9860441e Update 2024-08-10 12:45:11 +03:00
d4bdea8d56 Update 2024-08-10 12:44:23 +03:00
d327e9de65 Загрузить файлы в «data/home/content/people» 2024-08-10 12:43:46 +03:00
72b0b22088 Загрузить файлы в «data/home/content/people» 2024-08-10 12:43:38 +03:00
7bdc1fd674 Fix data 2024-08-10 12:04:40 +03:00
9cbef1a1e3 Merge remote-tracking branch 'spc/main' into dev 2024-08-10 11:55:19 +03:00
c8f6f9a6f3 Merge pull request 'varvara kaplenko data' (#1) from vviora/varvara_kaplenko:main into main
Reviewed-on: SPC/spc-site#1
2024-08-10 11:33:17 +03:00
dc0daa2b3e Загрузить файлы в «data/home/images/people» 2024-08-10 11:16:52 +03:00
716dc77922 Загрузить файлы в «data/home/content/people» 2024-08-10 11:16:03 +03:00
7d2a2ead3f Update to match upstream 2024-04-30 19:03:41 +03:00
7e7a89424c Modify mentors 2024-04-13 10:45:52 +03:00
aca13da8cc Modify mentors 2024-04-12 18:55:39 +03:00
c6e762f96b Update form link 2024-04-01 11:27:07 +03:00
a8eb773e6c Update mentors 2024-04-01 09:48:01 +03:00
183f02f26f Fix rendering for masters 2024-03-03 18:28:58 +03:00
be2a9499c6 Some fixes for magprog 2024-03-02 20:50:35 +03:00
5e207a1a64 Move data out of resources. Deliver as separate directory. 2024-03-02 19:10:56 +03:00
7053c866f9 Alternative way for link passing and substitution in markdown 2024-03-02 16:58:59 +03:00
523ac48fb6 Remove iframe. For some reason it breaks site 2024-03-01 09:30:38 +03:00
a1da3f9a5e Visual update for language switch 2024-02-29 19:54:03 +03:00
f73fb0c2fb Implement parent context and proper language switch 2024-02-29 09:29:22 +03:00
bf746a4227 Hack to fix language switch 2024-02-28 22:06:36 +03:00
f1ee6c5942 Update language management 2024-02-23 12:11:06 +03:00
c2a60646f7 Update to DataForge 0.8 2024-02-19 20:14:25 +03:00
671ae6357f Update to DataForge 0.8 2024-02-19 19:47:37 +03:00
72ac07db5a [WIP] refactor in progress 2024-01-19 22:25:23 +03:00
f65b537255 [WIP] refactor in progress 2024-01-04 19:06:08 +03:00
1923a1d296 [WIP] refactor in progress 2024-01-04 11:26:23 +03:00
d2a31ce33e update orgs 2023-10-28 14:05:15 +03:00
d0afbae699 Add Gorbachev.md. 2023-07-11 18:31:34 +03:00
8494a9d880 Update plugin version 2023-07-11 13:54:55 +03:00
6d051dc151 Update magprog 2023-04-03 22:27:11 +03:00
e79e363645 Update magprog 2023-04-03 21:13:27 +03:00
b5df13b5ef Fix line endings. Again 2023-03-27 16:24:26 +03:00
5f2439f42a Minor UI fixes 2023-03-27 13:39:19 +03:00
f61bb5cc90 Temporary workaround for resource-based data 2023-03-27 13:23:03 +03:00
1f0d0a8124 Implemented binary propagation 2023-03-27 10:23:25 +03:00
6c384b2d7b Merge branch 'dev' into feature/no-files 2023-03-27 09:41:35 +03:00
269451dbfa Fix text. Add Palmin 2023-03-15 18:42:50 +03:00
0ea7d41b6f Fix line endings and punctuation 2023-03-15 18:31:04 +03:00
9d5db776e9 Fix texts 2023-03-13 21:00:47 +03:00
ba578aa795 Update partens 2023-03-13 18:28:42 +03:00
5fb2c2379e
Merge MIPT-NPM-MR-29: newRITM 2023-03-13 13:33:04 +00:00
742244c92b WIP - working on file-less trees 2023-03-13 16:25:21 +03:00
Aleksandr Svetlichnyy
cad408e215
New file data/magprog/content/mentors/komisov[info].md 2023-03-13 09:08:40 +00:00
Aleksandr Svetlichnyy
817daf00f1
New file data/magprog/content/mentors/komisov.md 2023-03-13 09:07:40 +00:00
Aleksandr Svetlichnyy
8c31d75c7a
upload Komisov photo 2023-03-13 09:02:37 +00:00
Aleksandr Svetlichnyy
67e57353ca
New file data/magprog/content/mentors/kluev[info].md 2023-03-13 08:56:56 +00:00
Aleksandr Svetlichnyy
4e17ec5de9
upload a photo 2023-03-13 08:52:32 +00:00
Aleksandr Svetlichnyy
122303b82d
New file data/magprog/content/mentors/kluev.md 2023-03-13 08:51:56 +00:00
2a5bc95d16 Update mentors 2023-01-23 20:37:48 +03:00
7192f7fafe add BMK site 2023-01-23 20:33:48 +03:00
92b031392a Constants for language access 2023-01-09 11:24:11 +03:00
b11be7df2d Add language support 2023-01-08 21:26:09 +03:00
a1baa33102
Work on language support 2023-01-08 15:58:20 +03:00
e636d70c51
Update courses 2022-12-21 23:43:46 +03:00
fa294bef0f
Update member pages. Add date 2022-12-21 23:26:27 +03:00
ade8f61aa0
Update icons and page names 2022-10-04 12:55:05 +03:00
SPC-code
38b6147794
Merge pull request #8 from GregTheMadMonk/layout-fixes
Minor layout fixes
2022-10-04 12:02:09 +03:00
1756f0d6b1 Improve "Centre was created..." position on the main page
Improve the underlined image links fix
2022-09-27 02:30:47 +03:00
6f6960f8b8 Fix ul having too much bottom margin as last child in blockquote 2022-09-27 02:08:55 +03:00
6da4a70a1a Add 'All rights reserved' after 'SPC' to all footers 2022-09-27 02:04:18 +03:00
37156c79ad Remove underline from image links 2022-09-27 01:59:33 +03:00
950903c938 Update .gitignore 2022-09-27 01:32:03 +03:00
57d4f12f7f Replace list padding-left with list-style-position
Fixes the issue with list bullet points overlapping `float:left` images
2022-09-26 23:23:57 +03:00
f3eb441c61 Same as previous commit, but for /magprog 2022-09-26 22:56:11 +03:00
a6836c8516 Fix content overlapping footer on /people/* pages
Also, add executable permissions to gradlew

Known side-effects:
* "Centre was created..." on the home page now takes a little bit more
  vertical space
2022-09-26 22:37:39 +03:00
9284e107d7
Update education pages 2022-09-03 18:39:06 +03:00
38e739c5c4
Add forward headers 2022-09-03 15:40:37 +03:00
6d3d0420dd
Add forward headers 2022-09-03 14:11:36 +03:00
9e87eddcb6
Update build tools and DF 2022-09-03 11:54:56 +03:00
3896c13136 Merge MIPT-NPM-MR-25: dev 2022-07-19 15:06:48 +00:00
95714e4b40 add deployment configuration 2022-07-07 17:15:51 +00:00
2b5af660af
Quick-fix for sharing common data 2022-07-03 17:13:39 +03:00
7975a2072e
Add publishing 2022-07-03 16:39:38 +03:00
5e93f982f8
Spliting site and the snark project complete 2022-07-03 16:28:53 +03:00
eb81d46238
Spliting site and the snark project 2022-06-30 20:51:57 +03:00
4024eed50f
Update readme 2022-06-26 13:14:57 +03:00
4066712014
Final fix for static rendering 2022-06-26 12:46:12 +03:00
d3a6ab658a
Add ref resolution to basic page features 2022-06-26 12:32:22 +03:00
bf884732c1
Add text preprocessors 2022-06-25 23:27:29 +03:00
781b185349
Yet another bug with context receivers 2022-06-25 13:07:52 +03:00
f530b7605b
Fixing static gen after refactor 2022-06-24 18:46:15 +03:00
072655ac51
Complete refactor to new routing API 2022-06-24 17:54:52 +03:00
218e76a2a8
Complete refactor to new routing API 2022-06-24 17:23:08 +03:00
c15a0ea948
Complete refactor to new routing API 2022-06-24 16:39:10 +03:00
43bf8e8e96
Add Https redirect 2022-06-23 11:02:26 +03:00
846c02020b
Multiple engine logic cleanup 2022-06-23 10:44:16 +03:00
d657282a33
Resolving paths for static sites. 2022-06-22 23:35:16 +03:00
bafc75086a
Implementation for static site generator 2022-06-22 22:14:19 +03:00
d74c8be135
Merge remote-tracking branch 'origin/main' into dev
# Conflicts:
#	src/main/kotlin/ru/mipt/spc/master.kt
2022-06-22 21:39:30 +03:00
9fd4620947
Fix all errors with new SNARK architecture. 2022-06-22 21:37:22 +03:00
4966bfc9b3
Refactor page placement. 2022-06-22 12:18:35 +03:00
0a28331e05 Remove homepage link at matrts, it breaks the code 2022-06-21 13:37:03 +03:00
600a9b5529
Refactor snark part 2022-06-21 10:52:24 +03:00
285057fbb0
bug in PagesFrom 2022-06-20 20:32:44 +03:00
23a736a012
Refactor SPC home page to use decoupled representation from KTor 2022-06-20 17:10:37 +03:00
a907c57134
Separating from KTor 2022-06-20 14:11:41 +03:00
e9f71cdab9
fix links 2022-06-20 12:11:13 +03:00
4484bbfac7
Simplify deploy logic 2022-06-20 11:55:18 +03:00
cfc7fa5161
Add clarification to message 2022-06-20 11:05:13 +03:00
3f27061e25
Consulting page update 2022-06-20 11:04:37 +03:00
e02d218d1a
Research content update 2022-06-20 10:58:07 +03:00
fa9c042c75
Fix directory name in deploy 2022-06-19 21:41:51 +03:00
3a25c37a47
fix deploy task separator 2022-06-19 21:11:10 +03:00
895ca5f76a
Add readme 2022-06-19 20:49:20 +03:00
2324e9d81b
Fix deploy 2022-06-19 19:36:48 +03:00
2990e2f28f fix secrets names 2022-06-19 11:27:52 +00:00
892fa009e7 Change image 2022-06-19 11:25:29 +00:00
696ca38efe
Another attempt on deploy 2022-06-19 14:18:44 +03:00
a5121b8637 Experiment with CD 2022-06-16 06:58:17 +00:00
84848f611e Update CD 2022-06-15 17:40:33 +00:00
ddc0f58b34 Update CD 2022-06-15 17:37:04 +00:00
679d993b6d Update CD 2022-06-15 16:53:13 +00:00
8a1deab1f7 update CD 2022-06-15 16:44:42 +00:00
9495fdb96e Update CD 2022-06-15 16:39:31 +00:00
4f85177c0a Update CD 2022-06-15 16:37:21 +00:00
5e1625d98c Update CD 2022-06-15 16:29:59 +00:00
0f223da648 Update CD 2022-06-15 16:18:29 +00:00
ba883b5b11
Update consulting and magprog 2022-06-15 14:53:36 +03:00
8bc8f5348d
Always update build date 2022-06-08 19:07:20 +03:00
72c3dc87df
Fix name for Efanov 2022-06-08 19:00:53 +03:00
6e8a6c46c2
Update master's mentors 2022-06-08 18:37:54 +03:00
Tatiana Muhina
4d127f500d image 2022-06-08 09:53:09 +00:00
Tatiana Muhina
d4704211db New file data/magprog/content/mentors/Efanov[info].md 2022-06-08 09:51:53 +00:00
Tatiana Muhina
93a0a7534a correction 2022-06-08 09:46:49 +00:00
Tatiana Muhina
a9d77bd4c7 New file data/magprog/content/mentors/Efanov.md 2022-06-08 09:38:54 +00:00
def1ef13ff
Update consulting.md 2022-06-01 10:47:00 +03:00
6bcf7d6092 update CD 2022-05-27 07:40:25 +00:00
72bd67797c
Fix task outputs for build date 2022-05-26 22:57:55 +03:00
1c3fb97826
Fix task outputs for build date 2022-05-26 21:48:56 +03:00
d06cc8d359 update CD 2022-05-26 15:27:50 +00:00
7826311893 Update CD 2022-05-26 14:53:09 +00:00
c75cbe7217 update CD 2022-05-26 14:15:24 +00:00
56822a3644 Refactor masters 2022-05-26 11:55:50 +03:00
a85322231e
Merge remote-tracking branch 'origin/main' 2022-05-25 22:38:35 +03:00
21f2d82289
Update deployment options 2022-05-25 22:38:18 +03:00
7563693259 Fix typo in shell script 2022-05-25 19:06:15 +00:00
54803df50d update CD 2022-05-25 19:00:18 +00:00
7e0ce0254c
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	.space.kts
2022-05-25 21:53:42 +03:00
99eab81cb3
update CD 2022-05-25 21:52:55 +03:00
73949a23cb
Add FPMI label 2022-05-25 21:23:56 +03:00
2be1e9c275 update CD 2022-05-25 17:34:17 +00:00
98ad36d777 update CD 2022-05-25 17:28:59 +00:00
2ed8586cb1 update build 2022-05-25 16:18:00 +00:00
e8b9a35a61
Update CD 2022-05-25 18:40:23 +03:00
060583a418
Update mentors and emails 2022-05-25 18:28:30 +03:00
62380ddc65 Merge MIPT-NPM-MR-21: muhina 2022-05-25 14:50:57 +00:00
Tatiana Muhina
d09dcf4439 kharuk 2022-05-25 14:25:41 +00:00
Tatiana Muhina
2cc9c3296e New file data/magprog/content/mentors/kharuk[info].md 2022-05-25 14:24:44 +00:00
Tatiana Muhina
9b7a5d7e27 name 2022-05-25 14:22:05 +00:00
Tatiana Muhina
fed8e765c6 New file data/magprog/content/mentors/Kharuk.md 2022-05-25 14:21:33 +00:00
Tatiana Muhina
30157c4b18 New file data/magprog/content/mentors/kondratov[info].md 2022-05-25 14:12:48 +00:00
Tatiana Muhina
8dbbfafacc New file data/magprog/content/mentors/kondratov.md 2022-05-25 14:10:06 +00:00
Tatiana Muhina
3fa69b7594 image by tinkoff mentor 2022-05-25 14:01:11 +00:00
18ba3587e3
Update research 2022-05-25 12:59:39 +03:00
ccc68b614f
Some fixes at masters 2022-05-24 21:39:01 +03:00
b92f880ce4
Moving files around 2022-05-22 16:52:36 +03:00
2d98770984 Merge MIPT-NPM-MR-20: muhina 2022-05-22 11:51:39 +00:00
d88036c1bb
Add break in the moto 2022-05-21 20:10:44 +03:00
120989a333
Large content update 2022-05-21 19:21:21 +03:00
Tatiana Muhina
3597298bdb images 2022-05-21 15:41:35 +00:00
Tatiana Muhina
c638ffe1bd New file data/magprog/content/mentors/svetlichny[info].md 2022-05-21 15:35:15 +00:00
Tatiana Muhina
cc27baf248 New file data/magprog/content/mentors/nizovtseva[info].md 2022-05-21 15:24:40 +00:00
Tatiana Muhina
54729d259b New file data/magprog/content/mentors/nizovtseva.md 2022-05-21 14:44:45 +00:00
Tatiana Muhina
95889ef87f New file data/magprog/content/mentors/svetlichny.md 2022-05-21 14:38:15 +00:00
fd5b4f0b23
Research + Team 2022-05-21 13:38:15 +03:00
bfd865727b
language as string 2022-05-14 11:08:28 +03:00
d4236a65b8
home page added 2022-05-13 17:21:06 +03:00
303 changed files with 15622 additions and 5418 deletions

43
.gitignore vendored
View File

@ -1,39 +1,10 @@
.gradle
.gradle/
build/
.idea/
logs/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
/deploy.ps1
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
/logs/
.sass-cache
*.css.map

36
.space.kts Normal file
View File

@ -0,0 +1,36 @@
job("Deploy") {
startOn {
gitPush { enabled = false }
}
container(image = "gradle:jdk17-alpine") {
env["SPC_HOST"] = "{{ project:spc-host }}"
env["SPC_USER"] = "{{ project:spc-webmaster-user }}"
env["SPC_ID"] = "{{ project:spc-webmaster-id }}"
kotlinScript { api ->
api.space().projects.automation.deployments.start(
project = api.projectIdentifier(),
targetIdentifier = TargetIdentifier.Key("spc-site"),
version = "current",
// automatically update deployment status based on the status of the job
syncWithAutomationJob = true
)
api.gradle("uploadDistribution")
}
}
}
job("Restart service"){
startOn {
gitPush { enabled = false }
}
container(image = "gradle:jdk17-alpine") {
env["SPC_HOST"] = "{{ project:spc-host }}"
env["SPC_USER"] = "{{ project:spc-webmaster-user }}"
env["SPC_ID"] = "{{ project:spc-webmaster-id }}"
kotlinScript { api ->
api.gradle("reloadDistribution")
}
}
}

20
Epikhin.md Normal file
View File

@ -0,0 +1,20 @@
---
content_type: magprog_mentor
name: Андрей Епихин
id: Epikhin
image: images/mentors/Epikhin.jpg
language: ru
---
#### Организация
ИСП РАН, лаборатория СПО цифрового моделирования технических систем https://unicfd.ru/
#### Биография
Закончил МГТУ им.Н.Э.Баумана по специальности «Баллистика и аэродинамика». В 2018 году защитил диссертацию на соискание ученой степени кандидата технических наук по специальности «Аэродинамика и процессы теплообмена летательных аппаратов». В настоящее время является заведующим лаборатории цифрового моделирования технических систем Института системного программирования им. В.П. Иванникова РАН.
#### Направление исследований
Общая тема исследований сосредоточена на решении задач механики сплошной среды, включая разработку программ и библиотек для моделирования течений жидкостей и газов, цифровое моделирование актуальных задач промышленности. В рамках данного направления можно выделить две основные тематики:
1. Разработка и реализация методов и подходов для численного моделирования задач механики сплошной среды с применением свободного программного обеспечения и программирования.
2. Численное моделирование и решение задач аэродинамики струйных и отрывных течений, вычислительной аэродинамики и аэроакустики, расчет турбин и пропеллеров, размыва донной поверхности и др.
#### Требования к студентам
Кандидату необходимы знания и навыки в численных методах, аэрогазодинамике, программировании. При этом программирование выполняет роль прикладного инструмента, позволяющего реализовать новые модели и алгоритмы на основе выбранного открытого программного обеспечения. В качестве основного стека программ с открытым исходным кодом используются: OpenFOAM, Paraview, Salome.

5
Epikhin[info].md Normal file
View File

@ -0,0 +1,5 @@
**ИСП РАН**
Механика сплошной среды, разработка программ и библиотек для моделирования течений жидкостей и газов, цифровое моделирование актуальных задач промышленности.
Ключевые слова: *Механика сплошных сред, Открытое ПО, OpenFOAM, Paraview, Salome.*

20
Kuznetsov.md Normal file
View File

@ -0,0 +1,20 @@
---
content_type: magprog_mentor
name: Михаил Кузнецов
id: Kuznetsov
image: images/mentors/Kuznetsov.jpg
language: ru
---
#### Организация
ИЯИ РАН
#### Биография
Выпускник магистратуры ЯрГУ (2010), аспирантуры МФТИ (2014), кандидат физ.-мат. наук (2017), сотрудник ИЯИ РАН (2010-н.в.), постдок Свободного университета Брюсселя (2019-2022), преподаватель кафедры фундаментальных взаимодействий и космологии ЛФИ МФТИ (2022-н.в.), член международной коллаборации Telescope Array (2016-н.в.)
Научные интересы связаны с астрофизикой частиц и физикой космических лучей, включая непрямой поиск темной материи, разработку и применение новых методов обработки экспериментальных данных в астрофизике, в т.ч. методов машинного обучения. В настоящее время основное направление работы - исследование массового состава и анизотропии космических лучей высоких и сверхвысоких энергий, поиск их источников. Публикации: https://inspirehep.net/authors/1713002
#### Направление исследований
Астрофизика частиц: обработка экспериментальных данных, численное моделирование физических процессов, проверка теоретических моделей.
#### Требования к студентам
Знание одного, лучше двух языков программирования

5
Kuznetsov[info].md Normal file
View File

@ -0,0 +1,5 @@
**ИЯИ РАН**
Астрофизика частиц: обработка экспериментальных данных, численное моделирование физических процессов, проверка теоретических моделей.
Ключевые слова: *Астрофизика частиц, Python.*

22
README.md Normal file
View File

@ -0,0 +1,22 @@
# Scientific programming center site
The site is [here](https://sciprog.center/)
## The mechanics
The site is a unique mix between static and dynamic content rendering.
It uses [DataForge](https://github.com/mipt-npm/dataforge-core) and a prototype for SNARK project to load data lazily and
render it with very low resource consumption.
The idea is the following:
* The file tree from [data](/data) directory is lazily loaded into a DataForge `DataSet`structure. Each element in a `DataSet` is a lazy data with eagerly loaded metadata. In case of files, metadata includes some file parameters like extensions and creation time a front matter YAML translated into DF `Meta`.
* The `DataSet` is transformed using parsers defined in `SnarkPlugin`. Parser transforms the bytearray-like file content into some typed object like Markdown or Html. Json/yaml files are transformed into `Meta`. All objects are lazy, they are not parsed and computed until they are read.
* There could be additional transformation for tree. For example severl blocks could be combined into one. Data could be loaded inside the page, etc.
* The resulting `DataSet` is loaded into a `PageContext`, which is used by a site template to render resulting pages.
* In the future, there will be utilities to automatically transform into a `DataSet`, loading templates as plugins.
* Once computed, the data is cached in-memory and is not recomputed until the underlying data is changed.
* A `PageContex` is loaded as a context receiver for all page rendering activities. It allows to seamlessly load data into the page, also it could be substituted on language change or other configuration changes. Also one could use `PageContext` to isolate different parts of site from each other.
## References
Currently, we use two different designs from https://html5up.net/

View File

@ -1,58 +1,100 @@
import ru.mipt.npm.gradle.KScienceVersions
import space.kscience.gradle.KScienceVersions
import space.kscience.snark.plugin.JSch
import space.kscience.snark.plugin.execute
import space.kscience.snark.plugin.uploadDirectory
import space.kscience.snark.plugin.useSession
plugins {
id("ru.mipt.npm.gradle.project")
id("ru.mipt.npm.gradle.jvm")
id("space.kscience.gradle.project")
id("space.kscience.gradle.jvm")
id("space.kscience.snark")
application
}
//repositories{
// mavenLocal()
//}
group = "ru.mipt.npm"
version = "0.0.1-SNAPSHOT"
group = "center.sciprog"
version = "0.1.0"
application {
mainClass.set("ru.mipt.spc.ApplicationKt")
mainClass.set("io.ktor.server.netty.EngineMain")
val isDevelopment: Boolean = project.ext.has("development")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment", "-Xmx200M")
}
val dataforgeVersion by extra("0.6.0-dev-6")
val snarkVersion: String by extra
val ktorVersion = KScienceVersions.ktorVersion
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
implementation("io.ktor:ktor-server-core:$ktorVersion")
implementation("org.jetbrains.kotlinx:kotlinx-html:0.7.5")
implementation("io.ktor:ktor-server-html-builder:$ktorVersion")
implementation("org.jetbrains.kotlin-wrappers:kotlin-css")
implementation("io.ktor:ktor-server-host-common:$ktorVersion")
implementation("io.ktor:ktor-server-status-pages:$ktorVersion")
implementation("space.kscience:snark-ktor:$snarkVersion")
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("ch.qos.logback:logback-classic:1.2.11")
implementation("space.kscience:dataforge-workspace:$dataforgeVersion")
implementation("space.kscience:dataforge-io-yaml:$dataforgeVersion")
implementation("org.jetbrains:markdown:0.3.1")
implementation("io.ktor:ktor-server-http-redirect:$ktorVersion")
implementation("io.ktor:ktor-server-forwarded-header:$ktorVersion")
implementation("ch.qos.logback:logback-classic:1.4.12")
testImplementation("io.ktor:ktor-server-tests:$ktorVersion")
}
kotlin {
explicitApi = org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode.Disabled
sourceSets.all {
languageSettings {
languageVersion = "1.7"
apiVersion = "1.7"
}
apiValidation{
validationDisabled = true
}
/* Upload with JSch */
val host = System.getenv("SPC_HOST")
val user = System.getenv("SPC_USER")
val password = System.getenv("SPC_PASSWORD")
val privateKey = System.getenv("SPC_ID")
//val publicKey = System.getenv("SPC_PUBKEY")
val serviceName = "sciprog-site"
if (host != null && user != null || privateKey != null) {
val uploadDistribution by tasks.creating {
group = "distribution"
dependsOn("installDist")
doLast {
JSch {
addIdentity("webmaster", privateKey.encodeToByteArray(), null, null)
}.useSession(host, user) {
//stopping service during the upload
execute("sudo systemctl stop $serviceName")
uploadDirectory(buildDir.resolve("install/spc-site"), "/opt")
//adding an executable flag to the entry point
execute("sudo chmod +x /opt/spc-site/bin/spc-site")
execute("sudo systemctl start $serviceName")
}
}
}
val reloadDistribution by tasks.creating {
group = "distribution"
doLast {
JSch {
addIdentity("webmaster", privateKey.encodeToByteArray(), null, null)
}.useSession(host, user) {
execute("sudo systemctl restart $serviceName")
}
}
}
} else {
logger.error("Host, user or ID are not defined. Skipping deployment tasks.")
}
sourceSets {
main {
resources.srcDir(project.rootDir.resolve("data"))
val staticSite by tasks.creating(JavaExec::class){
doFirst {
buildDir.resolve("public").deleteRecursively()
}
group = "application"
mainClass.set("center.sciprog.StaticRenderKt")
classpath = sourceSets["main"].runtimeClasspath
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 730 KiB

After

Width:  |  Height:  |  Size: 730 KiB

View File

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 141 KiB

View File

Before

Width:  |  Height:  |  Size: 897 KiB

After

Width:  |  Height:  |  Size: 897 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

BIN
data/common/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1 @@
{"name":"Scientific Programming Centre","short_name":"SPC","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
/*
Forty by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
/* Banner */
body.is-preload #banner:after {
opacity: 0.85; }
body.is-preload #banner > .inner {
-moz-filter: none;
-webkit-filter: none;
-ms-filter: none;
filter: none;
-moz-transform: none;
-webkit-transform: none;
-ms-transform: none;
transform: none;
opacity: 1; }
/*# sourceMappingURL=noscript.css.map */

View File

@ -0,0 +1,2 @@
/* breakpoints.js v1.0 | @ajlkn | MIT licensed */
var breakpoints=function(){"use strict";function e(e){t.init(e)}var t={list:null,media:{},events:[],init:function(e){t.list=e,window.addEventListener("resize",t.poll),window.addEventListener("orientationchange",t.poll),window.addEventListener("load",t.poll),window.addEventListener("fullscreenchange",t.poll)},active:function(e){var n,a,s,i,r,d,c;if(!(e in t.media)){if(">="==e.substr(0,2)?(a="gte",n=e.substr(2)):"<="==e.substr(0,2)?(a="lte",n=e.substr(2)):">"==e.substr(0,1)?(a="gt",n=e.substr(1)):"<"==e.substr(0,1)?(a="lt",n=e.substr(1)):"!"==e.substr(0,1)?(a="not",n=e.substr(1)):(a="eq",n=e),n&&n in t.list)if(i=t.list[n],Array.isArray(i)){if(r=parseInt(i[0]),d=parseInt(i[1]),isNaN(r)){if(isNaN(d))return;c=i[1].substr(String(d).length)}else c=i[0].substr(String(r).length);if(isNaN(r))switch(a){case"gte":s="screen";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: -1px)";break;case"not":s="screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (max-width: "+d+c+")"}else if(isNaN(d))switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen";break;case"gt":s="screen and (max-width: -1px)";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+")";break;default:s="screen and (min-width: "+r+c+")"}else switch(a){case"gte":s="screen and (min-width: "+r+c+")";break;case"lte":s="screen and (max-width: "+d+c+")";break;case"gt":s="screen and (min-width: "+(d+1)+c+")";break;case"lt":s="screen and (max-width: "+(r-1)+c+")";break;case"not":s="screen and (max-width: "+(r-1)+c+"), screen and (min-width: "+(d+1)+c+")";break;default:s="screen and (min-width: "+r+c+") and (max-width: "+d+c+")"}}else s="("==i.charAt(0)?"screen and "+i:i;t.media[e]=!!s&&s}return t.media[e]!==!1&&window.matchMedia(t.media[e]).matches},on:function(e,n){t.events.push({query:e,handler:n,state:!1}),t.active(e)&&n()},poll:function(){var e,n;for(e=0;e<t.events.length;e++)n=t.events[e],t.active(n.query)?n.state||(n.state=!0,n.handler()):n.state&&(n.state=!1)}};return e._=t,e.on=function(e,n){t.on(e,n)},e.active=function(e){return t.active(e)},e}();!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.breakpoints=t()}(this,function(){return breakpoints});

2
data/home/assets/js/browser.min.js vendored Normal file
View File

@ -0,0 +1,2 @@
/* browser.js v1.0.1 | @ajlkn | MIT licensed */
var browser=function(){"use strict";var t={name:null,version:null,os:null,osVersion:null,touch:null,mobile:null,_canUse:null,canUse:function(e){t._canUse||(t._canUse=document.createElement("div"));var n=t._canUse.style,r=e.charAt(0).toUpperCase()+e.slice(1);return e in n||"Moz"+r in n||"Webkit"+r in n||"O"+r in n||"ms"+r in n},init:function(){for(var e=navigator.userAgent,n="other",r=0,i=[["firefox",/Firefox\/([0-9\.]+)/],["bb",/BlackBerry.+Version\/([0-9\.]+)/],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/],["opera",/OPR\/([0-9\.]+)/],["opera",/Opera\/([0-9\.]+)/],["edge",/Edge\/([0-9\.]+)/],["safari",/Version\/([0-9\.]+).+Safari/],["chrome",/Chrome\/([0-9\.]+)/],["ie",/MSIE ([0-9]+)/],["ie",/Trident\/.+rv:([0-9]+)/]],o=0;o<i.length;o++)if(e.match(i[o][1])){n=i[o][0],r=parseFloat(RegExp.$1);break}for(t.name=n,t.version=r,n="other",i=[["ios",/([0-9_]+) like Mac OS X/,function(e){return e.replace("_",".").replace("_","")}],["ios",/CPU like Mac OS X/,function(e){return 0}],["wp",/Windows Phone ([0-9\.]+)/,null],["android",/Android ([0-9\.]+)/,null],["mac",/Macintosh.+Mac OS X ([0-9_]+)/,function(e){return e.replace("_",".").replace("_","")}],["windows",/Windows NT ([0-9\.]+)/,null],["bb",/BlackBerry.+Version\/([0-9\.]+)/,null],["bb",/BB[0-9]+.+Version\/([0-9\.]+)/,null],["linux",/Linux/,null],["bsd",/BSD/,null],["unix",/X11/,null]],o=r=0;o<i.length;o++)if(e.match(i[o][1])){n=i[o][0],r=parseFloat(i[o][2]?i[o][2](RegExp.$1):RegExp.$1);break}"mac"==n&&"ontouchstart"in window&&(1024==screen.width&&1366==screen.height||834==screen.width&&1112==screen.height||810==screen.width&&1080==screen.height||768==screen.width&&1024==screen.height)&&(n="ios"),t.os=n,t.osVersion=r,t.touch="wp"==t.os?0<navigator.msMaxTouchPoints:!!("ontouchstart"in window),t.mobile="wp"==t.os||"android"==t.os||"ios"==t.os||"bb"==t.os}};return t.init(),t}();!function(e,n){"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?module.exports=n():e.browser=n()}(this,function(){return browser});

2
data/home/assets/js/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
/* jquery.scrollex v0.2.1 | (c) @ajlkn | github.com/ajlkn/jquery.scrollex | MIT licensed */
!function(t){function e(t,e,n){return"string"==typeof t&&("%"==t.slice(-1)?t=parseInt(t.substring(0,t.length-1))/100*e:"vh"==t.slice(-2)?t=parseInt(t.substring(0,t.length-2))/100*n:"px"==t.slice(-2)&&(t=parseInt(t.substring(0,t.length-2)))),t}var n=t(window),i=1,o={};n.on("scroll",function(){var e=n.scrollTop();t.map(o,function(t){window.clearTimeout(t.timeoutId),t.timeoutId=window.setTimeout(function(){t.handler(e)},t.options.delay)})}).on("load",function(){n.trigger("scroll")}),jQuery.fn.scrollex=function(l){var s=t(this);if(0==this.length)return s;if(this.length>1){for(var r=0;r<this.length;r++)t(this[r]).scrollex(l);return s}if(s.data("_scrollexId"))return s;var a,u,h,c,p;switch(a=i++,u=jQuery.extend({top:0,bottom:0,delay:0,mode:"default",enter:null,leave:null,initialize:null,terminate:null,scroll:null},l),u.mode){case"top":h=function(t,e,n,i,o){return t>=i&&o>=t};break;case"bottom":h=function(t,e,n,i,o){return n>=i&&o>=n};break;case"middle":h=function(t,e,n,i,o){return e>=i&&o>=e};break;case"top-only":h=function(t,e,n,i,o){return i>=t&&n>=i};break;case"bottom-only":h=function(t,e,n,i,o){return n>=o&&o>=t};break;default:case"default":h=function(t,e,n,i,o){return n>=i&&o>=t}}return c=function(t){var i,o,l,s,r,a,u=this.state,h=!1,c=this.$element.offset();i=n.height(),o=t+i/2,l=t+i,s=this.$element.outerHeight(),r=c.top+e(this.options.top,s,i),a=c.top+s-e(this.options.bottom,s,i),h=this.test(t,o,l,r,a),h!=u&&(this.state=h,h?this.options.enter&&this.options.enter.apply(this.element):this.options.leave&&this.options.leave.apply(this.element)),this.options.scroll&&this.options.scroll.apply(this.element,[(o-r)/(a-r)])},p={id:a,options:u,test:h,handler:c,state:null,element:this,$element:s,timeoutId:null},o[a]=p,s.data("_scrollexId",p.id),p.options.initialize&&p.options.initialize.apply(this),s},jQuery.fn.unscrollex=function(){var e=t(this);if(0==this.length)return e;if(this.length>1){for(var n=0;n<this.length;n++)t(this[n]).unscrollex();return e}var i,l;return(i=e.data("_scrollexId"))?(l=o[i],window.clearTimeout(l.timeoutId),delete o[i],e.removeData("_scrollexId"),l.options.terminate&&l.options.terminate.apply(this),e):e}}(jQuery);

View File

@ -0,0 +1,2 @@
/* jquery.scrolly v1.0.0-dev | (c) @ajlkn | MIT licensed */
(function(e){function u(s,o){var u,a,f;if((u=e(s))[t]==0)return n;a=u[i]()[r];switch(o.anchor){case"middle":f=a-(e(window).height()-u.outerHeight())/2;break;default:case r:f=Math.max(a,0)}return typeof o[i]=="function"?f-=o[i]():f-=o[i],f}var t="length",n=null,r="top",i="offset",s="click.scrolly",o=e(window);e.fn.scrolly=function(i){var o,a,f,l,c=e(this);if(this[t]==0)return c;if(this[t]>1){for(o=0;o<this[t];o++)e(this[o]).scrolly(i);return c}l=n,f=c.attr("href");if(f.charAt(0)!="#"||f[t]<2)return c;a=jQuery.extend({anchor:r,easing:"swing",offset:0,parent:e("body,html"),pollOnce:!1,speed:1e3},i),a.pollOnce&&(l=u(f,a)),c.off(s).on(s,function(e){var t=l!==n?l:u(f,a);t!==n&&(e.preventDefault(),a.parent.stop().animate({scrollTop:t},a.speed,a.easing))})}})(jQuery);

335
data/home/assets/js/main.js Normal file
View File

@ -0,0 +1,335 @@
/*
Forty by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
(function($) {
var $window = $(window),
$body = $('body'),
$wrapper = $('#wrapper'),
$header = $('#header'),
$banner = $('#banner');
// Breakpoints.
breakpoints({
xlarge: ['1281px', '1680px' ],
large: ['981px', '1280px' ],
medium: ['737px', '980px' ],
small: ['481px', '736px' ],
xsmall: ['361px', '480px' ],
xxsmall: [null, '360px' ]
});
/**
* Applies parallax scrolling to an element's background image.
* @return {jQuery} jQuery object.
*/
$.fn._parallax = (browser.name == 'ie' || browser.name == 'edge' || browser.mobile) ? function() { return $(this) } : function(intensity) {
var $window = $(window),
$this = $(this);
if (this.length == 0 || intensity === 0)
return $this;
if (this.length > 1) {
for (var i=0; i < this.length; i++)
$(this[i])._parallax(intensity);
return $this;
}
if (!intensity)
intensity = 0.25;
$this.each(function() {
var $t = $(this),
on, off;
on = function() {
$t.css('background-position', 'center 100%, center 100%, center 0px');
$window
.on('scroll._parallax', function() {
var pos = parseInt($window.scrollTop()) - parseInt($t.position().top);
$t.css('background-position', 'center ' + (pos * (-1 * intensity)) + 'px');
});
};
off = function() {
$t
.css('background-position', '');
$window
.off('scroll._parallax');
};
breakpoints.on('<=medium', off);
breakpoints.on('>medium', on);
});
$window
.off('load._parallax resize._parallax')
.on('load._parallax resize._parallax', function() {
$window.trigger('scroll');
});
return $(this);
};
// Play initial animations on page load.
$window.on('load', function() {
window.setTimeout(function() {
$body.removeClass('is-preload');
}, 100);
});
// Clear transitioning state on unload/hide.
$window.on('unload pagehide', function() {
window.setTimeout(function() {
$('.is-transitioning').removeClass('is-transitioning');
}, 250);
});
// Fix: Enable IE-only tweaks.
if (browser.name == 'ie' || browser.name == 'edge')
$body.addClass('is-ie');
// Scrolly.
$('.scrolly').scrolly({
offset: function() {
return $header.height() - 2;
}
});
// Tiles.
var $tiles = $('.tiles > article');
$tiles.each(function() {
var $this = $(this),
$image = $this.find('.image'), $img = $image.find('img'),
$link = $this.find('.link'),
x;
// Image.
// Set image.
$this.css('background-image', 'url(' + $img.attr('src') + ')');
// Set position.
if (x = $img.data('position'))
$image.css('background-position', x);
// Hide original.
$image.hide();
// Link.
if ($link.length > 0) {
$x = $link.clone()
.text('')
.addClass('primary')
.appendTo($this);
$link = $link.add($x);
$link.on('click', function(event) {
var href = $link.attr('href');
// Prevent default.
event.stopPropagation();
event.preventDefault();
// Target blank?
if ($link.attr('target') == '_blank') {
// Open in new tab.
window.open(href);
}
// Otherwise ...
else {
// Start transitioning.
$this.addClass('is-transitioning');
$wrapper.addClass('is-transitioning');
// Redirect.
window.setTimeout(function() {
location.href = href;
}, 500);
}
});
}
});
// Header.
if ($banner.length > 0
&& $header.hasClass('alt')) {
$window.on('resize', function() {
$window.trigger('scroll');
});
$window.on('load', function() {
$banner.scrollex({
bottom: $header.height() + 10,
terminate: function() { $header.removeClass('alt'); },
enter: function() { $header.addClass('alt'); },
leave: function() { $header.removeClass('alt'); $header.addClass('reveal'); }
});
window.setTimeout(function() {
$window.triggerHandler('scroll');
}, 100);
});
}
// Banner.
$banner.each(function() {
var $this = $(this),
$image = $this.find('.image'), $img = $image.find('img');
// Parallax.
$this._parallax(0.275);
// Image.
if ($image.length > 0) {
// Set image.
$this.css('background-image', 'url(' + $img.attr('src') + ')');
// Hide original.
$image.hide();
}
});
// Menu.
var $menu = $('#menu'),
$menuInner;
$menu.wrapInner('<div class="inner"></div>');
$menuInner = $menu.children('.inner');
$menu._locked = false;
$menu._lock = function() {
if ($menu._locked)
return false;
$menu._locked = true;
window.setTimeout(function() {
$menu._locked = false;
}, 350);
return true;
};
$menu._show = function() {
if ($menu._lock())
$body.addClass('is-menu-visible');
};
$menu._hide = function() {
if ($menu._lock())
$body.removeClass('is-menu-visible');
};
$menu._toggle = function() {
if ($menu._lock())
$body.toggleClass('is-menu-visible');
};
$menuInner
.on('click', function(event) {
event.stopPropagation();
})
.on('click', 'a', function(event) {
var href = $(this).attr('href');
event.preventDefault();
event.stopPropagation();
// Hide.
$menu._hide();
// Redirect.
window.setTimeout(function() {
window.location.href = href;
}, 250);
});
$menu
.appendTo($body)
.on('click', function(event) {
event.stopPropagation();
event.preventDefault();
$body.removeClass('is-menu-visible');
})
.append('<a class="close" href="#menu">Close</a>');
$body
.on('click', 'a[href="#menu"]', function(event) {
event.stopPropagation();
event.preventDefault();
// Toggle.
$menu._toggle();
})
.on('click', function(event) {
// Hide.
$menu._hide();
})
.on('keydown', function(event) {
// Hide on escape.
if (event.keyCode == 27)
$menu._hide();
});
})(jQuery);

595
data/home/assets/js/util.js Normal file
View File

@ -0,0 +1,595 @@
(function($) {
/**
* Generate an indented list of links from a nav. Meant for use with panel().
* @return {jQuery} jQuery object.
*/
$.fn.navList = function() {
var $this = $(this);
$a = $this.find('a'),
b = [];
$a.each(function() {
var $this = $(this),
indent = Math.max(0, $this.parents('li').length - 1),
href = $this.attr('href'),
target = $this.attr('target');
b.push(
'<a ' +
'class="link depth-' + indent + '"' +
( (typeof target !== 'undefined' && target != '') ? ' target="' + target + '"' : '') +
( (typeof href !== 'undefined' && href != '') ? ' href="' + href + '"' : '') +
'>' +
'<span class="indent-' + indent + '"></span>' +
$this.text() +
'</a>'
);
});
return b.join('');
};
/**
* Panel-ify an element.
* @param {object} userConfig User config.
* @return {jQuery} jQuery object.
*/
$.fn.panel = function(userConfig) {
// No elements?
if (this.length == 0)
return $this;
// Multiple elements?
if (this.length > 1) {
for (var i=0; i < this.length; i++)
$(this[i]).panel(userConfig);
return $this;
}
// Vars.
var $this = $(this),
$body = $('body'),
$window = $(window),
id = $this.attr('id'),
config;
// Config.
config = $.extend({
// Delay.
delay: 0,
// Hide panel on link click.
hideOnClick: false,
// Hide panel on escape keypress.
hideOnEscape: false,
// Hide panel on swipe.
hideOnSwipe: false,
// Reset scroll position on hide.
resetScroll: false,
// Reset forms on hide.
resetForms: false,
// Side of viewport the panel will appear.
side: null,
// Target element for "class".
target: $this,
// Class to toggle.
visibleClass: 'visible'
}, userConfig);
// Expand "target" if it's not a jQuery object already.
if (typeof config.target != 'jQuery')
config.target = $(config.target);
// Panel.
// Methods.
$this._hide = function(event) {
// Already hidden? Bail.
if (!config.target.hasClass(config.visibleClass))
return;
// If an event was provided, cancel it.
if (event) {
event.preventDefault();
event.stopPropagation();
}
// Hide.
config.target.removeClass(config.visibleClass);
// Post-hide stuff.
window.setTimeout(function() {
// Reset scroll position.
if (config.resetScroll)
$this.scrollTop(0);
// Reset forms.
if (config.resetForms)
$this.find('form').each(function() {
this.reset();
});
}, config.delay);
};
// Vendor fixes.
$this
.css('-ms-overflow-style', '-ms-autohiding-scrollbar')
.css('-webkit-overflow-scrolling', 'touch');
// Hide on click.
if (config.hideOnClick) {
$this.find('a')
.css('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
$this
.on('click', 'a', function(event) {
var $a = $(this),
href = $a.attr('href'),
target = $a.attr('target');
if (!href || href == '#' || href == '' || href == '#' + id)
return;
// Cancel original event.
event.preventDefault();
event.stopPropagation();
// Hide panel.
$this._hide();
// Redirect to href.
window.setTimeout(function() {
if (target == '_blank')
window.open(href);
else
window.location.href = href;
}, config.delay + 10);
});
}
// Event: Touch stuff.
$this.on('touchstart', function(event) {
$this.touchPosX = event.originalEvent.touches[0].pageX;
$this.touchPosY = event.originalEvent.touches[0].pageY;
})
$this.on('touchmove', function(event) {
if ($this.touchPosX === null
|| $this.touchPosY === null)
return;
var diffX = $this.touchPosX - event.originalEvent.touches[0].pageX,
diffY = $this.touchPosY - event.originalEvent.touches[0].pageY,
th = $this.outerHeight(),
ts = ($this.get(0).scrollHeight - $this.scrollTop());
// Hide on swipe?
if (config.hideOnSwipe) {
var result = false,
boundary = 20,
delta = 50;
switch (config.side) {
case 'left':
result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX > delta);
break;
case 'right':
result = (diffY < boundary && diffY > (-1 * boundary)) && (diffX < (-1 * delta));
break;
case 'top':
result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY > delta);
break;
case 'bottom':
result = (diffX < boundary && diffX > (-1 * boundary)) && (diffY < (-1 * delta));
break;
default:
break;
}
if (result) {
$this.touchPosX = null;
$this.touchPosY = null;
$this._hide();
return false;
}
}
// Prevent vertical scrolling past the top or bottom.
if (($this.scrollTop() < 0 && diffY < 0)
|| (ts > (th - 2) && ts < (th + 2) && diffY > 0)) {
event.preventDefault();
event.stopPropagation();
}
});
// Event: Prevent certain events inside the panel from bubbling.
$this.on('click touchend touchstart touchmove', function(event) {
event.stopPropagation();
});
// Event: Hide panel if a child anchor tag pointing to its ID is clicked.
$this.on('click', 'a[href="#' + id + '"]', function(event) {
event.preventDefault();
event.stopPropagation();
config.target.removeClass(config.visibleClass);
});
// Body.
// Event: Hide panel on body click/tap.
$body.on('click touchend', function(event) {
$this._hide(event);
});
// Event: Toggle.
$body.on('click', 'a[href="#' + id + '"]', function(event) {
event.preventDefault();
event.stopPropagation();
config.target.toggleClass(config.visibleClass);
});
// Window.
// Event: Hide on ESC.
if (config.hideOnEscape)
$window.on('keydown', function(event) {
if (event.keyCode == 27)
$this._hide(event);
});
return $this;
};
/**
* Apply "placeholder" attribute polyfill to one or more forms.
* @return {jQuery} jQuery object.
*/
$.fn.placeholder = function() {
// Browser natively supports placeholders? Bail.
if (typeof (document.createElement('input')).placeholder != 'undefined')
return $(this);
// No elements?
if (this.length == 0)
return $this;
// Multiple elements?
if (this.length > 1) {
for (var i=0; i < this.length; i++)
$(this[i]).placeholder();
return $this;
}
// Vars.
var $this = $(this);
// Text, TextArea.
$this.find('input[type=text],textarea')
.each(function() {
var i = $(this);
if (i.val() == ''
|| i.val() == i.attr('placeholder'))
i
.addClass('polyfill-placeholder')
.val(i.attr('placeholder'));
})
.on('blur', function() {
var i = $(this);
if (i.attr('name').match(/-polyfill-field$/))
return;
if (i.val() == '')
i
.addClass('polyfill-placeholder')
.val(i.attr('placeholder'));
})
.on('focus', function() {
var i = $(this);
if (i.attr('name').match(/-polyfill-field$/))
return;
if (i.val() == i.attr('placeholder'))
i
.removeClass('polyfill-placeholder')
.val('');
});
// Password.
$this.find('input[type=password]')
.each(function() {
var i = $(this);
var x = $(
$('<div>')
.append(i.clone())
.remove()
.html()
.replace(/type="password"/i, 'type="text"')
.replace(/type=password/i, 'type=text')
);
if (i.attr('id') != '')
x.attr('id', i.attr('id') + '-polyfill-field');
if (i.attr('name') != '')
x.attr('name', i.attr('name') + '-polyfill-field');
x.addClass('polyfill-placeholder')
.val(x.attr('placeholder')).insertAfter(i);
if (i.val() == '')
i.hide();
else
x.hide();
i
.on('blur', function(event) {
event.preventDefault();
var x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');
if (i.val() == '') {
i.hide();
x.show();
}
});
x
.on('focus', function(event) {
event.preventDefault();
var i = x.parent().find('input[name=' + x.attr('name').replace('-polyfill-field', '') + ']');
x.hide();
i
.show()
.focus();
})
.on('keypress', function(event) {
event.preventDefault();
x.val('');
});
});
// Events.
$this
.on('submit', function() {
$this.find('input[type=text],input[type=password],textarea')
.each(function(event) {
var i = $(this);
if (i.attr('name').match(/-polyfill-field$/))
i.attr('name', '');
if (i.val() == i.attr('placeholder')) {
i.removeClass('polyfill-placeholder');
i.val('');
}
});
})
.on('reset', function(event) {
event.preventDefault();
$this.find('select')
.val($('option:first').val());
$this.find('input,textarea')
.each(function() {
var i = $(this),
x;
i.removeClass('polyfill-placeholder');
switch (this.type) {
case 'submit':
case 'reset':
break;
case 'password':
i.val(i.attr('defaultValue'));
x = i.parent().find('input[name=' + i.attr('name') + '-polyfill-field]');
if (i.val() == '') {
i.hide();
x.show();
}
else {
i.show();
x.hide();
}
break;
case 'checkbox':
case 'radio':
i.attr('checked', i.attr('defaultValue'));
break;
case 'text':
case 'textarea':
i.val(i.attr('defaultValue'));
if (i.val() == '') {
i.addClass('polyfill-placeholder');
i.val(i.attr('placeholder'));
}
break;
default:
i.val(i.attr('defaultValue'));
break;
}
});
});
return $this;
};
/**
* Moves elements to/from the first positions of their respective parents.
* @param {jQuery} $elements Elements (or selector) to move.
* @param {bool} condition If true, moves elements to the top. Otherwise, moves elements back to their original locations.
*/
$.prioritize = function($elements, condition) {
var key = '__prioritize';
// Expand $elements if it's not already a jQuery object.
if (typeof $elements != 'jQuery')
$elements = $($elements);
// Step through elements.
$elements.each(function() {
var $e = $(this), $p,
$parent = $e.parent();
// No parent? Bail.
if ($parent.length == 0)
return;
// Not moved? Move it.
if (!$e.data(key)) {
// Condition is false? Bail.
if (!condition)
return;
// Get placeholder (which will serve as our point of reference for when this element needs to move back).
$p = $e.prev();
// Couldn't find anything? Means this element's already at the top, so bail.
if ($p.length == 0)
return;
// Move element to top of parent.
$e.prependTo($parent);
// Mark element as moved.
$e.data(key, $p);
}
// Moved already?
else {
// Condition is true? Bail.
if (condition)
return;
$p = $e.data(key);
// Move element back to its original location (using our placeholder).
$e.insertAfter($p);
// Unmark element as moved.
$e.removeData(key);
}
});
};
// Remove `border-bottom` from all `<a>` elements that also contain an `<img>`
document.querySelectorAll("a > img, a > span > img").forEach(
imgEl => {
while (imgEl.tagName != "A") imgEl = imgEl.parentElement;
imgEl.style.borderBottom = "none";
}
);
})(jQuery);

View File

@ -0,0 +1,47 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Basic */
// MSIE: Required for IEMobile.
@-ms-viewport {
width: device-width;
}
// MSIE: Prevents scrollbar from overlapping content.
body {
-ms-overflow-style: scrollbar;
}
// Ensures page width is always >=320px.
@include breakpoint('<=xsmall') {
html, body {
min-width: 320px;
}
}
// Set box model to border-box.
// Based on css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
background: _palette(bg);
// Stops initial animations until page loads.
&.is-preload {
*, *:before, *:after {
@include vendor('animation', 'none !important');
@include vendor('transition', 'none !important');
}
}
}

View File

@ -0,0 +1,76 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
// Reset.
// Based on meyerweb.com/eric/tools/css/reset (v2.0 | 20110126 | License: public domain)
html, body, div, span, applet, object,
iframe, h1, h2, h3, h4, h5, h6, p, blockquote,
pre, a, abbr, acronym, address, big, cite,
code, del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var, b,
u, i, center, dl, dt, dd, ol, ul, li, fieldset,
form, label, legend, table, caption, tbody,
tfoot, thead, tr, th, td, article, aside,
canvas, details, embed, figure, figcaption,
footer, header, hgroup, menu, nav, output, ruby,
section, summary, time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style:none;
}
blockquote, q {
quotes: none;
&:before,
&:after {
content: '';
content: none;
}
}
table {
border-collapse: collapse;
border-spacing: 0;
}
body {
-webkit-text-size-adjust: none;
}
mark {
background-color: transparent;
color: inherit;
}
input::-moz-focus-inner {
border: 0;
padding: 0;
}
input, select, textarea {
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
appearance: none;
}

View File

@ -0,0 +1,177 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Type */
body, input, select, textarea {
color: _palette(fg);
font-family: _font(family);
font-size: 17pt;
font-weight: _font(weight);
letter-spacing: _font(letter-spacing);
line-height: 1.65;
@include breakpoint('<=xlarge') {
font-size: 14pt;
}
@include breakpoint('<=large') {
font-size: 12pt;
}
@include breakpoint('<=xxsmall') {
font-size: 11pt;
}
}
a {
@include vendor('transition', (
'color #{_duration(transition)} ease-in-out',
'border-bottom-color #{_duration(transition)} ease-in-out'
));
border-bottom: dotted 1px;
color: inherit;
text-decoration: none;
&:hover {
border-bottom-color: transparent;
color: _palette(highlight) !important;
}
&:active {
color: desaturate(darken(_palette(highlight), 15), 5) !important;
}
}
strong, b {
color: _palette(fg-bold);
font-weight: _font(weight-bold);
}
em, i {
font-style: italic;
}
p {
margin: 0 0 _size(element-margin) 0;
}
h1, h2, h3, h4, h5, h6 {
color: _palette(fg-bold);
font-weight: _font(weight-bold);
line-height: 1.65;
margin: 0 0 (_size(element-margin) * 0.5) 0;
a {
color: inherit;
border-bottom: 0;
}
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 1.75em;
}
h3 {
font-size: 1.35em;
}
h4 {
font-size: 1.1em;
}
h5 {
font-size: 0.9em;
}
h6 {
font-size: 0.7em;
}
@include breakpoint('<=small') {
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.25em;
}
}
sub {
font-size: 0.8em;
position: relative;
top: 0.5em;
}
sup {
font-size: 0.8em;
position: relative;
top: -0.5em;
}
blockquote {
border-left: solid 4px _palette(border);
font-style: italic;
margin: 0 0 _size(element-margin) 0;
padding: (_size(element-margin) / 4) 0 (_size(element-margin) / 4) _size(element-margin);
ul:last-child {
margin-bottom: .25em;
}
}
code {
background: _palette(border-bg);
font-family: _font(family-fixed);
font-size: 0.9em;
margin: 0 0.25em;
padding: 0.25em 0.65em;
}
pre {
-webkit-overflow-scrolling: touch;
font-family: _font(family-fixed);
font-size: 0.9em;
margin: 0 0 _size(element-margin) 0;
code {
display: block;
line-height: 1.75;
padding: 1em 1.5em;
overflow-x: auto;
}
}
hr {
border: 0;
border-bottom: solid 1px _palette(border);
margin: _size(element-margin) 0;
&.major {
margin: (_size(element-margin) * 1.5) 0;
}
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}

View File

@ -0,0 +1,63 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Actions */
ul.actions {
@include vendor('display', 'flex');
cursor: default;
list-style: none;
margin-left: (_size(element-margin) * -0.5);
padding-left: 0;
li {
padding: 0 0 0 (_size(element-margin) * 0.5);
vertical-align: middle;
}
&.special {
@include vendor('justify-content', 'center');
width: 100%;
margin-left: 0;
li {
&:first-child {
padding-left: 0;
}
}
}
&.stacked {
@include vendor('flex-direction', 'column');
margin-left: 0;
li {
padding: (_size(element-margin) * 0.65) 0 0 0;
&:first-child {
padding-top: 0;
}
}
}
&.fit {
width: calc(100% + #{_size(element-margin) * 0.5});
li {
@include vendor('flex-grow', '1');
@include vendor('flex-shrink', '1');
width: 100%;
> * {
width: 100%;
}
}
&.stacked {
width: 100%;
}
}
}

View File

@ -0,0 +1,25 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Box */
.box {
border: solid 1px _palette(border);
margin-bottom: _size(element-margin);
padding: 1.5em;
> :last-child,
> :last-child > :last-child,
> :last-child > :last-child > :last-child {
margin-bottom: 0;
}
&.alt {
border: 0;
border-radius: 0;
padding: 0;
}
}

View File

@ -0,0 +1,130 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Button */
input[type="submit"],
input[type="reset"],
input[type="button"],
button,
.button {
@include vendor('appearance', 'none');
@include vendor('transition', (
'background-color #{_duration(transition)} ease-in-out',
'box-shadow #{_duration(transition)} ease-in-out',
'color #{_duration(transition)} ease-in-out'
));
background-color: transparent;
border: 0;
border-radius: 0;
box-shadow: inset 0 0 0 2px _palette(fg-bold);
color: _palette(fg-bold);
cursor: pointer;
display: inline-block;
font-size: 0.8em;
font-weight: _font(weight-bold);
height: 3.5em;
letter-spacing: _font(letter-spacing-alt);
line-height: 3.5em;
padding: 0 1.75em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
white-space: nowrap;
&:hover, &:active {
box-shadow: inset 0 0 0 2px _palette(highlight);
color: _palette(highlight);
}
&:active {
background-color: transparentize(_palette(highlight), 0.9);
box-shadow: inset 0 0 0 2px desaturate(darken(_palette(highlight), 15), 5);
color: desaturate(darken(_palette(highlight), 15), 5);
}
&.icon {
&:before {
margin-right: 0.5em;
}
}
&.fit {
width: 100%;
}
&.small {
font-size: 0.6em;
}
&.large {
font-size: 1.25em;
height: 3em;
line-height: 3em;
}
&.next {
padding-right: 4.5em;
position: relative;
&:before, &:after {
@include vendor('transition', 'opacity #{_duration(transition)} ease-in-out');
background-position: center right;
background-repeat: no-repeat;
background-size: 36px 24px;
content: '';
display: block;
height: 100%;
position: absolute;
right: 1.5em;
top: 0;
vertical-align: middle;
width: 36px;
}
&:before {
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="36px" height="24px" viewBox="0 0 36 24" zoomAndPan="disable"><style>line { stroke: #{_palette(fg-bold)}; stroke-width: 2px; }</style><line x1="0" y1="12" x2="34" y2="12" /><line x1="25" y1="4" x2="34" y2="12.5" /><line x1="25" y1="20" x2="34" y2="11.5" /></svg>');
}
&:after {
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="36px" height="24px" viewBox="0 0 36 24" zoomAndPan="disable"><style>line { stroke: #{_palette(highlight)}; stroke-width: 2px; }</style><line x1="0" y1="12" x2="34" y2="12" /><line x1="25" y1="4" x2="34" y2="12.5" /><line x1="25" y1="20" x2="34" y2="11.5" /></svg>');
opacity: 0;
z-index: 1;
}
&:hover, &:active {
&:after {
opacity: 1;
}
}
@include breakpoint('<=large') {
padding-right: 5em;
}
}
&.primary {
background-color: _palette(fg-bold);
box-shadow: none;
color: _palette(bg);
&:hover, &:active {
background-color: _palette(highlight);
color: _palette(bg) !important;
}
&:active {
background-color: desaturate(darken(_palette(highlight), 15), 5);
}
}
&.disabled,
&:disabled {
@include vendor('pointer-events', 'none');
cursor: default;
opacity: 0.25;
}
}

View File

@ -0,0 +1,23 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Contact Method */
.contact-method {
margin: 0 0 _size(element-margin) 0;
padding-left: 3.25em;
position: relative;
.icon {
left: 0;
position: absolute;
top: 0;
}
h3 {
margin: 0 0 (_size(element-margin) * 0.25) 0;
}
}

View File

@ -0,0 +1,234 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Form */
form {
margin: 0 0 _size(element-margin) 0;
> :last-child {
margin-bottom: 0;
}
> .fields {
$gutter: (_size(element-margin) * 0.75);
@include vendor('display', 'flex');
@include vendor('flex-wrap', 'wrap');
width: calc(100% + #{$gutter * 2});
margin: ($gutter * -1) 0 _size(element-margin) ($gutter * -1);
> .field {
@include vendor('flex-grow', '0');
@include vendor('flex-shrink', '0');
padding: $gutter 0 0 $gutter;
width: calc(100% - #{$gutter * 1});
&.half {
width: calc(50% - #{$gutter * 0.5});
}
&.third {
width: calc(#{100% / 3} - #{$gutter * (1 / 3)});
}
&.quarter {
width: calc(25% - #{$gutter * 0.25});
}
}
}
@include breakpoint('<=xsmall') {
> .fields {
$gutter: (_size(element-margin) * 0.75);
width: calc(100% + #{$gutter * 2});
margin: ($gutter * -1) 0 _size(element-margin) ($gutter * -1);
> .field {
padding: $gutter 0 0 $gutter;
width: calc(100% - #{$gutter * 1});
&.half {
width: calc(100% - #{$gutter * 1});
}
&.third {
width: calc(100% - #{$gutter * 1});
}
&.quarter {
width: calc(100% - #{$gutter * 1});
}
}
}
}
}
label {
color: _palette(fg-bold);
display: block;
font-size: 0.8em;
font-weight: _font(weight-bold);
letter-spacing: _font(letter-spacing-alt);
margin: 0 0 (_size(element-margin) * 0.5) 0;
text-transform: uppercase;
}
input[type="text"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="search"],
input[type="url"],
select,
textarea {
@include vendor('appearance', 'none');
background: _palette(border-bg);
border: none;
border-radius: 0;
color: inherit;
display: block;
outline: 0;
padding: 0 1em;
text-decoration: none;
width: 100%;
&:invalid {
box-shadow: none;
}
&:focus {
border-color: _palette(highlight);
box-shadow: 0 0 0 2px _palette(highlight);
}
}
select {
background-image: svg-url("<svg xmlns='http://www.w3.org/2000/svg' width='40' height='40' preserveAspectRatio='none' viewBox='0 0 40 40'><path d='M9.4,12.3l10.4,10.4l10.4-10.4c0.2-0.2,0.5-0.4,0.9-0.4c0.3,0,0.6,0.1,0.9,0.4l3.3,3.3c0.2,0.2,0.4,0.5,0.4,0.9 c0,0.4-0.1,0.6-0.4,0.9L20.7,31.9c-0.2,0.2-0.5,0.4-0.9,0.4c-0.3,0-0.6-0.1-0.9-0.4L4.3,17.3c-0.2-0.2-0.4-0.5-0.4-0.9 c0-0.4,0.1-0.6,0.4-0.9l3.3-3.3c0.2-0.2,0.5-0.4,0.9-0.4S9.1,12.1,9.4,12.3z' fill='#{_palette(border)}' /></svg>");
background-size: 1.25rem;
background-repeat: no-repeat;
background-position: calc(100% - 1rem) center;
height: _size(element-height);
padding-right: _size(element-height);
text-overflow: ellipsis;
option {
color: _palette(fg-bold);
background: _palette(bg);
}
&:focus {
&::-ms-value {
background-color: transparent;
}
}
&::-ms-expand {
display: none;
}
}
input[type="text"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="search"],
input[type="url"],
select {
height: _size(element-height);
}
textarea {
padding: 0.75em 1em;
}
input[type="checkbox"],
input[type="radio"], {
@include vendor('appearance', 'none');
display: block;
float: left;
margin-right: -2em;
opacity: 0;
width: 1em;
z-index: -1;
& + label {
@include icon(false, solid);
color: _palette(fg);
cursor: pointer;
display: inline-block;
font-weight: _font(weight);
padding-left: (_size(element-height) * 0.6) + 1em;
padding-right: 0.75em;
position: relative;
&:before {
background: _palette(border-bg);
content: '';
display: inline-block;
font-size: 0.8em;
height: (_size(element-height) * 0.75);
left: 0;
letter-spacing: 0;
line-height: (_size(element-height) * 0.75);
position: absolute;
text-align: center;
top: 0;
width: (_size(element-height) * 0.75);
}
}
&:checked + label {
&:before {
background: _palette(fg-bold);
border-color: _palette(highlight);
content: '\f00c';
color: _palette(bg);
}
}
&:focus + label {
&:before {
box-shadow: 0 0 0 2px _palette(highlight);
}
}
}
input[type="checkbox"] {
& + label {
&:before {
}
}
}
input[type="radio"] {
& + label {
&:before {
border-radius: 100%;
}
}
}
::-webkit-input-placeholder {
color: _palette(fg-light) !important;
opacity: 1.0;
}
:-moz-placeholder {
color: _palette(fg-light) !important;
opacity: 1.0;
}
::-moz-placeholder {
color: _palette(fg-light) !important;
opacity: 1.0;
}
:-ms-input-placeholder {
color: _palette(fg-light) !important;
opacity: 1.0;
}

View File

@ -0,0 +1,66 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Icon */
.icon {
@include icon;
border-bottom: none;
position: relative;
> .label {
display: none;
}
&:before {
line-height: inherit;
}
&.solid {
&:before {
font-weight: 900;
}
}
&.brands {
&:before {
font-family: 'Font Awesome 5 Brands';
}
}
&.alt {
&:before {
background-color: _palette(fg-bold);
border-radius: 100%;
color: _palette(bg);
display: inline-block;
height: 2em;
line-height: 2em;
text-align: center;
width: 2em;
}
}
}
a.icon {
&.alt {
&:before {
@include vendor('transition', 'background-color #{_duration(transition)} ease-in-out');
}
&:hover {
&:before {
background-color: _palette(accent1);
}
}
&:active {
&:before {
background-color: desaturate(darken(_palette(accent1), 15), 5);
}
}
}
}

View File

@ -0,0 +1,28 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Icons */
ul.icons {
cursor: default;
list-style: none;
padding-left: 0;
li {
display: inline-block;
padding: 0 1em 0 0;
&:last-child {
padding-right: 0;
}
}
@include breakpoint('<=small') {
li {
padding: 0 0.75em 0 0;
}
}
}

View File

@ -0,0 +1,62 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Image */
.image {
border: 0;
display: inline-block;
position: relative;
img {
display: block;
}
&.left,
&.right {
max-width: 30%;
img {
width: 100%;
}
}
&.left {
float: left;
margin: 0 1.5em 1.25em 0;
top: 0.25em;
}
&.right {
float: right;
margin: 0 0 1.25em 1.5em;
top: 0.25em;
}
&.fit {
display: block;
margin: 0 0 _size(element-margin) 0;
width: 100%;
img {
width: 100%;
}
}
&.main {
display: block;
margin: (_size(element-margin) * 1.25) 0;
width: 100%;
img {
width: 100%;
}
@include breakpoint('<=small') {
margin: (_size(element-margin) * 0.75) 0;
}
}
}

View File

@ -0,0 +1,56 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* List */
ol {
list-style: decimal;
margin: 0 0 _size(element-margin) 0;
list-style-position: inside;
li {
padding-left: 0.25em;
}
}
ul {
list-style: disc;
margin: 0 0 _size(element-margin) 0;
list-style-position: inside;
li {
padding-left: 0.5em;
}
&.alt {
list-style: none;
padding-left: 0;
li {
border-top: solid 1px _palette(border);
padding: 0.5em 0;
&:first-child {
border-top: 0;
padding-top: 0;
}
}
}
}
dl {
margin: 0 0 _size(element-margin) 0;
dt {
display: block;
font-weight: _font(weight-bold);
margin: 0 0 (_size(element-margin) * 0.5) 0;
}
dd {
margin-left: _size(element-margin);
}
}

View File

@ -0,0 +1,70 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Pagination */
ul.pagination {
cursor: default;
list-style: none;
padding-left: 0;
li {
display: inline-block;
padding-left: 0;
vertical-align: middle;
> .page {
@include vendor('transition', (
'background-color #{_duration(transition)} ease-in-out',
'color #{_duration(transition)} ease-in-out'
));
border-bottom: 0;
display: inline-block;
font-size: 0.8em;
font-weight: _font(weight-bold);
height: 1.5em;
line-height: 1.5em;
margin: 0 0.125em;
min-width: 1.5em;
padding: 0 0.5em;
text-align: center;
&.active {
background-color: _palette(fg-bold);
color: _palette(bg);
&:hover {
background-color: _palette(highlight);
color: _palette(bg) !important;
}
&:active {
background-color: desaturate(darken(_palette(highlight), 15), 5);
}
}
}
&:first-child {
padding-right: 0.75em;
}
&:last-child {
padding-left: 0.75em;
}
}
@include breakpoint('<=xsmall') {
li {
&:nth-child(n+2):nth-last-child(n+2) {
display: none;
}
&:first-child {
padding-right: 0;
}
}
}
}

View File

@ -0,0 +1,31 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Row */
.row {
@include html-grid(2em);
@include breakpoint('<=xlarge') {
@include html-grid(2em, 'xlarge');
}
@include breakpoint('<=large') {
@include html-grid(1.5em, 'large');
}
@include breakpoint('<=medium') {
@include html-grid(1.5em, 'medium');
}
@include breakpoint('<=small') {
@include html-grid(1.25em, 'small');
}
@include breakpoint('<=xsmall') {
@include html-grid(1.25em, 'xsmall');
}
}

View File

@ -0,0 +1,69 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Section/Article */
section, article {
&.special {
text-align: center;
}
}
header {
&.major {
width: -moz-max-content;
width: -webkit-max-content;
width: -ms-max-content;
width: max-content;
margin-bottom: _size(element-margin);
> :first-child {
margin-bottom: 0;
width: calc(100% + 0.5em);
&:after {
content: '';
background-color: _palette(fg-bold);
display: block;
height: 2px;
margin: 0.325em 0 0.5em 0;
width: 100%;
}
}
> p {
font-size: 0.7em;
font-weight: _font(weight-bold);
letter-spacing: _font(letter-spacing-alt);
margin-bottom: 0;
text-transform: uppercase;
}
body.is-ie & {
> :first-child {
&:after {
max-width: 9em;
}
}
> h1 {
&:after {
max-width: 100% !important;
}
}
}
}
@include breakpoint('<=small') {
&.major {
> p {
br {
display: none;
}
}
}
}
}

View File

@ -0,0 +1,119 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Spotlights */
.spotlights {
border-top: 0 !important;
& + * {
border-top: 0 !important;
}
> section {
@include vendor('display', 'flex');
@include vendor('flex-direction', 'row');
background-color: desaturate(lighten(_palette(bg-alt), 2), 1);
> .image {
background-position: center center;
background-size: cover;
border-radius: 0;
display: block;
position: relative;
width: 30%;
img {
border-radius: 0;
display: block;
width: 100%;
}
&:before {
background: transparentize(_palette(bg), 0.1);
content: '';
display: block;
height: 100%;
left: 0;
opacity: 0;
position: absolute;
top: 0;
width: 100%;
}
}
> .content {
@include vendor('display', 'flex');
@include vendor('flex-direction', 'column');
@include vendor('justify-content', 'center');
@include vendor('align-items', 'center');
@include padding(2em, 3em);
width: 70%;
> .inner {
margin: 0 auto;
max-width: 100%;
width: _size(inner);
}
}
&:nth-child(2n) {
@include vendor('flex-direction', 'row-reverse');
background-color: desaturate(lighten(_palette(bg-alt), 4), 2);
> .content {
@include vendor('align-items', 'flex-end');
}
}
}
@include breakpoint('<=xlarge') {
> section {
> .image {
width: 40%;
}
> .content {
width: 60%;
}
}
}
@include breakpoint('<=large') {
> section {
> .image {
width: 45%;
}
> .content {
width: 55%;
}
}
}
@include breakpoint('<=medium') {
> section {
display: block;
> .image {
width: 100%;
}
> .content {
@include padding(4em, 3em);
width: 100%;
}
}
}
@include breakpoint('<=small') {
> section {
> .content {
@include padding(3em, 1.5em);
}
}
}
}

View File

@ -0,0 +1,81 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Table */
.table-wrapper {
-webkit-overflow-scrolling: touch;
overflow-x: auto;
}
table {
margin: 0 0 _size(element-margin) 0;
width: 100%;
tbody {
tr {
border: solid 1px _palette(border);
border-left: 0;
border-right: 0;
&:nth-child(2n + 1) {
background-color: _palette(border-bg);
}
}
}
td {
padding: 0.75em 0.75em;
}
th {
color: _palette(fg-bold);
font-size: 0.9em;
font-weight: _font(weight-bold);
padding: 0 0.75em 0.75em 0.75em;
text-align: left;
}
thead {
border-bottom: solid 2px _palette(border);
}
tfoot {
border-top: solid 2px _palette(border);
}
&.alt {
border-collapse: separate;
tbody {
tr {
td {
border: solid 1px _palette(border);
border-left-width: 0;
border-top-width: 0;
&:first-child {
border-left-width: 1px;
}
}
&:first-child {
td {
border-top-width: 1px;
}
}
}
}
thead {
border-bottom: 0;
}
tfoot {
border-top: 0;
}
}
}

View File

@ -0,0 +1,183 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Tiles */
.tiles {
@include vendor('display', 'flex');
@include vendor('flex-wrap', 'wrap');
border-top: 0 !important;
& + * {
border-top: 0 !important;
}
article {
@include vendor('align-items', 'center');
@include vendor('display', 'flex');
@include vendor('transition', (
'transform 0.25s ease',
'opacity 0.25s ease',
'filter 1s ease',
'-webkit-filter 1s ease'
));
@include padding(4em, 4em);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
cursor: default;
height: 40vh;
max-height: 40em;
min-height: 23em;
overflow: hidden;
position: relative;
width: 40%;
.image {
display: none;
}
header {
position: relative;
z-index: 3;
}
h3 {
font-size: 1.75em;
a {
&:hover {
color: inherit !important;
}
}
}
.link.primary {
border: 0;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 4;
}
&:before {
@include vendor('transition', 'opacity 0.5s ease');
bottom: 0;
content: '';
display: block;
height: 100%;
left: 0;
opacity: 0.85;
position: absolute;
width: 100%;
z-index: 2;
}
&:after {
background-color: transparentize(_palette(bg), 0.75);
content: '';
display: block;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 1;
}
&:hover {
&:before {
opacity: 0;
}
}
&.is-transitioning {
@include vendor('transform', 'scale(0.95)');
@include vendor('filter', 'blur(0.5em)');
opacity: 0;
}
&:nth-child(4n - 1),
&:nth-child(4n - 2) {
width: 60%;
}
&:nth-child(6n - 5) {
&:before {
background-color: _palette(accent1);
}
}
&:nth-child(6n - 4) {
&:before {
background-color: _palette(accent2);
}
}
&:nth-child(6n - 3) {
&:before {
background-color: _palette(accent3);
}
}
&:nth-child(6n - 2) {
&:before {
background-color: _palette(accent4);
}
}
&:nth-child(6n - 1) {
&:before {
background-color: _palette(accent5);
}
}
&:nth-child(6n) {
&:before {
background-color: _palette(accent6);
}
}
}
@include breakpoint('<=large') {
article {
@include padding(4em, 3em);
height: 30vh;
max-height: 30em;
min-height: 20em;
}
}
@include breakpoint('<=medium') {
article {
width: 50% !important;
}
}
@include breakpoint('<=small') {
article {
@include padding(3em, 1.5em);
height: 16em;
max-height: none;
min-height: 0;
h3 {
font-size: 1.5em;
}
}
}
@include breakpoint('<=xsmall') {
display: block;
article {
height: 20em;
width: 100% !important;
}
}
}

View File

@ -0,0 +1,15 @@
// A custom style for main page block with SPC creation info
#main div.inner.home_creationinfo {
display: flex;
justify-content: center;
align-items: center;
padding-top: 2.25em;
a > span {
display: block;
}
p {
margin: 0 0 0 1em;
}
}

View File

@ -0,0 +1,177 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Banner */
#banner {
@include vendor('align-items', 'center');
@include vendor('background-image', 'url("../../images/banner.jpg")');
@include vendor('display', 'flex');
@include padding(4em, 0, (2em, 0, 0, 0));
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
border-bottom: 0 !important;
cursor: default;
height: 60vh;
margin-bottom: -3.25em;
max-height: 32em;
min-height: 22em;
position: relative;
top: -3.25em;
&:after {
@include vendor('transition', 'opacity #{_duration(banner)} ease');
@include vendor('transition-delay', '0.75s');
@include vendor('pointer-events', 'none');
background-color: _palette(bg);
content: '';
display: block;
height: 100%;
left: 0;
opacity: 0.85;
position: absolute;
top: 0;
width: 100%;
z-index: 1;
}
h1 {
font-size: 3.25em;
}
> .inner {
@include vendor('transition', (
'opacity 1.5s ease',
'transform 0.5s ease-out',
'filter 0.5s ease',
'-webkit-filter 0.5s ease'
));
padding: 0 !important;
position: relative;
z-index: 2;
.image {
display: none;
}
header {
width: auto;
> :first-child {
width: auto;
&:after {
max-width: 100%;
}
}
}
.content {
@include vendor('display', 'flex');
@include vendor('align-items', 'center');
margin: 0 0 _size(element-margin) 0;
> * {
margin-right: 1.5em;
margin-bottom: 0;
}
> :last-child {
margin-right: 0;
}
p {
font-size: 0.7em;
font-weight: _font(weight-bold);
letter-spacing: _font(letter-spacing-alt);
text-transform: uppercase;
}
}
}
&.major {
height: 75vh;
min-height: 30em;
max-height: 50em;
&.alt {
opacity: 0.75;
}
}
&.style1 { &:after { background-color: _palette(accent1); } }
&.style2 { &:after { background-color: _palette(accent2); } }
&.style3 { &:after { background-color: _palette(accent3); } }
&.style4 { &:after { background-color: _palette(accent4); } }
&.style5 { &:after { background-color: _palette(accent5); } }
&.style6 { &:after { background-color: _palette(accent6); } }
body.is-preload & {
&:after {
opacity: 1.0;
}
> .inner {
@include vendor('filter', 'blur(0.125em)');
@include vendor('transform', 'translateX(-0.5em)');
opacity: 0;
}
}
@include breakpoint('<=large') {
background-attachment: scroll;
}
@include breakpoint('<=small') {
@include padding(3em, 0, (2em, 0, 0, 0));
height: auto;
margin-bottom: -2.75em;
max-height: none;
min-height: 0;
top: -2.75em;
h1 {
font-size: 2em;
}
> .inner {
.content {
display: block;
> * {
margin-right: 0;
margin-bottom: _size(element-margin);
}
}
}
&.major {
height: auto;
min-height: 0;
max-height: none;
}
}
@include breakpoint('<=xsmall') {
@include padding(4em, 0, (2em, 0, 0, 0));
> .inner {
.content {
p {
br {
display: none;
}
}
}
}
&.major {
@include padding(6em, 0, (2em, 0, 0, 0));
}
}
}

View File

@ -0,0 +1,93 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Contact */
#contact {
border-bottom: solid 1px _palette(border);
overflow-x: hidden;
> .inner {
@include vendor('display', 'flex');
padding: 0 !important;
> :nth-child(2n - 1) {
@include padding(4em, 0, (0, 3em, 0, 0));
border-right: solid 1px _palette(border);
width: 60%;
}
> :nth-child(2n) {
padding-left: 3em;
width: 40%;
}
> .split {
padding: 0;
> * {
@include padding(3em, 0, (0, 0, 0, 3em));
position: relative;
&:before {
border-top: solid 1px _palette(border);
content: '';
display: block;
margin-left: -3em;
position: absolute;
top: 0;
width: calc(100vw + 3em);
}
}
> :first-child {
&:before {
display: none;
}
}
}
}
@include breakpoint('<=medium') {
> .inner {
display: block;
> :nth-child(2n - 1) {
@include padding(4em, 0, (0, 0, 0, 0));
border-right: 0;
width: 100%;
}
> :nth-child(2n) {
padding-left: 0;
width: 100%;
}
> .split {
> * {
@include padding(3em, 0, (0, 0, 0, 0));
&:before {
}
}
> :first-child {
&:before {
display: block;
}
}
}
}
}
@include breakpoint('<=small') {
> .inner {
> :nth-child(2n - 1) {
@include padding(3em, 0, (0, 0, 0, 0));
}
}
}
}

View File

@ -0,0 +1,42 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Footer */
#footer {
.copyright {
font-size: 0.8em;
list-style: none;
padding-left: 0;
li {
border-left: solid 1px _palette(border);
color: _palette(fg-light);
display: inline-block;
line-height: 1;
margin-left: 1em;
padding-left: 1em;
&:first-child {
border-left: 0;
margin-left: 0;
padding-left: 0;
}
}
}
@include breakpoint('<=xsmall') {
.copyright {
li {
display: block;
border-left: 0;
margin-left: 0;
padding-left: 0;
line-height: inherit;
}
}
}
}

View File

@ -0,0 +1,248 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Header */
@include keyframes('reveal-header') {
0% { top: -4em; opacity: 0; }
100% { top: 0; opacity: 1; }
}
#header {
@include vendor('display', 'flex');
background-color: _palette(bg-alt);
box-shadow: 0 0 0.25em 0 rgba(0,0,0,0.15);
cursor: default;
font-weight: _font(weight-bold);
height: 3.25em;
left: 0;
letter-spacing: _font(letter-spacing-alt);
line-height: 3.25em;
margin: 0;
position: fixed;
text-transform: uppercase;
top: 0;
width: 100%;
z-index: _misc(z-index-base);
.logo {
border: 0;
display: inline-block;
font-size: 0.8em;
height: inherit;
line-height: inherit;
padding: 0 1.5em;
strong {
@include vendor('transition', (
'background-color #{_duration(transition)} ease-in-out',
'color #{_duration(transition)} ease-in-out'
));
background-color: _palette(fg-bold);
color: _palette(bg);
display: inline-block;
line-height: 1.65em;
margin-right: 0.325em;
padding: 0 0.125em 0 (_font(letter-spacing-alt) + 0.125em);
}
&:hover {
strong {
background-color: _palette(highlight);
}
}
&:active {
strong {
background-color: desaturate(darken(_palette(highlight), 15), 5);
}
}
}
nav {
@include vendor('display', 'flex');
@include vendor('justify-content', 'flex-end');
@include vendor('flex-grow', '1');
height: inherit;
line-height: inherit;
a {
border: 0;
display: block;
font-size: 0.8em;
height: inherit;
line-height: inherit;
padding: 0 0.75em;
position: relative;
vertical-align: middle;
&:last-child {
padding-right: 1.5em;
}
&[href="#menu"] {
padding-right: 3.325em !important;
&:before, &:after {
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" width="24" height="32" viewBox="0 0 24 32" preserveAspectRatio="none"><style>line { stroke-width: 2px; stroke: #{_palette(fg-bold)}; }</style><line x1="0" y1="11" x2="24" y2="11" /><line x1="0" y1="21" x2="24" y2="21" /><line x1="0" y1="16" x2="24" y2="16" /></svg>');
background-position: center;
background-repeat: no-repeat;
background-size: 24px 32px;
content: '';
display: block;
height: 100%;
position: absolute;
right: 1.5em;
top: 0;
vertical-align: middle;
width: 24px;
}
&:after {
@include vendor('transition', 'opacity #{_duration(transition)} ease-in-out');
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" width="24" height="32" viewBox="0 0 24 32" preserveAspectRatio="none"><style>line { stroke-width: 2px; stroke: #{_palette(highlight)}; }</style><line x1="0" y1="11" x2="24" y2="11" /><line x1="0" y1="21" x2="24" y2="21" /><line x1="0" y1="16" x2="24" y2="16" /></svg>');
opacity: 0;
z-index: 1;
}
&:hover, &:active {
&:after {
opacity: 1;
}
}
&:last-child {
padding-right: 3.875em !important;
&:before, &:after {
right: 2em;
}
}
}
}
}
&.reveal {
@include vendor('animation', 'reveal-header 0.35s ease');
}
&.alt {
@include vendor('transition', 'opacity #{_duration(banner)} ease');
@include vendor('transition-delay', '0.75s');
@include vendor('animation', 'none');
background-color: transparent;
box-shadow: none;
position: absolute;
&.style1 { .logo { strong { color: _palette(accent1); } } }
&.style2 { .logo { strong { color: _palette(accent2); } } }
&.style3 { .logo { strong { color: _palette(accent3); } } }
&.style4 { .logo { strong { color: _palette(accent4); } } }
&.style5 { .logo { strong { color: _palette(accent5); } } }
&.style6 { .logo { strong { color: _palette(accent6); } } }
}
body.is-preload & {
&.alt {
opacity: 0;
}
}
@include breakpoint('<=xlarge') {
nav {
a {
&[href="#menu"] {
padding-right: 3.75em !important;
&:last-child {
padding-right: 4.25em !important;
}
}
}
}
}
@include breakpoint('<=large') {
nav {
a {
&[href="#menu"] {
padding-right: 4em !important;
&:last-child {
padding-right: 4.5em !important;
}
}
}
}
}
@include breakpoint('<=small') {
height: 2.75em;
line-height: 2.75em;
.logo {
padding: 0 1em;
}
nav {
a {
padding: 0 0.5em;
&:last-child {
padding-right: 1em;
}
&[href="#menu"] {
padding-right: 3.25em !important;
&:before, &:after {
right: 0.75em;
}
&:last-child {
padding-right: 4em !important;
&:before, &:after {
right: 1.5em;
}
}
}
}
}
}
@include breakpoint('<=xsmall') {
.logo {
span {
display: none;
}
}
nav {
a {
&[href="#menu"] {
overflow: hidden;
padding-right: 0 !important;
text-indent: 5em;
white-space: nowrap;
width: 5em;
&:before, &:after {
right: 0;
width: inherit;
}
&:last-child {
&:before, &:after {
width: 4em;
right: 0;
}
}
}
}
}
}
}

View File

@ -0,0 +1,26 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Main */
#main {
background-color: _palette(bg-alt);
> * {
border-top: solid 1px _palette(border);
&:first-child {
border-top: 0;
}
@include inner;
}
&.alt {
background-color: transparent;
border-bottom: solid 1px _palette(border);
}
}

View File

@ -0,0 +1,164 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Menu */
#menu {
@include vendor('transition', (
'transform #{_duration(menu)} ease',
'opacity #{_duration(menu)} ease',
'visibility #{_duration(menu)}'
));
@include vendor('align-items', 'center');
@include vendor('display', 'flex');
@include vendor('justify-content', 'center');
@include vendor('pointer-events', 'none');
background: transparentize(_palette(bg), 0.1);
box-shadow: none;
height: 100%;
left: 0;
opacity: 0;
overflow: hidden;
padding: 3em 2em;
position: fixed;
top: 0;
visibility: hidden;
width: 100%;
z-index: _misc(z-index-base) + 2;
.inner {
@include vendor('transition', (
'transform #{_duration(menu)} ease-out',
'opacity #{_duration(menu)} ease',
'visibility #{_duration(menu)}'
));
@include vendor('transform', 'rotateX(20deg)');
-webkit-overflow-scrolling: touch;
max-width: 100%;
max-height: 100vh;
opacity: 0;
overflow: auto;
text-align: center;
visibility: hidden;
width: 18em;
> :first-child {
margin-top: _size(element-margin);
}
> :last-child {
margin-bottom: (_size(element-margin) * 1.5);
}
}
ul {
margin: 0 0 (_size(element-margin) * 0.5) 0;
&.links {
list-style: none;
padding: 0;
> li {
padding: 0;
> a:not(.button) {
border: 0;
border-top: solid 1px _palette(border);
display: block;
font-size: 0.8em;
font-weight: _font(weight-bold);
letter-spacing: _font(letter-spacing-alt);
line-height: 4em;
text-decoration: none;
text-transform: uppercase;
}
> .button {
display: block;
margin: 0.5em 0 0 0;
}
&:first-child {
> a:not(.button) {
border-top: 0 !important;
}
}
}
}
}
.close {
@include vendor('transition', 'color #{_duration(transition)} ease-in-out');
-webkit-tap-highlight-color: rgba(0,0,0,0);
border: 0;
cursor: pointer;
display: block;
height: 4em;
line-height: 4em;
overflow: hidden;
padding-right: 1.25em;
position: absolute;
right: 0;
text-align: right;
text-indent: 8em;
top: 0;
vertical-align: middle;
white-space: nowrap;
width: 8em;
&:before, &:after {
@include vendor('transition', 'opacity #{_duration(transition)} ease-in-out');
background-position: center;
background-repeat: no-repeat;
content: '';
display: block;
height: 4em;
position: absolute;
right: 0;
top: 0;
width: 4em;
}
&:before {
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20px" height="20px" viewBox="0 0 20 20" zoomAndPan="disable"><style>line { stroke: #{_palette(fg-bold)}; stroke-width: 2; }</style><line x1="0" y1="0" x2="20" y2="20" /><line x1="20" y1="0" x2="0" y2="20" /></svg>');
}
&:after {
background-image: svg-url('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20px" height="20px" viewBox="0 0 20 20" zoomAndPan="disable"><style>line { stroke: #{_palette(highlight)}; stroke-width: 2; }</style><line x1="0" y1="0" x2="20" y2="20" /><line x1="20" y1="0" x2="0" y2="20" /></svg>');
opacity: 0;
}
&:hover, &:active {
&:after {
opacity: 1;
}
}
}
}
body.is-ie {
#menu {
background: transparentize(_palette(bg-alt), 0.025);
}
}
body.is-menu-visible {
#wrapper {
@include vendor('filter', 'blur(0.5em)');
}
#menu {
@include vendor('pointer-events', 'auto');
opacity: 1;
visibility: visible;
.inner {
@include vendor('transform', 'none');
opacity: 1;
visibility: visible;
}
}
}

View File

@ -0,0 +1,28 @@
///
/// Forty by HTML5 UP
/// html5up.net | @ajlkn
/// Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
///
/* Wrapper */
#wrapper {
@include vendor('transition', (
'filter #{_duration(menu)} ease',
'-webkit-filter #{_duration(menu)} ease',
'opacity 0.375s ease-out'
));
padding-top: 3.25em;
&.is-transitioning {
opacity: 0;
}
> * {
@include inner;
}
@include breakpoint('<=small') {
padding-top: 2.75em;
}
}

View File

@ -0,0 +1,223 @@
// breakpoints.scss v1.0 | @ajlkn | MIT licensed */
// Vars.
/// Breakpoints.
/// @var {list}
$breakpoints: () !global;
// Mixins.
/// Sets breakpoints.
/// @param {map} $x Breakpoints.
@mixin breakpoints($x: ()) {
$breakpoints: $x !global;
}
/// Wraps @content in a @media block targeting a specific orientation.
/// @param {string} $orientation Orientation.
@mixin orientation($orientation) {
@media screen and (orientation: #{$orientation}) {
@content;
}
}
/// Wraps @content in a @media block using a given query.
/// @param {string} $query Query.
@mixin breakpoint($query: null) {
$breakpoint: null;
$op: null;
$media: null;
// Determine operator, breakpoint.
// Greater than or equal.
@if (str-slice($query, 0, 2) == '>=') {
$op: 'gte';
$breakpoint: str-slice($query, 3);
}
// Less than or equal.
@elseif (str-slice($query, 0, 2) == '<=') {
$op: 'lte';
$breakpoint: str-slice($query, 3);
}
// Greater than.
@elseif (str-slice($query, 0, 1) == '>') {
$op: 'gt';
$breakpoint: str-slice($query, 2);
}
// Less than.
@elseif (str-slice($query, 0, 1) == '<') {
$op: 'lt';
$breakpoint: str-slice($query, 2);
}
// Not.
@elseif (str-slice($query, 0, 1) == '!') {
$op: 'not';
$breakpoint: str-slice($query, 2);
}
// Equal.
@else {
$op: 'eq';
$breakpoint: $query;
}
// Build media.
@if ($breakpoint and map-has-key($breakpoints, $breakpoint)) {
$a: map-get($breakpoints, $breakpoint);
// Range.
@if (type-of($a) == 'list') {
$x: nth($a, 1);
$y: nth($a, 2);
// Max only.
@if ($x == null) {
// Greater than or equal (>= 0 / anything)
@if ($op == 'gte') {
$media: 'screen';
}
// Less than or equal (<= y)
@elseif ($op == 'lte') {
$media: 'screen and (max-width: ' + $y + ')';
}
// Greater than (> y)
@elseif ($op == 'gt') {
$media: 'screen and (min-width: ' + ($y + 1) + ')';
}
// Less than (< 0 / invalid)
@elseif ($op == 'lt') {
$media: 'screen and (max-width: -1px)';
}
// Not (> y)
@elseif ($op == 'not') {
$media: 'screen and (min-width: ' + ($y + 1) + ')';
}
// Equal (<= y)
@else {
$media: 'screen and (max-width: ' + $y + ')';
}
}
// Min only.
@else if ($y == null) {
// Greater than or equal (>= x)
@if ($op == 'gte') {
$media: 'screen and (min-width: ' + $x + ')';
}
// Less than or equal (<= inf / anything)
@elseif ($op == 'lte') {
$media: 'screen';
}
// Greater than (> inf / invalid)
@elseif ($op == 'gt') {
$media: 'screen and (max-width: -1px)';
}
// Less than (< x)
@elseif ($op == 'lt') {
$media: 'screen and (max-width: ' + ($x - 1) + ')';
}
// Not (< x)
@elseif ($op == 'not') {
$media: 'screen and (max-width: ' + ($x - 1) + ')';
}
// Equal (>= x)
@else {
$media: 'screen and (min-width: ' + $x + ')';
}
}
// Min and max.
@else {
// Greater than or equal (>= x)
@if ($op == 'gte') {
$media: 'screen and (min-width: ' + $x + ')';
}
// Less than or equal (<= y)
@elseif ($op == 'lte') {
$media: 'screen and (max-width: ' + $y + ')';
}
// Greater than (> y)
@elseif ($op == 'gt') {
$media: 'screen and (min-width: ' + ($y + 1) + ')';
}
// Less than (< x)
@elseif ($op == 'lt') {
$media: 'screen and (max-width: ' + ($x - 1) + ')';
}
// Not (< x and > y)
@elseif ($op == 'not') {
$media: 'screen and (max-width: ' + ($x - 1) + '), screen and (min-width: ' + ($y + 1) + ')';
}
// Equal (>= x and <= y)
@else {
$media: 'screen and (min-width: ' + $x + ') and (max-width: ' + $y + ')';
}
}
}
// String.
@else {
// Missing a media type? Prefix with "screen".
@if (str-slice($a, 0, 1) == '(') {
$media: 'screen and ' + $a;
}
// Otherwise, use as-is.
@else {
$media: $a;
}
}
}
// Output.
@media #{$media} {
@content;
}
}

View File

@ -0,0 +1,90 @@
/// Removes a specific item from a list.
/// @author Hugo Giraudel
/// @param {list} $list List.
/// @param {integer} $index Index.
/// @return {list} Updated list.
@function remove-nth($list, $index) {
$result: null;
@if type-of($index) != number {
@warn "$index: #{quote($index)} is not a number for `remove-nth`.";
}
@else if $index == 0 {
@warn "List index 0 must be a non-zero integer for `remove-nth`.";
}
@else if abs($index) > length($list) {
@warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
}
@else {
$result: ();
$index: if($index < 0, length($list) + $index + 1, $index);
@for $i from 1 through length($list) {
@if $i != $index {
$result: append($result, nth($list, $i));
}
}
}
@return $result;
}
/// Gets a value from a map.
/// @author Hugo Giraudel
/// @param {map} $map Map.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function val($map, $keys...) {
@if nth($keys, 1) == null {
$keys: remove-nth($keys, 1);
}
@each $key in $keys {
$map: map-get($map, $key);
}
@return $map;
}
/// Gets a duration value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _duration($keys...) {
@return val($duration, $keys...);
}
/// Gets a font value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _font($keys...) {
@return val($font, $keys...);
}
/// Gets a misc value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _misc($keys...) {
@return val($misc, $keys...);
}
/// Gets a palette value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _palette($keys...) {
@return val($palette, $keys...);
}
/// Gets a size value.
/// @param {string} $keys Key(s).
/// @return {string} Value.
@function _size($keys...) {
@return val($size, $keys...);
}

View File

@ -0,0 +1,149 @@
// html-grid.scss v1.0 | @ajlkn | MIT licensed */
// Mixins.
/// Initializes the current element as an HTML grid.
/// @param {mixed} $gutters Gutters (either a single number to set both column/row gutters, or a list to set them individually).
/// @param {mixed} $suffix Column class suffix (optional; either a single suffix or a list).
@mixin html-grid($gutters: 1.5em, $suffix: '') {
// Initialize.
$cols: 12;
$multipliers: 0, 0.25, 0.5, 1, 1.50, 2.00;
$unit: 100% / $cols;
// Suffixes.
$suffixes: null;
@if (type-of($suffix) == 'list') {
$suffixes: $suffix;
}
@else {
$suffixes: ($suffix);
}
// Gutters.
$guttersCols: null;
$guttersRows: null;
@if (type-of($gutters) == 'list') {
$guttersCols: nth($gutters, 1);
$guttersRows: nth($gutters, 2);
}
@else {
$guttersCols: $gutters;
$guttersRows: 0;
}
// Row.
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
align-items: stretch;
// Columns.
> * {
box-sizing: border-box;
}
// Gutters.
&.gtr-uniform {
> * {
> :last-child {
margin-bottom: 0;
}
}
}
// Alignment.
&.aln-left {
justify-content: flex-start;
}
&.aln-center {
justify-content: center;
}
&.aln-right {
justify-content: flex-end;
}
&.aln-top {
align-items: flex-start;
}
&.aln-middle {
align-items: center;
}
&.aln-bottom {
align-items: flex-end;
}
// Step through suffixes.
@each $suffix in $suffixes {
// Suffix.
@if ($suffix != '') {
$suffix: '-' + $suffix;
}
@else {
$suffix: '';
}
// Row.
// Important.
> .imp#{$suffix} {
order: -1;
}
// Columns, offsets.
@for $i from 1 through $cols {
> .col-#{$i}#{$suffix} {
width: $unit * $i;
}
> .off-#{$i}#{$suffix} {
margin-left: $unit * $i;
}
}
// Step through multipliers.
@each $multiplier in $multipliers {
// Gutters.
$class: null;
@if ($multiplier != 1) {
$class: '.gtr-' + ($multiplier * 100);
}
&#{$class} {
margin-top: ($guttersRows * $multiplier * -1);
margin-left: ($guttersCols * $multiplier * -1);
> * {
padding: ($guttersRows * $multiplier) 0 0 ($guttersCols * $multiplier);
}
// Uniform.
&.gtr-uniform {
margin-top: $guttersCols * $multiplier * -1;
> * {
padding-top: $guttersCols * $multiplier;
}
}
}
}
}
}

View File

@ -0,0 +1,78 @@
/// Makes an element's :before pseudoelement a FontAwesome icon.
/// @param {string} $content Optional content value to use.
/// @param {string} $category Optional category to use.
/// @param {string} $where Optional pseudoelement to target (before or after).
@mixin icon($content: false, $category: regular, $where: before) {
text-decoration: none;
&:#{$where} {
@if $content {
content: $content;
}
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-style: normal;
font-variant: normal;
text-rendering: auto;
line-height: 1;
text-transform: none !important;
@if ($category == brands) {
font-family: 'Font Awesome 5 Brands';
}
@elseif ($category == solid) {
font-family: 'Font Awesome 5 Free';
font-weight: 900;
}
@else {
font-family: 'Font Awesome 5 Free';
font-weight: 400;
}
}
}
/// Applies padding to an element, taking the current element-margin value into account.
/// @param {mixed} $tb Top/bottom padding.
/// @param {mixed} $lr Left/right padding.
/// @param {list} $pad Optional extra padding (in the following order top, right, bottom, left)
/// @param {bool} $important If true, adds !important.
@mixin padding($tb, $lr, $pad: (0,0,0,0), $important: null) {
@if $important {
$important: '!important';
}
$x: 0.1em;
@if unit(_size(element-margin)) == 'rem' {
$x: 0.1rem;
}
padding: ($tb + nth($pad,1)) ($lr + nth($pad,2)) max($x, $tb - _size(element-margin) + nth($pad,3)) ($lr + nth($pad,4)) #{$important};
}
/// Encodes a SVG data URL so IE doesn't choke (via codepen.io/jakob-e/pen/YXXBrp).
/// @param {string} $svg SVG data URL.
/// @return {string} Encoded SVG data URL.
@function svg-url($svg) {
$svg: str-replace($svg, '"', '\'');
$svg: str-replace($svg, '%', '%25');
$svg: str-replace($svg, '<', '%3C');
$svg: str-replace($svg, '>', '%3E');
$svg: str-replace($svg, '&', '%26');
$svg: str-replace($svg, '#', '%23');
$svg: str-replace($svg, '{', '%7B');
$svg: str-replace($svg, '}', '%7D');
$svg: str-replace($svg, ';', '%3B');
@return url("data:image/svg+xml;charset=utf8,#{$svg}");
}

View File

@ -0,0 +1,47 @@
// Misc.
$misc: (
z-index-base: 10000
);
// Duration.
$duration: (
menu: 0.35s,
transition: 0.2s,
banner: 2.5s
);
// Size.
$size: (
border-radius: 4px,
element-height: 2.75em,
element-margin: 2em,
inner: 65em
);
// Font.
$font: (
family: ('Source Sans Pro', Helvetica, sans-serif),
family-fixed: ('Courier New', monospace),
weight: 300,
weight-bold: 600,
letter-spacing: 0.025em,
letter-spacing-alt: 0.25em
);
// Palette.
$palette: (
bg: #242943,
bg-alt: #2a2f4a,
fg: #ffffff,
fg-bold: #ffffff,
fg-light: rgba(244,244,255,0.2),
border: rgba(212,212,255,0.1),
border-bg: rgba(212,212,255,0.035),
highlight: #9bf1ff,
accent1: #6fc3df,
accent2: #8d82c4,
accent3: #ec8d81,
accent4: #e7b788,
accent5: #8ea9e8,
accent6: #87c5a4
);

View File

@ -0,0 +1,376 @@
// vendor.scss v1.0 | @ajlkn | MIT licensed */
// Vars.
/// Vendor prefixes.
/// @var {list}
$vendor-prefixes: (
'-moz-',
'-webkit-',
'-ms-',
''
);
/// Properties that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-properties: (
// Animation.
'animation',
'animation-delay',
'animation-direction',
'animation-duration',
'animation-fill-mode',
'animation-iteration-count',
'animation-name',
'animation-play-state',
'animation-timing-function',
// Appearance.
'appearance',
// Backdrop filter.
'backdrop-filter',
// Background image options.
'background-clip',
'background-origin',
'background-size',
// Box sizing.
'box-sizing',
// Clip path.
'clip-path',
// Filter effects.
'filter',
// Flexbox.
'align-content',
'align-items',
'align-self',
'flex',
'flex-basis',
'flex-direction',
'flex-flow',
'flex-grow',
'flex-shrink',
'flex-wrap',
'justify-content',
'order',
// Font feature.
'font-feature-settings',
'font-language-override',
'font-variant-ligatures',
// Font kerning.
'font-kerning',
// Fragmented borders and backgrounds.
'box-decoration-break',
// Grid layout.
'grid-column',
'grid-column-align',
'grid-column-end',
'grid-column-start',
'grid-row',
'grid-row-align',
'grid-row-end',
'grid-row-start',
'grid-template-columns',
'grid-template-rows',
// Hyphens.
'hyphens',
'word-break',
// Masks.
'mask',
'mask-border',
'mask-border-outset',
'mask-border-repeat',
'mask-border-slice',
'mask-border-source',
'mask-border-width',
'mask-clip',
'mask-composite',
'mask-image',
'mask-origin',
'mask-position',
'mask-repeat',
'mask-size',
// Multicolumn.
'break-after',
'break-before',
'break-inside',
'column-count',
'column-fill',
'column-gap',
'column-rule',
'column-rule-color',
'column-rule-style',
'column-rule-width',
'column-span',
'column-width',
'columns',
// Object fit.
'object-fit',
'object-position',
// Regions.
'flow-from',
'flow-into',
'region-fragment',
// Scroll snap points.
'scroll-snap-coordinate',
'scroll-snap-destination',
'scroll-snap-points-x',
'scroll-snap-points-y',
'scroll-snap-type',
// Shapes.
'shape-image-threshold',
'shape-margin',
'shape-outside',
// Tab size.
'tab-size',
// Text align last.
'text-align-last',
// Text decoration.
'text-decoration-color',
'text-decoration-line',
'text-decoration-skip',
'text-decoration-style',
// Text emphasis.
'text-emphasis',
'text-emphasis-color',
'text-emphasis-position',
'text-emphasis-style',
// Text size adjust.
'text-size-adjust',
// Text spacing.
'text-spacing',
// Transform.
'transform',
'transform-origin',
// Transform 3D.
'backface-visibility',
'perspective',
'perspective-origin',
'transform-style',
// Transition.
'transition',
'transition-delay',
'transition-duration',
'transition-property',
'transition-timing-function',
// Unicode bidi.
'unicode-bidi',
// User select.
'user-select',
// Writing mode.
'writing-mode',
);
/// Values that should be vendorized.
/// Data via caniuse.com, github.com/postcss/autoprefixer, and developer.mozilla.org
/// @var {list}
$vendor-values: (
// Cross fade.
'cross-fade',
// Element function.
'element',
// Filter function.
'filter',
// Flexbox.
'flex',
'inline-flex',
// Grab cursors.
'grab',
'grabbing',
// Gradients.
'linear-gradient',
'repeating-linear-gradient',
'radial-gradient',
'repeating-radial-gradient',
// Grid layout.
'grid',
'inline-grid',
// Image set.
'image-set',
// Intrinsic width.
'max-content',
'min-content',
'fit-content',
'fill',
'fill-available',
'stretch',
// Sticky position.
'sticky',
// Transform.
'transform',
// Zoom cursors.
'zoom-in',
'zoom-out',
);
// Functions.
/// Removes a specific item from a list.
/// @author Hugo Giraudel
/// @param {list} $list List.
/// @param {integer} $index Index.
/// @return {list} Updated list.
@function remove-nth($list, $index) {
$result: null;
@if type-of($index) != number {
@warn "$index: #{quote($index)} is not a number for `remove-nth`.";
}
@else if $index == 0 {
@warn "List index 0 must be a non-zero integer for `remove-nth`.";
}
@else if abs($index) > length($list) {
@warn "List index is #{$index} but list is only #{length($list)} item long for `remove-nth`.";
}
@else {
$result: ();
$index: if($index < 0, length($list) + $index + 1, $index);
@for $i from 1 through length($list) {
@if $i != $index {
$result: append($result, nth($list, $i));
}
}
}
@return $result;
}
/// Replaces a substring within another string.
/// @author Hugo Giraudel
/// @param {string} $string String.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {string} Updated string.
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
/// Replaces a substring within each string in a list.
/// @param {list} $strings List of strings.
/// @param {string} $search Substring.
/// @param {string} $replace Replacement.
/// @return {list} Updated list of strings.
@function str-replace-all($strings, $search, $replace: '') {
@each $string in $strings {
$strings: set-nth($strings, index($strings, $string), str-replace($string, $search, $replace));
}
@return $strings;
}
// Mixins.
/// Wraps @content in vendorized keyframe blocks.
/// @param {string} $name Name.
@mixin keyframes($name) {
@-moz-keyframes #{$name} { @content; }
@-webkit-keyframes #{$name} { @content; }
@-ms-keyframes #{$name} { @content; }
@keyframes #{$name} { @content; }
}
/// Vendorizes a declaration's property and/or value(s).
/// @param {string} $property Property.
/// @param {mixed} $value String/list of value(s).
@mixin vendor($property, $value) {
// Determine if property should expand.
$expandProperty: index($vendor-properties, $property);
// Determine if value should expand (and if so, add '-prefix-' placeholder).
$expandValue: false;
@each $x in $value {
@each $y in $vendor-values {
@if $y == str-slice($x, 1, str-length($y)) {
$value: set-nth($value, index($value, $x), '-prefix-' + $x);
$expandValue: true;
}
}
}
// Expand property?
@if $expandProperty {
@each $vendor in $vendor-prefixes {
#{$vendor}#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
}
}
// Expand just the value?
@elseif $expandValue {
@each $vendor in $vendor-prefixes {
#{$property}: #{str-replace-all($value, '-prefix-', $vendor)};
}
}
// Neither? Treat them as a normal declaration.
@else {
#{$property}: #{$value};
}
}

View File

@ -0,0 +1,79 @@
@import 'libs/vars';
@import 'libs/functions';
@import 'libs/mixins';
@import 'libs/vendor';
@import 'libs/breakpoints';
@import 'libs/html-grid';
@import 'fontawesome-all.min.css';
@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300italic,600,600italic');
/*
Forty by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
// Breakpoints.
@include breakpoints((
xlarge: (1281px, 1680px ),
large: (981px, 1280px ),
medium: (737px, 980px ),
small: (481px, 736px ),
xsmall: (361px, 480px ),
xxsmall: (null, 360px )
));
// Mixins.
@mixin inner {
> .inner {
@include padding(4em, 0);
margin: 0 auto;
max-width: _size(inner);
width: calc(100% - 6em);
overflow: auto;
@include breakpoint('<=small') {
@include padding(3em, 0);
width: calc(100% - 3em);
}
}
}
// Base.
@import 'base/reset';
@import 'base/page';
@import 'base/typography';
// Component.
@import 'components/row';
@import 'components/section';
@import 'components/form';
@import 'components/box';
@import 'components/icon';
@import 'components/image';
@import 'components/list';
@import 'components/actions';
@import 'components/icons';
@import 'components/pagination';
@import 'components/table';
@import 'components/button';
@import 'components/tiles';
@import 'components/contact-method';
@import 'components/spotlights';
// Layout.
@import 'layout/header';
@import 'layout/banner';
@import 'layout/main';
@import 'layout/contact';
@import 'layout/footer';
@import 'layout/wrapper';
@import 'layout/menu';
// Custom modifications.
@import 'custom/home_creationinfo';

View File

@ -0,0 +1,28 @@
@import 'libs/vars';
@import 'libs/functions';
@import 'libs/mixins';
@import 'libs/vendor';
@import 'libs/breakpoints';
@import 'libs/html-grid';
/*
Forty by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
*/
/* Banner */
#banner {
body.is-preload & {
&:after {
opacity: 0.85;
}
> .inner {
@include vendor('filter', 'none');
@include vendor('transform', 'none');
opacity: 1;
}
}
}

View File

@ -0,0 +1,17 @@
---
type: page
title: Architecture
language: en
---
## Lectures and consultations on research software architecture
### General architecture lectures
<iframe width="100%" height="315" src="https://www.youtube.com/embed/MNYb-aVDCl8" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<iframe width="100%" height="315" src="https://www.youtube.com/embed/Su_fgiC_q_M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
### Mathematics library design
<iframe width="100%" height="315" src="https://www.youtube.com/embed/yP5DIc2fVwQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

View File

@ -0,0 +1,16 @@
---
type: page
title: Development
language: en
---
## Infrastructure for NICA project
Together with [mipt-npm](https://npm.mipt.ru) laboratory we are working on developing infrastructure services for [NICA](https://nica.jinr.ru/) project. Those services include:
* Web-based data visualization.
* Web services for supercomputer task execution scenarios.
* Big data access and indexing services.
## Controls systems integration for [BabyIAXO](https://iaxo.desy.de/) experiment
Integration of different SCADA systems and development of device servers.

View File

@ -0,0 +1,14 @@
---
type: page
title: Expert activity
language: en
---
## Software design consultations for Tavrida Electric
Design of SCADA system, asynchronous message passing and consultation on Kotlin language.
## Library and framework design for SkolTech
Design of libraries and frameworks for applied research (machine learning).

View File

@ -0,0 +1,76 @@
---
type: page
title: Consulting
pageName: SPC.consulting
transformation: snark.basic
language: en
---
## Where does science begin?
In recent years, the rate of introduction of scientific developments into the industrial and even domestic spheres has accelerated significantly. No more waiting for many years before what was the cutting edge of science is put into practice. Such a rapid introduction also imposes its own limitations - close cooperation between scientists and industry became quite important.
In any industry, and especially in the science-intensive one, a clear technical requirements are of great importance. In order to do proper technical requirements one needs to have extensive knowledge. Our team includes specialists engaged in research in a variety of scientific areas - from elementary particle physics to biotechnology and computer science. This makes it easy for our experienced, highly qualified specialists to find the optimal solution even in the subject area. Regardless of the subject area, we work closely with the customer to better understand the task and its full-fledged solution.
Our research, which primarily includes open source projects, has already been appreciated by the international scientific community.
## We do
<!--suppress HtmlUnknownTarget -->
<section id="one" class="tiles">
<article>
<span class="image">
<img src="images/pic03.jpg" alt="" />
</span>
<header class="major">
<h3><a href="${resolvePageRef("consulting.research")}" class="link">Research</a></h3>
<p>Analytics, prototyping and research for fundamental science and industry.</p>
</header>
</article>
<article>
<span class="image">
<img src="images/pic04.jpg" alt="" />
</span>
<header class="major">
<h3><a href="${resolvePageRef("consulting.expert")}" class="link">Expert activity</a></h3>
<p>Analysis and improvement of existing scientific software and projects.</p>
</header>
</article>
<article>
<span class="image">
<img src="images/pic05.jpg" alt="" />
</span>
<header class="major">
<h3><a href="${resolvePageRef("consulting.architecture")}" class="link">Architecture</a></h3>
<p>Design the architecture for scientific and technological applications.</p>
</header>
</article>
<article>
<span class="image">
<img src="images/pic06.jpg" alt="" />
</span>
<header class="major">
<h3><a href="${resolvePageRef("consulting.development")}" class="link">Development</a></h3>
<p>The development and support of open-source and in-house solutions( libraries, frameworks and end-user application).</p>
</header>
</article>
</section>
<hr>
## How our team works
The primary feature of our work is research. We do not just do what customer tells us to do. We conduct a full-scale research and devise a way (algorithm, technology, etc), which would produce the best results.
Our team is deeply engaged in [education activity](/magprog). It allows us to invite the most promising young researchers and developers to work with us both on part-time and full-time basis and get a constant feedback on new technologies and methods. The connection to fundamental science allows to be aware of the latest technological and methodical advances.
Another unique feature of our work is that our team have experience both in research and industrial IT. That means that we not only produce "research code" and prototypes, but also able to provide **MVP** or even small-scale **product** development.
<hr>
## How to start?
Please contact us via email below. We will discuss your problem for free and tell you if we can do it and how much will it cost. Since we do research, each task needs individual approach and estimation. We provide discounts for open research and open source software development.
email: <a href="mailto:&#114;&#101;&#115;&#101;&#097;&#114;&#099;&#104;&#064;&#115;&#099;&#105;&#112;&#114;&#111;&#103;&#046;&#099;&#101;&#110;&#116;&#101;&#114;">&#114;&#101;&#115;&#101;&#097;&#114;&#099;&#104;&#064;&#115;&#099;&#105;&#112;&#114;&#111;&#103;&#046;&#099;&#101;&#110;&#116;&#101;&#114;</a>

View File

@ -0,0 +1,14 @@
---
type: page
title: Research
pageName: SPC.research
language: en
---
## Analysis of oil wells monitoring data for Aramco Innovations
Classical analysis of temperature data from simulation and real-life measurements. Full-cycle research from technical requirements and scientific overview to software integration.
## Public and fundamental research
See more at [research page](/research).

View File

@ -0,0 +1,59 @@
---
type: page
title: Education
pageName: SPC.education
transformation: snark.basic
language: en
---
<section id="masters">
<div class="inner">
<header class="major">
<h2>Master program</h2>
</header>
<p>Master program "Scientific programming" at MIPT aims to prepare specialists both in application programming and domain field (such as physics, biology, biotechnology, computer science and other research areas).</p>
<p> In modern science and technology, application level programming is an integral part of any major work. And in order to be successful in this field, one needs to know both software engineering and the domain field. </p>
<ul class="actions">
<li><a href="/education/masters" class="button next">More</a></li>
</ul>
</div>
</section>
<hr/>
## Courses in 20222023:
### [Scientific literature seminar](#)
*curated by [Aleksandr Svetlichnyi](${resolvePageRef("team")}#svetlichnyi)*
[Telegram](https://t.me/spc_seminar)
### [Statistical methods and data analysis](${resolvePageRef("education.stat-methods")})
*by [Alexander Nozik](team#nozik) and [Vladimir Palmin](${resolvePageRef("team.index")}#palmin)*
Actual program: [SPC-A-6](https://npm.mipt.ru/youtrack/articles/SPC-A-6)
[Telegram](https://t.me/mipt_statmethods)
### [Introduction to scientific programming in Kotlin](${resolvePageRef("education.kotlin")})
*by [Alexander Nozik](${resolvePageRef("team.index")}#nozik)*
Actual program: [SPC-A-6](https://npm.mipt.ru/youtrack/articles/SPC-A-6)
[Telegram](https://t.me/kotlin_mipt)
### [Numeric methods](https://npm.mipt.ru/youtrack/articles/SPC-A-3)
*by Konstantin Tikhonov and Rolan Grinis*
Actual program: [SPC-A-3](https://npm.mipt.ru/youtrack/articles/SPC-A-3)
### [Advanced Python](https://npm.mipt.ru/youtrack/articles/SPC-A-4)
*by Mikhail Zelenyy*
Actual program: [SPC-A-4](https://npm.mipt.ru/youtrack/articles/SPC-A-4)
[Telegram](https://t.me/mipt_npm_python)
### [Computational finance](https://npm.mipt.ru/youtrack/articles/SPC-A-10)
*by Rolan Grinis*
Actual program: [SPC-A-10](https://npm.mipt.ru/youtrack/articles/SPC-A-10)

View File

@ -0,0 +1,83 @@
---
type: page
title: Introduction to scientific programming in Kotlin
pageName: SPC.education.kotlin
transformation: snark.basic
language: en
---
Recording of lectures in 2019 is available [here](https://www.youtube.com/playlist?list=PL4_hYwCyhAvZzRpbK4iTy9S6_OWZNEiVk).
## Lecturer
[Alexander Nozik](${resolvePageRef("team.index")}#nozik)
## Course purpose
As science develops, computer methods are becoming more and more important in the daily work of a scientist. In conducting an experiment, computer methods and tools are used at all stages of the work: planning the experiment, preparing the installation, collecting data, processing and publishing it. In such a situation, the quality of the programs used is beginning to play an important role. In addition, there is a need for specialists who understand both science and programming and who develop and improve software tools.
Most students (and scientists) are more or less familiar with the basic tools of a programmer, for example, writing simple programs in Python. This is not enough for serious scientific development, so the course aims at a more advanced understanding of hardware, program structure and modern development tools.
As the main programming language we will use `Kotlin`, which appeared recently and managed to gain a large market share. Kotlin has several significant advantages as an initial language for advanced scientific programming:
* Strict typing, a clearly constructed system of types.
* High performance.
* Automatic memory management.
* Fully compatible with a huge number of Java libraries.
* Better toolkit.
* Extensive community.
* Possibility of commercial use.
## Format
The lessons are twice a week.
* One is a lecture at MIPT campus. Lectures are dedicated to Kotlin language features and specifics of its application to science and industry problems.
* The second one is practice. Practice is dedicated to work on students projects and additional material.
To get a mark student must complete 3 practical tasks during the semester. All tasks are accepted in form of Kotlin application of notebook and pass a code-review stage.
In this course we will learn to work in Kotlin language and apply it to scientific problems. We will focus on practical aspects and examples, so that no additional knowledge is needed to understand it. For practical examples we will use the development environment [IntelliJ IDEA Community Edition](https://www.jetbrains.com/idea/).
All questions related to the course will be discussed in telegram [Kotlin at MIPT](https://t.me/kotlin_mipt).
## Content
1. **From hard to soft**
1. Program as a set of instructions. Evolution of programs.
2. Memory structure. Segmentation fault.
3. Programming paradigms. Genealogy of languages.
4. Virtual machines, byte-code.
5. Compilation and optimization.
6. Static and dynamic linking. Libraries.
7. Program structure. Entry points.
2. **Kotlin language**
1. Variables, classes and objects.
2. Control flow. Procedural and functional approach.
3. Loops.
4. Data structures and operations on them.
5. Properties and Delegates.
6. Parametric types.
7. Extensions.
8. Boxing.
9. Multiplatform projects.
3. **Program Architecture**
1. Abstractions and interfaces.
2. Basics of collective development with the help of modern tools.
3. Ideology of object programming. Separation of behavior.
4. Ideology of functional programming.
4. **Scientific programming**.
1. Basics of numerical methods. The concept of numerical accuracy. Complexity of algorithms.
2. Numerical differentiation and integration.
3. Random Number Generators and Monte Carlo Modeling.
4. High-performance parallel and competitive computing.
5. The problem of I/O and the main methods to solve it.
6. Data collection systems. Protocols of data exchange.
7. Basics of work with big data.
8. Streaming data processing.
## Reporting
The offset is held in the form of a presentation based on the materials of an individual project. Interim reporting in the form of assignments is also provided.
## Recommended literature
* [Official documentation(en)](https://kotlinlang.org/docs/reference/)
* [Official documentation(ru)](https://kotlinlang.ru/)
* [Kotlin in action](https://dmkpress.com/catalog/computer/programming/java/978-5-97060-497-7/)

View File

@ -0,0 +1,70 @@
---
type: page
title: Statistical methods and data analysis
pageName: SPC.education.statMethods
transformation: snark.basic
language: en
---
## The purpose
Probability theory and mathematical statistics are an integral part of modern research. Calculation of errors, correct presentation of the result, risk assessment - all these are important components of the work of a scientist. At the same time, as practice shows, many scientists (and not just students) complain about the lack of practical skills in this area. This is due to the fact that the teaching of the theoretical aspect of probability theory is often well-placed in technical universities, but the purely practical aspect is completely overlooked.
In our course, we will try to analyze in detail the issues of the practical application of the statistical methods of in planning and processing the results of a physical experiment (using specific examples). Theoretical calculations will be mainly excluded from lectures and left for independent study.
## Course format
The course is planned in the optional format once a week, while lectures will be held every second week, and practical classes (seminars) will be held between the lectures, discussing examples and solving problems from modern experimental physics and everyday life (including laboratory work) .
Announcements of important events, as well as discussion of any issues related to the course, are available in the Telegram group (https://t.me/mipt_statmethods).
[Materials](https://github.com/mipt-npm-study/stat-methods)
## Course structure (preliminary program)
1. **Statistical decision-making theory.**
1. Decisions in deterministic tasks.
2. Decisions in non-deterministic tasks, risk function.
3. Conditional probability, decision-making strategies.
2. **Basic concepts of probability theory.**
1. Definitions of probability.
2. Function of plausibility.
3. Point and interval estimates of distribution parameters.
4. Confidence intervals.
3. **Errors in physical experiment.**
1. Statistical and systematic errors.
2. Properties of distributions at replacement of variables.
3. Uncorrector stacking.
4. Adding results of various experiments.
4. **Properties of distributions.**
1. Poisson's binomial distribution and distribution.
2. Normal distribution and its properties.
3. Average values, moments of distributions.
5. **Checking statistical hypotheses.**
1. Functions of random variables.
2. Statistical criteria and their properties.
3. Methods of criteria construction.
4. Criteria of data agreement with the theory.
6. **Evaluation of parameters.**
1. Parameter criteria.
2. Maximum probability and chi-square method.
3. Using the probability function to construct the Chi-square maximum and Chi-square maximum. Interval estimates.
4. Interval estimates in the case of normal distribution.
7. **Modern data analysis methods (optional).**
1. Fitting of experimental curves. Criteria of phytate quality. Computer methods for solving optimization problems.
2. Multi-parameter analysis. Analysis of correlations.
3. Fisher Information and its Application. Maximum information and its application.
the border between Rao and Kramer.
4. Two approaches to probability: frequency approach and subjective probability. The problem of unique events.
5. Using a computer to analyze experimental data.
## Reporting
The test takes place in the form of a presentation based on the materials of an individual project. Each student has the opportunity to prepare a report analyzing the results of a particular real or thought experiment (you can take laboratory work).
## Recommended literature
* The main textbook for the course - W. Idieu, D. Dryard, F. James, M. Ruth, B. Sadule.
*Statistical methods in experimental physics* M.: Atomizdat, 1976. The Russian-language edition of the book is a bibliographical rarity, but the English version is republished every few years. In addition, an electronic version of the Russian-language edition is available (including the course materials on Google-drive).
* A lot of useful information is contained in the introductory chapters to the MIPT laboratory workshop for the 1st and 3rd courses.
* In concentrated form, information on probability theory and mathematical statistics can be found in the online version of the Particle Data Group (PDG) handbook of particle physics: <http://pdg.lbl.gov/2014/reviews/rpp2014-rev-probability.pdf>; <http://pdg.lbl.gov/2014/reviews/rpp2014-rev-statistics.pdf>.

View File

@ -0,0 +1,4 @@
---
pageName: SPC
language: en
---

View File

@ -0,0 +1,23 @@
---
type: team
title: Varvara Kaplenko
id: vviora
order: 51
language: en
image:
path: images/people/vviora.jpg
position: left
---
**Project manager**
## About me
* Astrophysicist, who decided to get closer with programming
* Im in love with science, and I want to integrate it in business
* Project manager by day, esports player by night
* I believe that gaining soft skills is one of the most crucial things in life
## Education
* Bachelors degree in Fundamental Physics
* Internship at Astro Space Center of Lebedev Physics Institute
* Student at MIPT

View File

@ -0,0 +1 @@
**Project manager**

View File

@ -0,0 +1,12 @@
---
type: team
title: Tatiana Muhina
id: muhina
order: 50
language: en
image:
path: images/people/muhina.jpg
position: left
---
**Education manager**

View File

@ -0,0 +1,81 @@
---
type: team
title: Alexander Nozik
id: nozik
order: 1
language: en
image: images/people/nozik_2.png
---
**Director of the centre**
* PhD in particle physics.
* Director of [Scientific Programming Centre](/).
* Teacher of General Physics, Data Analysis and Kotlin at [MIPT](https://mipt.ru/).
email: <a href="mailto:&#100;&#105;&#114;&#101;&#099;&#116;&#111;&#114;&#064;&#115;&#099;&#105;&#112;&#114;&#111;&#103;&#046;&#099;&#101;&#110;&#116;&#101;&#114;">&#100;&#105;&#114;&#101;&#099;&#116;&#111;&#114;&#064;&#115;&#099;&#105;&#112;&#114;&#111;&#103;&#046;&#099;&#101;&#110;&#116;&#101;&#114;</a>
<blockquote>
<ul>
<li> I am against the war in Ukraine. It must be stopped. </li>
<li> I did not vote for Putin. I do not think that Putin is the legitimate president of Russia. </li>
<li> I hope for the better future. I publicly express my position in <a href="https://twitter.com/noraltavir">my twitter</a>.</li>
<li> I do not speak for the whole laboratory. </li>
</ul>
</blockquote>
## About me
When I finished the school, I had two choices: I liked physics and I liked programming. In the end I decided that physics is more interesting. Now I am doing programming in physics. Currently, I am doing software and physical data analysis for a number of experiments in particle physics (Troitsk nu-mass, IAXO and other experiments). I am leading development of scientific libraries and leading the development of new simulation software and models.
The [laboratory](https://npm.mipt.ru/) and the [centre](/) at MIPT, we created in the last years include young passionate researchers in different fields. My aim is to prepare the new generation of researchers, familiar with modern scientific software tools and able to develop new ones.
## Social
* [ResearchGate profile](https://www.researchgate.net/profile/Alexander_Nozik)
* [Twitter](https://twitter.com/noraltavir)
* [Telegram](https://t.me/noraltavir)
## Education
* Lyceum “2nd school” 1997 - 2002
* MIPT (bachelor, problems of physics and energetics) 2002 - 2006. Finished with honors.
* MIPT (master, fundamental particles and cosmology) 2006 - 2008
* [PhD in physics](https://www.researchgate.net/publication/260058278_Rezultaty_obrabotki_dannyh_eksperimenta_Troick_nu-mass_po_pramomu_izmereniu_massy_elektronnogo_nejtrino), INR RAS 2012 .
## Work experience
* INR RAS Laboratory assistant, 20042008
* INR RAS Researcher, 20082012
* INR RAS Senior researcher, 2012present
* MIPT Assistant, 20132018, The department of general physics laboratory practice and seminars. Special courses on programming and statistics.
* MIPT Associate professor, 2019present
* MIPT Senior researcher, 20192022, Deputy head of the [nuclear physics methods](https://npm.mipt.ru/) laboratory.
* JetBrains Research, 20202022, Head of the research group.
* SPC MIPT, 2022-present, Director.
## Other experience
* [Society of Scientific Workers](http://onr-russia.ru/), 2012-2022, member, board member, secretary of the board.
* Google Developer Expert in Kotlin, 2021-2022.
## The code
* Private GitHub account: https://github.com/altavir (blocked by GitHub for working at MIPT).
* The Centre GitHub account: https://github.com/SciProgCentre
## Achievements
* The best (until 2020) limit on electron neutrino mass: https://arxiv.org/abs/1108.5034
* The best limit on sterile neutrino contribution to the electron neutrino with masses up to 2 keV: https://arxiv.org/abs/1307.5687, https://arxiv.org/abs/1703.10779
* The data acquisition and analysis software in Troitsk nu-mass experiment.
* The Reactor model for TGF generation in thunderclouds.
* KMath library: https://github.com/mipt-npm/kmath.
## Publications
* ORCID: https://orcid.org/0000-0001-9075-0080
* Scopus ID: [24071435300](https://www.scopus.com/authid/detail.uri?authorId=24071435300)
* Web of Science ID: H-3844-2019
## Keywords
Scientific programming, Java, Kotlin, Particle physics, Neutrino, Data analysis, Mathematical statistics

View File

@ -0,0 +1,10 @@
---
language: en
---
**Director of the centre**
* PhD in particle physics.
* Director of [Scientific Programming Centre](/).
email: <a href="mailto:&#100;&#105;&#114;&#101;&#099;&#116;&#111;&#114;&#064;&#115;&#099;&#105;&#112;&#114;&#111;&#103;&#046;&#099;&#101;&#110;&#116;&#101;&#114;">&#100;&#105;&#114;&#101;&#099;&#116;&#111;&#114;&#064;&#115;&#099;&#105;&#112;&#114;&#111;&#103;&#046;&#099;&#101;&#110;&#116;&#101;&#114;</a>

View File

@ -0,0 +1,15 @@
---
type: team
title: Vladimir Palmin
id: palmin
order: 10
language: en
published: false
image:
path: images/people/palmin.jpg
position: left
---
**Analytics team lead**
Student at MIPT.

View File

@ -0,0 +1,20 @@
---
type: team
title: Aleksandr Svetlichnyi
id: svetlichnyi
order: 2
language: en
image:
path: images/people/svetlichnyi.jpeg
position: left
---
**Vice-director for education**
* Researcher at INR RAS.
* General physics teacher at MIPT.
* Deputy head of "scientific software" master program.
[ORCID](https://orcid.org/0000-0002-2086-7045)
[ResearchGate](https://www.researchgate.net/profile/Alexandr-Svetlichnyy)

View File

@ -0,0 +1,5 @@
---
language: en
---
**Vice-director for education**

View File

@ -0,0 +1,12 @@
---
type: team
title: Sergey Terentyev
id: terentyev
order: 5
language: en
image:
path: images/people/terentyev.jpg
position: left
---
**Vice-director for research**

View File

@ -0,0 +1,109 @@
---
type: project
title: BM@N infrastructure
order: 150
language: en
image: images/projects/bmn/nica.png
---
## Information Systems for BM@N
Our team works on development of information systems and services for BM@N (Baryonic Matter at Nuclotron) experiment, part of NICA (Nuclotron-based Ion Collider fAсility) megaproject (located in Dubna, Russia). These works are performed together with scientists from JINR and other institutions.
The overall view of NICA complex with already running experiment BM@N and future collider experiments MPD and SPD is shown in Fig. 1. BM@N studies collisions of elementary particles and ions with a fixed target with energies up to 6 GeV per nucleon, which is a very interesting energy region for fundamental nuclear physics research.
<span class="image fit">
<strong>Fig. 1</strong>
<img src="snark://ref/images/projects/bmn/nica.png" alt="Fig. 1"/>
</span>
### Event Metadata System
Event metadata systems (EMS) are widely used in the physics experiments on particle collisions, where large numbers of experimental events, typically billions, are collected. At the stage of particular physics analysis of experimental data, only a small subset of collected events meeting certain criteria is usually of interest, and passing over the whole amount of stored data to form the subset is overly time-consuming and resource-intensive. Instead, metadata systems allow one to obtain only the required events (or, at least, references to them) via searching and filtering based on given fields (event attributes) recorded in the metadata system.
The NICA Event Metadata System has been developed for storing necessary event metadata for the NICA experiments. The information system makes it possible to quickly search for a necessary subset of physics events by required parameters to use in further event data processing. It provides summary description of collision events and their identifiers to search and select events for a desired analysis task, enables their management and convenient access; provides online and offline interfaces for selecting events of interest, such as Web and REST API services, and a dedicated C++/ROOT interface.
The Event Metadata System, including the Event Catalogue based on PostgreSQL, Metadata API, Web Service, and other developed components, has been provisioned using a common deployment system for the first experiment of the NICA project, BM@N. The main interfaces to EMS, namely, Web UI and REST API have been developed using Kotlin multiplatform technology as a part of the single full-stack project. The EMS provides acceptable response times for the expected amount of the event metadata. The system and its services will be further evolved and improved following operational experience.
Figs. 2 and 3 illustrate high-level EMS architecture and its basic Web UI view.
<span class="image fit">
<strong>Fig. 2</strong>
<img src="snark://ref/images/projects/bmn/ems-arch.png" alt="Fig. 2"/>
</span>
<span class="image fit">
<strong>Fig. 3</strong>
<img src="snark://ref/images/projects/bmn/ems-web.png" alt="Fig. 3"/>
</span>
### Next-Generation Event Visualization (Event Display) System
In high-energy physics experiments, the ability to display both detector geometry and particle tracks has become an essential feature, required for physicists to better understand particular collision events as well as to present the physical results to a wider audience.
For BM@N experiment, a new event visualization solution was developed based on VisionForge, a modern open-source visualization system. An important part of the solution is integration of the system with experiment's software framework BmnRoot, which is a CERN ROOT-based environment.
Figs. 4, 5 illustrate how the Web interface of a new system looks like. The user can conveniently move and rotate the camera, zoom-in and zoom-out the scene as needed, browse the scene graph (object tree). For every object it is possible to change display properties such as color, opacity and visibility. Note that the full BM@N geometry model includes more than 400,000 primitives so rendering them all requires significant resources. To optimize the resource usage, so-called “prototypes” were implemented in VisionForge model for three-dimensional objects. For a single prototype its geometry is rendered only once and reused for multiple objects, which helps to significantly reduce memory usage.
<span class="image fit">
<strong>Fig. 4</strong>
<img src="snark://ref/images/projects/bmn/vis-1.png" alt="Fig. 4"/>
</span>
<span class="image fit">
<strong>Fig. 5</strong>
<img src="snark://ref/images/projects/bmn/vis-2.png" alt="Fig. 5"/>
</span>
### Condition Database Services
The Unified Condition Database (shortly called UniConDa) of the BM@N experiment is one of the advanced information systems required to support automation of experimental data collecting and processing, providing a central storage for experiment metadata being necessary for event data processing, including session and run information, detector and subsystem parameters, and descriptions of simulated event files.
The condition database has been earlier implemented based on the PostgreSQL database management system in accordance with a well-designed scheme. An ecosystem of its supplementary services is constantly being improved to increase overall degree of database integration and convenience of the use by collaboration members.
For the UniConDa ecosystem, the REST API, a modern HTTP-based interface for integration with both ROOT-based and non-ROOT software systems of the experiment, was developed.
Additionally, Smart Data Parser, a part of the BM@N information system based on the Unified Condition Database, was created to solve the task of the parameter data migration from accumulated files of ASCII text, CSV or XML formats to the Unified Condition Database of the BM@N experiment (Fig. 6).
<span class="image fit">
<strong>Fig. 6</strong>
<img src="snark://ref/images/projects/bmn/sdp.png" alt="Fig. 6"/>
</span>
### Monitoring Service
The software infrastructure of the BM@N experiment contains a set of various information systems that are essential for the work with experimental or simulated data on all processing stages, including the collection, storage, intermediate processing and physics analysis. In case one of such systems stops functioning, the work with BM@N data by collaboration members gets either impossible or, at least, much less productive. Due to this fact, the timely detection of possible failures in the systems due to software or hardware failures is fairly important.
The developed Monitoring Service is used to check availability and health status of information systems. This includes measuring, storing, visualizing and sending alert notifications on monitored parameters, such as CPU, memory and disk utilization, DBMS functioning parameters, response times of databases and API endpoints, ping round-trip times, and so on. The current implementation of the BM@N monitoring service is illustrated in Figs. 7, 8. Note that a related task of building highly available information services is currently a work in progress.
<span class="image fit">
<strong>Fig. 7</strong>
<img src="snark://ref/images/projects/bmn/mon-arch.png" alt="Fig. 7"/>
</span>
<span class="image fit">
<strong>Fig. 8</strong>
<img src="snark://ref/images/projects/bmn/mon-db.png" alt="Fig. 8"/>
</span>
### Slow Control System Viewer
Web interface for slow control system of BM@N was developed. It visualizes various sensor data graphs based on parameters and time intervals provided by user as shown in Fig. 9.
<span class="image fit">
<strong>Fig. 9</strong>
<img src="snark://ref/images/projects/bmn/scs.png" alt="Fig. 9"/>
</span>
### References
1. K. Gertsenberger, P. Klimai, M. Zelenyi. Auxiliary Services for the Condition Database of the BM@N Experiment at NICA // Phys.Part.Nucl.Lett. 20 (2023) 1217. https://www.doi.org/10.1134/S1547477123050291
2. E. Alexandrov, I. Alexandrov, A. Chebotov, A. Degtyarev, I. Filozova, K. Gertsenberger, P. Klimai, A. Yakovlev. Implementation of the Event Metadata System for physics analysis in the NICA experiments // Journal of Physics: Conference Series 2438 (2023) 012046. https://www.doi.org/10.1088/1742-6596/2438/1/012046
2. A. Degtyarev, K. Gertsenberger, P. Klimai. Usage of Apache Cassandra for Prototyping the Event Metadata System of the NICA Experiments // Phys.Part.Nucl.Lett. 19 (2022) 5, 562-565. https://doi.org/10.1134/S1547477122050144
3. A. Chebotov, K. Gertsenberger, P. Klimai, A. Moshkin. Information System Based on the Condition Database for the NICA Experiments, User WEB Application, and Related Services // Phys.Part.Nucl.Lett. 19 (2022) 5, 558-561. https://doi.org/10.1134/S1547477122050132
4. E. Alexandrov, I. Alexandrov, A. Degtyarev, K. Gertsenberger, I. Filozova, P. Klimai, A. Nozik, A. Yakovlev. Design of the Event Metadata System for the Experiments at NICA // Phys.Part.Nucl.Lett. 18 (2021) 5, 603-616. https://doi.org/10.1134/S1547477121050034
5. K. Gertsenberger, I. Alexandrov, I. Filozova, E. Alexandrov, A. Moshkin, A. Chebotov, M. Mineev, D. Pryahina, G. Shestakova, A. Yakovlev, A. Nozik, P. Klimai. Development of Information Systems for Online and Offline Data Processing in the NICA Experiments // Phys.Part.Nucl. 52 (2021) 4, 801-807. https://doi.org/10.1134/S1063779621040250
6. K.V. Gertsenberger, A.I. Chebotov, P.A. Klimai, I.N. Alexandrov, E.I. Alexandrov, I.A. Filozova, A.A. Moshkin. Implementation of the Condition Database for the Experiments of the NICA Complex // CEUR Workshop Proceedings, Vol. 3041 (2021) 128-132. https://doi.org/10.54546/MLIT.2021.53.54.001
7. E.I. Alexandrov, I.N. Alexandrov, A.G. Degtyarev, I.A. Filozova, K.V. Gertsenberger, P.A. Klimai, A.V. Yakovlev. Development of the Event Metadata System for the NICA experiments // CEUR Workshop Proceedings, Vol. 3041 (2021) 439-444. https://doi.org/10.54546/MLIT.2021.80.18.001
8. M.N.Kapishin et al, The Report on Project “Studies of Baryonic Matter at the Nuclotron (BM@N)”, https://bmn.jinr.ru/wp-content/uploads/2022/10/BMNproject_2021cor2.pdf

View File

@ -0,0 +1,5 @@
---
language: en
---
Our team works on development of information systems and services for BM@N (Baryonic Matter at Nuclotron) experiment, part of NICA (Nuclotron-based Ion Collider fAсility) megaproject (located in Dubna, Russia). These works are performed together with scientists from JINR and other institutions.

View File

@ -0,0 +1,31 @@
---
type: project
title: Controls-kt
order: 10
language: en
image: images/projects/controls-demo.png
---
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[Repository and documentation](https://github.com/mipt-npm/controls.kt)
Controls.kt is a data acquisition framework (work in progress). It is based on DataForge, a software framework for automated data processing. This repository contains a prototype of API and simple implementation
of a slow control system, including a demo.
Controls.kt uses some concepts and modules of DataForge,
such as `Meta` (immutable tree-like structure) and `Meta` (which
includes a scalar value, or a tree of values, easily convertable to/from JSON
if needed).
## Materials and publications
* Video - [A general overview seminar](https://youtu.be/LO-qjWgXMWc)
* Video - [A seminar about the system mechanics](https://youtu.be/wES0RV5GpoQ)
* Article - [A Novel Solution for Controlling Hardware Components of Accelerators and Beamlines](https://www.preprints.org/manuscript/202108.0336/v1)
### Features
Among other things, you can:
- Describe devices and their properties.
- Collect data from devices and execute arbitrary actions supported by a device.
- Property values can be cached in the system and requested from devices as needed, asynchronously.
- Connect devices to event bus via bidirectional message flows.

View File

@ -0,0 +1,7 @@
---
language: en
---
Controls.kt is a data acquisition framework (work in progress). It is based on DataForge, a software framework for automated data processing.
[Repository and documentation](https://github.com/mipt-npm/controls.kt)

View File

@ -0,0 +1,73 @@
---
type: project
title: DataForge
order: 5
language: en
image:
path: images/projects/df.svg
position: left
---
[Repository and documentation](https://github.com/mipt-npm/dataforge-core)
## Publications
* [A general overview](https://doi.org/10.1051/epjconf/201817705003)
* [An application in "Troitsk nu-mass" experiment](https://doi.org/10.1088/1742-6596/1525/1/012024)
## Video
A presentation on application of (old version of) DataForge to Troitsk nu-mass analysis.
<iframe width="100%" height="315" src="https://www.youtube.com/embed/OpWzLXUZnLI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
## Questions and Answers
In this section, we will try to cover DataForge main ideas in the form of questions and answers.
### General
**Q**: I have a lot of data to analyze. The analysis process is complicated, requires a lot of stages and data flow is not always obvious. To top it the data size is huge, so I don't want to perform operation I don't need (calculate something I won't need or calculate something twice). And yes, I need it to be performed in parallel and probably on remote computer. By the way, I am sick and tired of scripts that modify other scripts that control scripts. Could you help me?
**A**: Yes, that is precisely the problem DataForge was made to solve. It allows to perform some automated data manipulations with automatic optimization and parallelization. The important thing that data processing recipes are made in the declarative way, so it is quite easy to perform computations on a remote station. Also, DataForge guarantees reproducibility of analysis results.
**Q**: How does it work?
**A**: At the core of DataForge lies the idea of metadata processor. It utilizes the fact that in order to analyze something you need data itself and some additional information about what does that data represent and what does user want as a result. This additional information is called metadata and could be organized in a regular structure (a tree of values not unlike XML or JSON). The important thing is that this distinction leaves no place for user instructions (or scripts). Indeed, the idea of DataForge logic is that one do not need imperative commands. The framework configures itself according to input meta-data and decides what operations should be performed in the most efficient way.
**Q**: But where does it take algorithms to use?
**A**: Of course algorithms must be written somewhere. No magic here. The logic is written in specialized modules. Some modules are provided out of the box at the system core, some need to be developed for specific problem.
**Q**: So I still need to write the code? What is the difference then?
**A**: Yes, someone still needs to write the code. But not necessary you. Simple operations could be performed using provided core logic. Also, your group can have one programmer writing the logic and all other using it without any real programming expertise. The framework organized in a such way that one writes some additional logic, they do not need to think about complicated thing like parallel computing, resource handling, logging, caching etc. Most of the things are done by the DataForge.
### Platform
**Q**: Which platform does DataForge use? Which operating system is it working on?
**A**: The DataForge is mostly written in Kotlin-multiplatform and could be used on JVM, JS and native targets. Some modules and functions are supported only on JVM
**Q**: Can I use my C++/Fortran/Python code in DataForge?
A: Yes, as long as the code could be called from Java. Most of common languages have a bridge for Java access. There are completely no problems with compiled C/Fortran libraries. Python code could be called via one of existing python-java interfaces. It is also planned to implement remote method invocation for common languages, so your Python, or, say, Julia, code could run in its native environment. The metadata processor paradigm makes it much easier to do so.
### Features
**Q**: What other features does DataForge provide?
**A**: Alongside metadata processing (and a lot of tools for metadata manipulation and layering), DataForge has two additional important concepts:
* **Modularisation**. Contrary to lot other frameworks, DataForge is intrinsically modular. The mandatory part is a rather tiny core module. Everything else could be customized.
* **Context encapsulation**. Every DataForge task is executed in some context. The context isolates environment for the task and also works as dependency injection base and specifies interaction of the task with the external world.
### Misc
**Q**: So everything looks great, can I replace my ROOT / other data analysis framework with DataForge?
**A**: One must note, that DataForge is made for analysis, not for visualisation. The visualisation and user interaction capabilities of DataForge are rather limited compared to frameworks like ROOT, JAS3 or DataMelt. The idea is to provide reliable API and core functionality. In fact JAS3 and DataMelt could be used as a frontend for DataForge mechanics.
**Q**: How does DataForge compare to cluster computation frameworks like Apache Spark?
**A**: Again, it is not the purpose of DataForge to replace cluster software. DataForge has some internal parallelism mechanics and implementations, but they are most certainly worse than specially developed programs. Still, DataForge is not fixed on one single implementation. Your favourite parallel processing tool could be still used as a back-end for the DataForge. With full benefit of configuration tools, integrations and no performance overhead.
**Q**: Is it possible to use DataForge in notebook mode?
**A**: [Kotlin jupyter](https://github.com/Kotlin/kotlin-jupyter) allows to use any JVM program in a notebook mode. The dedicated module for DataForge is work in progress.

View File

@ -0,0 +1,7 @@
---
language: en
---
A metadata processing workflow manipulation framework.
[Repository and documentation](https://github.com/mipt-npm/dataforge-core)

View File

@ -0,0 +1,45 @@
---
type: project
title: KMath
order: 1
language: en
image:
path: images/projects/KMath.png
position: right
---
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
[Repository and documentation](https://github.com/mipt-npm/kmath)
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
## Publications and talks
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
## Goal
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
.
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
## Non-goals
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
experience for those, who want to work with specific types.

View File

@ -0,0 +1,7 @@
---
language: en
---
An experimental Kotlin library for mathematical operations, built on the principle of context-oriented programming using mathematical abstractions.
[Repository and documentation](https://github.com/mipt-npm/kmath)

Some files were not shown because too many files have changed in this diff Show More