diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a51da91
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+# Generated
+node_modules
+test/.astro
+test/node_modules
diff --git a/index.ts b/index.ts
new file mode 100644
index 0000000..ef298f0
--- /dev/null
+++ b/index.ts
@@ -0,0 +1 @@
+export { default as Zorn } from './src/Player.astro'
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..e425d07
--- /dev/null
+++ b/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@minpluto/zorn",
+ "author": "SudoVanilla",
+ "type": "module",
+ "version": "0.4.3",
+ "exports": {
+ ".": "./index.ts"
+ },
+ "files": [
+ "index.ts",
+ "src/*"
+ ],
+ "publishConfig": {
+ "access": "public"
+ },
+ "dependencies": {
+ "@iconoir/vue": "^7.8.0",
+ "astro": "^4.14.2"
+ }
+}
\ No newline at end of file
diff --git a/src/Controls.astro b/src/Controls.astro
new file mode 100644
index 0000000..405c4cb
--- /dev/null
+++ b/src/Controls.astro
@@ -0,0 +1,36 @@
+---
+// Icons
+import {
+ Backward15Seconds,
+ Enlarge,
+ Forward15Seconds,
+ PlaySolid,
+} from "@iconoir/vue";
+---
+
+
+
+
+
+
+
+
+
+
+
+ 00:00
+ 00:00
+ 00:00
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Controls/Controller.astro b/src/Controls/Controller.astro
new file mode 100644
index 0000000..229c5e3
--- /dev/null
+++ b/src/Controls/Controller.astro
@@ -0,0 +1,195 @@
+
\ No newline at end of file
diff --git a/src/Controls/Seek.astro b/src/Controls/Seek.astro
new file mode 100644
index 0000000..107e2cb
--- /dev/null
+++ b/src/Controls/Seek.astro
@@ -0,0 +1,83 @@
+
\ No newline at end of file
diff --git a/src/Controls/Sync.astro b/src/Controls/Sync.astro
new file mode 100644
index 0000000..c8b40a1
--- /dev/null
+++ b/src/Controls/Sync.astro
@@ -0,0 +1,66 @@
+
\ No newline at end of file
diff --git a/src/Index.scss b/src/Index.scss
new file mode 100644
index 0000000..543bbba
--- /dev/null
+++ b/src/Index.scss
@@ -0,0 +1,221 @@
+.video-container {
+ position: relative;
+ .video-controls, video {
+ border-radius: 12px;
+ }
+ *:focus {
+ border: 2px white solid;
+ transition: 1s border;
+ }
+ video {
+ width: 100%;
+ z-index: 1;
+ }
+ canvas {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ z-index: -1;
+ filter: blur(24px);
+ transform: scale(1.05);
+ }
+ .video-controls {
+ background: linear-gradient(0deg, rgba(0,0,0,0.7523460067620799) 0%, rgba(0,0,0,0) 15%, rgba(0,0,0,0) 94%, rgba(0,0,0,0.7495448863139005) 100%);;
+ position: absolute;
+ bottom: 4px;
+ left: 0px;
+ width: calc(100% - 24px);
+ padding: 12px;
+ z-index: 5;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ height: calc(100% - 28px);
+ transition: 0.3s opacity;
+ button {
+ color: white;
+ border-radius: 3rem;
+ aspect-ratio: 1;
+ border: none;
+ background: transparent;
+ display: flex;
+ align-items: center;
+ padding: 6px;
+ cursor: pointer;
+ &:hover {
+ background: rgba(255, 255, 255, 0.1);
+ }
+ }
+ .vc-top {
+ margin-top: 12px;
+ pointer-events: none;
+ opacity: 0;
+ transition: 0.3s opacity;
+ }
+ .vc-bottom {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ justify-content: space-between;
+ .vc-start,
+ .vc-end {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ }
+ .vc-center {
+ width: calc(100% - 220px);
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ p {
+ width: max-content;
+ }
+ }
+ .vc-seek {
+ background: rgb(255 255 255 / 10%);
+ width: 100%;
+ height: 6px;
+ position: relative;
+ display: block;
+ border-radius: 3rem;
+ .vc-progress-bar {
+ width: 1%;
+ background: #ff274d;
+ position: absolute;
+ left: 0px;
+ height: 100%;
+ border-radius: 3rem;
+ }
+ input#seek {
+ position: absolute;
+ top: -8px;
+ left: 0px;
+ width: 100%;
+
+ }
+ #seek[type="range"] {
+ -webkit-appearance: none;
+ appearance: none;
+ background: transparent;
+ cursor: pointer;
+ width: 100%;
+ }
+ #seek[type="range"]:focus {
+ outline: none;
+ }
+ #seek[type="range"]::-webkit-slider-runnable-track {
+ background-color: transparent;
+ border-radius: 3rem;
+ height: 1rem;
+ }
+ #seek[type="range"]::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ margin-top: -4px;
+ background-color: #ffffff;
+ border-radius: 3rem;
+ height: 1.5rem;
+ width: 1.5rem;
+ }
+ #seek[type="range"]:focus::-webkit-slider-thumb {
+ outline: 3px solid #ffffff;
+ outline-offset: 0.125rem;
+ }
+ #seek[type="range"]::-moz-range-track {
+ background-color: transparent;
+ border-radius: 3rem;
+ height: 1rem;
+ }
+ #seek[type="range"]::-moz-range-thumb {
+ background-color: #ffffff;
+ border: none;
+ border-radius: 3rem;
+ height: 1.5rem;
+ width: 1.5rem;
+ }
+ #seek[type="range"]:focus::-moz-range-thumb{
+ outline: 3px solid transparent;
+ outline-offset: 0.125rem;
+ }
+ }
+ .timestamp {
+ display: flex;
+ background: rgb(255 255 255 / 10%);
+ border-radius: 3rem;
+ align-items: center;
+ position: relative;
+ pointer-events: none;
+ color: white;
+ font-family: Arial, Helvetica, sans-serif;
+ #seek-tooltip {
+ z-index: 10;
+ background: #464646;
+ padding: 6px 12px;
+ border-radius: 3rem 0px 0px 3rem;
+ margin-right: -64px;
+ opacity: 0;
+ transition: 0.3s opacity;
+ }
+ #current {
+ background: rgb(255 255 255 / 15%);
+ padding: 6px 12px;
+ border-radius: 3rem 0px 0px 3rem;
+ }
+ #duration {
+ padding: 6px 12px;
+ }
+ }
+ }
+ }
+}
+
+.video-controls.hide {
+ opacity: 0;
+ transition: 0.3s opacity;
+}
+
+.vc-menu {
+ position: absolute;
+ right: 0px;
+ bottom: 0px;
+ background: rgb(0 0 0 / 25%);
+ border-radius: 6px;
+ margin: 0px 24px 90px 0px;
+ width: max-content;
+ min-width: 180px;
+ display: none;
+ flex-direction: column;
+ gap: 6px;
+ padding: 4px;
+ backdrop-filter: blur(24px) contrast(0.8) brightness(0.8);
+ hr {
+ margin: 0px;
+ width: 100%;
+ height: 1px;
+ }
+ button {
+ padding: 6px 12px !important;
+ margin: 0px !important;
+ aspect-ratio: inherit !important;
+ background: transparent !important;
+ border-radius: 4px !important;
+ display: flex;
+ justify-content: space-between;
+ font-size: 14px !important;
+ min-height: 36px;
+ &:hover {
+ background: rgb(95 95 95 / 51%) !important;
+ }
+ svg {
+ width: 14px;
+ }
+ }
+}
+
+button#has-switch svg {
+ width: 24px;
+}
\ No newline at end of file
diff --git a/src/Milieu.astro b/src/Milieu.astro
new file mode 100644
index 0000000..9546e08
--- /dev/null
+++ b/src/Milieu.astro
@@ -0,0 +1,95 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Player.astro b/src/Player.astro
new file mode 100644
index 0000000..9c6537a
--- /dev/null
+++ b/src/Player.astro
@@ -0,0 +1,30 @@
+---
+// Properties
+const {
+ Poster,
+ Video,
+ Audio, // For YouTube Frontends that wants to support 1080p and higher
+ CustomControls = true,
+ VideoAttributes,
+ AudioAttributes,
+ Milieu
+} = Astro.props
+
+// Components
+import Controls from './Controls.astro'
+import MilieuEffect from './Milieu.astro'
+import Controller from './Controls/Controller.astro'
+import Seek from './Controls/Seek.astro'
+import Sync from './Controls/Sync.astro'
+
+// Styles
+import './Index.scss'
+---
+
+
+
+ {Audio ?
: null }
+ {Milieu ?
: null }
+ {Audio ?
: null }
+ {CustomControls ?
: null }
+
\ No newline at end of file
diff --git a/test/astro.config.mjs b/test/astro.config.mjs
new file mode 100644
index 0000000..8de5d99
--- /dev/null
+++ b/test/astro.config.mjs
@@ -0,0 +1,4 @@
+import { defineConfig } from 'astro/config';
+import vue from '@astrojs/vue';
+
+export default defineConfig({integrations: [vue()]});
\ No newline at end of file
diff --git a/test/package.json b/test/package.json
new file mode 100644
index 0000000..89b7df9
--- /dev/null
+++ b/test/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "test",
+ "type": "module",
+ "version": "0.0.1",
+ "scripts": {
+ "dev": "astro dev",
+ "start": "astro dev",
+ "build": "astro check && astro build",
+ "preview": "astro preview",
+ "astro": "astro"
+ },
+ "dependencies": {
+ "@astrojs/check": "^0.9.2",
+ "@astrojs/vue": "^4.5.0",
+ "@minpluto/zorn": "../",
+ "astro": "^4.14.2",
+ "typescript": "^5.5.4",
+ "vue": "^3.4.38"
+ },
+ "devDependencies": {
+ "sass-embedded": "^1.77.8"
+ }
+}
\ No newline at end of file
diff --git a/test/src/env.d.ts b/test/src/env.d.ts
new file mode 100644
index 0000000..e16c13c
--- /dev/null
+++ b/test/src/env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/test/src/pages/index.astro b/test/src/pages/index.astro
new file mode 100644
index 0000000..3afe93d
--- /dev/null
+++ b/test/src/pages/index.astro
@@ -0,0 +1,27 @@
+---
+// Components
+import {Zorn} from '@minpluto/zorn'
+---
+
+
+
+
+Эни и Йойки: Недевчачьи игры. 1 серия. Мультфильмы для детей
+Translation: "Non-girly games"
+Created by Daniyar Yambushev
+Source: https://www.youtube.com/watch?v=MuyJtxzyU3o
+
+View with separated audio
+
+
\ No newline at end of file
diff --git a/test/tsconfig.json b/test/tsconfig.json
new file mode 100644
index 0000000..77da9dd
--- /dev/null
+++ b/test/tsconfig.json
@@ -0,0 +1,3 @@
+{
+ "extends": "astro/tsconfigs/strict"
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..0682c6f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "include": [
+ "./src",
+ "index.ts"
+ ],
+ "compilerOptions": {
+ "jsx": "react"
+ }
+}
\ No newline at end of file