diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..96250dd
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,6 @@
+{
+ "extends": "eslint-config-standard",
+ "rules": {
+ "no-unused-vars": "off"
+ }
+}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..c701365
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,24 @@
+name: CI
+
+on:
+ push:
+ branches:
+ - dev
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v2
+ - name: Install dependencies
+ run: npm install
+ - name: Lint CSS
+ run: npm run lint:css
+ - name: Lint JS
+ run: npm run lint:js
+ - name: Run Prettier
+ run: npm run format
\ No newline at end of file
diff --git a/.stylelintrc.json b/.stylelintrc.json
new file mode 100644
index 0000000..d1aa6e1
--- /dev/null
+++ b/.stylelintrc.json
@@ -0,0 +1,9 @@
+{
+ "extends": ["stylelint-config-standard"],
+ "rules": {
+ "selector-pseudo-class-no-unknown": null,
+ "selector-type-no-unknown": null,
+ "property-no-unknown": null,
+ "at-rule-no-unknown": null
+ }
+}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fea8c34
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+[Ссылка на сайт](http://kolbaser.ru/)
\ No newline at end of file
diff --git a/content.css b/content.css
new file mode 100644
index 0000000..12f6e86
--- /dev/null
+++ b/content.css
@@ -0,0 +1,194 @@
+/* stylelint-disable selector-class-pattern */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 100vh;
+ background: #f1f4fd;
+}
+
+.container {
+ max-width: 1200px;
+ width: 95%;
+}
+
+.slider-wrapper {
+ position: relative;
+}
+
+.slider-wrapper .slide-button {
+ position: absolute;
+ top: 50%;
+ outline: none;
+ border: none;
+ height: 50px;
+ width: 50px;
+ z-index: 5;
+ color: #fff;
+ display: flex;
+ cursor: pointer;
+ font-size: 2.2rem;
+ background: #000;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ transform: translateY(-50%);
+}
+
+.slider-wrapper .slide-button:hover {
+ background: #404040;
+}
+
+.slider-wrapper .slide-button#prev-slide {
+ left: -25px;
+ display: none;
+}
+
+.slider-wrapper .slide-button#next-slide {
+ right: -25px;
+}
+
+.slider-wrapper .image-list {
+ display: grid;
+ grid-template-columns: repeat(10, 1fr);
+ gap: 18px;
+ font-size: 0;
+ list-style: none;
+ margin-top: 100px;
+ margin-bottom: 30px;
+ overflow-x: auto;
+ scrollbar-width: none;
+}
+
+.slider-wrapper .image-list::-webkit-scrollbar {
+ display: none;
+}
+
+.slider-wrapper .image-list .image-item {
+ width: 325px;
+ height: 400px;
+ object-fit: cover;
+}
+
+.container .slider-scrollbar {
+ height: 24px;
+ width: 100%;
+ display: flex;
+ align-items: center;
+}
+
+.slider-scrollbar .scrollbar-track {
+ background: #ccc;
+ width: 100%;
+ height: 2px;
+ display: flex;
+ align-items: center;
+ border-radius: 4px;
+ position: relative;
+}
+
+.slider-scrollbar:hover .scrollbar-track {
+ height: 4px;
+}
+
+.slider-scrollbar .scrollbar-thumb {
+ position: absolute;
+ background: #000;
+ top: 0;
+ bottom: 0;
+ width: 50%;
+ height: 100%;
+ cursor: grab;
+ border-radius: inherit;
+}
+
+.slider-scrollbar .scrollbar-thumb:active {
+ cursor: grabbing;
+ height: 8px;
+ top: -2px;
+}
+
+.slider-scrollbar .scrollbar-thumb::after {
+ content: "";
+ position: absolute;
+ inset: -10px 0;
+}
+
+.return-btn {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+ z-index: 1000;
+}
+
+.return-btn img {
+ width: 50px;
+ height: auto;
+}
+
+#scroll-button {
+ position: fixed;
+ top: 30px;
+ left: 96%;
+ transform: translateX(-50%);
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+}
+
+#scroll-button img {
+ width: 50px;
+}
+
+.video-container {
+ display: flex;
+ justify-content: center;
+ margin-top: 150px;
+ margin-bottom: 70px;
+}
+
+video {
+ width: 80%;
+ max-width: 100%;
+ height: auto;
+}
+
+@media only screen and (width <= 1023px) {
+ .slider-wrapper .slide-button {
+ display: none !important;
+ }
+
+ .slider-wrapper .image-list {
+ gap: 10px;
+ margin-bottom: 15px;
+ scroll-snap-type: x mandatory;
+ }
+
+ .slider-wrapper .image-list .image-item {
+ width: 280px;
+ height: 380px;
+ }
+
+ .slider-scrollbar .scrollbar-thumb {
+ width: 20%;
+ }
+
+ .video-container {
+ margin-top: 150px;
+ margin-bottom: 70px;
+ }
+
+ #scroll-button {
+ left: 90%;
+ }
+
+ video {
+ width: 100%;
+ }
+}
\ No newline at end of file
diff --git a/content.html b/content.html
new file mode 100644
index 0000000..50595ee
--- /dev/null
+++ b/content.html
@@ -0,0 +1,59 @@
+
+
+
+
+
+ Котики!!!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..de38ea6
--- /dev/null
+++ b/index.html
@@ -0,0 +1,47 @@
+
+
+
+
+
+ Про меня
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Артем
+
+ Привет, я учусь в ИТМО. Можете написать мне в
+ телеграм.
+
+
+
+ Я очень люблю котиков, поэтому
+ тут
+ вы можете посмотреть видео и полистать фото c ними...
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..25fbb47
--- /dev/null
+++ b/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "visit",
+ "version": "1.0.0",
+ "description": "[Ссылка на сайт](http://kolbaser.ru/)",
+ "main": "script.js",
+ "scripts": {
+ "lint:css": "stylelint --fix --ignore-path .gitignore *.css",
+ "lint:js": "eslint . --fix",
+ "format": "prettier --write \"**/*.html\" \"**/*.json\""
+ },
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "eslint": "^8.57.0",
+ "eslint-config-standard": "^17.1.0",
+ "prettier": "^3.2.5",
+ "stylelint": "^16.2.1",
+ "stylelint-config-standard": "^36.0.0"
+ }
+}
diff --git a/res/1.jpg b/res/1.jpg
new file mode 100644
index 0000000..4253de7
Binary files /dev/null and b/res/1.jpg differ
diff --git a/res/10.jpg b/res/10.jpg
new file mode 100644
index 0000000..87e126a
Binary files /dev/null and b/res/10.jpg differ
diff --git a/res/2.jpg b/res/2.jpg
new file mode 100644
index 0000000..c4e6d98
Binary files /dev/null and b/res/2.jpg differ
diff --git a/res/3.jpg b/res/3.jpg
new file mode 100644
index 0000000..e34b380
Binary files /dev/null and b/res/3.jpg differ
diff --git a/res/4.jpg b/res/4.jpg
new file mode 100644
index 0000000..fbbaaff
Binary files /dev/null and b/res/4.jpg differ
diff --git a/res/5.jpg b/res/5.jpg
new file mode 100644
index 0000000..6537058
Binary files /dev/null and b/res/5.jpg differ
diff --git a/res/6.jpg b/res/6.jpg
new file mode 100644
index 0000000..05a3282
Binary files /dev/null and b/res/6.jpg differ
diff --git a/res/7.jpg b/res/7.jpg
new file mode 100644
index 0000000..7cacda4
Binary files /dev/null and b/res/7.jpg differ
diff --git a/res/8.jpg b/res/8.jpg
new file mode 100644
index 0000000..e34d500
Binary files /dev/null and b/res/8.jpg differ
diff --git a/res/9.jpg b/res/9.jpg
new file mode 100644
index 0000000..aecc770
Binary files /dev/null and b/res/9.jpg differ
diff --git a/res/down.png b/res/down.png
new file mode 100644
index 0000000..62770a0
Binary files /dev/null and b/res/down.png differ
diff --git a/res/home.png b/res/home.png
new file mode 100644
index 0000000..37a5efd
Binary files /dev/null and b/res/home.png differ
diff --git a/res/me.png b/res/me.png
new file mode 100644
index 0000000..8182511
Binary files /dev/null and b/res/me.png differ
diff --git a/res/post.jpg b/res/post.jpg
new file mode 100644
index 0000000..9f5f565
Binary files /dev/null and b/res/post.jpg differ
diff --git a/res/video.mp4 b/res/video.mp4
new file mode 100644
index 0000000..966f1b9
Binary files /dev/null and b/res/video.mp4 differ
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..3063004
--- /dev/null
+++ b/script.js
@@ -0,0 +1,113 @@
+const initSlider = () => {
+ const initCarousel = (containerId, images) => {
+ const container = document.getElementById(containerId)
+ let imageList = container.querySelector('.image-list')
+ let maxScrollLeft
+
+ const destroyCarousel = () => {
+ imageList.removeEventListener('scroll', handleScroll)
+ window.removeEventListener('resize', updateSlider)
+ imageList = null
+ maxScrollLeft = null
+ }
+
+ const updateMaxScrollLeft = () => {
+ maxScrollLeft = imageList.scrollWidth - imageList.clientWidth
+ }
+
+ const updateSlider = () => {
+ updateMaxScrollLeft()
+ updateScrollThumbPosition()
+ handleSlideButtons()
+ }
+
+ const handleScroll = () => {
+ updateScrollThumbPosition()
+ handleSlideButtons()
+ }
+
+ const updateScrollThumbPosition = () => {
+ const scrollPosition = imageList.scrollLeft
+ const thumbPosition =
+ (scrollPosition / maxScrollLeft) *
+ (sliderScrollbar.clientWidth - scrollbarThumb.offsetWidth)
+ scrollbarThumb.style.left = `${thumbPosition}px`
+ }
+
+ const handleSlideButtons = () => {
+ slideButtons[0].style.display = imageList.scrollLeft <= 0 ? 'none' : 'flex'
+ slideButtons[1].style.display =
+ imageList.scrollLeft >= maxScrollLeft ? 'none' : 'flex'
+ }
+
+ window.addEventListener('resize', updateSlider)
+
+ images.forEach(imageSrc => {
+ const image = document.createElement('img')
+ image.src = imageSrc
+ image.classList.add('image-item')
+ imageList.appendChild(image)
+ })
+
+ const slideButtons = container.querySelectorAll('.slide-button')
+ const sliderScrollbar = container.querySelector('.slider-scrollbar')
+ const scrollbarThumb = sliderScrollbar.querySelector('.scrollbar-thumb')
+
+ updateSlider()
+
+ slideButtons.forEach((button) => {
+ button.addEventListener('click', () => {
+ const direction = button.id === 'prev-slide' ? -1 : 1
+ const scrollAmount = imageList.clientWidth * direction
+ imageList.scrollBy({ left: scrollAmount, behavior: 'smooth' })
+ })
+ })
+
+ scrollbarThumb.addEventListener('mousedown', (e) => {
+ const startX = e.clientX
+ const thumbPosition = scrollbarThumb.offsetLeft
+ const maxThumbPosition = sliderScrollbar.clientWidth - scrollbarThumb.offsetWidth
+
+ const handleMouseMove = (e) => {
+ const deltaX = e.clientX - startX
+ const newThumbPosition = thumbPosition + deltaX
+ const boundedPosition = Math.max(
+ 0,
+ Math.min(maxThumbPosition, newThumbPosition)
+ )
+ const scrollPosition =
+ (boundedPosition / maxThumbPosition) * maxScrollLeft
+
+ scrollbarThumb.style.left = `${boundedPosition}px`
+ imageList.scrollLeft = scrollPosition
+ }
+
+ const handleMouseUp = () => {
+ document.removeEventListener('mousemove', handleMouseMove)
+ document.removeEventListener('mouseup', handleMouseUp)
+ }
+
+ document.addEventListener('mousemove', handleMouseMove)
+ document.addEventListener('mouseup', handleMouseUp)
+ })
+
+ imageList.addEventListener('scroll', handleScroll)
+
+ return destroyCarousel
+ }
+
+ const slider1Images = ['res/1.jpg', 'res/2.jpg', 'res/3.jpg', 'res/4.jpg', 'res/5.jpg', 'res/1.jpg']
+ const destroySlider1 = initCarousel('slider1', slider1Images)
+
+ const slider2Images = ['res/6.jpg', 'res/7.jpg', 'res/8.jpg', 'res/9.jpg', 'res/10.jpg', 'res/9.jpg']
+ const destroySlider2 = initCarousel('slider2', slider2Images)
+}
+
+function scrollToBottom () {
+ window.scrollTo({
+ top: document.body.scrollHeight,
+ behavior: 'smooth'
+ })
+}
+
+window.addEventListener('load', initSlider)
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..b1d7250
--- /dev/null
+++ b/style.css
@@ -0,0 +1,177 @@
+/* stylelint-disable selector-class-pattern */
+*,
+::before,
+::after {
+ box-sizing: border-box;
+}
+
+body {
+ margin: 0;
+ font-family: Montserrat, sans-serif;
+}
+
+img {
+ width: 100%;
+ height: 100%;
+}
+
+h1,
+h2,
+h3 {
+ margin: 0;
+}
+
+.header {
+ width: 100%;
+ padding: 15px 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 24px;
+ font-weight: 300;
+ color: gray;
+}
+
+.hero {
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.container {
+ max-width: 1230px;
+ width: 100%;
+ margin: 0 auto;
+ padding: 0 15px;
+}
+
+.hero-container {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
+ grid-gap: 20px;
+}
+
+.hero-about {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+.hero-title {
+ font-size: 48px;
+ line-height: 1.1;
+ margin-bottom: 20px;
+}
+
+.hero-prof {
+ color: #4facfe;
+ white-space: nowrap;
+}
+
+.hero-subtitle {
+ font-size: 32px;
+ font-weight: 400;
+}
+
+.hero-links {
+ display: flex;
+}
+
+.hero-description__link {
+ margin-top: 50px;
+ color: #000;
+}
+
+.hero-description__link:hover {
+ color: #4facfe;
+}
+
+.hero-box {
+ max-width: 500px;
+ justify-self: center;
+ overflow: hidden;
+ border: 10px solid #fff;
+ background-image: linear-gradient(to right, #4facfe 0%, #00f2fe 100%);
+ animation: ava-animate 5s infinite alternate;
+ box-shadow: 2px 5px 10px rgb(0 0 0 / 50%);
+}
+
+.hero-box__img {
+ animation: ava-bg 3s infinite alternate;
+}
+
+@keyframes fade {
+ from {
+ opacity: 0.4;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+@media screen and (width <= 978px) {
+ .hero {
+ padding-top: 30px;
+ }
+
+ .hero-container {
+ grid-row-gap: 20px;
+ }
+
+ .hero-title {
+ font-size: 28px;
+ margin-bottom: 10px;
+ }
+
+ .hero-subtitle {
+ font-size: 22px;
+ font-weight: 400;
+ }
+
+ .hero-description {
+ font-size: 14px;
+ }
+
+ .hero-about {
+ text-align: center;
+ }
+
+ .hero-links {
+ justify-content: center;
+ }
+
+ .hero-box {
+ max-width: 350px;
+ justify-self: center;
+ }
+}
+
+@keyframes ava-animate {
+ 0% {
+ border-radius: 62% 38% 72% 28% / 67% 32% 68% 33%;
+ }
+
+ 40% {
+ border-radius: 37% 63% 53% 47% / 67% 32% 68% 33%;
+ }
+
+ 60% {
+ border-radius: 23% 77% 39% 61% / 78% 54% 46% 22%;
+ }
+
+ 100% {
+ border-radius: 18% 82% 24% 76% / 43% 54% 46% 57%;
+ }
+}
+
+@keyframes ava-bg {
+ from {
+ backdrop-filter: hue-rotate(0);
+ }
+
+ to {
+ backdrop-filter: hue-rotate(90deg);
+ }
+}